public override void Decode(string timestamp, string device, string topic, byte[] payload)
        {
            string json       = Encoding.UTF8.GetString(payload);
            var    data       = JsonConvert.DeserializeObject <dynamic>(json);
            var    deviceName = Convert.ToString(data.deviceName);
            var    obj        = data["object"];
            var    present    = obj.present;

            if (deviceName.Contains("livboj"))
            {
                string value = "on";

                if (present == false)
                {
                    value = "off";
                }

                var message = new Fiware.DeviceMessage(deviceName, value);

                _fiwareContextBroker.PostMessage(message);
            }

            Console.WriteLine($"Got message from deviceName {deviceName}: {json}");

            // TODO: forward device message to the NGSI Context Broker
        }
        public void PostMessage(DeviceMessage message)
        {
            var settings = new JsonSerializerSettings
            {
                ContractResolver  = new CamelCasePropertyNamesContractResolver(),
                NullValueHandling = NullValueHandling.Ignore
            };

            var json = JsonConvert.SerializeObject(message, settings);

            var data = new StringContent(json, Encoding.UTF8, "application/json+ld");

            var url = $"{_contextBrokerURL}/ngsi-ld/v1/entities/{message.Id}/attrs/";

            Patch(_client, url, data);
        }
        public override void Decode(string timestamp, string device, string topic, byte[] payload)
        {
            string  json = Encoding.UTF8.GetString(payload);
            dynamic data = JsonConvert.DeserializeObject <dynamic>(json);

            payload = System.Convert.FromBase64String(Convert.ToString(data.data));

            string deviceInHex = device;

            device = Int64.Parse(device, System.Globalization.NumberStyles.HexNumber).ToString();

            ReadOnlySpan <byte> span = payload;

            /*
             *  uint8_t   Battery [%]
             *  uint16_t  raw Distance [mm]
             *  uint16_t  Angle [deg]
             *  unit16_t  Vertical distance [mm]
             *  unit16_t  Snow depth [mm]
             *  unit16_t  Laser signal strength [0-400] (lower is better)
             *  uint8_t   Laser sensor status
             *  int16_t   Temperature [°C]F
             *  unit8_t   Humidity [%]
             *  unit32_t  Pressure [Pa]
             *
             *  DEVEUI:s
             *  1199411787624306471 Stöde 62.4081681,16.5687632
             *  1199411787624306472 Matfors 62.348384, 17.016098
             *  1199411787624306473 Njurunda 62.310288, 17.369975
             *  1199411787624306480 Sundsvall 62.392013, 17.285092
             *  1199411787624306481 Alnö 62.424865, 17.434870
             *  1199411787624306482 Sidsjö 62.374817, 17.269407
             *  1199411787624306483 Granloholm 62.409886, 17.270434
             *  1199411787624306484 Kovland 62.466341, 17.147527
             *  1199411787624306485 Fagerdalsparken 62.381662, 17.282563
             *  1199411787624306486 Finsta 62.461594, 17.345016
             */
            double latitude  = 1.348364;
            double longitude = 1.016056;

            if (device == "1199411787624306471")
            {
                latitude  = 62.4081681;
                longitude = 16.5687632;
            }
            else if (device == "1199411787624306472")
            {
                latitude  = 62.348384;
                longitude = 17.016098;
            }
            else if (device == "1199411787624306473")
            {
                latitude  = 62.310288;
                longitude = 17.369975;
            }
            else if (device == "1199411787624306480")
            {
                latitude  = 62.392013;
                longitude = 17.285092;
            }
            else if (device == "1199411787624306481")
            {
                latitude  = 62.424865;
                longitude = 17.434870;
            }
            else if (device == "1199411787624306483")
            {
                latitude  = 62.409886;
                longitude = 17.270434;
            }
            else if (device == "1199411787624306482")
            {
                latitude  = 62.374817;
                longitude = 17.269407;
            }
            else if (device == "1199411787624306484")
            {
                latitude  = 62.466341;
                longitude = 17.147527;
            }
            else if (device == "1199411787624306485")
            {
                latitude  = 62.381662;
                longitude = 17.282563;
            }
            else if (device == "1199411787624306486")
            {
                latitude  = 62.461594;
                longitude = 17.345016;
            }

            // TODO: We need to decide on the device names. Should we use the name from the LoRa app server?
            string deviceName = "snow_" + deviceInHex;

            IoTHubMessageOrigin origin = new IoTHubMessageOrigin(deviceName, latitude, longitude);

            double volts = payload[0];

            volts = Math.Round(3 * ((volts * 0.005) + 1.1), 3);
            _messageQueue.PostMessage(new SensorStatusMessage(origin, timestamp, volts));

            const byte sensorStatusIsOK = 0;

            if (payload[11] == sensorStatusIsOK)
            {
                DateTime dt = DateTime.ParseExact(timestamp, "yyyy-MM-ddTHH:mm:ssZ", null);
                if (dt.Month < 5 || dt.Month > 10)
                {
                    double snowdepth = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 7, length: 2));
                    snowdepth = Math.Round(snowdepth / 10.0, 1);
                    _messageQueue.PostMessage(new TelemetrySnowdepth(origin, timestamp, snowdepth));
                }
                else
                {
                    Console.WriteLine($"Snowdepth readings are disabled.");
                }
            }
            else
            {
                Console.WriteLine($"Ignoring snowdepth reading from {deviceName}. Sensor is not OK.");
            }

            double temperature = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 12, length: 2));

            temperature = Math.Round((temperature / 10.0) - 100.0, 2);
            _messageQueue.PostMessage(new TelemetryTemperature(origin, timestamp, temperature));

            int humidity = payload[14];

            _messageQueue.PostMessage(new TelemetryHumidity(origin, timestamp, humidity));

            double pressure = BinaryPrimitives.ReadUInt32BigEndian(span.Slice(start: 15, length: 4));

            _messageQueue.PostMessage(new TelemetryPressure(origin, timestamp, (int)pressure));

            if (data.ContainsKey("rxInfo"))
            {
                dynamic rxInfo = data["rxInfo"];
                if (rxInfo.Count > 0)
                {
                    dynamic gateway = rxInfo[0];
                    int     maxRSSI = gateway.rssi;
                    int     snr     = gateway.loRaSNR;
                    string  name    = gateway.name;

                    for (int i = 1; i < rxInfo.Count; i++)
                    {
                        if (rxInfo[i].rssi > maxRSSI)
                        {
                            maxRSSI = rxInfo[i].rssi;
                            snr     = gateway.loRaSNR;
                            name    = rxInfo[i].name;
                        }
                    }

                    Console.WriteLine($"{deviceName} is connected to gateway {name} with rssi {maxRSSI} and snr {snr}");

                    double rssiLevel = Math.Round((125.0 - Math.Abs(maxRSSI)) / 100.0, 2);
                    rssiLevel = Math.Min(Math.Max(0, rssiLevel), 1.0); // RSSI level should be in range [0 1]

                    double snrLevel = Math.Round((snr + 20.0) / 32.0, 2);
                    snrLevel = Math.Min(Math.Max(0, snrLevel), 1.0);

                    deviceName = "se:servanet:lora:" + deviceName;

                    var msg = new Fiware.DeviceMessage(deviceName).WithRSSI(rssiLevel).WithSNR(snrLevel);
                    msg = msg.WithVoltage(Math.Min(Math.Max(0, volts / 4.925), 1));

                    try
                    {
                        _fiwareContextBroker.PostMessage(msg);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"Exception caught attempting to post Device update: {e.Message}");
                    };
                }
            }
        }
Example #4
0
        public override void Decode(string timestamp, string device, string topic, byte[] payload)
        {
            string json       = Encoding.UTF8.GetString(payload);
            var    data       = JsonConvert.DeserializeObject <dynamic>(json);
            var    deviceName = "se:servanet:lora:" + Convert.ToString(data.deviceName);
            var    dateStrNow = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");

            dynamic obj = null;

            if (data.ContainsKey("object"))
            {
                obj = data["object"];
            }

            if (deviceName.Contains("sn-elt-livboj-"))
            {
                if (obj.ContainsKey("present"))
                {
                    var    present = obj.present;
                    string value   = "on";

                    if (present == false)
                    {
                        value = "off";
                    }

                    var message = new Fiware.DeviceMessage(deviceName, value);

                    try {
                        _fiwareContextBroker.PostMessage(message);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"Exception caught attempting to post Device update: {e.Message}");
                    };
                }
                else
                {
                    Console.WriteLine($"No \"present\" property in message from deviceName {deviceName}!: {json}");
                    return;
                }
            }
            else if (deviceName.Contains("sk-elt-temp-"))
            {
                if (obj.ContainsKey("externalTemperature"))
                {
                    double value = obj.externalTemperature;

                    string stringValue = $"t%3D{value}";
                    var    message     = new Fiware.DeviceMessage(deviceName, stringValue);

                    if (obj.ContainsKey("vdd"))
                    {
                        double       batteryLevel      = obj.vdd;
                        const double MAX_BATTERY_LEVEL = 3665;

                        if (batteryLevel > MAX_BATTERY_LEVEL)
                        {
                            Console.WriteLine($"Battery level of {deviceName} is bigger than the max level. {batteryLevel} > {MAX_BATTERY_LEVEL}!");
                        }

                        batteryLevel = batteryLevel / MAX_BATTERY_LEVEL;
                        message      = message.WithVoltage(Math.Round(batteryLevel, 2));
                    }

                    try
                    {
                        _fiwareContextBroker.PostMessage(message);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"Exception caught attempting to post Device update: {e.Message}");
                    };
                }
                else
                {
                    Console.WriteLine($"No \"externalTemperature\" property in message from deviceName {deviceName}!: {json}");
                    return;
                }
            }
            else if (deviceName.Contains("TRSense01"))
            {
                if (obj.ContainsKey("L0_CNT") && obj.ContainsKey("R0_CNT"))
                {
                    string shortDeviceName = deviceName.Remove(0, 16);

                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 0, (int)obj.L0_CNT, (double)obj.L0_AVG);
                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 1, (int)obj.L1_CNT, (double)obj.L1_AVG);
                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 2, (int)obj.L2_CNT, (double)obj.L2_AVG);
                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 3, (int)obj.L3_CNT, (double)obj.L3_AVG);
                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 4, (int)obj.R0_CNT, (double)obj.R0_AVG);
                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 5, (int)obj.R1_CNT, (double)obj.R1_AVG);
                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 6, (int)obj.R2_CNT, (double)obj.R2_AVG);
                    ReportTrafficIntensityForLane(shortDeviceName, dateStrNow, 7, (int)obj.R3_CNT, (double)obj.R3_AVG);
                }
                else
                {
                    Console.WriteLine($"No \"L0_CNT\" property in message from deviceName {deviceName}!: {json}");
                    return;
                }
            }
            else if (deviceName.Contains("mcg-ers-co2-"))
            {
                if (obj.ContainsKey("co2"))
                {
                    double co2    = obj.co2;
                    var    aqoMsg = new Fiware.AirQualityObserved(deviceName, dateStrNow);
                    aqoMsg = aqoMsg.WithCO2(co2);

                    if (obj.ContainsKey("temperature"))
                    {
                        double temp = obj.temperature;
                        aqoMsg = aqoMsg.WithTemperature(temp);
                    }

                    if (obj.ContainsKey("humidity"))
                    {
                        double humidity = obj.humidity / 100.0;
                        aqoMsg = aqoMsg.WithHumidity(humidity);
                    }

                    var deviceMsg = new Fiware.DeviceMessage(deviceName);

                    if (obj.ContainsKey("vdd"))
                    {
                        double batteryLevel = obj.vdd;
                        batteryLevel = batteryLevel / 3665.0;
                        deviceMsg    = deviceMsg.WithVoltage(Math.Round(batteryLevel, 2));
                    }

                    try
                    {
                        _fiwareContextBroker.PostMessage(deviceMsg);
                        _fiwareContextBroker.CreateNewEntity(aqoMsg);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"Exception caught attempting to post Device update: {e.Message}");
                    };
                }
                else
                {
                    Console.WriteLine($"No \"co2\" property in message from deviceName {deviceName}!: {json}");
                    return;
                }
            }
            else if (data.ContainsKey("applicationName") && (data.applicationName == "Watermetering" || data.applicationName == "Soraker" || data.applicationName == "Bergsaker"))
            {
                deviceName = "se:servanet:lora:msva:" + Convert.ToString(data.deviceName);

                if (topic == "/event/up")
                {
                    if (obj != null && obj.ContainsKey("statusCode"))
                    {
                        int statusCode = obj.statusCode;
                        int curVol     = 0;

                        if (obj.ContainsKey("curVol"))
                        {
                            curVol = obj.curVol;
                            if (curVol >= 0)
                            {
                                var entity = new Fiware.WaterConsumptionObserved(deviceName + ":" + dateStrNow, deviceName, dateStrNow, curVol);

                                try
                                {
                                    _fiwareContextBroker.CreateNewEntity(entity);
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine($"Exception caught attempting to post WaterConsumptionObserved: {e.Message}");
                                };
                            }
                            else
                            {
                                Console.WriteLine($"Ignoring negative current volume: {curVol}");
                            }
                        }
                    }

                    if (data.ContainsKey("rxInfo"))
                    {
                        dynamic rxInfo = data["rxInfo"];
                        if (rxInfo.Count > 0)
                        {
                            dynamic gateway = rxInfo[0];
                            int     maxRSSI = gateway.rssi;
                            int     snr     = gateway.loRaSNR;
                            string  name    = gateway.name;

                            for (int i = 1; i < rxInfo.Count; i++)
                            {
                                if (rxInfo[i].rssi > maxRSSI)
                                {
                                    maxRSSI = rxInfo[i].rssi;
                                    snr     = gateway.loRaSNR;
                                    name    = rxInfo[i].name;
                                }
                            }

                            Console.WriteLine($"{deviceName} is connected to gateway {name} with rssi {maxRSSI} and snr {snr}");

                            double rssiLevel = Math.Round((125.0 - Math.Abs(maxRSSI)) / 100.0, 2);
                            rssiLevel = Math.Min(Math.Max(0, rssiLevel), 1.0); // RSSI level should be in range [0 1]

                            double snrLevel = Math.Round((snr + 20.0) / 32.0, 2);
                            snrLevel = Math.Min(Math.Max(0, snrLevel), 1.0);

                            var msg = new Fiware.DeviceMessage(deviceName).WithRSSI(rssiLevel).WithSNR(snrLevel);
                            try
                            {
                                _fiwareContextBroker.PostMessage(msg);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine($"Exception caught attempting to post Device update: {e.Message}");
                            };
                        }
                    }
                }
                else if (topic == "/event/status")
                {
                    if (data.externalPowerSource == false && data.batteryLevelUnavailable == false)
                    {
                        double batteryLevel = data.batteryLevel / 100.0;
                        var    msg          = new Fiware.DeviceMessage(deviceName).WithVoltage(Math.Round(batteryLevel, 2));
                        try
                        {
                            _fiwareContextBroker.PostMessage(msg);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"Exception caught attempting to post Device update: {e.Message}");
                        };
                    }
                }
            }

            Console.WriteLine($"Got message from {deviceName} on topic {topic}: {json}");
        }