public Task <LoRaADRTable> GetADRTable(DevEui devEUI)
 {
     lock (this.cache)
     {
         return(Task.FromResult(this.cache.Get <LoRaADRTable>(devEUI)));
     }
 }
        public DownlinkMessage(byte[] payload,
                               ulong xtime,
                               ReceiveWindow?rx1,
                               ReceiveWindow rx2,
                               DevEui devEui,
                               RxDelay lnsRxDelay,
                               LoRaDeviceClassType deviceClassType,
                               StationEui stationEui  = default,
                               uint?antennaPreference = null)
        {
            if (payload is null)
            {
                throw new ArgumentNullException(nameof(payload));
            }
            Data = payload;

            DevEui            = devEui;
            LnsRxDelay        = lnsRxDelay;
            DeviceClassType   = deviceClassType;
            AntennaPreference = antennaPreference;
            Rx1        = rx1;
            Rx2        = rx2;
            StationEui = stationEui;
            Xtime      = xtime;
        }
        internal async Task <LoRaADRResult> HandleADRRequest(DevEui devEUI, LoRaADRRequest request)
        {
            if (request == null)
            {
                return(null);
            }

            if (request.ClearCache)
            {
                _ = await this.adrManager.ResetAsync(devEUI);

                return(new LoRaADRResult());
            }

            var newEntry = new LoRaADRTableEntry
            {
                DevEUI    = devEUI,
                FCnt      = request.FCntUp,
                GatewayId = request.GatewayId,
                Snr       = request.RequiredSnr
            };

            if (request.PerformADRCalculation)
            {
                return(await this.adrManager.CalculateADRResultAndAddEntryAsync(devEUI, request.GatewayId, request.FCntUp, request.FCntDown, request.RequiredSnr, request.DataRate, request.MinTxPowerIndex, request.MaxDataRate, newEntry));
            }
            else
            {
                await this.adrManager.StoreADREntryAsync(newEntry);

                return(await this.adrManager.GetLastResultAsync(devEUI));
            }
        }
        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];
示例#5
0
        public async Task When_Direct_Method_Returns_Error_Code_Should_Forward_Status_Error()
        {
            var devEui           = new DevEui(0123456789);
            var preferredGateway = new LoRaDevicePreferredGateway("gateway1", 100);

            LoRaDevicePreferredGateway.SaveToCache(this.cacheStore, devEui, preferredGateway);

            this.serviceClient.Setup(x => x.InvokeDeviceMethodAsync("gateway1", LoraKeysManagerFacadeConstants.NetworkServerModuleId, It.IsNotNull <CloudToDeviceMethod>()))
            .ReturnsAsync(new CloudToDeviceMethodResult()
            {
                Status = (int)HttpStatusCode.BadRequest
            });

            var actual = await this.sendCloudToDeviceMessage.SendCloudToDeviceMessageImplementationAsync(
                devEui,
                new LoRaCloudToDeviceMessage()
            {
                Fport = TestPort,
            });

            Assert.IsType <ObjectResult>(actual);
            Assert.Equal((int)HttpStatusCode.BadRequest, ((ObjectResult)actual).StatusCode);

            this.serviceClient.VerifyAll();
            this.registryManager.VerifyAll();
        }
        public async Task When_Payload_Is_Empty_ExternalDecoder_Should_Be_Called_With_Empty_Payload()
        {
            var devEui       = new DevEui(0x12);
            var fport        = FramePorts.App8;
            var decodedValue = "{\"from\":\"http\"}";

            using var httpMessageHandler = new HttpMessageHandlerMock();
            httpMessageHandler.SetupHandler((r) =>
            {
                var queryDictionary = System.Web.HttpUtility.ParseQueryString(r.RequestUri.Query);
                Assert.Equal("0000000000000012", queryDictionary.Get("devEUI"));
                Assert.Equal(((byte)fport).ToString(CultureInfo.InvariantCulture), queryDictionary.Get("fport"));
                Assert.Empty(queryDictionary.Get("payload"));

                return(new HttpResponseMessage(System.Net.HttpStatusCode.OK)
                {
                    Content = new StringContent(decodedValue, Encoding.UTF8, "application/json"),
                });
            });

            using var httpClient = new HttpClient(httpMessageHandler);
            var target = new LoRaPayloadDecoder(httpClient);
            var result = await target.DecodeMessageAsync(devEui, Array.Empty <byte>(), fport, "http://test/decoder");

            var json = JsonConvert.SerializeObject(result.GetDecodedPayload());

            Assert.Equal(decodedValue, json);
        }
 public async Task UpdateADRTable(DevEui devEUI, LoRaADRTable table)
 {
     using var redisLock = new RedisLockWrapper(devEUI, this.redisCache);
     if (await redisLock.TakeLockAsync())
     {
         _ = await this.redisCache.StringSetAsync(GetEntryKey(devEUI), JsonConvert.SerializeObject(table));
     }
 }
示例#8
0
 public LoRaPayloadJoinRequest(JoinEui joinEui, DevEui devEui, DevNonce devNonce, Mic mic)
 {
     MHdr     = new MacHeader(MacMessageType.JoinRequest);
     AppEui   = joinEui;
     DevEUI   = devEui;
     DevNonce = devNonce;
     Mic      = mic;
 }
示例#9
0
            public void StationEui_Can_Be_Interpreted_As_Dev_Eui()
            {
                const ulong value      = 0x1a2b3c;
                var         devEui     = new DevEui(value);
                var         stationEui = new StationEui(value);

                Assert.Equal(devEui.ToString(), stationEui.ToString());
            }
        public Task <bool> Reset(DevEui devEUI)
        {
            lock (this.cache)
            {
                this.cache.Remove(devEUI);
            }

            return(Task.FromResult <bool>(true));
        }
示例#11
0
 public JoinRequestFrame(MacHeader mHdr, JoinEui joinEui, DevEui devEui, DevNonce devNonce, Mic mic, RadioMetadata radioMetadata)
 {
     MacHeader     = mHdr;
     JoinEui       = joinEui;
     DevEui        = devEui;
     DevNonce      = devNonce;
     Mic           = mic;
     RadioMetadata = radioMetadata;
 }
        public static async Task <bool> ResetADRCache(DevEui devEUI)
        {
            var path = $"FunctionBundler/{devEUI}";
            // the gateway id is only used to identify who is taking the lock when
            // releasing the cache. Hence we do not need a real GW id
            var payload = "{\"AdrRequest\":{\"ClearCache\": true},\"GatewayId\":\"integrationTesting\", \"FunctionItems\": " + (int)FunctionBundlerItemType.ADR + "}";

            return(await PostFunctionEndpointAsync(path, payload));
        }
        public ILoRaDeviceClient GetClient(DevEui devEui)
        {
            if (this.managedConnections.TryGetValue(GetConnectionCacheKey(devEui), out var managedConnection))
            {
                return(managedConnection.DeviceClient);
            }

            throw new ManagedConnectionException($"Connection for device {devEui} was not found");
        }
        internal async Task <DuplicateMsgResult> GetDuplicateMessageResultAsync(DevEui devEUI, string gatewayId, uint clientFCntUp, uint clientFCntDown, ILogger logger = null)
        {
            var isDuplicate     = true;
            var processedDevice = gatewayId;

            using (var deviceCache = new LoRaDeviceCache(this.cacheStore, devEUI, gatewayId))
            {
                if (await deviceCache.TryToLockAsync())
                {
                    // we are owning the lock now
                    if (deviceCache.TryGetInfo(out var cachedDeviceState))
                    {
                        var updateCacheState = false;

                        if (cachedDeviceState.FCntUp < clientFCntUp)
                        {
                            isDuplicate      = false;
                            updateCacheState = true;
                        }
                        else if (cachedDeviceState.FCntUp == clientFCntUp && cachedDeviceState.GatewayId == gatewayId)
                        {
                            isDuplicate     = false;
                            processedDevice = cachedDeviceState.GatewayId;
                        }
                        else
                        {
                            processedDevice = cachedDeviceState.GatewayId;
                        }

                        if (updateCacheState)
                        {
                            cachedDeviceState.FCntUp    = clientFCntUp;
                            cachedDeviceState.GatewayId = gatewayId;
                            _ = deviceCache.StoreInfo(cachedDeviceState);
                        }
                    }
                    else
                    {
                        // initialize
                        isDuplicate = false;
                        var state = deviceCache.Initialize(clientFCntUp, clientFCntDown);
                        logger?.LogDebug("initialized state for {id}:{gwid} = {state}", devEUI, gatewayId, state);
                    }
                }
                else
                {
                    processedDevice = "[unknown]";
                    logger?.LogWarning("Failed to acquire lock");
                }
            }

            return(new DuplicateMsgResult
            {
                IsDuplicate = isDuplicate,
                GatewayId = processedDevice
            });
        }
示例#15
0
        public async Task When_Querying_Devices_And_Finds_Class_A_Should_Send_Message()
        {
            var devEui = new DevEui(123456789);

            var deviceTwin = new Twin
            {
                Properties = new TwinProperties()
                {
                    Desired = new TwinCollection($"{{\"DevAddr\": \"03010101\"}}"),
                }
            };

            var query = new Mock <IQuery>(MockBehavior.Strict);

            query.Setup(x => x.HasMoreResults).Returns(true);
            query.Setup(x => x.GetNextAsTwinAsync())
            .ReturnsAsync(new[] { deviceTwin });

            this.registryManager.Setup(x => x.CreateQuery(It.IsNotNull <string>(), It.IsAny <int?>()))
            .Returns(query.Object);

            var actualMessage = new LoRaCloudToDeviceMessage()
            {
                MessageId = "myMessageId-1234",
                Fport     = TestPort,
                Payload   = "hello",
            };

            LoRaCloudToDeviceMessage     receivedC2DMessage = null;
            IDictionary <string, string> receivedProperties = null;

            this.serviceClient.Setup(x => x.SendAsync(devEui.ToString(), It.IsNotNull <Message>()))
            .Callback((string d, Message m) => (receivedProperties, receivedC2DMessage) = (m.Properties, JsonConvert.DeserializeObject <LoRaCloudToDeviceMessage>(Encoding.UTF8.GetString(m.GetBytes()))))
            .Returns(Task.CompletedTask);

            var actual = await this.sendCloudToDeviceMessage.SendCloudToDeviceMessageImplementationAsync(
                devEui,
                actualMessage);

            Assert.IsType <OkObjectResult>(actual);
            var responseValue = ((OkObjectResult)actual).Value as SendCloudToDeviceMessageResult;

            Assert.NotNull(responseValue);
            Assert.Equal("A", responseValue.ClassType);
            Assert.Equal(devEui, responseValue.DevEui);
            Assert.Equal(actualMessage.MessageId, responseValue.MessageID);

            Assert.Empty(receivedProperties);
            Assert.Equal(receivedC2DMessage.Fport, actualMessage.Fport);
            Assert.Equal(receivedC2DMessage.Payload, actualMessage.Payload);
            Assert.Equal(receivedC2DMessage.MessageId, actualMessage.MessageId);

            this.serviceClient.VerifyAll();
            this.registryManager.VerifyAll();
            query.VerifyAll();
        }
 public FunctionBundlerPipelineExecuter(IFunctionBundlerExecutionItem[] registeredHandlers,
                                        DevEui devEUI,
                                        FunctionBundlerRequest request,
                                        ILogger logger = null)
 {
     this.registeredHandlers = registeredHandlers;
     DevEUI  = devEUI;
     Request = request;
     Logger  = logger ?? NullLogger.Instance;
 }
示例#17
0
        public virtual async Task <LoRaADRResult> CalculateADRResultAndAddEntryAsync(DevEui devEUI, string gatewayId, uint fCntUp, uint fCntDown, float requiredSnr, DataRateIndex dataRate, int minTxPower, DataRateIndex maxDr, LoRaADRTableEntry newEntry = null)
        {
            var table = newEntry != null
                        ? await this.store.AddTableEntry(newEntry)
                        : await this.store.GetADRTable(devEUI);

            var currentStrategy = this.strategyProvider.GetStrategy();

            var result = currentStrategy.ComputeResult(table, requiredSnr, dataRate, minTxPower, maxDr);

            if (result == null)
            {
                // In this case we want to reset the device to default values as we have null values
                if (table == null ||
                    !table.CurrentNbRep.HasValue ||
                    !table.CurrentTxPower.HasValue ||
                    fCntUp > currentStrategy.MinimumNumberOfResult)
                {
                    result = ReturnDefaultValues(dataRate, currentStrategy.DefaultNbRep, currentStrategy.DefaultTxPower);
                }
                else
                {
                    result = await GetLastResultAsync(devEUI) ?? new LoRaADRResult();

                    result.NumberOfFrames = table.Entries.Count;
                    return(result);
                }
            }

            var nextFcntDown = await NextFCntDown(devEUI, gatewayId, fCntUp, fCntDown);

            result.CanConfirmToDevice = nextFcntDown > 0;

            if (result.CanConfirmToDevice)
            {
                if (table == null)
                {
                    // in a reset case, we may not have a table, but still want to store the default
                    // values that we sent to the client
                    table = new LoRaADRTable();
                }

                table.CurrentNbRep   = result.NbRepetition;
                table.CurrentTxPower = result.TxPower;
                await this.store.UpdateADRTable(devEUI, table);

                UpdateState(result);
                result.FCntDown = nextFcntDown;
            }

            result.NumberOfFrames = table.Entries.Count;
            this.logger.LogDebug($"calculated ADR: CanConfirmToDevice: {result.CanConfirmToDevice}, TxPower: {result.TxPower}, DataRate: {result.DataRate}");
            return(result);
        }
示例#18
0
 public BasicsStationConfigurationServiceTests()
 {
     this.stationEui = new StationEui(ulong.MaxValue);
     this.devEui     = DevEui.Parse(this.stationEui.ToString());
     this.loRaDeviceApiServiceMock = new Mock <LoRaDeviceAPIServiceBase>();
     this.loRaDeviceFactoryMock    = new Mock <ILoRaDeviceFactory>();
     this.memoryCache = new MemoryCache(new MemoryCacheOptions());
     this.sut         = new BasicsStationConfigurationService(this.loRaDeviceApiServiceMock.Object,
                                                              this.loRaDeviceFactoryMock.Object,
                                                              this.memoryCache,
                                                              NullLogger <BasicsStationConfigurationService> .Instance);
 }
示例#19
0
        public LoRaDeviceCache(ILoRaDeviceCacheStore cacheStore, DevEui devEUI, string gatewayId)
        {
            if (string.IsNullOrEmpty(gatewayId))
            {
                throw new ArgumentNullException(nameof(gatewayId));
            }

            this.cacheStore = cacheStore;
            this.devEUI     = devEUI;
            this.gatewayId  = gatewayId;
            this.cacheKey   = devEUI.ToString();
        }
        public async Task <bool> Reset(DevEui devEUI)
        {
            using (var redisLock = new RedisLockWrapper(devEUI, this.redisCache))
            {
                if (await redisLock.TakeLockAsync())
                {
                    return(await this.redisCache.KeyDeleteAsync(GetEntryKey(devEUI)));
                }
            }

            return(false);
        }
        public async Task Test_ClassC_Send_Message_Using_Function_Endpoint_Should_Be_Received()
        {
            var device = TestFixtureCi.Device24_ABP;

            LogTestStart(device);

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

            await ArduinoDevice.setIdAsync(device.DevAddr, device.DeviceID, null);

            await ArduinoDevice.setKeyAsync(device.NwkSKey, device.AppSKey, null);

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await ArduinoDevice.setClassTypeAsync(LoRaArduinoSerial._class_type_t.CLASS_C);

            // send one confirmed message for ensuring that a basicstation is "bound" to the device
            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);

            Log($"{device.DeviceID}: Sending confirmed '{msg}'");
            await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            TestFixtureCi.ClearLogs();

            // Now sending a c2d
            var c2d = new LoRaCloudToDeviceMessage()
            {
                DevEUI     = DevEui.Parse(device.DeviceID),
                MessageId  = Guid.NewGuid().ToString(),
                Fport      = FramePorts.App23,
                RawPayload = Convert.ToBase64String(new byte[] { 0xFF, 0x00 }),
            };

            TestLogger.Log($"[INFO] Using service API to send C2D message to device {device.DeviceID}");
            TestLogger.Log($"[INFO] {JsonConvert.SerializeObject(c2d, Formatting.None)}");

            // send message using the SendCloudToDeviceMessage API endpoint
            Assert.True(await LoRaAPIHelper.SendCloudToDeviceMessage(device.DevEui, c2d));

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            // 0000000000000024: received cloud to device message from direct method
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: received cloud to device message from direct method");

            Assert.Contains(ArduinoDevice.SerialLogs, (l) => l.Contains("PORT: 23; RX: \"FF00\"", StringComparison.Ordinal));
            Assert.Contains(ArduinoDevice.SerialLogs, (l) => l.Contains("RXWIN0, RSSI", StringComparison.Ordinal));
            await AssertUtils.ContainsWithRetriesAsync("+MSG: Done", ArduinoDevice.SerialLogs);
        }
        public async Task <LoRaADRTable> GetADRTable(DevEui devEUI)
        {
            using (var redisLock = new RedisLockWrapper(devEUI, this.redisCache))
            {
                if (await redisLock.TakeLockAsync())
                {
                    return(await GetADRTableCore(GetEntryKey(devEUI)));
                }
            }

            this.logger.LogError("Failed to acquire ADR redis lock. Can't deliver ADR Table");
            return(null);
        }
        public PreferredGatewayResult(DevEui devEUI, uint fcntUp, LoRaDevicePreferredGateway preferredGateway)
        {
            if (preferredGateway is null)
            {
                throw new ArgumentNullException(nameof(preferredGateway));
            }

            DevEUI             = devEUI;
            RequestFcntUp      = fcntUp;
            CurrentFcntUp      = preferredGateway.FcntUp;
            PreferredGatewayID = preferredGateway.GatewayID;
            Conflict           = fcntUp != preferredGateway.FcntUp;
        }
示例#24
0
        public virtual async Task <LoRaADRResult> GetLastResultAsync(DevEui devEUI)
        {
            var table = await this.store.GetADRTable(devEUI);

            return(table != null
                ? new LoRaADRResult
            {
                NbRepetition = table.CurrentNbRep,
                TxPower = table.CurrentTxPower,
                NumberOfFrames = table.Entries.Count
            }
                : null);
        }
示例#25
0
 internal FunctionBundler(DevEui devEui,
                          LoRaDeviceAPIServiceBase deviceApi,
                          FunctionBundlerRequest request,
                          IList <IFunctionBundlerExecutionItem> executionItems,
                          FunctionBundlerExecutionContext executionContext,
                          ILogger <FunctionBundler> logger)
 {
     this.devEui           = devEui;
     this.deviceApi        = deviceApi;
     this.request          = request;
     this.executionItems   = executionItems;
     this.executionContext = executionContext;
     this.logger           = logger;
 }
        public override async Task <bool> ABPFcntCacheResetAsync(DevEui devEUI, uint fcntUp, string gatewayId)
        {
            var client   = this.serviceFacadeHttpClientProvider.GetHttpClient();
            var url      = GetFullUri($"NextFCntDown?code={AuthCode}&DevEUI={devEUI}&ABPFcntCacheReset=true&GatewayId={gatewayId}&FCntUp={fcntUp}");
            var response = await client.GetAsync(url);

            if (!response.IsSuccessStatusCode)
            {
                this.logger.LogError($"error calling the NextFCntDown function, check the function log, {response.ReasonPhrase}");
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Searchs for devices that match the join request.
        /// </summary>
        public async Task <LoRaDevice> GetDeviceForJoinRequestAsync(DevEui devEUI, DevNonce devNonce)
        {
            this.logger.LogDebug("querying the registry for OTAA device");

            var searchDeviceResult = await this.loRaDeviceAPIService.SearchAndLockForJoinAsync(
                gatewayID : this.configuration.GatewayID,
                devEUI : devEUI,
                devNonce : devNonce);

            if (searchDeviceResult.IsDevNonceAlreadyUsed)
            {
                // another gateway processed the join request. If we have it in the cache
                // with existing session keys, we need to invalidate that entry, to ensure
                // it gets re-fetched on the next message
                if (this.deviceCache.TryGetByDevEui(devEUI, out var someDevice) && someDevice.AppSKey != null)
                {
                    _ = this.deviceCache.Remove(someDevice);
                    this.logger.LogDebug("Device was removed from cache.");
                }

                this.logger.LogInformation("join refused: Join already processed by another gateway.");
                return(null);
            }

            if (searchDeviceResult?.Devices == null || searchDeviceResult.Devices.Count == 0)
            {
                this.logger.LogInformation(searchDeviceResult.RefusedMessage ?? "join refused: no devices found matching join request");
                return(null);
            }

            var matchingDeviceInfo = searchDeviceResult.Devices[0];

            if (deviceCache.TryGetByDevEui(matchingDeviceInfo.DevEUI, out var cachedDevice))
            {
                // if we already have the device in the cache, then it is either from a previous
                // join rquest or it's a re-join. Both scenarios are ok, and we can use the cached
                // information.
                return(cachedDevice);
            }

            var loader     = GetOrCreateJoinDeviceLoader(matchingDeviceInfo);
            var loRaDevice = await loader.LoadAsync();

            if (!loader.CanCache)
            {
                RemoveJoinDeviceLoader(devEUI);
            }

            return(loRaDevice);
        }
        private async Task <IActionResult> SendMessageViaDirectMethodAsync(
            string preferredGatewayID,
            DevEui devEUI,
            LoRaCloudToDeviceMessage c2dMessage)
        {
            try
            {
                var method = new CloudToDeviceMethod(LoraKeysManagerFacadeConstants.CloudToDeviceMessageMethodName, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
                _ = method.SetPayloadJson(JsonConvert.SerializeObject(c2dMessage));

                var res = await this.serviceClient.InvokeDeviceMethodAsync(preferredGatewayID, LoraKeysManagerFacadeConstants.NetworkServerModuleId, method);

                if (IsSuccessStatusCode(res.Status))
                {
                    this.log.LogInformation("Direct method call to {gatewayID} and {devEUI} succeeded with {statusCode}", preferredGatewayID, devEUI, res.Status);

                    return(new OkObjectResult(new SendCloudToDeviceMessageResult()
                    {
                        DevEui = devEUI,
                        MessageID = c2dMessage.MessageId,
                        ClassType = "C",
                    }));
                }

                this.log.LogError("Direct method call to {gatewayID} failed with {statusCode}. Response: {response}", preferredGatewayID, res.Status, res.GetPayloadAsJson());

                return(new ObjectResult(res.GetPayloadAsJson())
                {
                    StatusCode = res.Status,
                });
            }
            catch (JsonSerializationException ex)
            {
                this.log.LogError(ex, "Failed to serialize C2D message {c2dmessage} to {devEUI}", JsonConvert.SerializeObject(c2dMessage), devEUI);
                return(new ObjectResult("Failed serialize C2D Message")
                {
                    StatusCode = (int)HttpStatusCode.InternalServerError
                });
            }
            catch (IotHubException ex)
            {
                this.log.LogError(ex, "Failed to send message for {devEUI} to the IoT Hub", devEUI);
                return(new ObjectResult("Failed to send message for device to the iot Hub")
                {
                    StatusCode = (int)HttpStatusCode.InternalServerError
                });
            }
        }
示例#29
0
        public async Task GetDeviceForJoinRequestAsync_When_Device_Api_Throws_Error_Should_Not_Catch()
        {
            var devEui   = new DevEui(1);
            var devNonce = new DevNonce(1);

            var apiService = new Mock <LoRaDeviceAPIServiceBase>();

            apiService.Setup(x => x.SearchAndLockForJoinAsync(ServerConfiguration.GatewayID, devEui, devNonce))
            .Throws(new InvalidOperationException());
            using var target = new LoRaDeviceRegistry(ServerConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object, DeviceCache);

            Task Act() => target.GetDeviceForJoinRequestAsync(devEui, devNonce);

            _ = await Assert.ThrowsAsync <InvalidOperationException>(Act);

            // Device was searched by DevAddr
            apiService.VerifyAll();
        }
        public async Task When_Device_Is_Found_Should_Returns_Device_Information()
        {
            // arrange
            var devEui     = new DevEui(13213123212131);
            var primaryKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey));

            var(registryManager, request) = SetupIotHubQuery(devEui.ToString(), PrimaryKey);
            var searchDeviceByDevEUI = new SearchDeviceByDevEUI(registryManager.Object);

            // act
            var result = await searchDeviceByDevEUI.GetDeviceByDevEUI(request, NullLogger.Instance);

            // assert
            var okObjectResult = Assert.IsType <OkObjectResult>(result);

            Assert.Equal(JsonConvert.SerializeObject(new { DevEUI = devEui.ToString(), PrimaryKey = primaryKey }), JsonConvert.SerializeObject(okObjectResult.Value));
            registryManager.VerifyAll();
        }