public static bool IsAppSpecific(this FramePort port) => port is >= FramePort.AppMin and <= FramePort.AppMax;
        public async Task When_Decoder_Is_Undefined_Return_In_Value(string decoder, string payloadString, FramePort fport)
        {
            var payload = Encoding.UTF8.GetBytes(payloadString);

            var target = new LoRaPayloadDecoder(NullLogger <LoRaPayloadDecoder> .Instance);
            var actual = await target.DecodeMessageAsync(new DevEui(0x12), payload, fport, decoder);

            Assert.NotNull(actual.Error);
        }
 public ValueTask <DecodePayloadResult> DecodeMessageAsync(DevEui devEui, byte[] payload, FramePort fport, string sensorDecoder) => this.decoder.DecodeMessageAsync(devEui, payload, fport, sensorDecoder);
        public async Task When_Decoder_Is_DecoderHexSensor_Return_In_Value(string decoder, string payloadString, object expectedValue, FramePort fport)
        {
            var payload = Encoding.UTF8.GetBytes(payloadString);

            var target = new LoRaPayloadDecoder(NullLogger <LoRaPayloadDecoder> .Instance);
            var actual = await target.DecodeMessageAsync(new DevEui(0x12), payload, fport, decoder);

            Assert.IsType <DecodedPayloadValue>(actual.Value);
            var decodedPayloadValue = (DecodedPayloadValue)actual.Value;

            Assert.Equal(expectedValue, decodedPayloadValue.Value);
        }
        public async ValueTask <DecodePayloadResult> DecodeMessageAsync(DevEui devEui, byte[] payload, FramePort fport, string sensorDecoder)
        {
            sensorDecoder ??= string.Empty;

            var base64Payload = ((payload?.Length ?? 0) == 0) ? string.Empty : Convert.ToBase64String(payload);

            // Call local decoder (no "http://" in SensorDecoder)
            if (Uri.TryCreate(sensorDecoder, UriKind.Absolute, out var url) && url.Scheme is "http")
            {
                // Support decoders that have a parameter in the URL
                // http://decoder/api/sampleDecoder?x=1 -> should become http://decoder/api/sampleDecoder?x=1&devEUI=11&fport=1&payload=12345

                var query = HttpUtility.ParseQueryString(url.Query);
                query["devEUI"]  = devEui.ToString();
                query["fport"]   = ((int)fport).ToString(CultureInfo.InvariantCulture);
                query["payload"] = base64Payload;

                var urlBuilder = new UriBuilder(url)
                {
                    Query = query.ToString()
                };

                if (urlBuilder.Path.EndsWith('/'))
                {
                    urlBuilder.Path = urlBuilder.Path[..^ 1];