001package org.vishia.guiViewCfg;
002
003import java.text.ParseException;
004import java.util.Map;
005import java.util.TreeMap;
006
007import org.vishia.communication.Address_InterProcessComm;
008import org.vishia.communication.InspcDataExchangeAccess;
009import org.vishia.communication.InterProcessComm;
010import org.vishia.communication.InterProcessCommFactory;
011import org.vishia.mainCmd.Report;
012
013/**This class organizes the receiving of data from a automation device. An own thread is created.
014 * In its run-routine the thread waits for receiving data via socket or another adequate 
015 * interprocess-communication.
016 * For evaluating the received data the routine {@link OamShowValues#show(byte[], int, int)} is called.
017 * <br><br>
018 * A datagram may contain more as one data-set. The datagram is defined with the inspector-datagram-
019 * definition, see {@link InspcDataExchangeAccess}.
020 * @author Hartmut Schorrig
021 *
022 */
023public class OamRcvValue implements Runnable
024{
025
026        /**Associated class which shows the values */
027        private final OamShowValues showValues;
028        
029        /**The thread. Composition. */
030        private final Thread thread;
031        
032        boolean bRun;
033
034        int ctCorruptData;
035        
036        boolean bIpcOpened;
037        
038        private final Map<String, String> indexUnknownVariable = new TreeMap<String, String>();
039        
040        InspcDataExchangeAccess.InspcDatagram datagramRcv = new InspcDataExchangeAccess.InspcDatagram();
041        
042        InspcDataExchangeAccess.Inspcitem infoEntity = new InspcDataExchangeAccess.Inspcitem();
043        
044        final Report log;
045
046
047        private final InterProcessComm ipc;
048
049        private final Address_InterProcessComm targetAddr = InterProcessCommFactory.getInstance().createAddress("UDP:localHost:60083");
050        
051        byte[] recvData = new byte[1500];
052        
053        byte[] sendData = new byte[1500];
054        
055        public OamRcvValue(
056                OamShowValues showValues
057        , Report log
058        )
059        {
060                thread = new Thread(this, "oamRcv");
061                this.log = log;
062                this.showValues = showValues;
063                String ownAddr = "UDP:0.0.0.0:0xeab2";
064                
065                ipc = InterProcessCommFactory.getInstance().create(ownAddr); //It creates and opens the UDP-Port.
066                ipc.open(null, true); //InterProcessComm.receiverShouldbeBlocking);
067                if(ipc != null){
068                        bIpcOpened = true;
069                }
070        }
071
072        /**Starts the receiver thread. */
073        public void start()
074        {
075                bRun = true;
076                thread.start();
077        }
078
079        
080        /**If the application is stopped, the thread have to be stopped firstly. 
081         * The socket will be closed in the receiver-thread, when it is stopped. */
082        public void stopThread(){
083                bRun = false;
084        }
085        
086        @Override public void run()
087        {
088                int[] result = new int[1];
089                Address_InterProcessComm sender = ipc.createAddress();
090                while(bRun){
091                        ipc.receiveData(result, recvData, sender);
092                        if(result[0] > 0) {
093                                try{ evalTelg(recvData, result[0]); }
094                                catch(ParseException exc){
095                                        ctCorruptData +=1;
096                                }
097                        }
098                }
099                ipc.close();
100                bIpcOpened = false;
101        }
102        
103        
104        private void evalTelg(byte[] recvData, int nrofBytes) throws ParseException
105        { 
106                datagramRcv.assign(recvData, nrofBytes);
107                datagramRcv.setBigEndian(true);
108                int nrofBytesInfoHead = infoEntity.getLengthHead();
109                int catastrophicalCount = 1000;
110                while(datagramRcv.sufficingBytesForNextChild(infoEntity.getLengthHead()) && --catastrophicalCount >=0){
111                        datagramRcv.addChild(infoEntity);
112                        int nrofBytesInfo = infoEntity.getLenInfo();
113                        if(nrofBytesInfo < nrofBytesInfoHead) throw new ParseException("head of info corrupt, nrofBytes", nrofBytesInfo);
114                        infoEntity.setLengthElement(nrofBytesInfo);
115                        int posBuffer = infoEntity.getPositionInBuffer() + nrofBytesInfoHead;
116                        int nrofBytes1 = nrofBytesInfo - nrofBytesInfoHead;
117                        this.showValues.show(recvData, nrofBytes1, posBuffer);
118                }
119                this.showValues.showRedraw();
120                if(catastrophicalCount <0) throw new RuntimeException("unterminated while-loop");
121        }
122        
123        
124        public void sendRequest()
125        {    
126          try{ Thread.sleep(300);} 
127    catch (InterruptedException e)
128    { //dialogZbnfConfigurator.terminate();
129    }
130
131                ipc.send(sendData, 10, targetAddr);
132        }
133        
134        
135        
136        /**Sheet anchor: close the socket before the object is removed.
137         * @see java.lang.Object#finalize()
138         */
139        @Override public void finalize()
140        {
141                if(bIpcOpened){
142                        ipc.close();
143                        bIpcOpened = false;
144                }
145        }
146        
147        
148}