Ejemplo n.º 1
0
        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();
        }