private static void FetchOneItem(Socket socket, bool paramsToWriteExists, RequestData par) { switch (par.ParameterKind) { case LogikaParam.Parameter: if (paramsToWriteExists && par.ModbusTable == ModbusTable.Holdings) { var value = Modbus.GetParamValue(new ParamAddr(par.NodeAddr, Modbus.ModifyToModbusRegisterAddress(par.StartAddr, ModbusTable.Holdings))); if (!string.IsNullOrWhiteSpace(value)) { Logika.WriteToParameter(socket, par, value); } } Logika.FetchParameter(socket, par); break; case LogikaParam.IndexArray: { if (paramsToWriteExists && par.ModbusTable == ModbusTable.Holdings) { var value = Modbus.GetParamValue(new ParamAddr(par.NodeAddr, Modbus.ModifyToModbusRegisterAddress(par.StartAddr, ModbusTable.Holdings))); if (!string.IsNullOrWhiteSpace(value)) { Logika.WriteToIndexArray(socket, par, value); } } Logika.FetchIndexArray(socket, par); } break; } }
private static void CheckAndStoreData(RequestData request, AnswerData result) { if (request.FormatData == "IEEEFP" && float.TryParse(result.Value, NumberStyles.Float, CultureInfo.GetCultureInfo("en-US"), out float floatValue)) { ushort addr = request.StartAddr; var n = 0; var bytes = BitConverter.GetBytes(floatValue); Array.Reverse(bytes); for (ushort i = 0; i < 2; i++) { var regAddr = Modbus.ModifyToModbusRegisterAddress(addr, request.ModbusTable); ushort value = BitConverter.ToUInt16(bytes, n); Modbus.SetRegisterValue(request.NodeAddr, regAddr, value); n = n + 2; // коррекция позиции смещения в принятых данных для записи addr += 1; } } else if (request.FormatData == "S32B" && int.TryParse(result.Value, NumberStyles.Integer, CultureInfo.GetCultureInfo("en-US"), out int intValue)) { ushort addr = request.StartAddr; var n = 0; var bytes = BitConverter.GetBytes(intValue); //Array.Reverse(bytes); <--- не делать реверс для uint for (ushort i = 0; i < 2; i++) { var regAddr = Modbus.ModifyToModbusRegisterAddress(addr, request.ModbusTable); ushort value = BitConverter.ToUInt16(bytes, n); Modbus.SetRegisterValue(request.NodeAddr, regAddr, Modbus.Swap(value)); // <--- Swap() для uint n = n + 2; // коррекция позиции смещения в принятых данных для записи addr += 1; } } }
private static void ModbusListener_DoWork(object sender, DoWorkEventArgs e) { var worker = (BackgroundWorker)sender; if (!(e.Argument is TcpTuning parameters)) { return; } // var listener = new TcpListener(IPAddress.Any, parameters.Port) { Server = { SendTimeout = parameters.SendTimeout, ReceiveTimeout = parameters.ReceiveTimeout } }; // do { Thread.Sleep(parameters.WaitForConnect); try { listener.Start(10); // Buffer for reading data var bytes = new byte[256]; while (!listener.Pending()) { Thread.Sleep(1); if (!worker.CancellationPending) { continue; } listener.Stop(); worker.ReportProgress(0, "Not listening"); return; } var clientData = listener.AcceptTcpClient(); // создаем отдельный поток для каждого подключения клиента ThreadPool.QueueUserWorkItem(arg => { try { // Get a stream object for reading and writing var stream = clientData.GetStream(); int count; // Loop to receive all the data sent by the client. while ((count = stream.Read(bytes, 0, bytes.Length)) != 0) { Thread.Sleep(1); var list = new List <string>(); for (var i = 0; i < count; i++) { list.Add(string.Format("{0}", bytes[i])); } if (count < 6) { continue; } var header1 = Convert.ToUInt16(bytes[0] * 256 + bytes[1]); var header2 = Convert.ToUInt16(bytes[2] * 256 + bytes[3]); var packetLen = Convert.ToUInt16(bytes[4] * 256 + bytes[5]); if (count != packetLen + 6) { continue; } var nodeAddr = bytes[6]; var funcCode = bytes[7]; var startAddr = Convert.ToUInt16(bytes[8] * 256 + bytes[9]); var regCount = Convert.ToUInt16(bytes[10] * 256 + bytes[11]); var singleValue = Convert.ToUInt16(bytes[10] * 256 + bytes[11]); List <byte> answer; byte bytesCount; byte[] msg; switch (funcCode) { case 3: // - read holding registers case 4: // - read input registers answer = new List <byte>(); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(header1))); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(header2))); bytesCount = Convert.ToByte(regCount * 2); packetLen = Convert.ToUInt16(bytesCount + 3); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(packetLen))); answer.Add(nodeAddr); answer.Add(funcCode); answer.Add(bytesCount); // for (ushort i = 0; i < regCount; i++) { var regAddr = Modbus.ModifyToModbusRegisterAddress((ushort)(i + startAddr), (ModbusTable)funcCode); ushort value = Modbus.GetRegisterValue(nodeAddr, regAddr); answer.AddRange(BitConverter.GetBytes(value)); } // msg = answer.ToArray(); stream.Write(msg, 0, msg.Length); break; //case 6: // write one register // Modbus.SetRegisterValue(nodeAddr, Modbus.ModifyToModbusRegisterAddress(startAddr, ModbusTable.Holdings), singleValue); // //------------------- // answer = new List<byte>(); // answer.AddRange(BitConverter.GetBytes(Modbus.Swap(header1))); // answer.AddRange(BitConverter.GetBytes(Modbus.Swap(header2))); // answer.AddRange(BitConverter.GetBytes(Modbus.Swap(6))); // answer.Add(nodeAddr); // answer.Add(funcCode); // answer.AddRange(BitConverter.GetBytes(Modbus.Swap(startAddr))); // answer.AddRange(BitConverter.GetBytes(Modbus.Swap(regCount))); // msg = answer.ToArray(); // stream.Write(msg, 0, msg.Length); // break; case 16: // write several registers var n = 13; ushort addr = startAddr; for (ushort i = 0; i < regCount; i++) { var regAddr = Modbus.ModifyToModbusRegisterAddress(addr, ModbusTable.Holdings); ushort value = BitConverter.ToUInt16(bytes, n); Modbus.SetRegisterValue(nodeAddr, regAddr, value); n += 2; // коррекция позиции смещения в принятых данных для записи addr += 1; } if (regCount == 2) { var regAddr = Modbus.ModifyToModbusRegisterAddress(startAddr, ModbusTable.Holdings); var value = (float)Modbus.TypedValueFromRegistersArray(nodeAddr, regAddr, typeof(float)); Modbus.SetParamValue(new ParamAddr(nodeAddr, regAddr), string.Format(CultureInfo.GetCultureInfo("en-US"), "{0}", value)); } //------------------- answer = new List <byte>(); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(header1))); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(header2))); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(6))); answer.Add(nodeAddr); answer.Add(funcCode); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(startAddr))); answer.AddRange(BitConverter.GetBytes(Modbus.Swap(regCount))); msg = answer.ToArray(); stream.Write(msg, 0, msg.Length); break; } } // Shutdown and end connection clientData.Close(); } catch (Exception ex) { if (!worker.CancellationPending) { worker.ReportProgress(0, ex.Message); } } }); } catch (SocketException ex) { if (!worker.CancellationPending) { worker.ReportProgress(0, ex.Message); } break; } } while (!worker.CancellationPending); listener.Stop(); }
/// <summary> /// Работа потока для опроса ЛОГИКИ /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void LogikaFetcher_DoWork(object sender, DoWorkEventArgs e) { var worker = (BackgroundWorker)sender; if (!(e.Argument is TcpTuning parameters)) { return; } var lastsecond = DateTime.Now.Second; var lastminute = -1; // DateTime.Now.Minute; var remoteEp = new IPEndPoint(parameters.Address, parameters.Port); while (!worker.CancellationPending) { var dt = DateTime.Now; if (lastsecond == dt.Second) { continue; } lastsecond = dt.Second; // прошла секунда Queue <RequestData> queue = null; try { using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { socket.SendTimeout = parameters.SendTimeout; socket.ReceiveTimeout = parameters.ReceiveTimeout; socket.Connect(remoteEp); Thread.Sleep(500); if (socket.Connected) { var paramsToWriteExists = Modbus.ParamsToWriteExists(); queue = new Queue <RequestData>(FetchItems(parameters, socket, paramsToWriteExists)); } } } catch (Exception ex) { worker.ReportProgress(0, ex.Message); } if (lastminute == dt.Minute) { continue; } lastminute = dt.Minute; // прошла минута try { using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { socket.SendTimeout = parameters.SendTimeout; socket.ReceiveTimeout = parameters.ReceiveTimeout; socket.Connect(remoteEp); Thread.Sleep(500); if (socket.Connected) { var paramsToWriteExists = Modbus.ParamsToWriteExists(); FetchItems(parameters, socket, paramsToWriteExists, true, queue); } } } catch (Exception ex) { worker.ReportProgress(0, ex.Message); } } }