/// <summary> /// Формирует пакет с запросом прибору /// </summary> /// <param name="rqData"></param> /// <returns></returns> private byte[] PackRequest(byte[] rqData) { List <byte> request = new List <byte>(); // Сетевой адрес request.Add((byte)this.NetworkAddress); // Пакет с запросом request.AddRange(rqData); ushort crc = ModBusCrc.Calc(request); request.Add((byte)(crc & 0x00FF)); request.Add((byte)((crc & 0xFF00) >> 8)); return(request.ToArray()); }
/// <summary> /// Вычисляет контрольную сумму для переданного блока данных, согласно /// спецификации протокола ModBus (Modicon Modbus Protocol Reference Guide) /// /// Для расчета контрольной суммы используется модифицированный CRC-16-IBM с полиномом 0xA001. /// В отличие от стандартного алгоритма CRC-16-IBM, начальное значение устанавливается равным 0xFFFF /// </summary> /// <param name="input">Массив байт, по которому нужно посчитать CRC</param> /// <returns>Значение контрольной суммы</returns> public static ushort Calc(IList <byte> input) { return(ModBusCrc.Calc(input, 0, input.Count)); }
private void remoteConsole_DeviceDataReceived(object sender, DeviceDataEventArgs args) { // Проверим, что консоль подключена к прибору if (!this.remoteConsole.IsConnected) { return; } // Получаем обработчик запроса VktDataReadEventHandler currentHandler = this.handlers.First.Value; this.handlers.RemoveFirst(); // Проверим длину считанного пакета if (args.Response.Length < 5) { // Повторяем запрос LogError("Неверная длина ответа прибора. Ожидалось не менее 5 байт, получено " + args.Response.Length); CallRequestError(); // Отключаемся try { this.remoteConsole.DisconnectAsync(null, null); } catch (Lers.PermissionDeniedException exc) { LogError("Ошибка отключения удалённого пульта. " + exc.Message); } return; } // Проверим контрольную сумму ushort calcCs = ModBusCrc.Calc(args.Response, 0, args.Response.Length - 2); ushort recvCrc = BitConverter.ToUInt16(args.Response, args.Response.Length - 2); if (calcCs != recvCrc) { LogWarning("Не сходится контрольная сумма ответа"); // Повторяем запрос SendRequest(args.Request, this.responseLength, currentHandler); return; } // Проверим сетевой адрес if (args.Response[0] != (byte)this.NetworkAddress) { LogWarning("В ответе указан неверный контрольный адрес"); // Повторяем запрос SendRequest(args.Request, this.responseLength, currentHandler); return; } // Возвращаем считанные прибором данные if (currentHandler != null) { byte[] rspData = new byte[args.Response.Length - 5]; Array.Copy(args.Response, 3, rspData, 0, rspData.Length); currentHandler(rspData); } }