コード例 #1
0
        private static List <Rxpk> GenerateRxpk(string datr, double freq)
        {
            string jsonUplink =
                @"{ ""rxpk"":[
                {
                    ""time"":""2013-03-31T16:21:17.528002Z"",
                    ""tmst"":3512348611,
                    ""chan"":2,
                    ""rfch"":0,
                    ""freq"":" + freq + @",
                    ""stat"":1,
                    ""modu"":""LORA"",
                    ""datr"":""" + datr + @""",
                    ""codr"":""4/6"",
                    ""rssi"":-35,
                    ""lsnr"":5.1,
                    ""size"":32,
                    ""data"":""AAQDAgEEAwIBBQQDAgUEAwItEGqZDhI=""
                }]}";

            var multiRxpkInput = Encoding.Default.GetBytes(jsonUplink);

            byte[] physicalUpstreamPyld = new byte[12];
            physicalUpstreamPyld[0] = 2;
            List <Rxpk> rxpk = Rxpk.CreateRxpk(physicalUpstreamPyld.Concat(multiRxpkInput).ToArray());

            return(rxpk);
        }
コード例 #2
0
        public void CheckEUValidUpstreamRxpk(double frequency, string datr, string expectedDatr)
        {
            string jsonUplink =
                "{\"rxpk\":[{\"time\":\"2013-03-31T16:21:17.528002Z\"," +
                "\"tmst\":3512348611," +
                "\"chan\":2," +
                "\"rfch\":0," +
                $"\"freq\": {frequency}," +
                "\"stat\":1," +
                "\"modu\":\"LORA\"," +
                $"\"datr\":\"{datr}\"," +
                "\"codr\":\"4/6\"," +
                "\"rssi\":-35," +
                "\"lsnr\":5.1," +
                "\"size\":32," +
                "\"data\":\"AAQDAgEEAwIBBQQDAgUEAwItEGqZDhI=\"," +
                "\"custom_prop_a\":\"a\"," +
                "\"custom_prop_b\":10" +
                " }]}";

            byte[] physicalUpstreamPyld = new byte[12];
            physicalUpstreamPyld[0] = 2;
            var request    = Encoding.Default.GetBytes(jsonUplink);
            var rxpks      = Rxpk.CreateRxpk(physicalUpstreamPyld.Concat(request).ToArray());
            var downstream = RegionManager.EU868.GetDownstreamDR(rxpks[0]);

            Assert.Equal(expectedDatr, downstream);
        }
コード例 #3
0
        public void When_Creating_From_Json_With_Custom_Elements_Has_Correct_Value()
        {
            string jsonUplink = @"{ ""rxpk"":[
                {
		            ""time"":""2013-03-31T16:21:17.528002Z"",
                    ""tmst"":3512348611,
                    ""chan"":2,
                    ""rfch"":0,
                    ""freq"":866.349812,
                    ""stat"":1,
                    ""modu"":""LORA"",
                    ""datr"":""SF7BW125"",
                    ""codr"":""4/6"",
                    ""rssi"":-35,
                    ""lsnr"":5.1,
                    ""size"":32,
                    ""data"":""AAQDAgEEAwIBBQQDAgUEAwItEGqZDhI="",
                    ""custom_prop_a"":""a"",
                    ""custom_prop_b"":10
                }]}";

            byte[] physicalUpstreamPyld = new byte[12];
            physicalUpstreamPyld[0] = 2;
            var request = Encoding.Default.GetBytes(jsonUplink);
            var rxpks   = Rxpk.CreateRxpk(physicalUpstreamPyld.Concat(request).ToArray());

            Assert.Single(rxpks);
            Assert.Equal(2, rxpks[0].ExtraData.Count);
            Assert.Contains("custom_prop_a", rxpks[0].ExtraData.Keys);
            Assert.Contains("custom_prop_b", rxpks[0].ExtraData.Keys);
            Assert.Equal("a", rxpks[0].ExtraData["custom_prop_a"]);
            Assert.Equal(10L, rxpks[0].ExtraData["custom_prop_b"]);
        }
コード例 #4
0
        public void TestJoinRequest()
        {
            byte[] physicalUpstreamPyld = new byte[12];
            physicalUpstreamPyld[0] = 2;
            string      jsonUplink       = @"{ ""rxpk"":[
                {
		            ""time"":""2013-03-31T16:21:17.528002Z"",
                    ""tmst"":3512348611,
                    ""chan"":2,
                    ""rfch"":0,
                    ""freq"":866.349812,
                    ""stat"":1,
                    ""modu"":""LORA"",
                    ""datr"":""SF7BW125"",
                    ""codr"":""4/6"",
                    ""rssi"":-35,
                    ""lsnr"":5.1,
                    ""size"":32,
                    ""data"":""AAQDAgEEAwIBBQQDAgUEAwItEGqZDhI=""
                }]}";
            var         joinRequestInput = Encoding.Default.GetBytes(jsonUplink);
            List <Rxpk> rxpk             = Rxpk.CreateRxpk(physicalUpstreamPyld.Concat(joinRequestInput).ToArray());

            TestRxpk(rxpk[0]);
        }
コード例 #5
0
        public void Multiple_Rxpk_Are_Detected_Correctly()
        {
            string jsonUplink = @"{""rxpk"":[{""tmst"":373051724,""time"":""2020-02-19T04:08:57.265951Z"",""chan"":0,""rfch"":0,""freq"":923.200000,""stat"":1,""modu"":""LORA"",""datr"":""SF9BW125"",""codr"":""4/5"",""lsnr"":12.5,""rssi"":-47,""size"":21,""data"":""gAMAABKgmAAIAvEgIbhjS0LBeM/d""},{""tmst"":373053772,""time"":""2020-02-19T04:08:57.265951Z"",""chan"":6,""rfch"":0,""freq"":923.000000,""stat"":-1,""modu"":""LORA"",""datr"":""SF9BW125"",""codr"":""4/5"",""lsnr"":-13.0,""rssi"":-97,""size"":21,""data"":""gJni7n4+wQBUl/E0sO4vB4gFePx7""}]}";

            byte[] physicalUpstreamPyld = new byte[12];
            physicalUpstreamPyld[0] = 2;
            var request = Encoding.Default.GetBytes(jsonUplink);
            var rxpks   = Rxpk.CreateRxpk(physicalUpstreamPyld.Concat(request).ToArray());

            Assert.Equal(2, rxpks.Count);
        }
コード例 #6
0
        public void TestUnconfirmedUplink()
        {
            string jsonUplinkUnconfirmedDataUp = @"{ ""rxpk"":[
               {
               ""time"":""2013-03-31T16:21:17.528002Z"",
                ""tmst"":3512348611,
                ""chan"":2,
                ""rfch"":0,
                ""freq"":866.349812,
                ""stat"":1,
                ""modu"":""LORA"",
                ""datr"":""SF7BW125"",
                ""codr"":""4/6"",
                ""rssi"":-35,
                ""lsnr"":5.1,
                ""size"":32,
                ""data"":""QAQDAgGAAQABppRkJhXWw7WC""
                 }]}";

            byte[] physicalUpstreamPyld = new byte[12];
            physicalUpstreamPyld[0] = 2;

            var         jsonUplinkUnconfirmedDataUpBytes = Encoding.Default.GetBytes(jsonUplinkUnconfirmedDataUp);
            List <Rxpk> rxpk = Rxpk.CreateRxpk(physicalUpstreamPyld.Concat(jsonUplinkUnconfirmedDataUpBytes).ToArray());

            Assert.True(LoRaPayload.TryCreateLoRaPayload(rxpk[0], out LoRaPayload loRaPayload));

            Assert.Equal(LoRaMessageType.UnconfirmedDataUp, loRaPayload.LoRaMessageType);

            LoRaPayloadData loRaPayloadUplinkObj = (LoRaPayloadData)loRaPayload;

            Assert.True(loRaPayloadUplinkObj.Fcnt.Span.SequenceEqual(new byte[2] {
                1, 0
            }));

            Assert.True(loRaPayloadUplinkObj.DevAddr.Span.SequenceEqual(new byte[4] {
                1, 2, 3, 4
            }));
            byte[] loRaPayloadUplinkNwkKey = new byte[16] {
                2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
            };

            Assert.True(loRaPayloadUplinkObj.CheckMic(ConversionHelper.ByteArrayToString(loRaPayloadUplinkNwkKey)));

            byte[] loRaPayloadUplinkAppKey = new byte[16] {
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
            };
            var key = ConversionHelper.ByteArrayToString(loRaPayloadUplinkAppKey);

            Assert.Equal("hello", Encoding.ASCII.GetString(loRaPayloadUplinkObj.PerformEncryption(key)));
        }
コード例 #7
0
 private void DispatchMessages(byte[] buffer, DateTime startTimeProcessing)
 {
     try
     {
         List <Rxpk> messageRxpks = Rxpk.CreateRxpk(buffer);
         if (messageRxpks != null)
         {
             foreach (var rxpk in messageRxpks)
             {
                 this.messageDispatcher.DispatchRequest(new LoRaRequest(rxpk, this, startTimeProcessing));
             }
         }
     }
     catch (Exception ex)
     {
         Logger.Log("UDP", $"failed to dispatch messages: {ex.Message}", LogLevel.Error);
     }
 }
コード例 #8
0
        public void TestKeys()
        {
            // create random message
            string jsonUplink       = @"{ ""rxpk"":[
                {
		            ""time"":""2013-03-31T16:21:17.528002Z"",
                    ""tmst"":3512348611,
                    ""chan"":2,
                    ""rfch"":0,
                    ""freq"":866.349812,
                    ""stat"":1,
                    ""modu"":""LORA"",
                    ""datr"":""SF7BW125"",
                    ""codr"":""4/6"",
                    ""rssi"":-35,
                    ""lsnr"":5.1,
                    ""size"":32,
                    ""data"":""AAQDAgEEAwIBBQQDAgUEAwItEGqZDhI=""
                }]}";
            var    joinRequestInput = Encoding.Default.GetBytes(jsonUplink);

            byte[] physicalUpstreamPyld = new byte[12];
            physicalUpstreamPyld[0] = 2;
            List <Rxpk> rxpk = Rxpk.CreateRxpk(physicalUpstreamPyld.Concat(joinRequestInput).ToArray());

            Assert.True(LoRaPayload.TryCreateLoRaPayload(rxpk[0], out LoRaPayload loRaPayload));
            Assert.Equal(LoRaMessageType.JoinRequest, loRaPayload.LoRaMessageType);
            var joinReq = (LoRaPayloadJoinRequest)loRaPayload;

            joinReq.DevAddr = new byte[4]
            {
                4, 3, 2, 1,
            };
            joinReq.DevEUI = new byte[8]
            {
                8, 7, 6, 5, 4, 3, 2, 1,
            };
            joinReq.DevNonce = new byte[2]
            {
                2, 1,
            };
            joinReq.AppEUI = new byte[8]
            {
                1, 2, 3, 4, 5, 6, 7, 8,
            };

            byte[] appNonce = new byte[3]
            {
                0, 0, 1,
            };
            byte[] netId = new byte[3]
            {
                3, 2, 1,
            };
            byte[] appKey = new byte[16]
            {
                1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8,
            };
            var key = joinReq.CalculateKey(LoRaPayloadKeyType.NwkSkey, appNonce, netId, joinReq.DevNonce.ToArray(), appKey);

            Assert.Equal(
                key,
                new byte[16] {
                223, 83, 195, 95, 48, 52, 204, 206, 208, 255, 53, 76, 112, 222, 4, 223,
            });
        }
コード例 #9
0
        async Task RunUdpListener()
        {
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, PORT);

            this.udpClient = new UdpClient(endPoint);

            Logger.LogAlways($"LoRaWAN server started on port {PORT}");

            while (true)
            {
                UdpReceiveResult receivedResults = await this.udpClient.ReceiveAsync();

                var startTimeProcessing = DateTime.UtcNow;
                // Logger.LogAlways($"UDP message received ({receivedResults.Buffer[3]}) from port: {receivedResults.RemoteEndPoint.Port} and IP: {receivedResults.RemoteEndPoint.Address.ToString()}");
                switch (PhysicalPayload.GetIdentifierFromPayload(receivedResults.Buffer))
                {
                // In this case we have a keep-alive PULL_DATA packet we don't need to start the engine and can return immediately a response to the challenge
                case PhysicalIdentifier.PULL_DATA:
                    if (this.pullAckRemoteLoRaAggregatorPort == 0)
                    {
                        this.pullAckRemoteLoRaAggregatorPort = receivedResults.RemoteEndPoint.Port;
                    }

                    this.SendAcknowledgementMessage(receivedResults, (int)PhysicalIdentifier.PULL_ACK, receivedResults.RemoteEndPoint);
                    break;

                // This is a PUSH_DATA (upstream message).
                case PhysicalIdentifier.PUSH_DATA:
                    this.SendAcknowledgementMessage(receivedResults, (int)PhysicalIdentifier.PUSH_ACK, receivedResults.RemoteEndPoint);

                    // Message processing runs in the background
                    var remoteEndPointAddress = receivedResults.RemoteEndPoint.Address.ToString();
                    _ = Task.Run(async() =>
                    {
                        List <Rxpk> messageRxpks = Rxpk.CreateRxpk(receivedResults.Buffer);
                        if (messageRxpks != null)
                        {
                            if (messageRxpks.Count == 1)
                            {
                                await this.ProcessRxpkAsync(receivedResults.RemoteEndPoint.Address.ToString(), messageRxpks[0], startTimeProcessing);
                            }
                            else if (messageRxpks.Count > 1)
                            {
                                Task toWait = null;
                                for (int i = 0; i < messageRxpks.Count; i++)
                                {
                                    var t = this.ProcessRxpkAsync(remoteEndPointAddress, messageRxpks[i], startTimeProcessing);
                                    if (toWait == null)
                                    {
                                        toWait = t;
                                    }
                                }

                                await toWait;
                            }
                        }
                    });

                    break;

                // This is a ack to a transmission we did previously
                case PhysicalIdentifier.TX_ACK:
                    if (receivedResults.Buffer.Length == 12)
                    {
                        Logger.Log(
                            "UDP",
                            $"Packet with id {ConversionHelper.ByteArrayToString(receivedResults.Buffer.RangeSubset(1, 2))} successfully transmitted by the aggregator",
                            LogLevel.Debug);
                    }
                    else
                    {
                        var logMsg = string.Format(
                            "Packet with id {0} had a problem to be transmitted over the air :{1}",
                            receivedResults.Buffer.Length > 2 ? ConversionHelper.ByteArrayToString(receivedResults.Buffer.RangeSubset(1, 2)) : string.Empty,
                            receivedResults.Buffer.Length > 12 ? Encoding.UTF8.GetString(receivedResults.Buffer.RangeSubset(12, receivedResults.Buffer.Length - 12)) : string.Empty);
                        Logger.Log("UDP", logMsg, LogLevel.Error);
                    }

                    break;

                default:
                    Logger.Log("UDP", "Unknown packet type or length being received", LogLevel.Error);
                    break;
                }
            }
        }