Пример #1
0
        public void TestJoinAccept()
        {
            byte[] AppNonce = new byte[3] {
                87, 11, 199
            };
            byte[] NetId = new byte[3] {
                34, 17, 1
            };
            byte[] DevAddr = new byte[4] {
                2, 3, 25, 128
            };
            var netId = BitConverter.ToString(NetId).Replace("-", "");
            LoRaPayloadJoinAccept joinAccept = new LoRaPayloadJoinAccept(netId, "00112233445566778899AABBCCDDEEFF", DevAddr, AppNonce);

            Console.WriteLine(BitConverter.ToString(joinAccept.ToMessage()));
            LoRaMessage joinAcceptMessage = new LoRaMessage(joinAccept, LoRaMessageType.JoinAccept, new byte[] { 0x01 });

            byte[] joinAcceptMic = new byte[4] {
                67, 72, 91, 188
            };
            Assert.True((((LoRaPayloadJoinAccept)joinAcceptMessage.payloadMessage).mic.ToArray().SequenceEqual(joinAcceptMic)));

            var msg = BitConverter.ToString(((LoRaPayloadJoinAccept)joinAcceptMessage.payloadMessage).ToMessage()).Replace("-", String.Empty);

            Assert.Equal("20493EEB51FBA2116F810EDB3742975142", msg);
        }
Пример #2
0
        public async Task processMessage(byte[] message, string connectionString)
        {
            LoRaMessage loraMessage = new LoRaMessage(message);

            if (!loraMessage.processed)
            {
                Console.WriteLine($"Skip message Reason: Processed attribyte eq 'False'");
            }
            else
            {
                Console.WriteLine($"Processing message from device: {BitConverter.ToString(loraMessage.payloadMessage.devAddr)}");

                Shared.loraKeysList.TryGetValue(BitConverter.ToString(loraMessage.payloadMessage.devAddr), out LoraKeys loraKeys);

                if (loraMessage.CheckMic(testKey))
                {
                    string decryptedMessage = null;
                    try
                    {
                        decryptedMessage = loraMessage.DecryptPayload(testKey);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Failed to decrypt message: {ex.Message}");
                    }

                    if (string.IsNullOrEmpty(decryptedMessage))
                    {
                        return;
                    }

                    Console.WriteLine($"Sending message '{decryptedMessage}' to hub...");

                    int hubSendCounter = 1;
                    while (HubRetryCount != hubSendCounter)
                    {
                        try
                        {
                            sender = new IoTHubSender(connectionString, testDeviceId);
                            await sender.sendMessage(decryptedMessage);

                            hubSendCounter = HubRetryCount;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"Failed to send message: {ex.Message}");
                            hubSendCounter++;
                        }
                    }
                }
                else
                {
                    Console.WriteLine("Check MIC failed! Message will be ignored...");
                }
            }
        }
        private byte[] ProcessNonLoraMessage(LoRaMessage loraMessage)
        {
            byte[] udpMsgForPktForwarder = new byte[0];
            if (loraMessage.physicalPayload.identifier == PhysicalIdentifier.PULL_DATA)
            {
                PhysicalPayload pullAck = new PhysicalPayload(loraMessage.physicalPayload.token, PhysicalIdentifier.PULL_ACK, null);

                udpMsgForPktForwarder = pullAck.GetMessage();
            }

            return(udpMsgForPktForwarder);
        }
Пример #4
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);
            LoRaMessage jsonUplinkUnconfirmedMessage     = new LoRaMessage(physicalUpstreamPyld.Concat(jsonUplinkUnconfirmedDataUpBytes).ToArray());

            Assert.Equal(LoRaMessageType.UnconfirmedDataUp, jsonUplinkUnconfirmedMessage.loRaMessageType);

            LoRaPayloadStandardData loRaPayloadUplinkObj = (LoRaPayloadStandardData)jsonUplinkUnconfirmedMessage.payloadMessage;


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


            Assert.True(loRaPayloadUplinkObj.devAddr.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(BitConverter.ToString(LoRaPayloadUplinkNwkKey).Replace("-", "")));

            byte[] LoRaPayloadUplinkAppKey = new byte[16] {
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
            };
            var key = BitConverter.ToString(LoRaPayloadUplinkAppKey).Replace("-", "");

            Assert.Equal("hello", (loRaPayloadUplinkObj.PerformEncryption(key)));
        }
Пример #5
0
        static void Main(string[] args)
        {
            byte[] leadingByte = StringToByteArray("0205DB00AA555A0000000101");

            string inputJson = "{\"rxpk\":[{\"tmst\":3121882787,\"chan\":2,\"rfch\":1,\"freq\":868.500000,\"stat\":1,\"modu\":\"LORA\",\"datr\":\"SF7BW125\",\"codr\":\"4/5\",\"lsnr\":7.0,\"rssi\":-16,\"size\":20,\"data\":\"QEa5KACANwAIXiRAODD6gSCHMSk=\"}]}";

            byte[]      messageraw = leadingByte.Concat(Encoding.Default.GetBytes(inputJson)).ToArray();
            LoRaMessage message    = new LoRaMessage(messageraw);

            Console.WriteLine("decrypted " + (message.DecryptPayload("2B7E151628AED2A6ABF7158809CF4F3C")));
            Console.WriteLine("mic is valid: " + message.CheckMic("2B7E151628AED2A6ABF7158809CF4F3C"));
            Console.Read();
        }
        static void Main(string[] args)
        {
            //Section testing different kind of decryption.
            byte[] leadingByte = StringToByteArray("0205DB00AA555A0000000101");

            string inputJson = "{\"rxpk\":[{\"tmst\":3121882787,\"chan\":2,\"rfch\":1,\"freq\":868.500000,\"stat\":1,\"modu\":\"LORA\",\"datr\":\"SF7BW125\",\"codr\":\"4/5\",\"lsnr\":7.0,\"rssi\":-16,\"size\":20,\"data\":\"QEa5KACANwAIXiRAODD6gSCHMSk=\"}]}";

            byte[]      messageraw = leadingByte.Concat(Encoding.Default.GetBytes(inputJson)).ToArray();
            LoRaMessage message    = new LoRaMessage(messageraw);

            Console.WriteLine("decrypted " + (message.DecryptPayload("2B7E151628AED2A6ABF7158809CF4F3C")));
            Console.WriteLine("mic is valid: " + message.CheckMic("2B7E151628AED2A6ABF7158809CF4F3C"));

            // join message
            string joinInputJson = "{\"rxpk\":[{\"tmst\":286781788,\"chan\":0,\"rfch\":1,\"freq\":868.100000,\"stat\":1,\"modu\":\"LORA\",\"datr\":\"SF12BW125\",\"codr\":\"4/5\",\"lsnr\":11.0,\"rssi\":-17,\"size\":23,\"data\":\"AEZIZ25pc2lSj4gAAAAAer5VEV5aL4c=\"}]}";

            //byte[] joinBytes = StringToByteArray("00DC0000D07ED5B3701E6FEDF57CEEAF00C886030AF2C9");

            byte[]      messageJoinraw = leadingByte.Concat(Encoding.Default.GetBytes(joinInputJson)).ToArray();
            LoRaMessage joinMessage    = new LoRaMessage(messageJoinraw);

            //Console.WriteLine("decrypted " + (joinMessage.DecryptPayload("2B7E151628AED2A6ABF7158809CF4F3C")));
            Console.WriteLine("mic is valid: " + joinMessage.CheckMic("2B7E151628AED2A6ABF7158809CF4F3C"));



            ////section building up a low level message for the concentrator
            // LoRaPayloadJoinAccept joinAcceptPayload = new LoRaPayloadJoinAccept("FF08F5", "2B7E151628AED2A6ABF7158809CF4F3C", StringToByteArray("00000000"));
            //var tmp = joinAcceptPayload.getFinalMessage(Encoding.Default.GetBytes("1234"));
            // Console.WriteLine(Convert.ToBase64String(tmp));
            // listener.Send(tmp, tmp.Length);



            ////Section running the server to monitor LoRaWan messages, working for upling msg
            //UdpServer udp = new UdpServer();
            // udp.RunServer(true);
            //Console.Read();


            ////Section testing correct build up of message, NOT WORKING
            //LoRaPayloadJoinAccept joinAccept = new LoRaPayloadJoinAccept("FF08F5", "2B7E151628AED2A6ABF7158809CF4F3C", StringToByteArray("00000000"));
            //LoRaMessage message = new LoRaMessage(joinAccept, LoRaMessageType.JoinAccept, new byte[] { 0x01 });
            //Console.Write(message.loraMetadata.rawB64data);
            //Console.Write(message.physicalPayload);
            //Console.Read();
            Console.Read();
            Console.Read();
        }
Пример #7
0
        public void test()
        {
            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"":""IBMeputKQRfOUiGYyaskCt4=""
                }]}";
            var         joinRequestInput   = Encoding.Default.GetBytes(jsonUplink);
            LoRaMessage joinRequestMessage = new LoRaMessage(joinRequestInput.Concat(joinRequestInput).ToArray());
        }
Пример #8
0
        // POST api/values
        public void Post([FromBody] LoRaMessage value)
        {
            System.Diagnostics.Debug.WriteLine(value.data);

            switch (value.deveui)
            {
            case "00:9D:5D:65:B2:3C:03:CF":
                ParseTempAndSoilCayennePacket(value.deveui, value.data);
                break;

            case "00:0F:B0:DE:9F:0B:E3:92":    //still need second dev eui
                ParseRiverCayennePacket(value.deveui, value.data);
                break;

            case "paulfoeui":
                ParseFosterPacket(value.deveui, value.data);
                break;

            default:
                InsertRecord(value.deveui, value.data);
                break;
            }
        }
        public async Task processMessage(byte[] message)
        {
            startTimeProcessing = DateTime.UtcNow;

            //gate the edge device id for checking if the device is linked to a specific gateway
            if (string.IsNullOrEmpty(GatewayID))
            {
                GatewayID = Environment.GetEnvironmentVariable("IOTEDGE_DEVICEID");
            }

            LoRaMessage loraMessage = new LoRaMessage(message);

            byte[] udpMsgForPktForwarder = new Byte[0];

            if (!loraMessage.isLoRaMessage)
            {
                udpMsgForPktForwarder = ProcessNonLoraMessage(loraMessage);
            }
            else
            {
                //join message
                if (loraMessage.loRaMessageType == LoRaMessageType.JoinRequest)
                {
                    udpMsgForPktForwarder = await ProcessJoinRequest(loraMessage);
                }

                //normal message
                else if (loraMessage.loRaMessageType == LoRaMessageType.UnconfirmedDataUp || loraMessage.loRaMessageType == LoRaMessageType.ConfirmedDataUp)
                {
                    udpMsgForPktForwarder = await ProcessLoraMessage(loraMessage);
                }
            }


            //send reply to pktforwarder
            await UdpServer.UdpSendMessage(udpMsgForPktForwarder);
        }
Пример #10
0
        /// <summary>收到数据</summary>
        /// <param name="e"></param>
        protected override void OnReceive(ReceivedEventArgs e)
        {
            var msg = new LoRaMessage();

            msg.Read(e.Packet.GetStream(), null);

            WriteLog("{0,-9}<= {1}", msg.Command, msg.Payload?.ToStr());

            switch (msg.Command)
            {
            case LoRaType.PushData: PushData(msg.Payload); break;

            case LoRaType.PushAck:
                break;

            case LoRaType.PullData:
                break;

            case LoRaType.PullResp:
                break;

            case LoRaType.PullAck:
                break;

            case LoRaType.TxAck:
                break;

            default:
                break;
            }

            var rs = msg.CreateReply();

            WriteLog("{0,-9}=> {1}", rs.Command, rs.Payload?.ToStr());

            Send(rs.ToPacket());
        }
        private async Task <byte[]> ProcessLoraMessage(LoRaMessage loraMessage)
        {
            bool validFrameCounter = false;

            byte[]  udpMsgForPktForwarder = new byte[0];
            string  devAddr = BitConverter.ToString(loraMessage.payloadMessage.devAddr).Replace("-", "");
            Message c2dMsg  = null;



            Cache.TryGetValue(devAddr, out LoraDeviceInfo loraDeviceInfo);



            if (loraDeviceInfo == null)
            {
                loraDeviceInfo = await LoraDeviceInfoManager.GetLoraDeviceInfoAsync(devAddr);

                Logger.Log(loraDeviceInfo.DevEUI, $"processing message, device not in cache", Logger.LoggingLevel.Info);

                Cache.AddToCache(devAddr, loraDeviceInfo);
            }
            else
            {
                Logger.Log(loraDeviceInfo.DevEUI, $"processing message, device in cache", Logger.LoggingLevel.Info);
            }



            if (loraDeviceInfo.IsOurDevice)
            {
                //either there is no gateway linked to the device or the gateway is the one that the code is running
                if (String.IsNullOrEmpty(loraDeviceInfo.GatewayID) || loraDeviceInfo.GatewayID.ToUpper() == GatewayID.ToUpper())
                {
                    if (loraMessage.CheckMic(loraDeviceInfo.NwkSKey))
                    {
                        if (loraDeviceInfo.HubSender == null)
                        {
                            loraDeviceInfo.HubSender = new IoTHubSender(loraDeviceInfo.DevEUI, loraDeviceInfo.PrimaryKey);
                        }


                        UInt16 fcntup = BitConverter.ToUInt16(((LoRaPayloadStandardData)loraMessage.payloadMessage).fcnt, 0);


                        //check if the frame counter is valid: either is above the server one or is an ABP device resetting the counter (relaxed seqno checking)
                        if (fcntup > loraDeviceInfo.FCntUp || (fcntup == 1 && String.IsNullOrEmpty(loraDeviceInfo.AppEUI)))
                        {
                            //save the reset fcnt for ABP (relaxed seqno checking)
                            if (fcntup == 1 && String.IsNullOrEmpty(loraDeviceInfo.AppEUI))
                            {
                                _ = loraDeviceInfo.HubSender.UpdateFcntAsync(fcntup, 0, true);
                            }

                            validFrameCounter = true;
                            Logger.Log(loraDeviceInfo.DevEUI, $"valid frame counter, msg: {fcntup} server: {loraDeviceInfo.FCntUp}", Logger.LoggingLevel.Info);



                            byte[] decryptedMessage = null;
                            try
                            {
                                decryptedMessage = loraMessage.DecryptPayload(loraDeviceInfo.AppSKey);
                            }
                            catch (Exception ex)
                            {
                                Logger.Log(loraDeviceInfo.DevEUI, $"failed to decrypt message: {ex.Message}", Logger.LoggingLevel.Error);
                            }



                            Rxpk rxPk = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0];


                            dynamic fullPayload = JObject.FromObject(rxPk);

                            string jsonDataPayload = "";

                            uint fportUp = (uint)((LoRaPayloadStandardData)loraMessage.payloadMessage).fport[0];

                            fullPayload.port = fportUp;

                            fullPayload.fcnt = fcntup;

                            if (String.IsNullOrEmpty(loraDeviceInfo.SensorDecoder))
                            {
                                jsonDataPayload  = Convert.ToBase64String(decryptedMessage);
                                fullPayload.data = jsonDataPayload;
                            }
                            else
                            {
                                Logger.Log(loraDeviceInfo.DevEUI, $"decoding with: {loraDeviceInfo.SensorDecoder} port: {fportUp}", Logger.LoggingLevel.Info);
                                jsonDataPayload  = LoraDecoders.DecodeMessage(decryptedMessage, fportUp, loraDeviceInfo.SensorDecoder);
                                fullPayload.data = JObject.Parse(jsonDataPayload);
                            }


                            fullPayload.eui       = loraDeviceInfo.DevEUI;
                            fullPayload.gatewayid = GatewayID;

                            //todo check what the other ts are if milliseconds or seconds
                            fullPayload.edgets = (long)((startTimeProcessing - new DateTime(1970, 1, 1)).TotalMilliseconds);


                            string iotHubMsg = fullPayload.ToString(Newtonsoft.Json.Formatting.None);


                            await loraDeviceInfo.HubSender.SendMessageAsync(iotHubMsg);

                            Logger.Log(loraDeviceInfo.DevEUI, $"sent message '{jsonDataPayload}' to hub", Logger.LoggingLevel.Info);

                            loraDeviceInfo.FCntUp = fcntup;
                        }
                        else
                        {
                            validFrameCounter = false;
                            Logger.Log(loraDeviceInfo.DevEUI, $"invalid frame counter, msg: {fcntup} server: {loraDeviceInfo.FCntUp}", Logger.LoggingLevel.Info);
                        }

                        //start checking for new c2d message, we do it even if the fcnt is invalid so we support replying to the ConfirmedDataUp
                        //todo ronnie should we wait up to 900 msec?
                        c2dMsg = await loraDeviceInfo.HubSender.ReceiveAsync(TimeSpan.FromMilliseconds(20));

                        byte[] bytesC2dMsg = null;
                        byte[] fport       = null;
                        byte[] fctl        = new byte[1] {
                            32
                        };

                        //check if we got a c2d message to be added in the ack message and preprare the message
                        if (c2dMsg != null)
                        {
                            //check if there is another message
                            var secondC2dMsg = await loraDeviceInfo.HubSender.ReceiveAsync(TimeSpan.FromMilliseconds(20));

                            if (secondC2dMsg != null)
                            {
                                //put it back to the queue for the next pickup
                                _ = loraDeviceInfo.HubSender.AbandonAsync(secondC2dMsg);

                                //set the fpending flag so the lora device will call us back for the next message
                                fctl = new byte[1] {
                                    48
                                };
                            }

                            bytesC2dMsg = c2dMsg.GetBytes();


                            fport = new byte[1] {
                                1
                            };

                            if (bytesC2dMsg != null)
                            {
                                Logger.Log(loraDeviceInfo.DevEUI, $"C2D message: {Encoding.UTF8.GetString(bytesC2dMsg)}", Logger.LoggingLevel.Info);
                            }

                            //todo ronnie implement a better max payload size by datarate
                            //cut to the max payload of lora for any EU datarate
                            if (bytesC2dMsg.Length > 51)
                            {
                                Array.Resize(ref bytesC2dMsg, 51);
                            }

                            Array.Reverse(bytesC2dMsg);
                        }


                        //if confirmation or cloud to device msg send down the message
                        if (loraMessage.loRaMessageType == LoRaMessageType.ConfirmedDataUp || c2dMsg != null)
                        {
                            //check if we are not too late for the 1 and 2 window
                            if (((DateTime.UtcNow - startTimeProcessing) <= TimeSpan.FromMilliseconds(1900)))
                            {
                                //increase the fcnt down and save it to iot hub twins
                                loraDeviceInfo.FCntDown++;

                                Logger.Log(loraDeviceInfo.DevEUI, $"down frame counter: {loraDeviceInfo.FCntDown}", Logger.LoggingLevel.Info);


                                //Saving both fcnts to twins
                                _ = loraDeviceInfo.HubSender.UpdateFcntAsync(loraDeviceInfo.FCntUp, loraDeviceInfo.FCntDown);

                                var _datr = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].datr;

                                uint _rfch = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].rfch;

                                double _freq = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].freq;

                                uint txDelay = 0;


                                //if we are already longer than 900 mssecond move to the 2 second window
                                //uncomment to force second windows usage
                                //Thread.Sleep(901);
                                if ((DateTime.UtcNow - startTimeProcessing) > TimeSpan.FromMilliseconds(900))
                                {
                                    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("RX2_DATR")))
                                    {
                                        Logger.Log(loraDeviceInfo.DevEUI, $"using standard second receive windows", Logger.LoggingLevel.Info);

                                        //using EU fix DR for RX2
                                        _freq = 869.525;
                                        _datr = "SF12BW125";
                                    }
                                    //if specific twins are set, specify second channel to be as specified
                                    else
                                    {
                                        _freq = double.Parse(Environment.GetEnvironmentVariable("RX2_FREQ"));
                                        _datr = Environment.GetEnvironmentVariable("RX2_DATR");
                                        Logger.Log(loraDeviceInfo.DevEUI, $"using custom DR second receive windows freq : {_freq}, datr:{_datr}", Logger.LoggingLevel.Info);
                                    }

                                    txDelay = 1000000;
                                }


                                long _tmst = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].tmst + txDelay;


                                Byte[] devAddrCorrect = new byte[4];
                                Array.Copy(loraMessage.payloadMessage.devAddr, devAddrCorrect, 4);
                                Array.Reverse(devAddrCorrect);

                                //todo mik check what is the A0
                                LoRaPayloadStandardData ackLoRaMessage = new LoRaPayloadStandardData(StringToByteArray("A0"),
                                                                                                     devAddrCorrect,
                                                                                                     fctl,
                                                                                                     BitConverter.GetBytes(loraDeviceInfo.FCntDown),
                                                                                                     null,
                                                                                                     fport,
                                                                                                     bytesC2dMsg,
                                                                                                     1);


                                ackLoRaMessage.PerformEncryption(loraDeviceInfo.AppSKey);
                                ackLoRaMessage.SetMic(loraDeviceInfo.NwkSKey);



                                byte[] rndToken = new byte[2];
                                Random rnd      = new Random();
                                rnd.NextBytes(rndToken);

                                //todo ronnie should check the device twin preference if using confirmed or unconfirmed down
                                LoRaMessage ackMessage = new LoRaMessage(ackLoRaMessage, LoRaMessageType.ConfirmedDataDown, rndToken, _datr, 0, _freq, _tmst);

                                udpMsgForPktForwarder = ackMessage.physicalPayload.GetMessage();


                                //confirm the message to iot hub only if we are in time for a delivery
                                if (c2dMsg != null)
                                {
                                    _ = loraDeviceInfo.HubSender.CompleteAsync(c2dMsg);
                                    Logger.Log(loraDeviceInfo.DevEUI, $"complete the c2d msg to IoT Hub", Logger.LoggingLevel.Info);
                                }
                            }
                            else
                            {
                                PhysicalPayload pushAck = new PhysicalPayload(loraMessage.physicalPayload.token, PhysicalIdentifier.PUSH_ACK, null);
                                udpMsgForPktForwarder = pushAck.GetMessage();


                                _ = loraDeviceInfo.HubSender.UpdateFcntAsync(loraDeviceInfo.FCntUp, null);


                                //put back the c2d message to the queue for the next round
                                _ = loraDeviceInfo.HubSender.AbandonAsync(c2dMsg);

                                Logger.Log(loraDeviceInfo.DevEUI, $"too late for down message, sending only ACK to gateway", Logger.LoggingLevel.Info);
                            }
                        }
                        //No ack requested and no c2d message we send the udp ack only to the gateway
                        else if (loraMessage.loRaMessageType == LoRaMessageType.UnconfirmedDataUp && c2dMsg == null)
                        {
                            PhysicalPayload pushAck = new PhysicalPayload(loraMessage.physicalPayload.token, PhysicalIdentifier.PUSH_ACK, null);
                            udpMsgForPktForwarder = pushAck.GetMessage();



                            if (validFrameCounter)
                            {
                                _ = loraDeviceInfo.HubSender.UpdateFcntAsync(loraDeviceInfo.FCntUp, null);
                            }
                        }
                    }
                    else
                    {
                        Logger.Log(loraDeviceInfo.DevEUI, $"with devAddr {devAddr} check MIC failed. Device will be ignored from now on", Logger.LoggingLevel.Info);
                        loraDeviceInfo.IsOurDevice = false;
                    }
                }
                else
                {
                    Logger.Log(loraDeviceInfo.DevEUI, $"ignore message because is not linked to this GatewayID", Logger.LoggingLevel.Info);
                }
            }
            else
            {
                Logger.Log(devAddr, $"device with devAddr {devAddr} is not our device, ignore message", Logger.LoggingLevel.Info);
            }

            Logger.Log(loraDeviceInfo.DevEUI, $"processing time: {DateTime.UtcNow - startTimeProcessing}", Logger.LoggingLevel.Info);

            return(udpMsgForPktForwarder);
        }
        private async Task <byte[]> ProcessJoinRequest(LoRaMessage loraMessage)
        {
            byte[] udpMsgForPktForwarder = new Byte[0];

            LoraDeviceInfo joinLoraDeviceInfo;

            var joinReq = (LoRaPayloadJoinRequest)loraMessage.payloadMessage;

            Array.Reverse(joinReq.devEUI);
            Array.Reverse(joinReq.appEUI);


            string devEui   = BitConverter.ToString(joinReq.devEUI).Replace("-", "");
            string devNonce = BitConverter.ToString(joinReq.devNonce).Replace("-", "");

            Logger.Log(devEui, $"join request received", Logger.LoggingLevel.Info);

            //checking if this devnonce was already processed or the deveui was already refused
            Cache.TryGetValue(devEui, out joinLoraDeviceInfo);


            //we have a join request in the cache
            if (joinLoraDeviceInfo != null)
            {
                //it is not our device so ingore the join
                if (!joinLoraDeviceInfo.IsOurDevice)
                {
                    Logger.Log(devEui, $"join request refused the device is not ours", Logger.LoggingLevel.Info);
                    return(null);
                }
                //is our device but the join was not valid
                else if (!joinLoraDeviceInfo.IsJoinValid)
                {
                    //if the devNonce is equal to the current it is a potential replay attck
                    if (joinLoraDeviceInfo.DevNonce == devNonce)
                    {
                        Logger.Log(devEui, $"join request refused devNonce already used", Logger.LoggingLevel.Info);
                        return(null);
                    }

                    //Check if the device is trying to join through the wrong gateway
                    if (!String.IsNullOrEmpty(joinLoraDeviceInfo.GatewayID) && joinLoraDeviceInfo.GatewayID.ToUpper() != GatewayID.ToUpper())
                    {
                        Logger.Log(devEui, $"trying to join not through its linked gateway, ignoring join request", Logger.LoggingLevel.Info);
                        return(null);
                    }
                }
            }



            joinLoraDeviceInfo = await LoraDeviceInfoManager.PerformOTAAAsync(GatewayID, devEui, BitConverter.ToString(joinReq.appEUI).Replace("-", ""), devNonce);

            if (joinLoraDeviceInfo.IsJoinValid)
            {
                byte[] appNonce = StringToByteArray(joinLoraDeviceInfo.AppNonce);

                byte[] netId = StringToByteArray(joinLoraDeviceInfo.NetId);



                byte[] devAddr = StringToByteArray(joinLoraDeviceInfo.DevAddr);

                string appKey = joinLoraDeviceInfo.AppKey;

                Array.Reverse(netId);
                Array.Reverse(appNonce);

                LoRaPayloadJoinAccept loRaPayloadJoinAccept = new LoRaPayloadJoinAccept(
                    //NETID 0 / 1 is default test
                    BitConverter.ToString(netId).Replace("-", ""),
                    //todo add app key management
                    appKey,
                    //todo add device address management
                    devAddr,
                    appNonce
                    );

                var _datr = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].datr;

                uint _rfch = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].rfch;

                double _freq = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].freq;
                //set tmst for the normal case
                long _tmst = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].tmst + 5000000;

                //uncomment to force second windows usage
                //Thread.Sleep(4600-(int)(DateTime.Now - startTimeProcessing).TotalMilliseconds);
                //in this case it's too late, we need to break
                if ((DateTime.UtcNow - startTimeProcessing) > TimeSpan.FromMilliseconds(6000))
                {
                    Logger.Log(devEui, $"processing of the join request took too long, sending no message", Logger.LoggingLevel.Info);
                    var physicalResponse = new PhysicalPayload(loraMessage.physicalPayload.token, PhysicalIdentifier.PULL_RESP, null);

                    return(physicalResponse.GetMessage());
                }
                //in this case the second join windows must be used
                else if ((DateTime.UtcNow - startTimeProcessing) > TimeSpan.FromMilliseconds(4500))
                {
                    Logger.Log(devEui, $"processing of the join request took too long, using second join accept receive window", Logger.LoggingLevel.Info);
                    _tmst = ((UplinkPktFwdMessage)loraMessage.loraMetadata.fullPayload).rxpk[0].tmst + 6000000;
                    if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("RX2_DATR")))
                    {
                        Logger.Log(devEui, $"using standard second receive windows for join request", Logger.LoggingLevel.Info);

                        //using EU fix DR for RX2
                        _freq = 869.525;
                        _datr = "SF12BW125";
                    }
                    //if specific twins are set, specify second channel to be as specified
                    else
                    {
                        Logger.Log(devEui, $"using custom DR second receive windows for join request", Logger.LoggingLevel.Info);

                        _freq = double.Parse(Environment.GetEnvironmentVariable("RX2_FREQ"));
                        _datr = Environment.GetEnvironmentVariable("RX2_DATR");
                    }
                }


                LoRaMessage joinAcceptMessage = new LoRaMessage(loRaPayloadJoinAccept, LoRaMessageType.JoinAccept, loraMessage.physicalPayload.token, _datr, 0, _freq, _tmst);

                udpMsgForPktForwarder = joinAcceptMessage.physicalPayload.GetMessage();


                joinLoraDeviceInfo.HubSender = new IoTHubSender(joinLoraDeviceInfo.DevEUI, joinLoraDeviceInfo.PrimaryKey);

                //open the connection to iot hub without waiting for perf optimization in case of the device start sending a msg just after join request
                _ = joinLoraDeviceInfo.HubSender.OpenAsync();

                //join request resets the frame counters
                joinLoraDeviceInfo.FCntUp   = 0;
                joinLoraDeviceInfo.FCntDown = 0;


                //update the frame counter on the server
                _ = joinLoraDeviceInfo.HubSender.UpdateFcntAsync(joinLoraDeviceInfo.FCntUp, joinLoraDeviceInfo.FCntDown);



                //add to cache for processing normal messages. This awoids one additional call to the server.
                Cache.AddToCache(joinLoraDeviceInfo.DevAddr, joinLoraDeviceInfo);

                Logger.Log(devEui, $"join accept sent", Logger.LoggingLevel.Info);
            }

            //add to cache to avoid replay attack, btw server side does the check too.
            Cache.AddToCache(devEui, joinLoraDeviceInfo);

            return(udpMsgForPktForwarder);
        }
Пример #13
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);
            LoRaMessage joinRequestMessage = new LoRaMessage(physicalUpstreamPyld.Concat(joinRequestInput).ToArray());

            if (joinRequestMessage.loRaMessageType != LoRaMessageType.JoinRequest)
            {
                Console.WriteLine("Join Request type was not parsed correclty");
            }
            byte[] joinRequestAppKey = new byte[16]
            {
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
            };
            var joinRequestBool = joinRequestMessage.CheckMic(BitConverter.ToString(joinRequestAppKey).Replace("-", ""));

            if (!joinRequestBool)
            {
                Console.WriteLine("Join Request type was not computed correclty");
            }

            byte[] joinRequestAppEui = new byte[8]
            {
                1, 2, 3, 4, 1, 2, 3, 4
            };

            byte[] joinRequestDevEUI = new byte[8]
            {
                2, 3, 4, 5, 2, 3, 4, 5
            };
            byte[] joinRequestDevNonce = new byte[2]
            {
                16, 45
            };

            Array.Reverse(joinRequestAppEui);
            Array.Reverse(joinRequestDevEUI);
            Array.Reverse(joinRequestDevNonce);
            LoRaPayloadJoinRequest joinRequestMessagePayload = ((LoRaPayloadJoinRequest)joinRequestMessage.payloadMessage);

            Assert.True(joinRequestMessagePayload.appEUI.SequenceEqual(joinRequestAppEui));
            Assert.True(joinRequestMessagePayload.devEUI.SequenceEqual(joinRequestDevEUI));
            Assert.True(joinRequestMessagePayload.devNonce.SequenceEqual(joinRequestDevNonce));
        }
Пример #14
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;
            LoRaMessage joinRequestMessage = new LoRaMessage(physicalUpstreamPyld.Concat(joinRequestInput).ToArray());

            var joinReq = (LoRaPayloadJoinRequest)joinRequestMessage.payloadMessage;

            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(new byte[1] {
                0x01
            }, appNonce, netId, joinReq.devNonce, appKey);

            Assert.Equal(key, new byte[16] {
                223, 83, 195, 95, 48, 52, 204, 206, 208, 255, 53, 76, 112, 222, 4, 223
            }
                         );
        }