private byte[] Compose(IRegisterMessage message, out IReadOnlyCollection <IRegisterGroup> composedGroups) { byte[] data = GetDataBytes(message, out composedGroups); byte[] packet = PreparePacketWithHeader(_info.MinPacketLength + data.Length, message.SlaveDeviceAddress); Array.Copy(data, 0, packet, _info.DataOffset, data.Length); packet[packet.Length - 1] = CheckSum.Crc8(packet.Take(packet.Length - _info.PacketCheckSumSize).ToArray()); return(packet); }
public void ComposeRange(int firstRegisterAddress, int registerCount, MessageType messageType, OperationType operationType, byte[] expected) { // Arrange // fill checkSums expected[3] = CheckSum.Crc8(expected.AsSpan().Slice(0, 3).ToArray()); expected[expected.Length - 1] = CheckSum.Crc8(expected.AsSpan().Slice(0, expected.Length - 1).ToArray()); IRegisterMessage message = _messageFactory.CreateRange(firstRegisterAddress, registerCount, operationType, messageType); // Act byte[] actual = _composer.Compose(message, out IReadOnlyCollection <IRegisterGroup> composedGroups); // Assert Assert.Equal(expected, actual); }
public void ProcessNextMessage() { using (var listener = new MessageListener(_protocol)) { IRegisterMessage message = _registersUpdatePolicy.GetNextMessage(_slaveDevice); if (message is EmptyMessage) { _log.AppendMessage(LogMessageType.Info, $"Nothing to process. Skip {_slaveDevice.Name}"); return; } _log.AppendMessage(LogMessageType.Info, $"Sending {message.OperationType}-register message"); _protocol.SendAsPossible(message, out IReadOnlyCollection <IRegisterGroup> requestRegisters); _log.AppendMessage(LogMessageType.Info, $"Register groups with addresses {requestRegisters.GetAllAddressesAsString()} was requested"); while (true) { if (!listener.WaitMessage(_dispatcher.RequestTimeout, out IMessage receivedMessage)) { throw new DeviceNotRespondException("Device Not responding"); } if (receivedMessage.Type != MessageType.Response) { continue; } // All high priority messages should be handled in separate thread. if (receivedMessage is HighPriorityMessage) { continue; } if (receivedMessage.SlaveDeviceAddress != _slaveDevice.Address) { _dispatcher.OnUnexpectedDeviceResponse(_slaveDevice, receivedMessage.SlaveDeviceAddress); continue; } if (receivedMessage is IErrorMessage errorMessage) { ProcessErrorMessage(errorMessage); } if (!(receivedMessage is IReceivedMessage response)) { throw new InvalidMetaDataException("Wrong response received"); } _log.AppendMessage(LogMessageType.Info, "Response received, updating registers"); UpdateRegisters(requestRegisters, response.Registers, response.OperationType); _log.AppendMessage(LogMessageType.Info, "Registers updated"); break; } } }
private byte[] GetDataBytes(IRegisterMessage message, out IReadOnlyCollection <IRegisterGroup> composedGroups) { byte gByte; bool withValues = false; switch (message.Type) { case MessageType.Request: gByte = MilliGanjubusInfo.GRequest; break; case MessageType.Response: gByte = (byte)(MilliGanjubusInfo.GReply << 4); withValues = true; break; default: throw new NandakaBaseException("Undefined message type"); } bool isRange = RegisterConverter.IsRange(message.RegisterGroups, _info); switch (message.OperationType) { case OperationType.Read: if (isRange) { gByte |= MilliGanjubusInfo.FReadRange; } else { gByte |= MilliGanjubusInfo.FReadSeries; } break; case OperationType.Write: if (isRange) { gByte |= MilliGanjubusInfo.FWriteRange; } else { gByte |= MilliGanjubusInfo.FWriteSeries; } // By default assume that this is read operation. Otherwise invert variable. withValues = !withValues; break; default: throw new NandakaBaseException("Undefined operation type"); } byte[] dataHeader = { gByte }; if (isRange) { return(RegisterConverter.ComposeDataAsRange(message.RegisterGroups, _info, dataHeader, withValues, out composedGroups)); } return(RegisterConverter.ComposeDataAsSeries(message.RegisterGroups, _info, dataHeader, withValues, out composedGroups)); }