public override void Decode(string timestamp, string device, string topic, byte[] payload) { if (topic == UplinkPort1Topic) { ReadOnlySpan <byte> span = payload; double millivolts = payload[10]; IoTHubMessageOrigin originWoPosition = new IoTHubMessageOrigin(device); _messageQueue.PostMessage(new SensorStatusMessage(originWoPosition, timestamp, millivolts * 0.025)); double latitude = BinaryPrimitives.ReadInt32LittleEndian(span.Slice(start: 0, length: 4)); double longitude = BinaryPrimitives.ReadInt32LittleEndian(span.Slice(start: 4, length: 4)); bool inTrip = (payload[8] & 0x80) != 0; bool lastFixFailed = (payload[8] & 0x40) != 0; double heading = (payload[8] & 0x3F); // Maska bort de första två bitarna för att få heading double speed = payload[9]; // TODO: Bestäm vad som är ett bra filter här egentligen ... if (speed > 0) { IoTHubMessageOrigin originWoDevice = new IoTHubMessageOrigin(latitude / 10000000.0, longitude / 10000000.0); _messageQueue.PostMessage(new BicycleMovementMessage(originWoDevice, timestamp, heading * 5.625, speed)); } } }
public SensorStatusMessage ToStatusMessage() { AVLProperty p = TwoByteIO.Find(x => x.ID == "67"); if (p != null) { double lat, lon; Double.TryParse(Latitude, out lat); Double.TryParse(Longitude, out lon); DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); dt = dt.AddMilliseconds(long.Parse(TimeStamp)); IoTHubMessageOrigin origin = new IoTHubMessageOrigin($"icom-{IMEI}", lat / 10000000.0, lon / 10000000.0); return(new SensorStatusMessage(origin, dt.ToString("yyyy-MM-ddTHH:mm:ssZ"), p.Value / 1000.0)); } return(null); }
public CarMovementMessage ToCarMovementMessage() { if (IsIgnitionOn()) { double lat, lon, heading, velocity; Double.TryParse(Latitude, out lat); Double.TryParse(Longitude, out lon); Double.TryParse(Angle, out heading); Double.TryParse(Speed, out velocity); DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); dt = dt.AddMilliseconds(long.Parse(TimeStamp)); IoTHubMessageOrigin origin = new IoTHubMessageOrigin(lat / 10000000.0, lon / 10000000.0); return(new CarMovementMessage(origin, dt.ToString("yyyy-MM-ddTHH:mm:ssZ"), heading, velocity)); } return(null); }
public override void Decode(string timestamp, string device, string topic, byte[] payload) { if (payload.Length != 19 || topic != WeatherTopic) { return; } ReadOnlySpan <byte> span = payload; // TODO: Denna hårdkodning gäller endast för den väderstation som sitter på MIUN, vi kommer // att behöva hantera sensorposition på ett intelligentare sätt framöver när de blir fler. double latitude = 62.391944; double longitude = 17.285917; IoTHubMessageOrigin origin = new IoTHubMessageOrigin(device, latitude, longitude); double millivolts = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 17, length: 2)); _messageQueue.PostMessage(new SensorStatusMessage(origin, timestamp, millivolts / 1000.0)); double temperature = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 0, length: 2)); _messageQueue.PostMessage(new TelemetryTemperature(origin, timestamp, (temperature - 4000) / 100.0)); const double kmphToMpS = 1000.0 / 60.0 / 60.0; double windspeed = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 9, length: 2)); windspeed = Math.Round(windspeed * kmphToMpS / 100.0, 2); int winddirection = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 11, length: 2)); _messageQueue.PostMessage(new TelemetryWind(origin, timestamp, windspeed, winddirection)); double lux = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 13, length: 2)); double uvidx = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(start: 15, length: 2)); _messageQueue.PostMessage(new TelemetryLight(origin, timestamp, lux * 10, uvidx / 100.0)); }
public TelemetryLight(IoTHubMessageOrigin origin, string timestamp, double lux, double uvIndex) : base(origin, timestamp, "telemetry.light") { Lux = Math.Round(lux, 2); UvIndex = Math.Round(uvIndex, 2); }
public IoTHubMessage(IoTHubMessageOrigin origin, string timestamp, string topic) { Origin = origin; Timestamp = timestamp; Topic = topic; }
public override void Decode(string timestamp, string device, string topic, byte[] payload) { string json = Encoding.UTF8.GetString(payload); SnowdepthPayloadData data = JsonConvert.DeserializeObject <SnowdepthPayloadData>(json); payload = System.Convert.FromBase64String(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? device = "snow_" + deviceInHex; IoTHubMessageOrigin origin = new IoTHubMessageOrigin(device, 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 {device}. 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)); }
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}"); }; } } }
public override void Decode(string timestamp, string device, string topic, byte[] payload) { //8121069065192625893 Circle K 62.387146,17.2948968 //8121069065166743827 Skolhusallen 62.389056,17.2993245 //8121069065154928350 Storgatan 62.3919559,17.294769 //8121069065048831975 Universitetsallen 62.394618,17.2894867 //8121069065164496276 Parkgatan 62.385353,17.3108438 //8121069065126998713 Köpmangatan 62.38861,17.3083424 if (topic != AirQualityTopic) { return; } ReadOnlySpan <byte> span = payload; double latitude = 0; double longitude = 0; if (device == "8121069065192625893") { latitude = 62.387146; longitude = 17.2948968; } else if (device == "8121069065166743827") { latitude = 62.389056; longitude = 17.2993245; } else if (device == "8121069065154928350") { latitude = 62.3919559; longitude = 17.294769; } else if (device == "8121069065048831975") { latitude = 62.394618; longitude = 17.2894867; } else if (device == "8121069065164496276") { latitude = 62.385353; longitude = 17.3108438; } else if (device == "8121069065126998713") { latitude = 62.38861; longitude = 17.3083424; } else { Console.WriteLine("Unknown air quality sensor " + device + ". Position unknown!"); return; } IoTHubMessageOrigin origin = new IoTHubMessageOrigin(device, latitude, longitude); //pack('HHhHHH', pm10, pm25, (DTH_temp + 2732), DTH_humi, sensor_error, NO2ppm) double pm10 = BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(start: 0, length: 2)); _messageQueue.PostMessage(new TelemetryPM10(origin, timestamp, pm10 / 10.0)); double pm25 = BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(start: 2, length: 2)); _messageQueue.PostMessage(new TelemetryPM25(origin, timestamp, pm25 / 10.0)); _messageQueue.PostMessage(new TelemetryTemperature( origin, timestamp, ConvertTemperature( BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(start: 4, length: 2)), device ))); int humidity = BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(start: 6, length: 2)); _messageQueue.PostMessage(new TelemetryHumidity(origin, timestamp, (int)(humidity / 10.0))); if (device != "8121069065126998713") { var no2StartIndex = (device != "8121069065166743827") ? 10 : 8; double no2 = BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(start: no2StartIndex, length: 2)); _messageQueue.PostMessage(new TelemetryNO2(origin, timestamp, ConvertNO2(no2, device))); } }