// Thread to Process PLC Read Queue static void ProcessPLC(S7PLC plc) { do { try { System.Threading.Thread.Sleep(5000); S7Client client = new S7Client(); client.SetConnectionType(System.Convert.ToUInt16(plc.connection_type)); client.SetConnectionParams(plc.ip, System.Convert.ToUInt16(plc.local_tsap), System.Convert.ToUInt16(plc.remote_tsap)); Console.WriteLine("Try to connect " + plc.server_name); int res = client.Connect(); if (res != 0 || client.Connected == false) { continue; } Console.WriteLine("Connected " + plc.server_name + " IP:" + plc.ip); S7Client.S7CpuInfo Info = new S7Client.S7CpuInfo(); res = client.GetCpuInfo(ref Info); if (res == 0) { Console.WriteLine(plc.server_name + " Module Type Name : " + Info.ModuleTypeName); Console.WriteLine(plc.server_name + " Serial Number : " + Info.SerialNumber); Console.WriteLine(plc.server_name + " AS Name : " + Info.ASName); Console.WriteLine(plc.server_name + " Module Name : " + Info.ModuleName); } ; System.Threading.Thread.Sleep(1000); while (client.Connected) { foreach (S7RW read in plc.reads) { CheckCommand(client, plc); byte[] Buffer = new byte[1024]; int BytesRead = 0; res = client.ReadArea( System.Convert.ToInt32(read.data_area), System.Convert.ToInt32(read.db), System.Convert.ToInt32(read.offset), System.Convert.ToInt32(read.amount), System.Convert.ToInt32(StringToWordLengthCode(read.data_type)), Buffer, ref BytesRead); if (res == 0) { // HexDump(Buffer, BytesRead); for (int i = 0; i < read.amount; i++) { int bytecnt; double value = 0; switch (read.data_type) { case "BIT": bytecnt = i / 8; value = System.Convert.ToDouble(S7.GetBitAt(Buffer, bytecnt, i % 8)); break; case "BYTE": bytecnt = i; value = S7.GetByteAt(Buffer, bytecnt); break; case "CHAR": bytecnt = i; value = S7.GetByteAt(Buffer, bytecnt); break; case "WORD": bytecnt = i * 2; value = S7.GetWordAt(Buffer, bytecnt); break; case "DWORD": bytecnt = i * 4; value = S7.GetDWordAt(Buffer, bytecnt); break; case "INT": bytecnt = i * 2; value = S7.GetIntAt(Buffer, bytecnt); break; case "DINT": bytecnt = i * 4; value = S7.GetDIntAt(Buffer, bytecnt); break; case "REAL": bytecnt = i * 4; value = S7.GetRealAt(Buffer, bytecnt); break; case "COUNTER": bytecnt = i * 2; value = S7.GetCounter((ushort)((Buffer[bytecnt + 1] << 8) + (Buffer[bytecnt]))); break; case "TIMER": bytecnt = i * 2; value = (ushort)((Buffer[bytecnt + 1] << 8) + (Buffer[bytecnt])); break; default: Console.WriteLine("Unsupported data type: " + read.data_type); break; } SendUdp(Encoding.ASCII.GetBytes( "[{\"point_key\":" + (read.point_number + i) + ",\"value\":" + value + ",\"failed\":false" + "}]")); if (logread) { Console.WriteLine(plc.server_name + " " + read.name + " OSHMI_POINT_NUMBER=" + (read.point_number + i) + " VALUE=" + value + " " + read.data_type); } } } else { Console.WriteLine(plc.server_name + " Error " + read.name); } System.Threading.Thread.Sleep(System.Convert.ToInt32(read.delay_ms)); } } // client.Disconnect(); Console.WriteLine("Disconnected " + plc.server_name); } catch (Exception e) { // EXCEPTION HANDLER Console.WriteLine("Exception " + plc.server_name); Console.WriteLine(e); } System.Threading.Thread.Sleep(10000); } while (true); }
//------------------------------------------------------------------------- // Main //------------------------------------------------------------------------- public static void Main(string[] args) { List <S7PLC> servers = new List <S7PLC>(); IniParser ini = new IniParser(ConfigFile); string test = ini.GetSetting("RTU_2", "IP", ""); Console.WriteLine(test); for (int i = 1; i < 100; i++) { string rtu = "RTU_" + i.ToString(); string ip = ini.GetSetting(rtu, "IP", ""); if (ip == null || ip == "") { break; } NumberOfServers += 1; string server_name = rtu; uint connection_type = StringDHToUint(ini.GetSetting(rtu, "CONNECTION_TYPE", "2")); uint rack = StringDHToUint(ini.GetSetting(rtu, "RACK", "0")); uint slot = StringDHToUint(ini.GetSetting(rtu, "SLOT", "0")); uint local_tsap = StringDHToUint(ini.GetSetting(rtu, "LOCAL_TSAP", "0x200")); uint remote_tsap = StringDHToUint(ini.GetSetting(rtu, "REMOTE_TSAP", "0x200")); string password = ini.GetSetting(rtu, "PASSWORD", ""); List <S7RW> reads = new List <S7RW>(); List <S7RW> writes = new List <S7RW>(); for (int j = 1; j < 10000; j++) { string line = ini.GetSetting(rtu, "READ_" + j.ToString(), ""); if (line == null || line == "") { break; } string[] arrstr = Regex.Split(line, "\\s+"); if (arrstr.Length != 7) { break; } string name = "READ_" + j.ToString(); string data_type = arrstr[0]; uint data_area = StringDHToUint(arrstr[1]); uint db = StringDHToUint(arrstr[2]); uint offset = StringDHToUint(arrstr[3]); uint amount = StringDHToUint(arrstr[4]); uint point_number = StringDHToUint(arrstr[5]); uint delay_ms = StringDHToUint(arrstr[6]); S7RW s7r = new S7RW { name = name, data_type = data_type, data_area = data_area, db = db, offset = offset, amount = amount, point_number = point_number, delay_ms = delay_ms }; reads.Add(s7r); } for (int j = 1; j < 10000; j++) { string line = ini.GetSetting(rtu, "WRITE_" + j.ToString(), ""); if (line == null || line == "") { break; } string[] arrstr = Regex.Split(line, "\\s+"); if (arrstr.Length != 6) { break; } string name = "WRITE_" + j.ToString(); string data_type = arrstr[0]; uint data_area = StringDHToUint(arrstr[1]); uint db = StringDHToUint(arrstr[2]); uint offset = StringDHToUint(arrstr[3]); uint amount = 1; uint point_number = StringDHToUint(arrstr[4]); uint bit = StringDHToUint(arrstr[5]); S7RW s7w = new S7RW { name = name, data_type = data_type, data_area = data_area, db = db, offset = offset, amount = amount, point_number = point_number, bit = bit }; writes.Add(s7w); } S7PLC s7plc = new S7PLC { ip = ip, server_name = server_name, connection_type = connection_type, rack = rack, slot = slot, local_tsap = local_tsap, remote_tsap = remote_tsap, password = password, reads = reads, writes = writes }; servers.Add(s7plc); } foreach (S7PLC srv in servers) { Thread t = new Thread(() => ProcessPLC(srv)); t.Start(); } Thread u = new Thread(() => ListenUDP()); u.Start(); Console.WriteLine(Version); Console.WriteLine("Press any key to end."); Console.ReadKey(); Environment.Exit(Environment.ExitCode); }
static void CheckCommand(S7Client client, S7PLC plc) { // check for controls OSHMI_control oc; bool found = false; if (ControlQueue.TryDequeue(out oc)) { DateTime dt = DateTime.Now; if (dt.Ticks / 10000000 < oc.timestamp / 10000000 + 10) // past ten seconds expires the command (discards it) { if (!oc.servers_checked.Contains(plc.server_name)) { foreach (S7RW write in plc.writes) { if (write.point_number == oc.oshmi_point_key) { found = true; byte[] buffer = { 0, 0, 0, 0 }; ushort[] usbuffer = { 0 }; switch (write.data_type) { case "BIT": S7.SetBitAt(ref buffer, 0, System.Convert.ToInt32(write.bit), System.Convert.ToBoolean(oc.value)); break; case "BYTE": S7.SetByteAt(buffer, 0, System.Convert.ToByte(oc.value)); break; case "CHAR": S7.SetByteAt(buffer, 0, System.Convert.ToByte(oc.value)); break; case "WORD": S7.SetWordAt(buffer, 0, System.Convert.ToUInt16(oc.value)); break; case "DWORD": S7.SetDWordAt(buffer, 0, System.Convert.ToUInt32(oc.value)); break; case "INT": S7.SetIntAt(buffer, 0, System.Convert.ToInt16(oc.value)); break; case "DINT": S7.SetDIntAt(buffer, 0, System.Convert.ToInt32(oc.value)); break; case "REAL": S7.SetRealAt(buffer, 0, System.Convert.ToSingle(oc.value)); break; case "COUNTER": S7.SetCounterAt(usbuffer, 0, System.Convert.ToUInt16(oc.value)); buffer[1] = (byte)((usbuffer[0] & 0xFF00) >> 8); buffer[0] = (byte)(usbuffer[0] & 0x00FF); break; case "TIMER": S7.SetWordAt(buffer, 0, System.Convert.ToUInt16(oc.value)); break; default: Console.WriteLine(plc.server_name + " Write unsupported data type: " + write.data_type); return; } client.WriteArea(System.Convert.ToInt32(write.data_area), System.Convert.ToInt32(write.db), System.Convert.ToInt32(write.offset), 1, System.Convert.ToInt32(StringToWordLengthCode(write.data_type)), buffer); Console.Write(plc.server_name + " WRITEN COMMAND TAG " + oc.oshmi_cmd_tag + " KEY " + oc.oshmi_point_key + " VAL " + oc.value + " " + write.data_type); break; } } if (!found) { oc.countdown--; if (oc.countdown > 0) { oc.servers_checked.Add(plc.server_name); // mark as checked ControlQueue.Enqueue(oc); // return command object to the queue if not the last to check } else if (logcommand) { Console.Write(plc.server_name + " DISCARDED COMMAND (NOT FOUND) ON TAG " + oc.oshmi_cmd_tag + " KEY " + oc.oshmi_point_key + " VAL " + oc.value); } } } else { ControlQueue.Enqueue(oc); // return command object to the queue if not the last to check } } else if (logcommand) { Console.Write(plc.server_name + " DISCARDED COMMAND (TIMEOUT) ON TAG " + oc.oshmi_cmd_tag + " KEY " + oc.oshmi_point_key + " VAL " + oc.value); } } }