/// <summary> /// Processing answers from Simulator - Process Controller /// </summary> public void ProcessPCAnwers(TimeSpan timeout, CancellationToken token) { DataLinkHandler dataLinkHandler = new DataLinkHandler(); while (!token.IsCancellationRequested) { bool isSuccessful; IORequestBlock answer = IORequests.DequeueAnswer(out isSuccessful, timeout); if (isSuccessful) { bool isChange = false; RTU rtu; if ((rtu = dbContext.GetRTUByName(answer.ProcessControllerName)) != null) { switch (rtu.Protocol) { case IndustryProtocols.ModbusTCP: ModbusHandler mdbHandler = new ModbusHandler(); try { mdbHandler.UnpackData(answer.RcvBuff, answer.RcvMsgLength); switch (mdbHandler.Response.FunCode) { case FunctionCodes.ReadDiscreteInput: { BitReadResponse response = (BitReadResponse)mdbHandler.Response; var responsePVCount = answer.Flags; ushort varAddr = answer.ReqAddress; for (int i = 0; i < responsePVCount; i++, varAddr++) { ProcessVariable pv; if (rtu.GetProcessVariableByAddress(varAddr, out pv)) { Digital target = (Digital)pv; try { bool isOpened = response.BitValues[i]; if (target.State != target.ValidStates[isOpened ? 1 : 0]) { isChange = true; target.State = target.ValidStates[isOpened ? 1 : 0]; Console.WriteLine(" CHANGE! Digital variable {0}, state: {1}", target.Name, target.State); dMSProxy.ChangeOnSCADADigital(target.Name, target.State); } } catch { Console.WriteLine("Digital variable {0}, state: INVALID", target.Name); } } } if (isChange) { ScadaModelParser parser = new ScadaModelParser(); parser.SerializeScadaModel(); } } break; // analog input case FunctionCodes.ReadInputRegisters: { RegisterReadResponse response = (RegisterReadResponse)mdbHandler.Response; var responsePVCount = answer.Flags; ushort varAddr = answer.ReqAddress; for (int i = 0; i < responsePVCount; i++, varAddr++) { ProcessVariable pv; if (rtu.GetProcessVariableByAddress(varAddr, out pv)) { Analog target = (Analog)pv; try { ushort newRawAcqValue = response.RegValues[target.RelativeAddress]; float newAcqValue; AnalogProcessor.RawValueToEGU(target, newRawAcqValue, out newAcqValue); if (target.AcqValue != newAcqValue) { isChange = true; target.RawAcqValue = newRawAcqValue; target.AcqValue = newAcqValue; Console.WriteLine(" CHANGE! Analog variable {0}, AcqValue: {1}", target.Name, target.AcqValue); //to do: propagacija analogih promena(ako se secate Pavlica je prvo rekao da nam to ne treba da samo jednom zakucamo vrednost na pocetku) xD dMSProxy.ChangeOnSCADAAnalog(target.Name, target.AcqValue); } } catch { // Console.WriteLine("Digital variable {0}, state: INVALID", target.Name); } } } if (isChange) { ScadaModelParser parser = new ScadaModelParser(); parser.SerializeScadaModel(); } } break; } } catch (Exception e) { Console.WriteLine(e.Message); } break; case IndustryProtocols.DNP3TCP: byte len = answer.RcvBuff[2]; byte actualLen = (byte)(2 + 1 + 5 + 2); // start + len + ctrl + dest + source + crc len -= 5; // minus header while (len > 0) { if (len < 16) { // last chunk actualLen += (byte)(len + 2); break; } actualLen += (byte)(16 + 2); len -= 16; } byte[] message = new byte[actualLen]; for (int i = 0; i < actualLen; i++) { message[i] = answer.RcvBuff[i]; } List <UserLevelObject> userLevelObjects = dataLinkHandler.PackUp(message); if (userLevelObjects == null) { continue; } DNP3UserLayerHandler dNP3UserLayerHandler = new DNP3UserLayerHandler(new DNP3Handler(), dbContext); List <Tuple <string, float> > tuples = dNP3UserLayerHandler.ReadAllAnalogInputPointsReadResponse(userLevelObjects, rtu.Name); foreach (Tuple <string, float> tuple in tuples) { try { dMSProxy.ChangeOnSCADAAnalog(tuple.Item1, tuple.Item2); } catch { dMSProxy = new DMSSCADAProxy(); } } break; } } } } Console.WriteLine("ProcessPCAnswers.shutdown=true"); return; }
/// <summary> /// Processing answers from Simulator - Process Controller /// </summary> public void ProcessPCAnwers(TimeSpan timeout, CancellationToken token) { while (!token.IsCancellationRequested) { bool isSuccessful; IORequestBlock answer = IORequests.DequeueAnswer(out isSuccessful, timeout); if (isSuccessful) { bool isChange = false; RTU rtu; // sporno //while (!Database.IsConfigurationRunning) if ((rtu = dbContext.GetRTUByName(answer.ProcessControllerName)) != null) { switch (rtu.Protocol) { case IndustryProtocols.ModbusTCP: ModbusHandler mdbHandler = new ModbusHandler(); try { mdbHandler.UnpackData(answer.RcvBuff, answer.RcvMsgLength); switch (mdbHandler.Response.FunCode) { case FunctionCodes.ReadDiscreteInput: { BitReadResponse response = (BitReadResponse)mdbHandler.Response; var responsePVCount = answer.Flags; ushort varAddr = answer.ReqAddress; for (int i = 0; i < responsePVCount; i++, varAddr++) { ProcessVariable pv; if (rtu.GetProcessVariableByAddress(varAddr, out pv)) { Digital target = (Digital)pv; try { bool isOpened = response.BitValues[i]; if (target.State != target.ValidStates[isOpened ? 1 : 0]) { isChange = true; target.State = target.ValidStates[isOpened ? 1 : 0]; Console.WriteLine(" CHANGE! Digital variable {0}, state: {1}", target.Name, target.State); DMSClient dMSClient = new DMSClient(); dMSClient.ChangeOnSCADADigital(target.Name, target.State); } } catch { Console.WriteLine("Digital variable {0}, state: INVALID", target.Name); } } } if (isChange) { ScadaModelParser parser = new ScadaModelParser(); parser.SerializeScadaModel(); } } break; // analog input case FunctionCodes.ReadInputRegisters: { RegisterReadResponse response = (RegisterReadResponse)mdbHandler.Response; var responsePVCount = answer.Flags; ushort varAddr = answer.ReqAddress; for (int i = 0; i < responsePVCount; i++, varAddr++) { ProcessVariable pv; if (rtu.GetProcessVariableByAddress(varAddr, out pv)) { Analog target = (Analog)pv; try { ushort newRawAcqValue = response.RegValues[target.RelativeAddress]; float newAcqValue; AnalogProcessor.RawValueToEGU(target, newRawAcqValue, out newAcqValue); if (target.AcqValue != newAcqValue) { isChange = true; target.RawAcqValue = newRawAcqValue; target.AcqValue = newAcqValue; Console.WriteLine(" CHANGE! Analog variable {0}, AcqValue: {1}", target.Name, target.AcqValue); //to do: propagacija analogih promena(ako se secate Pavlica je prvo rekao da nam to ne treba da samo jednom zakucamo vrednost na pocetku) xD DMSClient dMSClient = new DMSClient(); dMSClient.ChangeOnSCADAAnalog(target.Name, target.AcqValue); } } catch { // Console.WriteLine("Digital variable {0}, state: INVALID", target.Name); } } } if (isChange) { ScadaModelParser parser = new ScadaModelParser(); parser.SerializeScadaModel(); } } break; } } catch (Exception e) { Console.WriteLine(e.Message); } break; } } } } Console.WriteLine("ProcessPCAnswers.shutdown=true"); return; }
/// <summary> /// Processing answers from Simulator - Process Controller /// </summary> public void ProcessPCAnwers() { while (!isShutdown) { bool isSuccessful; IORequestBlock answer = IORequests.DequeueAnswer(out isSuccessful); if (isSuccessful) { RTU rtu; // sporno //while (!Database.IsConfigurationRunning) // Thread.Sleep(100); if ((rtu = dbContext.GetRTUByName(answer.ProcessControllerName)) != null) { switch (rtu.Protocol) { case IndustryProtocols.ModbusTCP: ModbusHandler mdbHandler = new ModbusHandler(); mdbHandler.UnpackData(answer.RcvBuff, answer.RcvMsgLength); switch (mdbHandler.Response.FunCode) { case FunctionCodes.ReadDiscreteInput: { BitReadResponse response = (BitReadResponse)mdbHandler.Response; ProcessVariable pv; Digital target = null; if (rtu.GetProcessVariableByAddress(answer.ReqAddress, out pv)) { target = (Digital)pv; } if (target != null) { int[] array = new int[1]; response.BitValues.CopyTo(array, 0); try { if (target.State != target.ValidStates[array[0]]) { Console.WriteLine("CHANGE!"); target.State = target.ValidStates[array[0]]; ScadaModelParser parser = new ScadaModelParser(); parser.SerializeScadaModel(); DMSClient dMSClient = new DMSClient(); dMSClient.ChangeOnSCADA(target.Name, target.State); } } catch { // Console.WriteLine("Digital variable {0}, state: INVALID", target.Name); } } } break; case FunctionCodes.ReadInputRegisters: { RegisterReadResponse response = (RegisterReadResponse)mdbHandler.Response; ProcessVariable pv; Analog target = null; // i ovde se zapravo cita iz baze! preko RTUa. znaci pristupamo rtuu, a moguce je da se desava rekonfiguracija. if (rtu.GetProcessVariableByAddress(answer.ReqAddress, out pv)) { target = (Analog)pv; } if (target != null) { ushort newRawAcqValue = response.RegValues[0]; try { float newAcqValue; AnalogProcessor.RawValueToEGU(target, newRawAcqValue, out newAcqValue); // videti kad menjas kommande if (target.AcqValue != newAcqValue) { Console.WriteLine("CHANGE analog!"); target.RawAcqValue = newRawAcqValue; target.AcqValue = newAcqValue; ScadaModelParser parser = new ScadaModelParser(); parser.SerializeScadaModel(); DMSClient dMSClient = new DMSClient(); // to do // dMSClient.ChangeOnSCADA(target.Name, target.State); } } catch { // Console.WriteLine("Digital variable {0}, state: INVALID", target.Name); } } } break; } break; } } else { Console.WriteLine("Answer disposed. Process Controller with name ={0} does not exit.", answer.ProcessControllerName); } } Thread.Sleep(100); } Console.WriteLine("ProcessPCAnswers.shutdown=true"); return; }