private void PortValueSingleEncoder_Decode <T>(string dataAsString, byte expectedPortId, PortModeInformationDataType expectedDataType, T[] expectedData)
        {
            var knowledge = new ProtocolKnowledge();

            var serviceProvider = new ServiceCollection()
                                  .AddPoweredUp()
                                  .BuildServiceProvider();


            KnowledgeManager.ApplyDynamicProtocolKnowledge(new HubAttachedIOForAttachedDeviceMessage(0x63, DeviceType.TechnicMediumHubTiltSensor, new Version("0.0.0.1"), new Version("0.0.0.1"))
            {
                HubId = 0
            }, knowledge, serviceProvider.GetService <IDeviceFactory>());

            // arrange
            var data = BytesStringUtil.StringToData(dataAsString);

            // act
            var message = MessageEncoder.Decode(data, knowledge) as PortValueSingleMessage;

            // assert
            Assert.Collection(message.Data,
                              d =>
            {
                Assert.Equal(d.PortId, expectedPortId);
                Assert.Equal(d.DataType, expectedDataType);

                if (d is PortValueData <T> actual)
                {
                    Assert.Collection(actual.InputValues, expectedData.Cast <T>().Select <T, Action <T> >(expected => actual => Assert.Equal(expected, actual)).ToArray());
                }
            }
                              );
        }
        public void PortValueCombinedModeEncoder_Decode(string dataAsString, byte expectedPortId, byte[] expectedModes, PortModeInformationDataType[] expectedDataType, int[] expectedData)
        {
            var knowledge = new ProtocolKnowledge();

            var serviceProvider = new ServiceCollection()
                                  .AddPoweredUp()
                                  .BuildServiceProvider();

            KnowledgeManager.ApplyDynamicProtocolKnowledge(new HubAttachedIOForAttachedDeviceMessage(0x00, DeviceType.TechnicLargeLinearMotor, new Version("0.0.0.1"), new Version("0.0.0.1"))
            {
                HubId = 0
            }, knowledge, serviceProvider.GetService <IDeviceFactory>());
            KnowledgeManager.ApplyDynamicProtocolKnowledge(new PortInputFormatSetupCombinedModeForSetModeDataSetMessage(
                                                               PortId: 0x00,
                                                               CombinationIndex: 0, // should refer 0b0000_0000_0000_1110 => SPEED POS APOS
                                                               ModeDataSets: new PortInputFormatSetupCombinedModeModeDataSet[] {
                new PortInputFormatSetupCombinedModeModeDataSet(0x01, 0),
                new PortInputFormatSetupCombinedModeModeDataSet(0x02, 0),
                new PortInputFormatSetupCombinedModeModeDataSet(0x03, 0),
            }
                                                               ), knowledge, serviceProvider.GetService <IDeviceFactory>());

            // arrange
            var data = BytesStringUtil.StringToData(dataAsString);

            // act
            var message = MessageEncoder.Decode(data, knowledge) as PortValueCombinedModeMessage;

            // assert
            Assert.Equal(expectedPortId, message.PortId);
            Assert.Collection(message.Data, Enumerable.Range(0, expectedModes.Length).Select <int, Action <PortValueData> >(pos => portValueData =>
            {
                Assert.Equal(expectedPortId, portValueData.PortId);
                Assert.Equal(expectedDataType[pos], portValueData.DataType);
                Assert.Equal(expectedDataType[pos], portValueData.DataType);

                if (portValueData is PortValueData <sbyte> actual)
                {
                    Assert.Equal(expectedData[pos], actual.InputValues[0]);
                }
                if (portValueData is PortValueData <short> actual2)
                {
                    Assert.Equal(expectedData[pos], actual2.InputValues[0]);
                }
                if (portValueData is PortValueData <int> actual3)
                {
                    Assert.Equal(expectedData[pos], actual3.InputValues[0]);
                }
            }).ToArray());
        }