protected FunctionServiceResult ProcessReadRegisters(Sample[] samples, PacketType? packetType)
        {
            //Get the raw bytes
            var messageBytes = samples
                .Select(s => s.Value)
                .ToArray();

            //We'll assume that this is a response
            byte numberOfBytes = messageBytes[2];

            //Get the number of registers
            var numberOfRegisters = numberOfBytes / 2;

            //Get the registers themselves
            var registers = GetRegisters(messageBytes, numberOfRegisters, 3);

            //Create the visual factory
            Func<Visual> visualFactory = () =>
            {
                var viewModel = new RegistersViewModel(registers);

                return new RegistersView()
                {
                    DataContext = viewModel
                };
            };

            var summary = $"{numberOfRegisters} registers.";

            return new FunctionServiceResult(summary, visualFactory, packetType);
        }
        public static FunctionServiceResult Process(Sample[] samples)
        {
            try
            {
                IFunctionService service;

                if (samples.Length < 5)
                {
                    return new FunctionServiceResult("Packet not long enough.");
                }

                byte rawFunctionCode = samples[1].Value;

                FunctionCode functionCode = (FunctionCode)(rawFunctionCode & 0x7F);

                if ((rawFunctionCode & 0x80) > 0)
                {
                    var exceptionDescription = SlaveExceptionDescriptionFactory.GetExceptionDescription(samples[2].Value);

                    return new FunctionServiceResult(error: exceptionDescription);
                }

                if (_functionServices.TryGetValue(functionCode, out service))
                {
                    return service.Process(samples);
                }

                return new FunctionServiceResult(error: "Unsupported function code.");

            }
            catch (Exception ex)
            {
                return new FunctionServiceResult(ex.Message);
            }
        }
        public override FunctionServiceResult Process(Sample[] samples)
        {
            if (samples.Length == NumberOfRegistersMessageLength)
            {
                return ProcessNumberOfRegisters(samples, PacketType.Request);
            }

            return ProcessReadRegisters(samples, PacketType.Response);
        }
        protected FunctionServiceResult ProcessNumberOfRegisters(Sample[] samples, PacketType? packetType)
        {
            if (samples.Length != NumberOfRegistersMessageLength)
                throw new ArgumentException($"The message must be 8 bytes long. It was {samples.Length}.");

            //Get the raw bytes
            var messageBytes = samples
                .Select(s => s.Value)
                .ToArray();

            ushort address = EndianBitConverter.Big.ToUInt16(messageBytes, 2);
            ushort number = EndianBitConverter.Big.ToUInt16(messageBytes, 4);

            var summary = $"Read {number} registers starting at {address}";

            return new FunctionServiceResult(summary, packetType: packetType);
        }
        private FunctionServiceResult ProcessWriteRegisters(Sample[] samples)
        {
            // http://www.simplymodbus.ca/FC16.htm

            //Get the raw bytes
            var messageBytes = samples
                .Select(s => s.Value)
                .ToArray();

            var dataAddress = EndianBitConverter.Big.ToUInt16(messageBytes, 2);
            var numberOfRegisters = EndianBitConverter.Big.ToUInt16(messageBytes, 4);

            var bytesToFollow = messageBytes[6];

            if (bytesToFollow != numberOfRegisters*2)
            {
                return
                    new FunctionServiceResult(
                        $"The bytes to follow {bytesToFollow} does not match the number of registers {numberOfRegisters}.");
            }

            var registers = GetRegisters(messageBytes, numberOfRegisters, 7);

            Func<Visual> visualFactory = () =>
            {
                var viewModel = new RegistersViewModel(registers.ToArray(), dataAddress);

                return new RegistersView()
                {
                    DataContext = viewModel
                };
            };

            var summary = $"Write {numberOfRegisters} registers starting at register {dataAddress}";

            return new FunctionServiceResult(summary, visualFactory, PacketType.Request);
        }
 public abstract FunctionServiceResult Process(Sample[] samples);