// Performs join public async Task <bool> JoinAsync(SimulatedPacketForwarder packetForwarder, int timeoutInMs = 30 * 1000) { if (this.IsJoined) { return(true); } var token = await RandomTokenGenerator.GetTokenAsync(); this.LastPayload = new PhysicalPayload(token, PhysicalIdentifier.PUSH_DATA, null); var header = this.LastPayload.GetSyncHeader(packetForwarder.MacAddress); var joinRequest = this.CreateJoinRequest(); var joinCompleted = new SemaphoreSlim(0); var joinRequestUplinkMessage = joinRequest.SerializeUplink(this.AppKey); packetForwarder.SubscribeOnce((response) => { // handle join var txpk = Txpk.CreateTxpk(response, this.LoRaDevice.AppKey); byte[] convertedInputMessage = Convert.FromBase64String(txpk.Data); var joinAccept = new LoRaPayloadJoinAccept(convertedInputMessage, this.AppKey); var result = this.HandleJoinAccept(joinAccept); // may need to return bool and only release if true. joinCompleted.Release(); return(result); }); await packetForwarder.SendAsync(header, joinRequest.GetByteMessage()); TestLogger.Log($"[{this.LoRaDevice.DeviceID}] Join request: {BitConverter.ToString(header).Replace("-", string.Empty)}"); #if DEBUG if (System.Diagnostics.Debugger.IsAttached) { timeoutInMs = 60 * 1000; } #endif return(await joinCompleted.WaitAsync(timeoutInMs)); }
async Task RunUdpListener() { while (true) { UdpReceiveResult receivedResults = await udpClient.ReceiveAsync(); // Logger.LogAlways($"UDP message received ({receivedResults.Buffer.Length} bytes) from port: {receivedResults.RemoteEndPoint.Port}"); // If 4, it may mean we received a confirmation if (receivedResults.Buffer.Length >= 4) { // get the token byte[] token = new byte[2]; token[0] = receivedResults.Buffer[1]; token[1] = receivedResults.Buffer[2]; // identifier var identifier = (PhysicalIdentifier)receivedResults.Buffer[3]; // Find the device try { foreach (var dev in this.listDevices) { if (dev.LastPayload != null) { if ((dev.LastPayload.Token[0] == token[0]) && (dev.LastPayload.Token[1] == token[1])) { string device = dev.LoRaDevice.DevEUI; // check last operation and answer // Is is a simple push data? if (identifier == PhysicalIdentifier.PUSH_ACK) { if (dev.LastPayload.Identifier == PhysicalIdentifier.PUSH_DATA) { Logger.Log(device, $"PUSH_DATA confirmation receiveced from NetworkServer", LogLevel.Information); } else { Logger.Log(device, $"PUSH_ACK confirmation receiveced from ", LogLevel.Information); } } else if (identifier == PhysicalIdentifier.PULL_RESP) { // we asked something, we get an answer var txpk = Txpk.CreateTxpk(receivedResults.Buffer, dev.LoRaDevice.AppKey); LoRaPayload.TryCreateLoRaPayloadForSimulator(txpk, dev.LoRaDevice.AppKey, out LoRaPayload loraMessage); // Check if the device is not joined, then it is maybe the answer if ((loraMessage.LoRaMessageType == LoRaMessageType.JoinAccept) && (dev.LoRaDevice.DevAddr == string.Empty)) { Logger.Log(device, $"Received join accept", LogLevel.Information); var payload = (LoRaPayloadJoinAccept)loraMessage; // TODO Need to check if the time is not passed // Calculate the keys var netid = payload.NetID.ToArray(); Array.Reverse(netid); var appNonce = payload.AppNonce.ToArray(); Array.Reverse(appNonce); var devNonce = dev.LoRaDevice.GetDevNonce(); Array.Reverse(devNonce); var appSKey = payload.CalculateKey(LoRaPayloadKeyType.AppSKey, appNonce, netid, devNonce, dev.LoRaDevice.GetAppKey()); dev.LoRaDevice.AppSKey = BitConverter.ToString(appSKey).Replace("-", ""); var nwkSKey = payload.CalculateKey(LoRaPayloadKeyType.NwkSkey, appNonce, netid, devNonce, dev.LoRaDevice.GetAppKey()); dev.LoRaDevice.NwkSKey = BitConverter.ToString(nwkSKey).Replace("-", ""); dev.LoRaDevice.NetId = BitConverter.ToString(netid).Replace("-", ""); dev.LoRaDevice.AppNonce = BitConverter.ToString(appNonce).Replace("-", ""); var devAdd = payload.DevAddr; // Array.Reverse(devAdd); dev.LoRaDevice.DevAddr = BitConverter.ToString(devAdd.ToArray()).Replace("-", ""); } } } } } } catch (Exception ex) { Logger.Log($"Something when wrong: {ex.Message}", LogLevel.Error); } // if (receivedResults.Buffer[3] == (byte)PhysicalIdentifier.PUSH_ACK) // { // //Bingo // Logger.LogAlways($"Confirmation receiveced"); // } } // try // { // // TODO: process the message not really implemented yet // MessageProcessor messageProcessor = new MessageProcessor(); // _ = messageProcessor.processMessage(receivedResults.Buffer); // } // catch (Exception ex) // { // Logger.Log($"Error processing the message {ex.Message}", LogLevel.Error); // } } }