Пример #1
0
        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;
                }
                }
            }
        }
Пример #2
0
        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());
        }
Пример #3
0
        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;
            }
        }
Пример #4
0
        public void TestAckFrame()
        {
            var frame = MBusFrame.FromByteArray(MBusFrameType.SingleChar, NullLogger.Instance, new[] { MBus.SingleCharFrame });

            Assert.NotNull(frame);
            Assert.Equal(typeof(AckFrame), frame.GetType());
        }
Пример #5
0
        protected override async Task WriteFrame(MBusFrame frame)
        {
            OpenConnection();
            var data = frame.ToByteFrame();

            Logger.LogHexOut(data);
            await _udpClient.SendAsync(data.Span.ToArray(), data.Length);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
 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);
     }
 }
Пример #10
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        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();
        }
Пример #14
0
        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);
        }
Пример #15
0
        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;
            }
        }
Пример #16
0
        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;
            }
        }
Пример #17
0
        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);
        }
Пример #18
0
        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;
                }
                }
            }
        }
Пример #19
0
        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);
        }
Пример #20
0
 public ScanResult(int deviceId, MBusFrame frame)
 {
     DeviceId = deviceId;
     Frame    = frame;
 }
Пример #21
0
        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);
        }
Пример #22
0
 protected abstract Task WriteFrame(MBusFrame frame);