/// <summary> /// Обработчик принятых данных, после анализа посылка, /// в случае корректности запроса отвечает,но только по функции 0x04, адресу 0x20 /// по всем адресам приборов 1-247 /// </summary> /// <param name="sender">SerialPort</param> /// <param name="e"></param> private void SlavePort_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort serialPort = (sender as SerialPort); if (serialPort.BytesToRead == 0) { return; } byte[] buffer = new byte[256]; int count = serialPort.Read(buffer, 0, serialPort.BytesToRead); if (count > 0 && buffer.IsCorrectCrc(count)) { byte slaveAddress = buffer[0]; byte function = buffer[1]; UInt16 registerAddress = (UInt16)(buffer[2] << 8 | buffer[3]); UInt16 registerCount = (UInt16)(buffer[4] << 8 | buffer[5]); if ((slaveAddress >= 1 && slaveAddress <= 247) && (function == 0x04) && (registerAddress == 0x20) && (registerCount == 0x01)) { UInt16 randomData = (UInt16)random.Next(0, 1000); buffer[0] = slaveAddress; buffer[1] = function; buffer[2] = 0x02; buffer[3] = (byte)(randomData >> 8); buffer[4] = (byte)randomData; buffer.AddModbusCrc(count: 5); serialPort.BaseStream.Write(buffer, 0, count: 7); } } }
/// <summary> /// Запускает цикл асинхронного опроса одного из портов /// </summary> /// <param name="serialPort">Опрашиваемый порт</param> /// <param name="deviceAddressRange">Адресы опрошиваемых устройст</param> private static async void StartModbusPollAsync(SerialPort serialPort, List <byte> deviceAddressRange) { const byte function = 0x04; const byte registerAddressHigh = 0x00; const byte registerAddressLow = 0x20; const byte registerCountHigh = 0x00; const byte registerCountLow = 0x01; await Task.Factory.StartNew(() => { /*Основной цикл опроса одного порта*/ while (true) { /*Ассинхронно запускаю алгоритм опроса, и сразу же начинаю засекать период*/ Task.Factory.StartNew(async() => { await Task.Factory.StartNew(() => { deviceAddressRange.ForEach(address => { #region Формирую и отправляю запрос byte[] buffer = new byte[256]; buffer[0] = address; buffer[1] = function; buffer[2] = registerAddressHigh; buffer[3] = registerAddressLow; buffer[4] = registerCountHigh; buffer[5] = registerCountLow; buffer.AddModbusCrc(count: 6); string logMessage = $"{DateTime.Now.ToString("HH:mm:ss.fff")}:{serialPort.PortName}: TX: "; logMessage += buffer.ToStringHex(count: 8) + "\r\n"; serialPort.BaseStream.Write(buffer, 0, count: 8); #endregion #region Обрабатываю полученный ответ Task <int> taskReader = serialPort.BaseStream.ReadAsync(buffer, 0, 256); if (taskReader.Wait(250)) { buffer = buffer.Take(count: taskReader.Result).ToArray(); } else { Logger.Write($"\t\t{serialPort.PortName}:RX: TIMEOUT"); } #endregion #region Записываю историю logMessage += $"{DateTime.Now.ToString("HH:mm:ss.fff")}:{serialPort.PortName}: RX: "; logMessage += buffer.ToStringHex(count: taskReader.Result); Logger.Write(logMessage); #endregion }); }); }); /*Период опроса*/ Task.Delay(1000).Wait(); } }, TaskCreationOptions.LongRunning); }