Exemplo n.º 1
0
        public LoRaPayloadJoinRequest CreateJoinRequest()
        {
            byte[] devNonce = new byte[2];
            if (string.IsNullOrEmpty(this.DevNonce) || (!this.isFirstJoinRequest))
            {
                Random random = new Random();
                // DevNonce[0] = 0xC8; DevNonce[1] = 0x86;
                random.NextBytes(devNonce);
                this.DevNonce = BitConverter.ToString(devNonce).Replace("-", string.Empty);
                Array.Reverse(devNonce);
                this.isFirstJoinRequest = false;
            }
            else
            {
                devNonce = ConversionHelper.StringToByteArray(this.DevNonce);
                Array.Reverse(devNonce);
            }

            TestLogger.Log($"[{this.LoRaDevice.DeviceID}] Join request sent DevNonce: {BitConverter.ToString(devNonce).Replace("-", string.Empty)} / {this.DevNonce}");
            var joinRequest = new LoRaPayloadJoinRequest(this.LoRaDevice.AppEUI, this.LoRaDevice.DeviceID, devNonce);

            joinRequest.SetMic(this.LoRaDevice.AppKey);

            return(joinRequest);
        }
        public byte[] GetJoinRequest()
        {
            // create a join request
            var AppEUI = LoRaTools.Utils.ConversionHelper.ByteArrayToString(this.LoRaDevice.GetAppEUI());
            var DevEUI = LoRaTools.Utils.ConversionHelper.ByteArrayToString(this.LoRaDevice.GetDevEUI());

            byte[] DevNonce = new byte[2];
            if ((this.LoRaDevice.DevNonce == "") || (!this.isFirstJoinRequest))
            {
                Random random = new Random();
                // DevNonce[0] = 0xC8; DevNonce[1] = 0x86;
                random.NextBytes(DevNonce);
                this.LoRaDevice.DevNonce = BitConverter.ToString(DevNonce).Replace("-", "");
                Array.Reverse(DevNonce);
                this.isFirstJoinRequest = false;
            }
            else
            {
                DevNonce = this.LoRaDevice.GetDevNonce();
                Array.Reverse(DevNonce);
            }

            Logger.LogAlways(this.LoRaDevice.DevEUI, $"Join request sent DevNonce: {BitConverter.ToString(DevNonce).Replace("-","")}");
            var join = new LoRaPayloadJoinRequest(AppEUI, DevEUI, DevNonce);

            join.SetMic(this.LoRaDevice.AppKey);

            return(join.GetByteMessage());
        }
Exemplo n.º 3
0
        public void When_Creating_Join_Request_Recreating_Should_Pass_Mic_Check(
            string appEUIText,
            string devEUIText,
            string appKeyText,
            string devNonceText)
        {
            var wrongAppKeyText = "00000000000000000000000000003333";

            // create a join request
            var devNonce = ConversionHelper.StringToByteArray(devNonceText);

            Array.Reverse(devNonce);

            var join = new LoRaPayloadJoinRequest(appEUIText, devEUIText, devNonce);

            Assert.Equal(appEUIText, join.GetAppEUIAsString());
            Assert.Equal(devEUIText, join.GetDevEUIAsString());
            var uplinkMessage = join.SerializeUplink(appKeyText);

            Assert.False(join.CheckMic(wrongAppKeyText), "Mic check with wrong appKey should not pass");
            Assert.True(join.CheckMic(appKeyText), "Mic check should work after setting it");

            var rxpk = uplinkMessage.Rxpk[0];

            Assert.True(LoRaPayload.TryCreateLoRaPayload(rxpk, out LoRaPayload parsedLoRaPayload));
            Assert.IsType <LoRaPayloadJoinRequest>(parsedLoRaPayload);
            var parsedLoRaJoinRequest = (LoRaPayloadJoinRequest)parsedLoRaPayload;

            Assert.True(parsedLoRaPayload.CheckMic(appKeyText), "Parsed join request should pass mic check with correct appKey");
            Assert.False(parsedLoRaJoinRequest.CheckMic(wrongAppKeyText), "Parsed join request should not pass mic check with wrong appKey");
        }
Exemplo n.º 4
0
        public byte[] GetJoinRequest()
        {
            //create a join request
            byte[] AppEUI = LoRaDevice.GetAppEUI();
            Array.Reverse(AppEUI);
            byte[] DevEUI = LoRaDevice.GetDevEUI();
            Array.Reverse(DevEUI);

            byte[] DevNonce = new byte[2];
            if ((LoRaDevice.DevNonce == "") || (!isFirstJoinRequest))
            {
                Random random = new Random();
                // DevNonce[0] = 0xC8; DevNonce[1] = 0x86;
                random.NextBytes(DevNonce);
                LoRaDevice.DevNonce = BitConverter.ToString(DevNonce).Replace("-", "");
                Array.Reverse(DevNonce);
                isFirstJoinRequest = false;
            }
            else
            {
                DevNonce = LoRaDevice.GetDevNonce();
                Array.Reverse(DevNonce);
            }

            Logger.Log(LoRaDevice.DevEUI, $"Join request sent DevNonce: {BitConverter.ToString(DevNonce).Replace("-","")}", Logger.LoggingLevel.Always);
            var join = new LoRaPayloadJoinRequest(AppEUI, DevEUI, DevNonce);

            join.SetMic(LoRaDevice.AppKey);

            return(join.GetByteMessage());
        }
Exemplo n.º 5
0
        byte[] CreateJoinRequest()
        {
            //create a join request
            byte[] AppEUI = ConversionHelper.StringToByteArray(LoRaDevice.AppEUI);
            Array.Reverse(AppEUI);
            byte[] DevEUI = ConversionHelper.StringToByteArray(LoRaDevice.DeviceID);
            Array.Reverse(DevEUI);

            byte[] devNonce = new byte[2];
            if ((string.IsNullOrEmpty(this.DevNonce)) || (!isFirstJoinRequest))
            {
                Random random = new Random();
                // DevNonce[0] = 0xC8; DevNonce[1] = 0x86;
                random.NextBytes(devNonce);
                this.DevNonce = BitConverter.ToString(devNonce).Replace("-", "");
                Array.Reverse(devNonce);
                isFirstJoinRequest = false;
            }
            else
            {
                devNonce = ConversionHelper.StringToByteArray(this.DevNonce);
                Array.Reverse(devNonce);
            }

            TestLogger.Log($"[{LoRaDevice.DeviceID}] Join request sent DevNonce: {BitConverter.ToString(devNonce).Replace("-","")} / {this.DevNonce}");
            var join = new LoRaPayloadJoinRequest(AppEUI, DevEUI, devNonce);

            join.SetMic(this.LoRaDevice.AppKey);

            return(join.GetByteMessage());
        }
Exemplo n.º 6
0
        public void When_Creating_Join_Request_From_Bytes_Should_Pass_Mic_Check(
            string appEUI,
            string devEUI,
            string appKey)
        {
            var rawJoinRequestBytes = new byte[] { 0, 4, 0, 0, 0, 0, 16, 229, 251, 4, 0, 0, 0, 0, 16, 229, 251, 254, 228, 147, 93, 188, 238 };
            var messageType         = rawJoinRequestBytes[0];

            Assert.Equal((int)LoRaMessageType.JoinRequest, messageType);
            var joinRequest = new LoRaPayloadJoinRequest(rawJoinRequestBytes);

            Assert.NotNull(joinRequest);
            Assert.Equal(appEUI, joinRequest.GetAppEUIAsString());
            Assert.Equal(devEUI, joinRequest.GetDevEUIAsString());
            Assert.True(joinRequest.CheckMic(appKey));
        }
        public ConcentratorDeduplicationTest()
        {
            this.cache             = new MemoryCache(new MemoryCacheOptions());
            this.connectionManager = new LoRaDeviceClientConnectionManager(this.cache, NullLogger <LoRaDeviceClientConnectionManager> .Instance);

            this.simulatedABPDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(0));
            this.dataPayload        = this.simulatedABPDevice.CreateConfirmedDataUpMessage("payload");
            this.dataRequest        = WaitableLoRaRequest.Create(this.dataPayload);
            this.loRaDevice         = new LoRaDevice(this.simulatedABPDevice.DevAddr, this.simulatedABPDevice.DevEUI, this.connectionManager);

            this.simulatedOTAADevice = new SimulatedDevice(TestDeviceInfo.CreateOTAADevice(0));
            this.joinPayload         = this.simulatedOTAADevice.CreateJoinRequest(appkey: this.simulatedOTAADevice.AppKey);
            this.joinRequest         = WaitableLoRaRequest.Create(this.joinPayload);
            this.joinRequest.SetPayload(this.joinPayload);

            this.concentratorDeduplication = new ConcentratorDeduplication(
                this.cache,
                NullLogger <IConcentratorDeduplication> .Instance);
        }
Exemplo n.º 8
0
        public void JoinRequest_Should_Succeed_Mic_Check()
        {
            var appEUIText  = "0005100000000004";
            var appEUIBytes = ConversionHelper.StringToByteArray(appEUIText);

            var devEUIText  = "0005100000000004";
            var devEUIBytes = ConversionHelper.StringToByteArray(devEUIText);

            var devNonceText  = "ABCD";
            var devNonceBytes = ConversionHelper.StringToByteArray(devNonceText);

            var appKey = "00000000000000000005100000000004";

            var joinRequest = new LoRaPayloadJoinRequest(appEUIText, devEUIText, devNonceBytes);

            joinRequest.SetMic(appKey);
            Assert.True(joinRequest.CheckMic(appKey));
            Assert.True(joinRequest.CheckMic(appKey)); // ensure multiple calls work!

            var rxpk = new LoRaTools.LoRaPhysical.Rxpk()
            {
                Chan = 7,
                Rfch = 1,
                Freq = 903.700000,
                Stat = 1,
                Modu = "LORA",
                Datr = "SF10BW125",
                Codr = "4/5",
                Rssi = -17,
                Lsnr = 12.0f,
            };

            var data = joinRequest.GetByteMessage();

            rxpk.Data = Convert.ToBase64String(data);
            rxpk.Size = (uint)data.Length;

            byte[] decodedJoinRequestBytes = Convert.FromBase64String(rxpk.Data);
            var    decodedJoinRequest      = new LoRaTools.LoRaMessage.LoRaPayloadJoinRequest(decodedJoinRequestBytes);

            Assert.True(decodedJoinRequest.CheckMic(appKey));
        }
Exemplo n.º 9
0
        private static void TestRxpk(Rxpk rxpk)
        {
            Assert.True(LoRaPayload.TryCreateLoRaPayload(rxpk, out LoRaPayload loRaPayload));
            Assert.Equal(LoRaMessageType.JoinRequest, loRaPayload.LoRaMessageType);
            LoRaPayloadJoinRequest joinRequestMessage = (LoRaPayloadJoinRequest)loRaPayload;

            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(ConversionHelper.ByteArrayToString(joinRequestAppKey));

            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);
            Assert.True(joinRequestMessage.AppEUI.ToArray().SequenceEqual(joinRequestAppEui));
            Assert.True(joinRequestMessage.DevEUI.ToArray().SequenceEqual(joinRequestDevEUI));
            Assert.True(joinRequestMessage.DevNonce.ToArray().SequenceEqual(joinRequestDevNonce));
        }
Exemplo n.º 10
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));
        }
        /// <summary>
        /// Process OTAA join request
        /// </summary>
        async Task <DownlinkPktFwdMessage> ProcessJoinRequestAsync(Rxpk rxpk, LoRaPayloadJoinRequest joinReq, DateTime startTimeProcessing)
        {
            var timeWatcher = new LoRaOperationTimeWatcher(this.loraRegion, startTimeProcessing);

            using (var processLogger = new ProcessLogger(timeWatcher))
            {
                byte[] udpMsgForPktForwarder = new byte[0];

                var devEUI = joinReq.GetDevEUIAsString();
                var appEUI = joinReq.GetAppEUIAsString();

                // set context to logger
                processLogger.SetDevEUI(devEUI);

                var devNonce = joinReq.GetDevNonceAsString();
                Logger.Log(devEUI, $"join request received", LogLevel.Information);

                var loRaDevice = await this.deviceRegistry.GetDeviceForJoinRequestAsync(devEUI, appEUI, devNonce);

                if (loRaDevice == null)
                {
                    return(null);
                }

                if (string.IsNullOrEmpty(loRaDevice.AppKey))
                {
                    Logger.Log(loRaDevice.DevEUI, "join refused: missing AppKey for OTAA device", LogLevel.Error);
                    return(null);
                }

                if (loRaDevice.AppEUI != appEUI)
                {
                    Logger.Log(devEUI, "join refused: AppEUI for OTAA does not match device", LogLevel.Error);
                    return(null);
                }

                if (!joinReq.CheckMic(loRaDevice.AppKey))
                {
                    Logger.Log(devEUI, "join refused: invalid MIC", LogLevel.Error);
                    return(null);
                }

                // Make sure that is a new request and not a replay
                if (!string.IsNullOrEmpty(loRaDevice.DevNonce) && loRaDevice.DevNonce == devNonce)
                {
                    Logger.Log(devEUI, "join refused: DevNonce already used by this device", LogLevel.Information);
                    loRaDevice.IsOurDevice = false;
                    return(null);
                }

                // Check that the device is joining through the linked gateway and not another
                if (!string.IsNullOrEmpty(loRaDevice.GatewayID) && !string.Equals(loRaDevice.GatewayID, this.configuration.GatewayID, StringComparison.InvariantCultureIgnoreCase))
                {
                    Logger.Log(devEUI, $"join refused: trying to join not through its linked gateway, ignoring join request", LogLevel.Information);
                    loRaDevice.IsOurDevice = false;
                    return(null);
                }

                var netIdBytes = BitConverter.GetBytes(this.configuration.NetId);
                var netId      = new byte[3]
                {
                    netIdBytes[0],
                    netIdBytes[1],
                    netIdBytes[2]
                };
                var appNonce      = OTAAKeysGenerator.GetAppNonce();
                var appNonceBytes = LoRaTools.Utils.ConversionHelper.StringToByteArray(appNonce);
                var appKeyBytes   = LoRaTools.Utils.ConversionHelper.StringToByteArray(loRaDevice.AppKey);
                var appSKey       = OTAAKeysGenerator.CalculateKey(new byte[1] {
                    0x02
                }, appNonceBytes, netId, joinReq.DevNonce, appKeyBytes);
                var nwkSKey = OTAAKeysGenerator.CalculateKey(new byte[1] {
                    0x01
                }, appNonceBytes, netId, joinReq.DevNonce, appKeyBytes);
                var devAddr = OTAAKeysGenerator.GetNwkId(netId);

                if (!timeWatcher.InTimeForJoinAccept())
                {
                    // in this case it's too late, we need to break and avoid saving twins
                    Logger.Log(devEUI, $"join refused: processing of the join request took too long, sending no message", LogLevel.Information);
                    return(null);
                }

                Logger.Log(loRaDevice.DevEUI, $"saving join properties twins", LogLevel.Debug);
                var deviceUpdateSucceeded = await loRaDevice.UpdateAfterJoinAsync(devAddr, nwkSKey, appSKey, appNonce, devNonce, LoRaTools.Utils.ConversionHelper.ByteArrayToString(netId));

                Logger.Log(loRaDevice.DevEUI, $"done saving join properties twins", LogLevel.Debug);

                if (!deviceUpdateSucceeded)
                {
                    Logger.Log(devEUI, $"join refused: join request could not save twins", LogLevel.Error);
                    return(null);
                }

                var windowToUse = timeWatcher.ResolveJoinAcceptWindowToUse(loRaDevice);
                if (windowToUse == 0)
                {
                    Logger.Log(devEUI, $"join refused: processing of the join request took too long, sending no message", LogLevel.Information);
                    return(null);
                }

                double freq = 0;
                string datr = null;
                uint   tmst = 0;
                if (windowToUse == 1)
                {
                    try
                    {
                        datr = this.loraRegion.GetDownstreamDR(rxpk);
                        freq = this.loraRegion.GetDownstreamChannelFrequency(rxpk);
                    }
                    catch (RegionLimitException ex)
                    {
                        Logger.Log(devEUI, ex.ToString(), LogLevel.Error);
                    }

                    // set tmst for the normal case
                    tmst = rxpk.Tmst + this.loraRegion.Join_accept_delay1 * 1000000;
                }
                else
                {
                    Logger.Log(devEUI, $"processing of the join request took too long, using second join accept receive window", LogLevel.Information);
                    tmst = rxpk.Tmst + this.loraRegion.Join_accept_delay2 * 1000000;
                    if (string.IsNullOrEmpty(this.configuration.Rx2DataRate))
                    {
                        Logger.Log(devEUI, $"using standard second receive windows for join request", LogLevel.Information);
                        // using EU fix DR for RX2
                        freq = this.loraRegion.RX2DefaultReceiveWindows.frequency;
                        datr = this.loraRegion.DRtoConfiguration[RegionFactory.CurrentRegion.RX2DefaultReceiveWindows.dr].configuration;
                    }
                    else
                    {
                        Logger.Log(devEUI, $"using custom  second receive windows for join request", LogLevel.Information);
                        freq = this.configuration.Rx2DataFrequency;
                        datr = this.configuration.Rx2DataRate;
                    }
                }

                loRaDevice.IsOurDevice = true;
                this.deviceRegistry.UpdateDeviceAfterJoin(loRaDevice);

                // Build join accept downlink message
                Array.Reverse(netId);
                Array.Reverse(appNonceBytes);

                return(this.CreateJoinAcceptDownlinkMessage(
                           netId,
                           loRaDevice.AppKey,
                           devAddr,
                           appNonceBytes,
                           datr,
                           freq,
                           tmst,
                           devEUI));
            }
        }