diff --git a/CHANGELOG b/CHANGELOG index 70123a4..25465d1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ ## 1.2.10 ### New Features ### Bugfixes +* Parse also all Doublevalues as Int ### Changes * Change Online Map MaxZoom to 19 * Searchfunction case insensitive diff --git a/Communcation.yml b/Communcation.yml new file mode 100644 index 0000000..f4f2413 --- /dev/null +++ b/Communcation.yml @@ -0,0 +1,238 @@ +asyncapi: 2.0.0 +info: + title: Lora-Internal-Flow + version: '1.0.0' + description: | + Internal Communication for: + * Lora-Gateway + * Lora-Map + license: + name: LGPL3 + url: http://www.gnu.org/licenses/lgpl-3.0.html + +servers: + production: + url: 127.0.0.1:{port} + protocol: mqtt + description: Lora-Broker + security: + - userPassword: [] + variables: + port: + description: Secure connection (TLS) is available through port 8883. + default: '1883' + enum: + - '1883' + - '8883' + +defaultContentType: application/json + +channels: + lora/data/{deviceID}: + description: The topic on whitch the devices are shown for Tracking data. + parameters: + deviceID: + $ref: '#/components/parameters/deviceID' + subscribe: + summary: Send informations over a Tracker on that topic with an id + operationId: loradata + message: + $ref: '#/components/messages/loradata' + + + smartylighting/streetlights/1/0/action/{streetlightId}/dim: + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + publish: + operationId: dimLight + message: + $ref: '#/components/messages/dimLight' + +components: + messages: + loradata: + name: trackerData + title: Positionsdata + summary: Informs you about a Position and Status of a Tracker + contentType: application/json + payload: + $ref: "#/components/schemas/loradataPayload" + dimLight: + name: dimLight + title: Dim light + summary: Command a particular streetlight to dim the lights. + payload: + $ref: "#/components/schemas/dimLightPayload" + + schemas: + loradataPayload1: + type: object + properties: + lumens: + type: integer + minimum: 0 + description: Light intensity measured in lumens. + sentAt: + $ref: "#/components/schemas/sentAt" + loradataPayload: + $ref: "#/components/schemas/loradataObject" + dimLightPayload: + type: object + properties: + percentage: + type: integer + description: Percentage to which the light should be dimmed to. + minimum: 0 + maximum: 100 + sentAt: + $ref: "#/components/schemas/sentAt" + sentAt: + type: string + format: date-time + description: Date and time when the message was sent. + loradataObject: + type: object + required: + - BatteryLevel + - Gps + - Name + - Receivedtime + - Rssi + - Snr + properties: + Bandwidth: + type: integer + description: Bandwidth on witch the Signal was recieved + minimum: 7800 + maximum: 500000 + BatteryLevel: + type: number + description: Voltage of the battery from the device + minimum: 2.5 + maximum: 5 + Calculatedcrc: + type: integer + description: The calculated CRC + Codingrate: + type: integer + description: The Codingrate in witch the Signal was recieved + minimum: 5 + maximum: 8 + Crcstatus: + type: string + description: Shows the CRC-Status in a Field + enum: + - Ok + - Bad + - No + Frequency: + type: integer + description: The Frequency on that the Message was arrived + Gps: + type: object + description: Gps-Data of a Message + required: + - Fix + - Hdop + - Height + - LastGPSPos + - LastLatitude + - LastLongitude + - Latitude + - Longitude + properties: + Fix: + type: boolean + description: Status of the Tracker, true if it has GPS-Signal + Hdop: + type: number + description: Dislocation from GPS-Reciever + minimum: 0.8 + maximum: 25 + Height: + type: number + description: Height of the GPS-Reciever + LastGPSPos: + type: string + description: Timestamp when the GPS-Reciever has its last position + format: dd/mm/YYYY hh:MM:ss + default: 01/01/2019 12:00:00 + LastLatitude: + type: number + description: Last Latitude of the GPS-Reciever + default: 50.7 + LastLongitude: + type: number + description: Last Longitude of the GPS-Reciever + default: 7.2 + Latitude: + type: number + description: Latitude of the GPS-Reciever + default: 50.7 + Longitude: + type: number + description: Longitude of the GPS-Reciever + default: 7.2 + Time: + type: string + description: Timestamp of the GPS-Reciever, that it gets from the Satelites + format: dd/mm/YYYY hh:MM:ss + default: 01/01/2019 12:00:00 + Host: + type: string + description: Name of the Gateway that Recieves the Data + Name: + type: string + description: Name of the GPS-Tracker, must be unique between every Device + format: "/[a-z]{2}/i" + PacketRssi: + type: number + description: Recieve Signal Strength Index for the whole LORA-Messgae + Receivedtime: + type: string + description: Timestamp of the Gateway, when it recieves the LORA-Message + format: dd/mm/YYYY hh:MM:ss + default: 01/01/2019 12:00:00 + Recieverinterface: + type: integer + description: Internal virtual Radio of the Gateway, witch recieves the LORA-Messange + Recieverradio: + type: integer + description: Internal Radio of the Gateway, witch recieves the LORA-Messange + Rssi: + type: number + description: Recieve Signal Strength Index for the LORA-Message + Snr: + type: number + description: Signal to Noise Ratio of the LORA-Message + Snrmax: + type: number + description: Maximum Signal to Noise Ratio of the LORA-Message + Snrmin: + type: number + description: Minimum Signal to Noise Ratio of the LORA-Message + Spreadingfactor: + type: integer + description: The Spreadingfactor of the LORA-Message + minimum: 7 + maximum: 12 + Time: + type: integer + description: Internal Timecounter of the LORA-Reciever + + + securitySchemes: + userPassword: + type: userPassword + description: Using Username and Password to connect to online broker + + parameters: + streetlightId: + description: The ID of the streetlight. + schema: + type: string + deviceID: + description: The ID of the streetlight. + schema: + type: string diff --git a/Communication.md b/Communication.md new file mode 100644 index 0000000..b5b5c99 --- /dev/null +++ b/Communication.md @@ -0,0 +1,853 @@ +# Lora-Internal-Flow 1.0.0 documentation + + + +Internal Communication for: +* Lora-Gateway +* Lora-Map + + +## Table of Contents + + + +* [Servers](#servers) + + +* [Channels](#channels) + + + + + + +## Servers + + + + + + + + + + + + + + + + + + + + + + +
URLProtocolDescription
127.0.0.1:{port}mqttLora-Broker
+
+ URL Variables + + + + + + + + + + + + + + + + + +
NameDefault valuePossible valuesDescription
port + 1883 + +
  • 1883
  • 8883
+
Secure connection (TLS) is available through port 8883.
+
+
+
+ Security Requirements + + + + + + + + + + + + + + + + + + + +
TypeInNameSchemeFormatDescription
userPassword

Using Username and Password to connect to online broker

+
+
+
+ + + + + + +## Channels + + + + + + +The topic on whitch the devices are shown for Tracking data. + + + + +#### Channel Parameters + + + +##### deviceID + + +The ID of the streetlight. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
deviceID + + stringAny
+ + + + + +### `subscribe` lora/data/{deviceID} + +#### Message + + + +Informs you about a Position and Status of a Tracker + + + + + + + +##### Payload + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
Bandwidth + + integer

Bandwidth on witch the Signal was recieved

+
Any
BatteryLevel + + number

Voltage of the battery from the device

+
Any
Calculatedcrc + + integer

The calculated CRC

+
Any
Codingrate + + integer

The Codingrate in witch the Signal was recieved

+
Any
Crcstatus + + string

Shows the CRC-Status in a Field

+
Ok, Bad, No
Frequency + + integer

The Frequency on that the Message was arrived

+
Any
Gps + + object

Gps-Data of a Message

+
Any
Gps.Fix + + boolean

Status of the Tracker, true if it has GPS-Signal

+
Any
Gps.Hdop + + number

Dislocation from GPS-Reciever

+
Any
Gps.Height + + number

Height of the GPS-Reciever

+
Any
Gps.LastGPSPos + + string

Timestamp when the GPS-Reciever has its last position

+
Any
Gps.LastLatitude + + number

Last Latitude of the GPS-Reciever

+
Any
Gps.LastLongitude + + number

Last Longitude of the GPS-Reciever

+
Any
Gps.Latitude + + number

Latitude of the GPS-Reciever

+
Any
Gps.Longitude + + number

Longitude of the GPS-Reciever

+
Any
Gps.Time + + string

Timestamp of the GPS-Reciever, that it gets from the Satelites

+
Any
Host + + string

Name of the Gateway that Recieves the Data

+
Any
Name + + string

Name of the GPS-Tracker, must be unique between every Device

+
Any
PacketRssi + + number

Recieve Signal Strength Index for the whole LORA-Messgae

+
Any
Receivedtime + + string

Timestamp of the Gateway, when it recieves the LORA-Message

+
Any
Recieverinterface + + integer

Internal virtual Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Recieverradio + + integer

Internal Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Rssi + + number

Recieve Signal Strength Index for the LORA-Message

+
Any
Snr + + number

Signal to Noise Ratio of the LORA-Message

+
Any
Snrmax + + number

Maximum Signal to Noise Ratio of the LORA-Message

+
Any
Snrmin + + number

Minimum Signal to Noise Ratio of the LORA-Message

+
Any
Spreadingfactor + + integer

The Spreadingfactor of the LORA-Message

+
Any
Time + + integer

Internal Timecounter of the LORA-Reciever

+
Any
+ + + +###### Example of payload _(generated)_ + +```json +{ + "Bandwidth": 7800, + "BatteryLevel": 2.5, + "Calculatedcrc": 0, + "Codingrate": 5, + "Crcstatus": "Ok", + "Frequency": 0, + "Gps": { + "Fix": true, + "Hdop": 0.8, + "Height": 0, + "LastGPSPos": "01/01/2019 12:00:00", + "LastLatitude": 50.7, + "LastLongitude": 7.2, + "Latitude": 50.7, + "Longitude": 7.2, + "Time": "01/01/2019 12:00:00" + }, + "Host": "string", + "Name": "string", + "PacketRssi": 0, + "Receivedtime": "01/01/2019 12:00:00", + "Recieverinterface": 0, + "Recieverradio": 0, + "Rssi": 0, + "Snr": 0, + "Snrmax": 0, + "Snrmin": 0, + "Spreadingfactor": 7, + "Time": 0 +} +``` + + + + + + + + + + + + + + +#### Channel Parameters + + + +##### streetlightId + + +The ID of the streetlight. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
streetlightId + + stringAny
+ + + + + +### `publish` smartylighting/streetlights/1/0/action/{streetlightId}/dim + +#### Message + + + +Command a particular streetlight to dim the lights. + + + + + + + +##### Payload + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
percentage + + integer

Percentage to which the light should be dimmed to.

+
Any
sentAt + + string

Date and time when the message was sent.

+
Any
+ + + +###### Example of payload _(generated)_ + +```json +{ + "percentage": 0, + "sentAt": "2019-09-24T12:10:43Z" +} +``` + + + + + + + + + + diff --git a/Lora-Map/Model/AlarmItem.cs b/Lora-Map/Model/AlarmItem.cs index 8160ad0..36c3854 100644 --- a/Lora-Map/Model/AlarmItem.cs +++ b/Lora-Map/Model/AlarmItem.cs @@ -23,34 +23,34 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { public AlarmItem(JsonData json) => this.Update(json); public void Update(JsonData json) { - this.Rssi = (Double)json["Rssi"]; - this.Snr = (Double)json["Snr"]; - if(DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) { + this.Rssi = json["Rssi"].IsInt ? (Int32)json["Rssi"] : (Double)json["Rssi"]; + this.Snr = json["Snr"].IsInt ? (Int32)json["Snr"] : (Double)json["Snr"]; + if (DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) { this.Lorarecievedtime = updatetime.ToUniversalTime(); } this.Recievedtime = DateTime.UtcNow; - this.Latitude = (Double)json["Gps"]["Latitude"]; - this.Longitude = (Double)json["Gps"]["Longitude"]; + this.Latitude = json["Gps"]["Latitude"].IsInt ? (Int32)json["Gps"]["Latitude"] : (Double)json["Gps"]["Latitude"]; + this.Longitude = json["Gps"]["Longitude"].IsInt ? (Int32)json["Gps"]["Longitude"] : (Double)json["Gps"]["Longitude"]; this.Fix = (Boolean)json["Gps"]["Fix"]; - if(!this.Fix) { - this.Latitude = (Double)json["Gps"]["LastLatitude"]; - this.Longitude = (Double)json["Gps"]["LastLongitude"]; + if (!this.Fix) { + this.Latitude = json["Gps"]["LastLatitude"].IsInt ? (Int32)json["Gps"]["LastLatitude"] : (Double)json["Gps"]["LastLatitude"]; + this.Longitude = json["Gps"]["LastLongitude"].IsInt ? (Int32)json["Gps"]["LastLongitude"] : (Double)json["Gps"]["LastLongitude"]; } this.UTM = new UTMData(this.Latitude, this.Longitude); - this.Hdop = (Double)json["Gps"]["Hdop"]; - this.Height = (Double)json["Gps"]["Height"]; + this.Hdop = json["Gps"]["Hdop"].IsInt ? (Int32)json["Gps"]["Hdop"] : (Double)json["Gps"]["Hdop"]; + this.Height = json["Gps"]["Height"].IsInt ? (Int32)json["Gps"]["Height"] : (Double)json["Gps"]["Height"]; this.SetHistory(json); } private void SetHistory(JsonData json) { - String key = ((Double)json["BatteryLevel"]).ToString(); - key += "_" + ((Int32)json["Calculatedcrc"]).ToString(); - key += "_" + ((Double)json["Gps"]["Hdop"]).ToString(); - key += "_" + ((Double)json["Gps"]["Height"]).ToString(); - key += "_" + ((Boolean)json["Gps"]["Fix"]).ToString(); - key += "_" + ((Double)json["Gps"]["LastLatitude"]).ToString(); - key += "_" + ((Double)json["Gps"]["LastLongitude"]).ToString(); - key += "_" + ((String)json["Gps"]["Time"]); + String key = json["BatteryLevel"].ToString(); + key += "_" + json["Calculatedcrc"].ToString(); + key += "_" + json["Gps"]["Hdop"].ToString(); + key += "_" + json["Gps"]["Height"].ToString(); + key += "_" + json["Gps"]["Fix"].ToString(); + key += "_" + json["Gps"]["LastLatitude"].ToString(); + key += "_" + json["Gps"]["LastLongitude"].ToString(); + key += "_" + json["Gps"]["Time"].ToString(); if(!this.buttonhistory.ContainsValue(key)) { this.buttonhistory.Add(DateTime.UtcNow, key); if(this.buttonhistory.Count > 10) { @@ -61,21 +61,21 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { public static String GetId(JsonData json) => (String)json["Name"]; - public static Boolean CheckJson(JsonData json) => - json.ContainsKey("Rssi") && json["Rssi"].IsDouble && - json.ContainsKey("Snr") && json["Snr"].IsDouble && - json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString && - json.ContainsKey("Gps") && json["Gps"].IsObject && - json["Gps"].ContainsKey("Latitude") && json["Gps"]["Latitude"].IsDouble && - json["Gps"].ContainsKey("Longitude") && json["Gps"]["Longitude"].IsDouble && - json["Gps"].ContainsKey("LastLatitude") && json["Gps"]["LastLatitude"].IsDouble && - json["Gps"].ContainsKey("LastLongitude") && json["Gps"]["LastLongitude"].IsDouble && - json["Gps"].ContainsKey("Hdop") && json["Gps"]["Hdop"].IsDouble && - json["Gps"].ContainsKey("Fix") && json["Gps"]["Fix"].IsBoolean && - json["Gps"].ContainsKey("Height") && json["Gps"]["Height"].IsDouble && - json["Gps"].ContainsKey("Time") && json["Gps"]["Time"].IsString && - json.ContainsKey("Name") && json["Name"].IsString && - json.ContainsKey("Calculatedcrc") && json["Calculatedcrc"].IsInt && - json.ContainsKey("BatteryLevel") && json["BatteryLevel"].IsDouble; + public static Boolean CheckJson(JsonData json) => + json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt) + && json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt) + && json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString + && json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt) + && json.ContainsKey("Gps") && json["Gps"].IsObject + && json["Gps"].ContainsKey("Latitude") && (json["Gps"]["Latitude"].IsDouble || json["Gps"]["Latitude"].IsInt) + && json["Gps"].ContainsKey("Longitude") && (json["Gps"]["Longitude"].IsDouble || json["Gps"]["Longitude"].IsInt) + && json["Gps"].ContainsKey("LastLatitude") && (json["Gps"]["LastLatitude"].IsDouble || json["Gps"]["LastLatitude"].IsInt) + && json["Gps"].ContainsKey("LastLongitude") && (json["Gps"]["LastLongitude"].IsDouble || json["Gps"]["LastLongitude"].IsInt) + && json["Gps"].ContainsKey("LastGPSPos") && json["Gps"]["LastGPSPos"].IsString + && json["Gps"].ContainsKey("Hdop") && (json["Gps"]["Hdop"].IsDouble || json["Gps"]["Hdop"].IsInt) + && json["Gps"].ContainsKey("Fix") && json["Gps"]["Fix"].IsBoolean + && json["Gps"].ContainsKey("Height") && (json["Gps"]["Height"].IsDouble || json["Gps"]["Height"].IsInt) + && json.ContainsKey("Name") && json["Name"].IsString && + json.ContainsKey("Calculatedcrc") && json["Calculatedcrc"].IsInt; } } \ No newline at end of file diff --git a/Lora-Map/Model/PositionItem.cs b/Lora-Map/Model/PositionItem.cs index 9149ba6..f94c1c5 100644 --- a/Lora-Map/Model/PositionItem.cs +++ b/Lora-Map/Model/PositionItem.cs @@ -37,45 +37,46 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { this.Group = null; } } - public static Boolean CheckJson(JsonData json) => json.ContainsKey("Rssi") && json["Rssi"].IsDouble - && json.ContainsKey("Snr") && json["Snr"].IsDouble + public static Boolean CheckJson(JsonData json) => + json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt) + && json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt) && json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString - && json.ContainsKey("BatteryLevel") && json["BatteryLevel"].IsDouble + && json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt) && json.ContainsKey("Gps") && json["Gps"].IsObject - && json["Gps"].ContainsKey("Latitude") && json["Gps"]["Latitude"].IsDouble - && json["Gps"].ContainsKey("Longitude") && json["Gps"]["Longitude"].IsDouble - && json["Gps"].ContainsKey("LastLatitude") && json["Gps"]["LastLatitude"].IsDouble - && json["Gps"].ContainsKey("LastLongitude") && json["Gps"]["LastLongitude"].IsDouble + && json["Gps"].ContainsKey("Latitude") && (json["Gps"]["Latitude"].IsDouble || json["Gps"]["Latitude"].IsInt) + && json["Gps"].ContainsKey("Longitude") && (json["Gps"]["Longitude"].IsDouble || json["Gps"]["Longitude"].IsInt) + && json["Gps"].ContainsKey("LastLatitude") && (json["Gps"]["LastLatitude"].IsDouble || json["Gps"]["LastLatitude"].IsInt) + && json["Gps"].ContainsKey("LastLongitude") && (json["Gps"]["LastLongitude"].IsDouble || json["Gps"]["LastLongitude"].IsInt) && json["Gps"].ContainsKey("LastGPSPos") && json["Gps"]["LastGPSPos"].IsString - && json["Gps"].ContainsKey("Hdop") && json["Gps"]["Hdop"].IsDouble + && json["Gps"].ContainsKey("Hdop") && (json["Gps"]["Hdop"].IsDouble || json["Gps"]["Hdop"].IsInt) && json["Gps"].ContainsKey("Fix") && json["Gps"]["Fix"].IsBoolean - && json["Gps"].ContainsKey("Height") && json["Gps"]["Height"].IsDouble + && json["Gps"].ContainsKey("Height") && (json["Gps"]["Height"].IsDouble || json["Gps"]["Height"].IsInt) && json.ContainsKey("Name") && json["Name"].IsString; public static String GetId(JsonData json) => (String)json["Name"]; public void Update(JsonData json) { - this.Rssi = (Double)json["Rssi"]; - this.Snr = (Double)json["Snr"]; + this.Rssi = json["Rssi"].IsInt ? (Int32)json["Rssi"] : (Double)json["Rssi"]; + this.Snr = json["Snr"].IsInt ? (Int32)json["Snr"] : (Double)json["Snr"]; if(DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) { this.Lorarecievedtime = updatetime.ToUniversalTime(); } this.Recievedtime = DateTime.UtcNow; - this.Battery = Math.Round((Double)json["BatteryLevel"], 2); + this.Battery = Math.Round(json["BatteryLevel"].IsInt ? (Int32)json["BatteryLevel"] : (Double)json["BatteryLevel"], 2); this.Batterysimple = this.Battery < 3.44 ? 0 : this.Battery < 3.53 ? 1 : this.Battery < 3.6525 ? 2 : this.Battery < 3.8825 ? 3 : 4; - this.Latitude = (Double)json["Gps"]["Latitude"]; - this.Longitude = (Double)json["Gps"]["Longitude"]; + this.Latitude = json["Gps"]["Latitude"].IsInt ? (Int32)json["Gps"]["Latitude"] : (Double)json["Gps"]["Latitude"]; + this.Longitude = json["Gps"]["Longitude"].IsInt ? (Int32)json["Gps"]["Longitude"] : (Double)json["Gps"]["Longitude"]; this.Fix = (Boolean)json["Gps"]["Fix"]; if(!this.Fix) { - this.Latitude = (Double)json["Gps"]["LastLatitude"]; - this.Longitude = (Double)json["Gps"]["LastLongitude"]; + this.Latitude = json["Gps"]["LastLatitude"].IsInt ? (Int32)json["Gps"]["LastLatitude"] : (Double)json["Gps"]["LastLatitude"]; + this.Longitude = json["Gps"]["LastLongitude"].IsInt ? (Int32)json["Gps"]["LastLongitude"] : (Double)json["Gps"]["LastLongitude"]; } this.UTM = new UTMData(this.Latitude, this.Longitude); if(DateTime.TryParse((String)json["Gps"]["LastGPSPos"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime lastgpstime)) { this.Lastgpspostime = lastgpstime.ToUniversalTime(); } - this.Hdop = (Double)json["Gps"]["Hdop"]; - this.Height = (Double)json["Gps"]["Height"]; + this.Hdop = json["Gps"]["Hdop"].IsInt ? (Int32)json["Gps"]["Hdop"] : (Double)json["Gps"]["Hdop"]; + this.Height = json["Gps"]["Height"].IsInt ? (Int32)json["Gps"]["Height"] : (Double)json["Gps"]["Height"]; }