private void DecryptFrame(MBusFrame data) { DriverContext.Logger.LogTrace($"Check frame {data?.CiField}"); if (data != null && data.CiField == 0x5B) { var controlHigh = data.RawData.Span[18]; DriverContext.Logger.LogTrace($"Check frame if frame is supported {controlHigh}"); switch (controlHigh & 0x0F) { case 5: { if (!(OmsHelper.AesDecrypt(_aesKey, data, _logger) is VariableDataFrame variableDataFrame)) { DriverContext.Logger.LogError("Could not encrypt data frame"); return; } foreach (var child in Children) { if (child is OmsDriverAttribute att) { att.SetData(variableDataFrame); } } break; } } } }
public void TestShortFrame() { var frame = MBusFrame.FromByteArray(MBusFrameType.ShortFrame, NullLogger.Instance, new byte[] { 0x10, 0x40, 0xF0, 0x30, 0x16 }); Assert.NotNull(frame); Assert.Equal(typeof(ShortFrame), frame.GetType()); }
public virtual async Task <MBusFrame> ReadDevice(int deviceId, bool resetBeforeRead, int deviceTimeout) { try { Open(); if (_config.ResetBeforeRead || resetBeforeRead) { var init = await ResetDevice(deviceId); if (init == null) { return(null); } } MBusFrame readFrame = MBusFrame.CreateShortFrame(MBus.ControlMaskReqUd2, (byte)deviceId); await TelegramMonitor.NotifyTelegram(TelegramDirection.Output, "SELF", deviceId.ToString(), readFrame.ToString(), ""); await WriteFrame(readFrame); var res = await ReadFrame(); if (res != null) { await TelegramMonitor.NotifyTelegram(TelegramDirection.Output, res.AddressField.ToString(), "SELF", res.ToString(), ""); } return(res); } catch { Close(); throw; } }
public void TestAckFrame() { var frame = MBusFrame.FromByteArray(MBusFrameType.SingleChar, NullLogger.Instance, new[] { MBus.SingleCharFrame }); Assert.NotNull(frame); Assert.Equal(typeof(AckFrame), frame.GetType()); }
protected override async Task WriteFrame(MBusFrame frame) { OpenConnection(); var data = frame.ToByteFrame(); Logger.LogHexOut(data); await _udpClient.SendAsync(data.Span.ToArray(), data.Length); }
public static byte[] GetCipherFromMBusFrame(MBusFrame frame) { var cipher = new byte[frame.RawData.Length - 21]; Array.Copy(frame.RawData.Span.ToArray(), OffsetUserData + 12, cipher, 0, cipher.Length); return(cipher); }
public void TestInvalidCrcTest() { var completeFrame = Automatica.Core.Driver.Utility.Utils.StringToByteArray( "68F7F768081172175885062D2C0804040000000C78175885060406E791000004142CDB00000422D90300000459B9270000045D081200000461B1150000042D5B010000142DC0010000043B1F020000143B74020000841006000000008420060000000084401400000000848040140000000084C0400600000000046D1A2F65114406518200004414B2C30000542D26020000543B03040000C4100600000000C4200600000000C4401400000000C480401400000000C4C0400600000000426C5F1C0F00000000E7E40000636600000000000000000000000000005BC9A50234530000E0B20300899C680000000000010001070709010300000000005816"); var frame = MBusFrame.FromByteArray(MBusFrameType.LongFrame, NullLogger.Instance, completeFrame) as VariableDataFrame; Assert.Null(frame); }
public void Test_MBusFrame_Get_Iv() { var excpectedIv = Automatica.Core.Driver.Utility.Utils.StringToByteArray("2D4C00000000010E0D0D0D0D0D0D0D0D"); var frame = MBusFrame.FromByteArray(MBusFrameType.LongFrame, NullLogger.Instance, Automatica.Core.Driver.Utility.Utils.StringToByteArray( "685F5F6853F05B000000002D4C010E0D0050053FD0FEB726760CC7AAF0B52B41F0C541BD6306DCD8B91B3DA2311EF13D2514D0960082161EFEC4B6CB1E0B3328BE6177DCA594C1280024A835F1D655BA7182B256E94BD33AC0A6B08DA46781EB4E91E01216")); var iv = OmsHelper.GetIvFromMBusFrame(frame); Assert.Equal(excpectedIv, iv); }
protected override async Task WriteFrame(MBusFrame frame) { try { _stream.DiscardOutBuffer(); var buffer = frame.ToByteFrame(); Logger.LogHexOut(buffer); await _stream.WriteAsync(buffer); } catch (Exception e) { Logger.LogError($"Could not write frame {e}", e); } }
public static byte[] AesDecryptFrame(byte[] aesKey, MBusFrame frame) { var iv = GetIvFromMBusFrame(frame); var cipher = GetCipherFromMBusFrame(frame); var encrypted = DecryptByteArray(cipher, cipher.Length, aesKey, iv); if (encrypted[0] != 0x2f || encrypted[1] != 0x2f || encrypted[encrypted.Length - 1] != 0x2f || encrypted[encrypted.Length - 2] != 0x2f) { return(new byte[0]); } return(encrypted); }
public void TestVariableDataFrame2() { var completeFrame = Automatica.Core.Driver.Utility.Utils.StringToByteArray( "68F7F768081172175885062D2C0804040000000C78175885060406E791000004142CDB00000422D90300000459B9270000045D081200000461B1150000042D5B010000142DC0010000043B1F020000143B74020000841006000000008420060000000084401400000000848040140000000084C0400600000000046D1A2F65114406518200004414B2C30000542D26020000543B03040000C4100600000000C4200600000000C4401400000000C480401400000000C4C0400600000000426C5F1C0F00000000E7E40000636600000000000000000000000000005BC9A50234530000E0B20300899C680000000000010001070709010300000000009816"); var frame = MBusFrame.FromByteArray(MBusFrameType.LongFrame, NullLogger.Instance, completeFrame) as VariableDataFrame; Assert.NotNull(frame); Assert.Equal(37351000d, frame.DataBlocks[1].Value); Assert.Equal(561.08, frame.DataBlocks[2].Value); Assert.Equal(985, frame.DataBlocks[3].Value); Assert.Equal(101.69, frame.DataBlocks[4].Value); Assert.Equal(46.160000000000004, frame.DataBlocks[5].Value); }
public void Test_MBusFrame_Decrypt() { var expectedData = Automatica.Core.Driver.Utility.Utils.StringToByteArray( "2F2F066D42222C5024100403C9D58D0004833C2BCA4B008410FB827386291D008410FB82F33CE5555900042B0000000004AB3CCD05000004FB140000000004FB943CA30100000483FF04000000002F2F"); var frame = MBusFrame.FromByteArray(MBusFrameType.LongFrame, NullLogger.Instance, Automatica.Core.Driver.Utility.Utils.StringToByteArray( "685F5F6873F05B000000002D4C010E00005005F72A3BA99D9128AB6008BEEE5336CA296EA1FFD143471C72DEAE2F716AB169FF071CC08605BC4EE99FC9D36ADE999BC910605B159ECBA642961D47560EB9C1E18071A883A18E7D5D9C8D81B9989880D6B016")); var key = "57B7CBDF2154C01795C75CCCEAD572CF"; var aesKey = Automatica.Core.Driver.Utility.Utils.StringToByteArray(key); var decryptedFrame = OmsHelper.AesDecryptFrame(aesKey, frame); Assert.Equal(expectedData, decryptedFrame); }
private async void _timer_Elapsed(object sender, ElapsedEventArgs e) { _timer.Stop(); await _waitSemaphore.WaitAsync(); try { DriverContext.Logger.LogTrace("Try read oms device..."); var frame = await _mbus.TryReadFrame(); if (frame != null) { DriverContext.Logger.LogTrace($"Read frame...1({frame.GetType()})"); MBusFrame data = null; if (frame is ShortFrame) { await _mbus.SendAck(); data = await _mbus.TryReadFrame(); } else { data = frame; } if (data != null) { DriverContext.Logger.LogTrace($"Read frame...2({data.GetType()})"); DecryptFrame(data); await _mbus.SendAck(); } else { DriverContext.Logger.LogDebug($"could not read frame"); } } } finally { _waitSemaphore.Release(1); } _timer.Start(); }
protected override async Task <MBusFrame> ReadFrame() { try { _receiveTimeoutTimer.Start(); _cts = new CancellationTokenSource(); var read = await Automatica.Core.Base.Extensions.AsyncExtensions.WithCancellation(_udpClient.ReceiveAsync(), _cts.Token); _receiveTimeoutTimer.Stop(); var data = read.Buffer; _cts = null; Logger.LogHexIn(data); if (read.Buffer.Length >= 4 && data[1] == data[2] && data[0] == data[3]) { var length = data[1]; if (data.Length == length + 6) { if (data[0] == MBus.ShortFrameStart) { return(MBusFrame.FromByteArray(MBusFrameType.ShortFrame, Logger, data)); } if (data[0] == MBus.ControlFrameLongFrameStart) { return(MBusFrame.FromByteArray( data[2] == 3 ? MBusFrameType.ControlFrame : MBusFrameType.LongFrame, Logger, data)); } } } else if (data.Length == 1 && data[0] == MBus.SingleCharFrame) { return(new AckFrame()); } } catch (Exception e) { _receiveTimeoutTimer.Stop(); Logger.LogError($"Error reading mbus frame {e}"); } _receiveTimeoutTimer.Stop(); return(null); }
public virtual async Task <MBusFrame> SetPrimaryAddres(int deviceId, int newDeviceId) { try { Open(); var frame = MBusFrame.CreateChangePrimaryAddressFrame((byte)deviceId, (byte)newDeviceId); Console.WriteLine(ByteArrayToString(frame.ToByteFrame())); await WriteFrame(frame); return(await ReadFrame()); } catch { Close(); throw; } }
public virtual async Task <MBusFrame> ResetDevice(int deviceId) { try { Open(); MBusFrame readFrame = MBusFrame.CreateShortFrame(MBus.ControlMaskSndUd, (byte)deviceId); Console.WriteLine(ByteArrayToString(readFrame.ToByteFrame())); await WriteFrame(readFrame); return(await ReadFrame()); } catch { Close(); throw; } }
public static MBusFrame AesDecrypt(byte[] aesKey, MBusFrame frame, ILogger logger) { var encrypted = AesDecryptFrame(aesKey, frame); if (encrypted == null || encrypted.Length == 0) { return(null); } var vdaFrame = new byte[encrypted.Length - 4]; Array.Copy(encrypted, 2, vdaFrame, 0, encrypted.Length - 4); var varDataFrame = new VariableDataFrame(); varDataFrame.ParseVariableDataFrame(vdaFrame, 0, logger); return(varDataFrame); }
private void DecryptFrame(MBusFrame data) { if (data != null && data.CiField == 0x5B) { var controlHigh = data.RawData.Span[OffsetUserData + 11]; var controlLow = data.RawData.Span[OffsetUserData + 10]; switch (controlHigh & 0x0F) { case 5: { int countEncBlocks = controlLow >> 4; System.Console.WriteLine( $"AES with dyn.init vector {countEncBlocks} d 16 byte blocks plus % d unencrypted data {data.RawData.Length - 12 - 16 * countEncBlocks}"); var encrypted = OmsHelper.AesDecrypt(_aesKey, data, NullLogger.Instance); break; } } } }
public static byte[] GetIvFromMBusFrame(MBusFrame frame) { var userData = frame.RawData.Span; var iv = new byte[16]; iv[0] = userData[OffsetUserData + 4]; iv[1] = userData[OffsetUserData + 5]; iv[2] = userData[OffsetUserData + 0]; iv[3] = userData[OffsetUserData + 1]; iv[4] = userData[OffsetUserData + 2]; iv[5] = userData[OffsetUserData + 3]; iv[6] = userData[OffsetUserData + 6]; iv[7] = userData[OffsetUserData + 7]; var ivByte = userData[OffsetUserData + 8]; for (int i = 0; i < 8; i++) { iv[8 + i] = ivByte; } return(iv); }
public ScanResult(int deviceId, MBusFrame frame) { DeviceId = deviceId; Frame = frame; }
private async Task <MBusFrame> ReadFrameInternal() { try { int firstChar = _stream.ReadByte(); if (firstChar == MBus.ShortFrameStart) { Logger.LogDebug("Start parsing short frame..."); Thread.Sleep(100); byte[] shortFrame = new byte[5]; shortFrame[0] = (byte)firstChar; var bytesRead = await _stream.ReadAsync(shortFrame, 1, 4); if (bytesRead != 4) { Logger.LogDebug($"Could not parse short frame (read bytes {bytesRead}/4)"); return(null); } Logger.LogDebug("Short frame in..."); Logger.LogHexIn(shortFrame); var frame = MBusFrame.FromByteArray(MBusFrameType.ShortFrame, Logger, shortFrame); return(frame); } if (firstChar == MBus.SingleCharFrame) { Logger.LogDebug("Ack frame in..."); return(new AckFrame()); } if (firstChar == MBus.ControlFrameLongFrameStart) { Logger.LogDebug("Start parsing long frame..."); Thread.Sleep(200); byte[] headerBuffer = new byte[4]; headerBuffer[0] = (byte)firstChar; var bytesRead = await _stream.ReadAsync(headerBuffer, 1, 3); Logger.LogHexIn(headerBuffer); if (bytesRead != 3) { Logger.LogDebug($"Could not read header...read {bytesRead}/3"); return(null); } if (headerBuffer[0] == 0x68 && headerBuffer[0] == headerBuffer[3] && headerBuffer[1] == headerBuffer[2]) { int lengthToRead = headerBuffer[1] + 2; //read with checksum and stop byte byte[] data = new byte[lengthToRead]; var dataMemory = new Memory <byte>(data); bytesRead = await _stream.ReadAsync(dataMemory); Logger.LogHexIn(dataMemory); if (bytesRead != lengthToRead) { Logger.LogDebug($"Invalid length of read data...({bytesRead}/{lengthToRead})"); return(null); //invalid length of data read } if (data[data.Length - 1] != 0x16) { Logger.LogDebug("Invalid stop byte..."); return(null); //invalid stop byte } var packageType = headerBuffer[2] == 3 ? MBusFrameType.ControlFrame : MBusFrameType.LongFrame; return(MBusFrame.FromSpan(packageType, Logger, headerBuffer.AsSpan(), dataMemory.Span)); } } } catch (IOException ioe) { Logger.LogError($"Could not read frame {ioe}", ioe); Close(); Thread.Sleep(100); Open(); } catch (Exception e) { Logger.LogError($"Could not read frame {e}", e); } return(null); }
protected abstract Task WriteFrame(MBusFrame frame);