using LFP_Manager.DataStructure; using LFP_Manager.Function; using SnmpSharpNet; using System; using System.Net; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using LFP_Manager.Utils; using System.Windows.Forms; using static DevExpress.Xpo.Helpers.AssociatedCollectionCriteriaHelper; namespace LFP_Manager.Threads { public delegate void SetResult(string result, bool error); public delegate void DataUpdate(object sender, ref DeviceSystemData rData); class CsSnmpThread { #region VARIABLES private DeviceSystemData SystemData; private CommConfig Config; private Thread snmpThread = null; private bool snmpThreadHold = true; private string targetIP = ""; private bool snmpDataRecv = false; private string snmpResult = ""; private bool AutoSnmpTx = true; private int type = 0; private int OidIndex = 0; private int OidMax = 0; private int OidIndexBase = 0; private int CommTimeOut = 0; private string[] OidList; private int SetSnmpMode = 0; private int SetSnmpMode1 = 0; private UInt32 SetSnmpValue = 0; private string SetSnmpStringData; public event DataUpdate OnUpdate = null; public event SetResult OnSetResult = null; #endregion #region CONSTRUCTORS public CsSnmpThread() { snmpThread = new Thread(snmpThreadFuncA); snmpThread.Start(); } public CsSnmpThread(CommConfig aConfig, ref DeviceSystemData aSystemData) { Config = aConfig; type = Config.SnmpModelIndex; OidIndex = 0; OidList = CsSnmpConstData.SnmpOidInfo; OidMax = OidList.Length; SystemData = aSystemData; snmpThread = new Thread(snmpThreadFuncA); snmpThread.Start(); } #endregion #region PUBLIC FUNCTION public void disposeThread() { snmpThreadHold = true; snmpThread.Abort(); } public void Start(string IP, bool autoTx) { targetIP = IP; snmpThreadHold = false; AutoSnmpTx = autoTx; } public void Stop() { snmpThreadHold = true; } public bool GetStatus() { return snmpThreadHold; } public string GetResult() { string result = ""; if (snmpDataRecv) { result = snmpResult; snmpDataRecv = false; } return result; } public void SetAutoTx(bool autoTx) { AutoSnmpTx = autoTx; } #endregion #region COMM. THREAD public string GetSnmpOidInfo(int index) { return OidList[index]; } bool SetCmdbySnmp(UdpTarget sTarget, int mode, UInt32 value, string svalue) { bool resultError = false; Pdu SetPdu = new Pdu(PduType.Set); // Set a value to unsigned integer SetPdu.VbList.Clear(); switch (mode) { case 1: // Reset Command SetPdu.VbList.Add(new Oid(".1.3.6.1.4.1.33.13.1.0"), new Integer32(Convert.ToInt32(value))); break; case 2: // Module Quantity Set SetPdu.VbList.Add(new Oid(".1.3.6.1.4.1.33.2.4.0"), new Integer32(Convert.ToInt32(value))); break; case 3: // Alarm Output Mode SetPdu.VbList.Add(new Oid(".1.3.6.1.4.1.33.2.5.0"), new Integer32(Convert.ToInt32(value))); break; case 4: // Manufacture Date SetPdu.VbList.Add(new Oid(".1.3.6.1.4.1.33.2.6.0"), new Integer32(Convert.ToInt32(value))); break; case 5: // BMS Serial Number SetPdu.VbList.Add(new Oid(".1.3.6.1.4.1.33.2.7.0"), new OctetString(svalue)); break; } // Set Agent security parameters AgentParameters aparam = new AgentParameters(SnmpVersion.Ver1, new OctetString("public")); // Make SNMP request try { // Send request and wait for response SnmpV1Packet result = sTarget.Request(SetPdu, aparam) as SnmpV1Packet; // If result is null then agent didn't reply or we couldn't parse the reply. if (result != null) { // ErrorStatus other then 0 is an error returned by // the Agent - see SnmpConstants for error definitions if (result.Pdu.ErrorStatus != 0) { // agent reported an error with the request snmpResult = String.Format("Error in SNMP reply. Error {0} index {1}", result.Pdu.ErrorStatus, result.Pdu.ErrorIndex); if (OnSetResult != null) { OnSetResult(snmpResult, true); } } else { // Everything is ok. Agent will return the new value for the OID we changed string resultString; if (result.Pdu.VbList[0].Type == AsnType.OCTETSTRING) resultString = result.Pdu.VbList[0].Value.ToString(); else resultString = result.Pdu.VbList[0].Value.ToString(); snmpResult = String.Format("SNMP Received data. result {0}", resultString); OnSetResult?.Invoke(snmpResult, false); } } else { if (snmpDataRecv == false) { snmpResult = DateTime.Now.ToString("[yyyy-MM-dd hh:mm:ss] ") + String.Format("No response received from SNMP agent."); snmpDataRecv = true; OnSetResult?.Invoke(snmpResult, true); } } } catch (Exception ex) { if (snmpDataRecv == false) { snmpResult = "[" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "] " + String.Format("Exception : {0}", ex.Message); snmpDataRecv = true; OnSetResult?.Invoke(snmpResult, true); } resultError = true; } return resultError; } public void SetDataBySnmp(int mode, UInt32 value) { SetSnmpMode = mode; SetSnmpValue = value; } public void SetDataBySnmp(int mode, string value) { SetSnmpMode1 = mode; SetSnmpStringData = value; } private void snmpThreadFuncA() { while (true) { if (snmpThreadHold == false) { // SNMP community name OctetString community = new OctetString("admin"); // Define agent parameters class AgentParameters param = new AgentParameters(community); // Set SNMP version to 1 (or 2) param.Version = SnmpVersion.Ver1; // Construct the agent address object // IpAddress class is easy to use here because // it will try to resolve constructor parameter if it doesn't // parse to an IP address String dstAddr = targetIP; IpAddress agent = new IpAddress(dstAddr); // Construct target UdpTarget target = new UdpTarget((IPAddress)agent, 161, 1000, 1); // Pdu class used for all requests Pdu pdu = new Pdu(PduType.Get); if (SetSnmpMode != 0) { SetCmdbySnmp(target, SetSnmpMode, SetSnmpValue, SetSnmpStringData); SetSnmpMode = 0; } else if (SetSnmpMode1 != 0) { SetCmdbySnmp(target, SetSnmpMode1, SetSnmpValue, SetSnmpStringData); SetSnmpMode1 = 0; } else { // SNMP GET while (AutoSnmpTx) { snmpResult = ""; if ((SetSnmpMode != 0) || (SetSnmpMode1 != 0)) { break; } pdu.VbList.Clear(); pdu.VbList.Add(GetSnmpOidInfo(OidIndex)); // Make SNMP request try { //SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param); target.Timeout = 100; // agent reported an error with the request snmpResult = csLog.trx_msg_print(string.Format("SEND {0}: OID [{1}]" , target.Address.ToString() , pdu.VbList[0].Oid.ToString() ) , 0 ) ; OnSetResult?.Invoke(snmpResult, true); SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param); // If result is null then agent didn't reply or we couldn't parse the reply. if (result != null) { // ErrorStatus other then 0 is an error returned by // the Agent - see SnmpConstants for error definitions if (result.Pdu.ErrorStatus != 0) { // agent reported an error with the request snmpResult = csLog.trx_msg_print(string.Format("Error in SNMP reply. Error {0} index {1} - {2}" , result.Pdu.ErrorStatus , result.Pdu.ErrorIndex , result.Pdu.VbList[0].Oid.ToString() ) , 1 ) ; OnSetResult?.Invoke(snmpResult, true); } else { snmpResult = csLog.trx_msg_print(string.Format("RECV {0}: OID [{1}]: [{2}]" , target.Address.ToString() , result.Pdu.VbList[0].Oid.ToString() , result.Pdu.VbList[0].Value.ToString() ) , 1 ) ; OnSetResult?.Invoke(snmpResult, true); String resultTxt = ""; // Reply variables are returned in the same order as they were added // to the VbList //resultTxt = String.Format("[{0}] ({1}): {2}", // result.Pdu.VbList[0].Oid.ToString(), // SnmpConstants.GetTypeName(result.Pdu.VbList[0].Value.Type), // result.Pdu.VbList[0].Value.ToString()); resultTxt = String.Format(".{0}", result.Pdu.VbList[0].Oid.ToString()); uint[] resultInt = (uint[])result.Pdu.VbList[0].Oid; int len = resultInt.Length; if ((resultInt[0] == 1) && (resultInt[1] == 3) && (resultInt[2] == 6) && (resultInt[3] == 1) && (resultInt[4] == 2) && (resultInt[5] == 1) && (resultInt[6] == 15) ) { //double resultDouble = 0.0; if (result.Pdu.VbList[0].Value.Type == AsnType.OCTETSTRING) { try { //resultDouble = Convert.ToDouble(result.Pdu.VbList[0].Value.ToString()); csMakeDataFunction.SetSnmpData((int)resultInt[7], result.Pdu.VbList[0].Value.ToString(), ref SystemData); } catch (Exception ex) { MessageBox.Show(ex.Message); } } else if (result.Pdu.VbList[0].Type == AsnType.OCTETSTRING) { MessageBox.Show(result.Pdu.VbList[0].Value.ToString()); } CalcAvgTemperatureModule(ref SystemData, (uint)SystemData.tempQty); CheckShelfCommFail(ref SystemData); OnUpdate?.Invoke(this, ref SystemData); } CommTimeOut = 0; SystemData.CommFail = false; } Thread.Sleep(50); } else { if (snmpDataRecv == false) { snmpResult = DateTime.Now.ToString("[yyyy-MM-dd hh:mm:ss] ") + String.Format("No response received from SNMP agent."); snmpDataRecv = true; } CommTimeOut++; if (CommTimeOut >= 20) { SystemData.CommFail = true; InitModuleData(); CommTimeOut = 20; } } OidIndex++; OidIndex %= OidMax; Thread.Sleep(1); } catch (Exception ex) { snmpResult = csLog.trx_msg_print(string.Format("Exception in SNMP reply. Error {0} - {1}" , pdu.VbList[0].Oid.ToString() , ex.Message ) , 1 ) ; OnSetResult?.Invoke(snmpResult, true); CommTimeOut++; if (CommTimeOut >= 10) { SystemData.CommFail = true; InitModuleData(); CommTimeOut = 10; } break; } } CheckShelfCommFail(ref SystemData); OnUpdate?.Invoke(this, ref SystemData); } pdu.Clone(); target.Close(); Thread.Sleep(500); } } } private void InitModuleData() { SystemData.ValueData.voltageOfPack = 0; SystemData.ValueData.current = 0; SystemData.ValueData.averageCurrent = 0; SystemData.ValueData.rSOC = 0; SystemData.ValueData.stateOfHealth = 0; for (int i = 0; i < SystemData.ValueData.CellVoltage.Length; i++) { SystemData.ValueData.CellVoltage[i] = 0; } for (int i = 0; i < SystemData.ValueData.CellTemperature.Length; i++) { SystemData.ValueData.CellTemperature[i] = 0; } SystemData.AvgData.avgCellVoltage = 0; SystemData.AvgData.diffCellVoltage = 0; SystemData.AvgData.maxCellVoltage = 0; SystemData.AvgData.minCellVoltage = 0; SystemData.AvgData.maxCellNum = 0; SystemData.AvgData.minCellNum = 0; SystemData.AvgData.avgTemp = 0; SystemData.AvgData.diffTemp = 0; SystemData.AvgData.maxTemp = 0; SystemData.AvgData.minTemp = 0; SystemData.AvgData.maxTempNum = 0; SystemData.AvgData.minTempNum = 0; } private void CheckShelfCommFail(ref DeviceSystemData aSystemData) { if (aSystemData.StatusData.batteryStatus == 0x0003) { aSystemData.ShelfCommFail = true; } else { aSystemData.ShelfCommFail = false; } } #endregion static void CalcAvgTemperatureModule(ref DeviceSystemData aSystemData, UInt32 tSize) { short i, j; int sum; TMinMax min, max; min = new TMinMax(); max = new TMinMax(); sum = 0; max.value = 0; max.num = 0; min.value = 0; min.num = 0; j = 0; for (i = 0; i < tSize; i++) { if (j == 0) { max.value = aSystemData.ValueData.CellTemperature[i]; max.num = i; min.value = aSystemData.ValueData.CellTemperature[i]; min.num = i; } if (max.value < aSystemData.ValueData.CellTemperature[i]) { max.value = aSystemData.ValueData.CellTemperature[i]; max.num = i; } if (min.value > aSystemData.ValueData.CellTemperature[i]) { min.value = aSystemData.ValueData.CellTemperature[i]; min.num = i; } sum += aSystemData.ValueData.CellTemperature[i]; j++; } if (j == 0) { aSystemData.AvgData.avgTemp = 0; } else { aSystemData.AvgData.avgTemp = (short)(sum / j); } aSystemData.AvgData.maxTemp = max.value; aSystemData.AvgData.maxTempNum = max.num; aSystemData.AvgData.minTemp = min.value; aSystemData.AvgData.minTempNum = min.num; } } }