Exemplo n.º 1
0
 private static void CacheFcnt(FCnt serverFCnt, IDatabase cache, string cacheKey)
 {
     cache.StringSet(cacheKey, JsonConvert.SerializeObject(serverFCnt), new TimeSpan(30, 0, 0, 0), When.Always, CommandFlags.DemandMaster);
 }
Exemplo n.º 2
0
        public static IActionResult Run(HttpRequest req, ILogger log, ExecutionContext context, ApiVersion currentApiVersion)
        {
            // set the current version in the response header
            req.HttpContext.Response.Headers.Add(ApiVersion.HttpHeaderName, currentApiVersion.Version);

            var requestedVersion = req.GetRequestedVersion();

            if (requestedVersion == null || !currentApiVersion.SupportsVersion(requestedVersion))
            {
                return(new BadRequestObjectResult($"Incompatible versions (requested: '{requestedVersion.Name ?? string.Empty}', current: '{currentApiVersion.Name}')"));
            }

            FCnt   serverFCnt;
            string devEUI            = req.Query["DevEUI"];
            string fCntDown          = req.Query["FCntDown"];
            string fCntUp            = req.Query["FCntUp"];
            string gatewayId         = req.Query["GatewayId"];
            string abpFcntCacheReset = req.Query["ABPFcntCacheReset"];
            int    newFCntDown       = 0;

            if (redisCache == null)
            {
                lock (typeof(FCntCacheCheck))
                {
                    if (redisCache == null)
                    {
                        var config = new ConfigurationBuilder()
                                     .SetBasePath(context.FunctionAppDirectory)
                                     .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                                     .AddEnvironmentVariables()
                                     .Build();

                        var redisConnectionString = config.GetConnectionString("RedisConnectionString");

                        if (string.IsNullOrEmpty(redisConnectionString))
                        {
                            string errorMsg = "Missing RedisConnectionString in settings";
                            throw new Exception(errorMsg);
                        }

                        var redis = ConnectionMultiplexer.Connect(redisConnectionString);
                        redisCache = redis.GetDatabase();
                    }
                }
            }

            if (!string.IsNullOrEmpty(abpFcntCacheReset))
            {
                redisCache.KeyDelete(devEUI);
                return((ActionResult) new OkObjectResult(null));
            }

            if (!string.IsNullOrEmpty(devEUI) && !string.IsNullOrEmpty(fCntDown) && !string.IsNullOrEmpty(fCntUp) && !string.IsNullOrEmpty(gatewayId))
            {
                int clientFCntDown = int.Parse(fCntDown);
                int clientFCntUp   = int.Parse(fCntUp);

                string cacheKey = devEUI;

                try
                {
                    if (redisCache.LockTake(cacheKey + "msglock", gatewayId, new TimeSpan(0, 0, 10)))
                    {
                        string cachedFCnt = redisCache.StringGet(cacheKey, CommandFlags.DemandMaster);
                        // we have it cached
                        if (!string.IsNullOrEmpty(cachedFCnt))
                        {
                            serverFCnt = (FCnt)JsonConvert.DeserializeObject(cachedFCnt, typeof(FCnt));
                            // it is a new message coming up by the first gateway
                            if (clientFCntUp > serverFCnt.FCntUp)
                            {
                                if (clientFCntDown >= serverFCnt.FCntDown)
                                {
                                    newFCntDown = (int)(clientFCntDown + 1);
                                }
                                else
                                {
                                    newFCntDown = (int)(serverFCnt.FCntDown + 1);
                                }

                                serverFCnt.FCntUp    = clientFCntUp;
                                serverFCnt.FCntDown  = newFCntDown;
                                serverFCnt.GatewayId = gatewayId;

                                CacheFcnt(serverFCnt, redisCache, cacheKey);
                            }

                            // it is a retry message coming up by the same first gateway
                            else if (clientFCntUp == serverFCnt.FCntUp && gatewayId == serverFCnt.GatewayId)
                            {
                                newFCntDown         = serverFCnt.FCntDown + 1;
                                serverFCnt.FCntDown = newFCntDown;

                                CacheFcnt(serverFCnt, redisCache, cacheKey);
                            }
                            else
                            {
                                // we tell not to send any ack or downstream msg
                                newFCntDown = 0;
                            }
                        }

                        // it is the first message from this device
                        else
                        {
                            newFCntDown          = clientFCntDown + 1;
                            serverFCnt           = new FCnt();
                            serverFCnt.FCntDown  = newFCntDown;
                            serverFCnt.FCntUp    = clientFCntUp;
                            serverFCnt.GatewayId = gatewayId;

                            CacheFcnt(serverFCnt, redisCache, cacheKey);
                        }
                    }
                }
                finally
                {
                    redisCache.LockRelease(cacheKey + "msglock", gatewayId);
                }
            }
            else
            {
                string errorMsg = "Missing DevEUI or FCntDown or FCntUp or GatewayId";
                throw new Exception(errorMsg);
            }

            return((ActionResult) new OkObjectResult(newFCntDown));
        }
Exemplo n.º 3
0
        public static async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, ExecutionContext context)
        {
            FCnt   serverFCnt;
            string devEUI            = req.Query["DevEUI"];
            string fCntDown          = req.Query["FCntDown"];
            string fCntUp            = req.Query["FCntUp"];
            string gatewayId         = req.Query["GatewayId"];
            string ABPFcntCacheReset = req.Query["ABPFcntCacheReset"];
            int    newFCntDown       = 0;

            if (redisCache == null)
            {
                lock (typeof(FCntCacheChechk))
                {
                    if (redisCache == null)
                    {
                        var config = new ConfigurationBuilder()
                                     .SetBasePath(context.FunctionAppDirectory)
                                     .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                                     .AddEnvironmentVariables()
                                     .Build();

                        var redisConnectionString = config.GetConnectionString("RedisConnectionString");


                        if (string.IsNullOrEmpty(redisConnectionString))
                        {
                            string errorMsg = "Missing RedisConnectionString in settings";
                            throw new Exception(errorMsg);
                        }

                        var redis = ConnectionMultiplexer.Connect(redisConnectionString);
                        redisCache = redis.GetDatabase();
                    }
                }
            }

            if (!string.IsNullOrEmpty(ABPFcntCacheReset))
            {
                redisCache.KeyDelete(devEUI);
                return((ActionResult) new OkObjectResult(null));
            }

            if (!String.IsNullOrEmpty(devEUI) && !String.IsNullOrEmpty(fCntDown) && !String.IsNullOrEmpty(fCntUp) && !String.IsNullOrEmpty(gatewayId))
            {
                int clientFCntDown = int.Parse(fCntDown);
                int clientFCntUp   = int.Parse(fCntUp);

                string cacheKey = devEUI;

                try
                {
                    if (redisCache.LockTake(cacheKey + "msglock", gatewayId, new TimeSpan(0, 0, 10)))
                    {
                        string cachedFCnt = redisCache.StringGet(cacheKey, CommandFlags.DemandMaster);
                        //we have it cached
                        if (!string.IsNullOrEmpty(cachedFCnt))
                        {
                            serverFCnt = (FCnt)JsonConvert.DeserializeObject(cachedFCnt, typeof(FCnt));
                            //it is a new message coming up by the first gateway
                            if (clientFCntUp > serverFCnt.FCntUp)
                            {
                                if (clientFCntDown >= serverFCnt.FCntDown)
                                {
                                    newFCntDown = (int)(clientFCntDown + 1);
                                }
                                else
                                {
                                    newFCntDown = (int)(serverFCnt.FCntDown + 1);
                                }

                                serverFCnt.FCntUp    = clientFCntUp;
                                serverFCnt.FCntDown  = newFCntDown;
                                serverFCnt.GatewayId = gatewayId;

                                CacheFcnt(serverFCnt, redisCache, cacheKey);
                            }
                            //it is a retry message coming up by the same first gateway
                            else if (clientFCntUp == serverFCnt.FCntUp && gatewayId == serverFCnt.GatewayId)
                            {
                                newFCntDown         = serverFCnt.FCntDown + 1;
                                serverFCnt.FCntDown = newFCntDown;

                                CacheFcnt(serverFCnt, redisCache, cacheKey);
                            }
                            else
                            {
                                //we tell not to send any ack or downstream msg
                                newFCntDown = 0;
                            }
                        }
                        //it is the first message from this device
                        else
                        {
                            newFCntDown          = clientFCntDown + 1;
                            serverFCnt           = new FCnt();
                            serverFCnt.FCntDown  = newFCntDown;
                            serverFCnt.FCntUp    = clientFCntUp;
                            serverFCnt.GatewayId = gatewayId;

                            CacheFcnt(serverFCnt, redisCache, cacheKey);
                        }
                    }
                }
                finally
                {
                    redisCache.LockRelease(cacheKey + "msglock", gatewayId);
                }
            }
            else
            {
                string errorMsg = "Missing DevEUI or FCntDown or FCntUp or GatewayId";
                throw new Exception(errorMsg);
            }
            return((ActionResult) new OkObjectResult(newFCntDown));
        }