Modem and Geolocation API

The Modem and Geolocation API supports devices implementing subsets of the Modem Protocol where the modem stack may be executed on a LoRa Edge™ chip or on the host MCU.

The Modem and Geolocation API supports the following functionality:

  • Add devices to, and remove devices from, the device owner account.

  • List/iterate/count the associated devices.

  • Get the device information for selected devices, including the history of log messages, uploaded files, and received streaming records.

  • Request and set attributes for devices, add and clear device requests, and query pending requests.

  • Forward LoRaWAN® messages transmitted by a device to the Cloud Service, and receive any device state updates. The results return the current state of the device, any file or streaming records completed by the message, and, optionally, a downlink message to be sent by the caller to the device.

  • Forward GNSS or Wi-Fi scans to the Modem and Geolocation Service and retrieve modem state updates containing the current, calculated positions of the devices.

  • Device clock synchronization for accurate GNSS positioning and seamless Almanac updates over-the-air for GNSS positioning.

  • Configure settings such as ports of individual devices or specify default settings.

  • Convenience functions, such as clearing device logs.

Request limits

Certain API endpoints limit request parameters. These limits are currently:

  • DEVICE_ADD_LIMIT: 256

  • DEVICE_LIST_LIMIT: 256

  • DEVICE_INFO_LIMIT: 128

  • DEVICE_REQUEST_LIMIT: 128

  • UPLINK_SEND_LIMIT: 128

  • REQUEST_LIST_LIMIT: 8

Device Management API

The basic device management functions allow adding, removing, listing, and moving devices, as well as getting device information. Note that devices are added to the modem management platform implicitly by uplink messages when those messages reference devices that do not already exist.

Add Devices

POST /api/v1/device/add

Explicitly registers devices with the account of the caller. Note that devices are automatically provisioned when an uplink is presented to the service and the device specified in the uplink is not yet registered.

Request Headers

Request Body:

The request body must contain at least one device EUI, and may contain up to DEVICE_ADD_LIMIT.

{
   "deveuis":  [ DEVEUI, .. ]   // Required. List of device EUIs.
}
  • deveuis: Required, list of device EUIs.

Response:

Status Codes
Response Headers

Response JSON:

If successful, the result field of the response points to a mapping of device EUIs to result objects. Each EUI result object carries either a Boolean value or an error. The Boolean value signals whether the device was created during the invocation (True) or existed prior to the invocation (False).

{
   DEVEUI: {
     "error":  STRING,      // Optional. Per-EUI error
     "result": BOOLEAN      // Optional. True if device has been created
   }
   // ...
}

Example Request:

POST /api/v1/device/add HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{
  "deveuis": [ "00-00-00-00-00-00-00-01", ... "00-00-00-00-00-00-00-05" ]
}

Example Response:

{
  "result": {
    "00-00-00-00-00-00-00-01": { "result": true },
    // ...
    "00-00-00-00-00-00-00-05": { "result": true }
  }
}

Remove Devices

POST /api/v1/device/remove

Removes devices from the device owner referenced by the calling token.

Request Headers

Request Body:

The request body must contain the EUI of at least one device to be removed, and may contain up to DEVICE_ADD_LIMIT EUIs.

{
   "deveuis":  [ DEVEUI, .. ]  // Required. List of device EUIs.
}
  • deveuis: Required. List of device EUIs.

Response:

Status Codes
Response Headers

Response JSON:

The request returns a mapping of device EUIs to response objects. If successful, each response object returns a Boolean value in the result field. A value of True indicates the device existed before and was deleted. A value of False indicates that the device did not exist before and still does not exist. If removal of the device failed, an error message is returned in the error field.

Example Request:

POST /api/v1/device/remove HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{
  "deveuis": [ "00-00-00-00-00-00-00-01", ... "00-00-00-00-00-00-00-05" ]
}

Example Response:

{
  "result": { "00-00-00-00-00-00-00-01": { "result": true } }
  // ...
}

Configure Device Ports

POST /api/v1/device/set

Set the device port to protocol mapping for provisioned devices. The parameters dmport, gnssport, gnssngport, wifiport and streamport allow to specify the port on which LoRa Cloud expects the messages of the associated protocol to arrive. Specifying null for a port parameter resets the port to the default port setting of the system. If a port is omitted, that particular port is not updated. This API call should only be invoked after devices have been provisioned and before uplinks from these devices are forwarded.

Request Headers

Request Body:

The request body must contain at least one device EUI and one port specification.

{
   "deveuis":    [ DEVEUI, .. ], // Required. List of device EUIs.
   "dmport":     UINT1,          // Optional, 1 <= p <= 255: DM port to set, null: reset to default
   "gnssport":   UINT1,          // Optional, 1 <= p <= 255: GNSS port to set, null: reset to default
   "gnssngport": UINT1,          // Optional, 1 <= p <= 255: GNSSNG port to set, null: reset to default
   "wifiport":   UINT1,          // Optional, 1 <= p <= 255: Wi-Fi port to set, null: reset to default
   "streamport": UINT1           // Optional, 1 <= p <= 255: STREAM port to set, null: reset to default
}
  • deveuis: Required, list of device EUIs.

  • dmport: Optional, DM port. If null, the current setting is reset to the system default.

  • gnssport: Optional, GNSS port. If null, the current setting is reset to the system default.

  • gnssngport: Optional, GNSSNG port. If null, the current setting is reset to the system default.

  • wifiport: Optional, Wi-Fi port. If null, the current setting is reset to the system default.

  • streamport: Optional, stream port. If null, any stream session is reset and the default stream session based on modem messages is re-instantiated.

See Modem Service Protocol Payloads and Device Ports for protocol and port details.

Response:

Status Codes
Response Headers

Response JSON:

The invocation returns a mapping of EUIs to response objects, where each response object points to a result object (DeviceInfo) or to an error.

Example Request:

POST /api/v1/device/set HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{
  "deveuis":  [ "00-00-00-00-00-00-00-01", ... "00-00-00-00-00-00-00-05" ],
  "dmport":   199,
  "gnssport": 198,
  "gnssngport": 192,
  "wifiport": 197
}

List Devices

POST /api/v1/device/list

Lists devices. Returns up to the specified number of device EUIs. It is possible to specify which device EUI should be used as a starting point for the list.

Request Headers

Request Body:

The request body must contain the field cnt and, optionally, the device EUI to be used as a starting point.

{
   "cnt":    INT,    // Required. Number of EUIs to return, 1<=cnt<=DEVICE_LIST_LIMIT
   "deveui": STRING  // Optional. The device EUI which should be used as a starting point for the list.
}
  • cnt: Required. Number of EUIs to return

  • deveui: Optional. EUI to be used as the starting point.

Response:

Status Codes
Response Headers

Response JSON:

If successful, a list of device EUIs is returned. If there are errors, a list of error messages is returned.

Example Request:

POST /api/v1/device/list HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{
  "cnt": 2,
  "deveui": "00-00-00-00-00-00-00-01"
}

Example Response:

{ "result": [ "00-00-00-00-00-00-00-02" , "00-00-00-00-00-00-00-03" ] }

Count Devices

GET /api/v1/device/count

Counts the devices associated with the caller token.

Request Headers

Request Body:

Any request body is ignored.

Response:

Status Codes
Response Headers

Response JSON:

If successful, an integer specifying the number of devices associated with the caller token is returned. If errors are encountered, a list of error messages is returned.

Example Request:

GET /api/v1/device/count HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{ }

Example Response:

{ "result": 2 }

Get Device Information

POST /api/v1/device/info

Returns the device state for the specified devices.

Request Headers

Request Body:

The request body must contain at least one EUI.

{
   "deveuis":  [ DEVEUI, .. ]  // Required. List of device EUIs.
}
  • deveuis: Required. List of device EUIs; may contain up to DEVICE_INFO_LIMIT EUIs.

Response:

Status Codes
Response Headers

Response JSON:

The invocation returns a mapping of EUIs to response objects, where each response object points to a result object (DeviceInfo) or to an error.

Example Request:

POST /api/v1/device/info HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{ "deveuis": [ "00-00-00-00-00-00-00-01", "00-00-00-00-00-00-00-02" ] }

Example Response:

{
 "result": {
   "00-00-00-00-00-00-00-01": {
     "result": {
     // DeviceInfo ...
   }
   // ...
 }
}

Clear Device State

POST /api/v1/device/clear

Clears the device state on the server including modem fields and stream and file upload sessions but with the exception of configured ports. Note that this endpoint is typically used only during device development. Otherwise partial session resets take place on “joining” messages of end devices.

Request Headers

Request Body:

The request body must contain at least one EUI.

{
   "deveuis":  [ DEVEUI, .. ]  // Required. List of device EUIs.
}
  • deveuis: Required. List of device EUIs;

Response:

Status Codes
Response Headers

Response JSON:

The invocation returns a mapping of EUIs to response objects, where each response object points to a result object (DeviceInfo) or to an error.

Example Request:

POST /api/v1/device/clear HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{ "deveuis": [ "00-00-00-00-00-00-00-01", "00-00-00-00-00-00-00-02" ] }

Example Response:

{
 "result": {
   "00-00-00-00-00-00-00-01": {
     "result": {
     // DeviceInfo ...
   }
   // ...
 }
}

Iterate and Get Device Information

POST /api/v1/device/list_infos

Iterates over all devices and returns device information for each. The invocation returns a map of device EUIs to device state objects. It is up to the caller to filter the returned EUIs for succeeding calls.

Request Headers

Request Body:

The request body must contain the field cnt and, optionally, a starting device EUI.

{
   "cnt":    INT,    // Required. Number of EUIs to return, 1<=cnt<=DEVICE_LIST_LIMIT
   "deveui": DEVEUI  // Optional. The device EUI which should be used as a starting point for the list.
}
  • cnt: Required. Number of EUIs to return

  • deveui: Optional. Device EUI to be used as the starting point for the list.

Response:

Status Codes
Response Headers

Response JSON:

If successful, the result field points to a list of objects in the following format, where the list is sorted by the deveui field. If errors are encountered, the errors field points to a list of error messages.

[
  {
    "deveui":    DEVEUI,     // Required. Device EUI.
    "info":      DEVICEINFO  //  Required. Device information.
  }.
  ...
]
  • deveui: Required. Device EUI.

  • info: Required. A DeviceInfo object.

Device Communication API

These calls relate to the communication with devices, the manipulation of device states, and the signaling of downlink messages.

The most important API calls, /uplink/send and /device/send, take uplinks received by devices, update the internal devices states and return device information and any completed files, streaming records or resolved positions. /uplink/send accepts multiple device uplinks in a single request, /device/send accepts a single uplink.

Add Device Requests

POST /api/v1/requests/add

The Modem Service protocol allows a number requests to be triggered which are transmitted by LoRaWAN downlink messages to the device. The Modem Service allows you to queue such requests and manages the interaction between the back end and the device until the request has been fulfilled by the device.

Once a request is queued with the service, the service will generate the corresponding downlink message on each new modem uplink. The caller must schedule the downlink messages on the network server. Upon arrival of the next uplink, the service checks the completion status of pending requests. If any requests remain pending, a new downlink message is generated. If all requests have been completed, requests are cleared. The application must schedule the downlink messages in order, and must not re-transmit downlink messages.

Request Headers

Request Body:

The request body expects the EUIs of the destination devices and a list of requests. Each request includes the type field, denoting the request type and, optionally, a request-specific parameter.

{
  "deveuis":    [ DEVEUI, ..],  // Required. List of device EUIs, up to DEVICE_REQUEST_LIMIT
  "requests":   [ REQUEST, .. ] // Required. List of request objects, up to REQUEST_LIST_LIMIT
}
  • deveuis: Required. List device EUIs (at least one must be provided). Up to DEVICE_REQUEST_LIMIT EUIs are allowed.

  • requests: Required. List of ModemRequest objects.

Response:

Status Codes
Response Headers

Response JSON:

The response contains a mapping of EUIs to response objects.

If successful, each EUI response returns a DeviceInfo object in the result field if the request could be added to the device. The DeviceInfo object encapsulates the state of a device, including any pending requests. If errors were encountered, they are signaled in the error field of the response object.

Set Device Requests

POST /api/v1/requests/set

Convenience function. Clears all requests before adding new requests.

Request Headers

Request Body:

See Add Device Requests.

Response:

Status Codes
Response Headers

Response JSON:

The invocation returns a map of EUIs to response objects. Each EUI response returns an DeviceInfo object in the result field if the request could be added to the device. The DeviceInfo object encapsulates the state of a device, including any pending requests. If errors were encountered, they are signaled in the error field of the response object.

Clear Device Requests

POST /api/v1/requests/clear

Clears all pending requests.

Request Headers

Request Body:

The request body must contain at least one EUI, and may contain up to DEVICE_REQUEST_LIMIT EUIs.

{
   "deveuis":  [ DEVEUI, .. ]  // Required. List of device EUIs.
}
  • deveuis: Required. Device EUIs.

Response:

Status Codes
Response Headers

Response JSON:

Invoking this API returns a mapping of device EUIs to response objects. Each EUI response includes an DeviceInfo object in the result field if the request could be added to the device. The DeviceInfo object encapsulates the state of a device, including any pending requests. If errors were encountered, they are signaled in the error field of the response object.

Fetch File Uploads

POST /api/v1/uploads/fetch

The Modem Service caches the last few file uploads for a device, in case a back-end application may have missed a file response on an uplink request. The fetch call makes it possible to retrieve the file upload history and to clear the history in the device state on the server.

Request Headers

Request Body:

The request body must contain at least one EUI, and may contain up to DEVICE_REQUEST_LIMIT EUIs.

{
   "deveuis":  [ DEVEUI, .. ]  // Required. List of device EUIs.
}
  • deveuis: Required. List of device EUIs.

Response:

Status Codes
Response Headers

Response JSON:

The invocation returns a map of EUIs to response objects. If successful, each EUI response returns an object in the result field with two fields, “info”, a DeviceInfo object, and “files”, an array of FileObject objects.

Device Owner Configuration API

These API calls allow you to get and set device specific default settings for a device owner.

Get Device Owner Configuration

GET /api/v1/devowner/config

Returns the current Device Owner configuration.

Request Headers

Response:

Status Codes
Response Headers

Response JSON:

{
  "autoprovision": BOOL,    // Required. True if device owner allows for devices to be provisioned on 1st uplink.
  "device_quota":  UINT,    // Required. 0 unlimited, > 0 the configured device quota. Tier quotas still apply.
  "device_defaults": {      // Specification for defaults for created devices:
    "dmport":      UINT1,   //   Optional. DM port to set for new devices, or NULL to indicate default system port.
    "gnssport":    UINT1,   //   Optional. GNSS port to set for new devices, or NULL to indicate default system port.
    "gnssngport":  UINT1,   //   Optional. GNSSNG port to set for new devices, or NULL to indicate default system port.
    "wifiport":    UINT1,   //   Optional. Wi-Fi port to set for new devices, or NULL to indicate default system port.
    "streamport":  UINT1    //   Optional. Stream port to set for new devices, or NULL to indicate default system port.
}
  • autoprovision: Required. True if the device owner allows for a device being provisioned on the first uplink.

  • device_quota: Required. Specifies the specific device quota of the device owner. Tier-specific device quotas always apply. Any port specifications must be larger than 0 and less then 256.

  • device_defaults: Required. Specifies the device ports as configured by the device owner.

See Modem Service Protocol Payloads and Device Ports for protocol and port details.

Update Device Owner Configuration

POST /api/v1/devowner/config

Updates the current Device Owner configuration.

Request Headers

Request Body:

The request body contains the configuration for the device owner.

{
  "autoprovision": BOOL,    // Optional. True if the device owner allows devices to be provisioned on 1st uplink.
  "device_quota":  INT,     // Optional. 0 unlimited, > 0 the device quota (in multiples of 1000) to be configured. Tier quotas still apply.
  "device_defaults": {      // Optional specification for default settings for created devices:
     "dmport":     UINT1,     // Optional, DM port to set for new devices, null to reset to default system port
     "gnssport":   UINT1,     // Optional, GNSS port to set for new devices, null to reset to default system port
     "gnssngport": UINT1,     // Optional, GNSSNG port to set for new devices, null to reset to default system port
     "wifiport":   UINT1,     // Optional, Wi-Fi port to set for new devices, null to reset to default system port
     "streamport": UINT1      // Optional, STREAM port to set for new devices, null to reset to default system port
  }
}
  • autoprovision: Optional. True if device owner allows for a device being provisioned on 1st uplink. False if autoprovisioning is not supported.

  • device_quota: Optional. In case of zero, no quota is set by the device owner (but the upper limit of the tier quota applies). If positive, the quota to be set for the device owner, in thousands (1000s).

  • device_defaults: Optional. If a port is specified, a UINT1 or null is valid. An UINT1 overwrites the default port, null resets to the default port of the system.

Response:

Status Codes
Response Headers

Response JSON:

If successful, the result field is empty and no errors are returned.

Example Request:

POST /api/v1/devowner/config HTTP/1.1
Host: mgs.loracloud.com
Content-Type: application/json
{
  "autoprovision": true,       // Enable auto-provisioning
  "device_quota":  5,          // 5000 devices
  "device_defaults": {
    "dmport":     199,         // Set DM port to 199
    "gnssport":   null,        // Leave GNSS port untouched
    "gnssngport":   null,      // Leave GNSSNG port untouched
    "wifiport":   null,        // Leave Wi-Fi port untouched
    "streamport": null         // Leave streamport untouched
  }
}

Modem Service JSON Formats

Device Info

“Device Info” objects encapsulate the current state of a modem as known to the server.

DEVICEINFO = {
  "fports":          FPORTS,                  // Current device port settings
  "info_fields":     INFO_FIELDS,             // Current view of modem fields by service
  "pending_requests": {
    "requests":      [ PENDING_REQUEST, .. ]  // List of pending requests
  },
  "log_messages":    [ LOG_MESSAGE, .. ],     // Service-level messages related to this device
  "uploaded_files":  [ FILE, .. ],            // History of uploaded files
  "uploaded_stream_records": [ STREAM, .. ],  // History of uploaded records
  "last_uplink":      UPLINK_MSG              // Most-recently handled uplink
}
  • fports: Required. Current DevicePorts settings.

  • info_fields: Required. List of InfoFields objects

  • pending_requests: Required. List of PendingRequest objects

  • log_messages: Required. List of log messages, LogMessage

  • uploaded_files: Required. History of uploaded files, FileObject

  • uploaded_stream_records: Required. History of uploaded records, StreamObject

  • last_uplink: Required. Last uplink, UplinkMsg

INFO_FIELDS

This object contains the value of the various information fields and the timestamp of the last update.

INFO_FIELDS = {
 "status":   null | { "timestamp": FLOAT, "value": STATUS_FIELD },
 "charge":   null | { "timestamp": FLOAT, "value": UINT2 },
 "voltage":  null | { "timestamp": FLOAT, "value": FLOAT },
 "temp":     null | { "timestamp": FLOAT, "value": INT },
 "signal":   null | { "timestamp": FLOAT, "value": { "rssi": INT, "snr": FLOAT }},
 "uptime":   null | { "timestamp": FLOAT, "value": UINT2 },
 "rxtime":   null | { "timestamp": FLOAT, "value": UINT2 },
 "firmware": null | { "timestamp": FLOAT, "value": { "fwcrc": HEX, "fwtotal": UINT2, "fwcompleted": UINT2 }},
 "adrmode":  null | { "timestamp": FLOAT, "value": ADRMODE }, // encoding see REQUEST
 "joineui":  null | { "timestamp": FLOAT, "value": DEVEUI },
 "interval": null | { "timestamp": FLOAT, "value": REPINTV }, // encoding see REQUEST
 "region":   null | { "timestamp": FLOAT, "value": UINT1 },   // according to device manual
 "crashlog": null | { "timestamp": FLOAT, "value": STRING },
 "rstcount": null | { "timestamp": FLOAT, "value": UINT2 },
 "deveui":   null | { "timestamp": FLOAT, "value": DEVEUI },
 "rfu":      null | { "timestamp": FLOAT, "value": UINT2 }, // Reserved for future use
 "session":  null | { "timestamp": FLOAT, "value": UINT2 },
 "chipeui":  null | { "timestamp": FLOAT, "value": DEVEUI }
 "streampar":null | { "timestamp": FLOAT, "value": STREAMPAR }.
 "appstatus":null | { "timestamp": FLOAT, "value": HEX }.
 "alcsync":  null | { "timestamp": FLOAT, "value": ALCSYNC_FIELD }.
}

STATUS_FIELD = {
  "brownout":  BOOL,
  "crash":     BOOL,
  "mute":      BOOL,
  "joined":    BOOL,
  "suspend":   BOOL,
  "upload":    BOOL,
}

STREAMPAR = {
  "port":     UINT1,
  "encmode":  BOOL
}

ALCSYNC_FIELD = {
  "token": UINT1,  // Token, selected by modem
  "time":  UINT4   // Time reported by modem for time correction
}
  • timestamp: Required. Float. UTC timestamp.

Modem Request

This object encapsulates a modem request. Each request contains a field, type, denoting the request type and, optionally, a request-specific parameter.

REQUEST = {
  "type":     STRING, // Required. Request type.
  "param":    ANY,    // Optional. Request specific parameter.
}

RESET_REQUEST = {
  "type":      "RESET",   // RESET request
  "param":     UINT1      // 0x1, 0x2 or 0x3
}

REJOIN_REQUEST = {
  "type":      "REJOIN"   // REJOIN request
}

MUTE_REQUEST = {
  "type":      "MUTE"     // MUTE request
  "param":     UINT1      // Mute parameter
}

GETINFO_REQUEST = {
  "type":      "GETINFO", // GETINFO request
  "param":     [ FIELD, ..]    // Required. List of field names given below
}

FIELD = [ "status", "charge", "voltage", "temp", "signal", "uptime",
          "rxtime", "firmware", "adrmode", "joineui", "interval", "region",
          "crashlog", "rstcount", "deveui", "session", "chipeui" ]

SETCONF_REQUEST = {
  "type":      "SETCONF",  // SETCONF request
  "param":     {           // Required. Map of SETCONF type to value
    "adrmode":   ADRMODE,  // Optional. ADR mode
    "joineui":   JOINEUI,  // Optional. EUI
    "interval":  REPINTV,  // Optional. Reporting interval
    "region":    UINT1,    // Optional. Regulatory region (according to device manual)
  }
}

ADRMODE: UINT1
 0x00: LNS controlled
 0x01: Mobile Long Range
 0x02: Mobile Low Power

REPINTV: UINT1
 Bits 7-6: unit (sec=0x00, day=0x01, hour=0x10, min=0x11)
 Bits 5-0: value (0-63)

FILEDONE_REQUEST = {
  "type":      "FILEDONE", // FILEDONE request
  "param":    {
    "sid":    INT,    // Required. File session id
    "sctr":   INT,    // Required. File counter
  }
}

Pending Request

This object encapsulates a pending request.

PENDING_REQUEST = {
  "id":        INT,    // Request ID
  "cookie":    ANY,    // Value for request completion check
  "timestamp": FLOAT,  // Timestamp, UTC, of request generation
  "request"  : REQUEST // The request as generated by caller
}
  • id: Required. Integer. Request ID.

  • cookie: Required. Internal value for request-completion check.

  • timestamp: Required. Float. UTC timestamp.

  • request: Required. The associated ModemRequest.

STREAM Update

This lists both the signals and the fully-assembled streaming records that are received by the decoder. Each entry denotes an assembled packet with application data and record offset.

If some of the fragments of a stream record are lost during transmission, they will be reconstructed based on the following fragments. This may result in records being delivered to the application in a different order than sent by the device. The application can use the stream offset of each reconstructed record to re-establish the order.

[
 [ UINT,      // Required. Stream offset of the record
   HEX        // Required. HEX string, Stream record data
 ],
 ..
]

Position Solution

A Position Solution object contains the position solution calculated from GNSS or Wi-Fi observations. The algorithm_type field distinguishes between the two cases:

  • gnss: The Position Solution object is a GNSS position solution POSITION_SOLUTION_GNSS

  • gnssng: The Position Solution object is a GNSS-NG position solution POSITION_SOLUTION_GNSSNG

  • wifi: The Position Solution object is a Wi-Fi position solution POSITION_SOLUTION_WIFI

POSITION_SOLUTION = POSITION_SOLUTION_GNSS | POSITION_SOLUTION_GNSSNG | POSITION_SOLUTION_WIFI
POSITION_SOLUTION_GNSS = {
  "algorithm_type": "gnss",             // Required.
  "ecef":      [FLOAT, FLOAT, FLOAT],   // Required. Calculated position in ECEF coordinates [m, m, m]
  "llh":       [FLOAT, FLOAT, FLOAT],   // Required. Calculated position in WGS84 llh coordinates [deg, deg, m]
  "capture_time_gps":  FLOAT,           // Required. Calculated capture time in seconds GPST
  "gdop":      FLOAT,                   // Required. Geometric Dilution of Precision
  "accuracy":  FLOAT,                   // Required. Estimate of calculated position accuracy in meters
  "timestamp": FLOAT                    // Required. Uplink message timestamp corresponding to position solution
}
  • ecef: Required. Calculated position in Earth-centered, fixed Cartesian coordinates in meters [X,Y,Z].

  • llh: Required. Calculated position in WGS84 latitude [deg], longitude [deg], altitude above reference ellipsoid [m].

  • capture_time_gps: Required. Calculated capture time in seconds GPST.

  • gdop: Required. Geometric Dilution of Precision in meters.

  • accuracy: Required. Estimate of calculated position accuracy. Values >0.0 are in meters. Value 0.0 means an accuracy estimate is not available.

  • timestamp: Required. Uplink message timestamp corresponding to position solution.

POSITION_SOLUTION_GNSSNG = {
  "algorithm_type": "gnssng",           // Required.
  "ecef":      [FLOAT, FLOAT, FLOAT],   // Required. Calculated position in ECEF coordinates [m, m, m]
  "llh":       [FLOAT, FLOAT, FLOAT],   // Required. Calculated position in WGS84 llh coordinates [deg, deg, m]
  "capture_time_gps":  FLOAT,           // Required. Calculated capture time in seconds GPST
  "capture_times_gps":  [FLOAT|null, .. ],    // Required. Calculated capture time in seconds GPST
  "gdop":      FLOAT,                   // Required. Geometric Dilution of Precision
  "accuracy":  FLOAT,                   // Required. Estimate of calculated position accuracy in meters
  "timestamp": FLOAT                    // Required. Uplink message timestamp corresponding to position solution
}

The fields are identical to the POSITION_SOLUTION_GNSS object except for the additional field capture_times_gps.

  • capture_times_gps: Required. Calculated capture time of the most recent scan of the group which was considered in the solution calculation. In seconds GPST.

POSITION_SOLUTION_WIFI = {
  "algorithm_type": "wifi"              // Required.
  "llh":       [FLOAT, FLOAT, FLOAT],   // Required. Calculated position in WGS84 llh coordinates [deg, deg, m]
  "timestamp": FLOAT                    // Required. Uplink message timestamp corresponding to position solution
}
  • llh: Required. Calculated position in WGS84 latitude [deg], longitude [deg], altitude above reference ellipsoid [m]

  • timestamp: Required. Uplink message timestamp corresponding to position solution

FILE Object

A FILE object carries the contents of a file uploaded and de-fragmented by a modem to the service.

FILE = {
  "sctr":       UINT1,  // Required. File counter.
  "timestamp":  FLOAT,  // Required. UTC timestamp of the last message having led to a fully de-fragmented file
  "port":       UINT1,  // Required. Target port for uploaded files; may be null on error
  "data":       HEX,    // Required. Contents of an uploaded file; may be null on error
  "hash":       HEX,    // Required. SHA256 short hash over plain data (8/4 bytes for plain/encrypted upload); may be null on error
  "encmode":    BOOL,   // Required. File encrypted; may be null on error
  "message":    STRING, // Optional. May contain a log message of the service
}

STREAM Object

A fully-assembled record of the streaming session, stored in the stream record history along with the device state.

STREAM = {
  "timestamp":  FLOAT,  // Required. UTC timestamp of the last message having led to a fully de-fragmented stream record
  "port":       UINT1,  // Required. Target port for the uploaded stream
  "data":       HEX,    // Required. Contents of the stream record
  "off":        UINT2   // Required. Application record counter (byte offset)
}

Log Message

A log message associated with a device.

LOG_MESSAGE = {
  "logmsg":    STRING,  // Required. Log message
  "level":     STRING,  // Required. "WARNING", "INFO" or "ERROR
  "timestamp": FLOAT    // Required. Timestamp, UTC, Float
}

Device Ports

The configured port settings for a device.

FPORTS = {
  "dmport":      UINT1,   // Configured or default port for Modem messages
  "gnssport":  UINT1,   // Configured or default port for GNSS messages
  "gnssngport":  UINT1,   // Configured or default port for GNSSNG messages
  "wifiport":    UINT1,   // Configured or default port for Wi-Fi messages
  "streamport":  UINT1    // Configured or default port for Stream messages
}

Note that streamport and dmport are the same by default as the DM port implicitly allows for a stream session tunneled through DM messages. If the streamport is explicitly set for a device, the Modem Service opens a stream session for the specified port and closes any existing session.

The default ports for devices are 199 for the DM port, 198 for the GNSS port, 197 for the Wi-Fi port and 192 for the GNSSNG port (Modem Service Protocol Payloads). The default port for Stream messages is the DM port where the DM protocol allows to stream records by using the tag U-APPSTREAMDATA (Modem Service Protocol Payloads). It is only necessary to configure the stream port explicitly when the device sends records on a port different from the DM port and without relying on the DM protocol for the stream.

The DM, GNSS, GNSSNG, Wi-Fi and stream ports must differ from each other in a device configuration. In general, LoRa Cloud does not support the multiplexing of different protocols over a single port besides the DM protocol allowing for embedding GNSS, Wi-Fi or stream records in tagged DM messages (Modem Service Protocol Payloads).

Modem Service Protocol Management

At the heart of the Modem Service is the exchange of protocol messages with the end device. Four protocols are defined which provide the device to cloud functionality available in LoRa Cloud MGS.

Note

More details on the specific protocols, their functions and defintions is available in Section Modem Service Protocol Payloads.

The main entry point for the protocol message exchange is the */device/send API (alternatively the */uplink/send API for batch uplink delivery). The message payload is encapsulated in the UplinkMsg API object where the port and msgtype fields are used to specify the protocol to which the delivered payload belongs.

Almost all use cases of the protocols can be split into the following Scenarios.

  • Scenario 1: Modem Protocol over LoRaWAN

  • Scenario 2: LoRa Edge GNSS/GNSSNG/Wi-Fi positioning protocols over LoRaWAN

  • Scenario 3: LoRa Edge GNSS/GNSSNG/Wi-Fi positioning protocols transport agnostic

Scenario 1: Modem Protocol over LoRaWAN

The modem port is configurable in the modem firmware. The device configuration in LoRa Cloud has to be in sync with the configured modem port on device. If the device modem port configuration deviates from the default value, the modem port has to be set for the corresponding device in LoRa Cloud MGS using the */device/set API or globally for all newly created devices of a Device Owner using the */devowner/config API. The modem port is typically not changed during the device lifetime, so the configuration must be set just once.

Assuming a proper configuration of the modem port, the Application Backend logic is just expected to forward the payloads of that port to LoRa Cloud MGS in msgtype:updf uplink messages.

This scenario is suitable for all LoRa Basics Modem based devices. LoRaWAN is the implied transport layer for this protocol.

_images/protomgt-1.svg

Scenario 2: LoRa Edge GNSS/GNSSNG/Wi-Fi positioning protocols over LoRaWAN

When LoRa Edge GNSS/GNSSNG/Wi-Fi positioning protocol messages are exchanged directly over LoRaWAN, the message exchange is very similar to the Modem Protocol described above. The application firmware on device assembles the protocol messages according to the definition in Section Modem Service Protocol Payloads using geolocation messages from a LoRa Edge chip’s SPI interface. The corresponding GNSS, GNSSNG and Wi-Fi ports in LoRa Cloud MGS have to be configured in sync with the device’s application firmware.

With proper configuration of the GNSS, GNSSNG and Wi-Fi ports, the Application Backend logic is just expected to forward the payloads of these ports to LoRa Cloud MGS using msgtype:updf and port:GNSS_PORT / port:GNSSNG_PORT / port:WIFI_PORT. The downlinks of these protocols will be scheduled on the respective ports, as well.

_images/protomgt-2.svg

Note

The flow-chart depicts only the GNSS positioning protocol for conciseness. The same flow applies for the GNSSNG and Wi-Fi positioning protocol as well

Scenario 3: LoRa Edge GNSS/GNSSNG/Wi-Fi positioning protocols transport agnostic

The third scenario makes no assumption about the underlying transport layer with the drawback of more complex message handling in the Application Backend logic. This could be necessary in situations where

  • the GNSS/GNSSNG/Wi-Fi payloads are sent over a non-LoRaWAN link (e.g. LoRa, BLE, Sigfox, etc), or

  • the GNSS/GNSSNG/Wi-Fi payloads are encoded in an application specific way, or

  • the GNSS/GNSSNG/Wi-Fi payloads are sent over one of the Advanced Transport Services of the LoRa Basics Modem.

The Application Backend Logic has to extract the GNSS/Wi-Fi payloads from an application specific message (or set of messages). The GNSS/GNSSNG/Wi-Fi payload has to be submitted with msgtype:gnss(ng)/msgtype:wifi in this case. Conversely, the downlinks of the GNSS/GNSSNG/Wi-Fi position protocol has to be encoded according to the application specific message definition.

Note

Note that port:0 in the downlink indicates the absence of any specific port. This field must be ignored. In LoRaWAN, downlinks must not be sent on FPort 0.

_images/protomgt-3.svg

Modem Service Protocol Payloads

The four protocols supported by Modem Service are distinguished by the msgtype field and/or the port.

The following default port-protocol-mapping applies unless otherwise configured via Configure Device Ports:

The following msgtype-protocol-mapping applies for non-LoRaWAN transports:

Modem Protocol

The modem messages are exchanged between a modem and Modem Service over the configured modem port. These messages are sent and processed directly by the modem. Applications control the modem functionality via the modem device API and the LoRa Cloud API and are not required to inspect messages to use of the modem management features.

LoRa Edge GNSS positioning protocol

The LoRa Edge GNSS positioning messages consist of a single tag-value pair per message in uplink and downlink direction. Their purpose is to deliver GNSS scan results to the geolocation solver and communicate aiding information adjustments back to the device.

LoRa Edge GNSS positioning uplink messages are generated directly by a LoRa Edge chip and can be retrieved using the GNSSReadResults command (See the LoRa Edge User Manuals for more details).

Note

The response to the LoRa Edge chip’s GNSSReadResults SPI command starts with a destination byte. For successful GNSS scans, the destination byte is always 0x01. This destination byte is not part of the GNSS positioning message and must be removed before transmitting the message.

Uplink Message:

bytes: 1:1:TAG | 2:VL: VALUE

Downlink Message:

bytes: 1:1:TAG | 2:VL: VALUE

The following tag-value pairs are defined:

Direction

Tag

Value

Value length

Description

Uplink

0x00

U-GNSSLOC-REQAID

0 bytes

Aiding position request

Uplink

>0x00 1

U-GNSSLOC-NAV

variable

Navigation message (NAV1/NAV2/NAV3)

Downlink

0x00

D-GNSSLOC-AIDP

3 bytes

Aiding position update

1

LoRa Edge GNSS positioning protocol uplink messages with non-zero tag byte are Navigation messages.

U-GNSSLOC-REQAID - 0x00: Aiding position request

bytes: 1:1: HDR=0x00

The value of the REQAID message is empty.

U-GNSSLOC-NAV - >0x00 GNSS Navigation message (NAV1/NAV2/NAV3)

All LoRa Edge GNSS positioning protocol uplink messages with non-zero tag byte are Navigation messages (NAV messages). They carry the signal measurements which are necessary to compute a position solution. Navigation messages come in three versions, NAV1, NAV2, and NAV3, depending on the microcode version which runs on LoRa Edge chipset.

bytes: 1:1: TAG | 7:VL: GNSS_SCAN_RES

Description of the fields:

TAG

A NAV-internal tag byte. Depends on the internal structure of the NAV message. Non-zero.

GNSS_SCAN_RES

GNSS scan result containing GNSS signal measurements.

D-GNSSLOC-AIDP - 0x00: Aiding position update

bytes: 2:1:TAG=0x00 | 3:3:POS

Description of the fields:

POS

An estimate of the device’s position encoded in WGS84 latitude/longitude coordinates.

bits: heading="POS" 23-16:LAT_LSB | 15-12:LON_LSB | 11-8:LAT_MSB | 7-0:LON_MSB

Description of the fields:

LAT = LAT_LSB | (LAT_MSB << 8)

WGS84 latitude coordinate of the aiding position. Type: int12, unit: 180/2^12 deg

LON = LON_LBS | (LON_MSB << 4)

WGS84 longitude coordinate of the aiding position. Type: int12, unit: 360/2^12 deg

Examples:

Min Value: POS='000880': LAT = -2048*180/2**12 [-90.000 deg], LON =  -2048*360/2**12 [-180.000 deg]

Max Value: POS='fff77f': LAT =  2047*180/2**12 [ 89.9560 deg], LON =  2047*360/2**12 [ 179.912 deg]

LoRa Edge GNSS-NG (NAV-Group) positioning protocol

The LoRa Edge GNSS NAV-Group protocol allows to combine multiple NAV-messages into groups which are evaluated as multi-frame GNSS solver requests.

The device-side implementation of this protocol is available as part of the LoRa Basics Modem Geolocation SDK (SWSD004) starting from version 1.2.0. For more information please refer to the SWSD004 documentation.

Grouping of NAV-messages is done with the help of the U-GNSSNG-NAV payload of the GNSS-NG protocol:

U-GNSSNG-NAV: GNSS Grouped NAV Message

The U-GNSSNG-NAV payload consists of a 1-byte Group Header Byte (GHDR) followed by a single U-GNSSLOC-NAV record. The purpose of the GHDR byte is to flag NAV-messages, which result from a static position and thus can be combined into a multi-frame solution. Such multi-frame solutions from a static position are more precise and have a higher chance of resulting in a position solution.

bytes: 1:1: GHDR | 7:VL: U-GNSSLOC-NAV

Description of the fields:

GHDR

Group Header.

bits: heading="GHDR" 7:EOG | 6-5:RFU=0b00 | 4-0:GRP_TOKEN

Description of the fields:

EOG

End of Group Flag. When set to 1, the device indicates that the NAV-messages of the group should be evaluated to a position.

RFU

Reserved for future use. Must be set to 0b00.

GRP_TOKEN

The group token is a 5-bit unsigned integer ranging from 2 to 31 (including). Values 0 and 1 are not allowed. Upon reset, the first value of the group token must be chosen as a random value between 2 and 31 (including) and is incremented by 1 for each new group thereafter. Group token 31 is followed by 2. Subsequent messages with a constant group token value are associated to the same group.

U-GNSSLOC-NAV*

A message of type U-GNSSLOC-NAV which gets added to the current group. Note, that U-GNSSLOC-REQAID is not an allowed value.

In addition to the encoding of grouped NAV messages, the GNSS-NG protocol allows to exchange control flow information via Extension messages:

Extension messages

Uplinks:

Extention messages in uplink direction are identified by the Extension Marker EXT_MRK which is the second byte set to 0.

If EXT_MRK is not 0, then the message is interpreted as a U-GNSSNG-NAV message.

If EXT_MRK is 0, then the message is interpreted according as a Tag-Value-Pair according to the following structure:

bytes: 1:1:TAG | 1:1:EXT_MRK=0x00 | 2:VL: VALUE

Downlinks:

In downlink direction, the messages are always Tag-Value-Pairs:

bytes: 3:1:TAG | 6:VL: VALUE

The following tag-value pairs are defined for up- and downlink directions:

Direction

Tag

Value

Value length

Description

Uplink

0x00

U-GNSSNG-APC0

3 bytes

Aiding position check type 0

Uplink

0x01

U-GNSSNG-APC1

variable

Aiding position check type 1

Downlink

0x00

D-GNSSNG-AIDP

3 bytes

Aiding position update

U-GNSSNG-APC0 - 0x00: Aiding Position Check Type 0

The purpose of the Aiding Position Check Type 0 message is to allow the device to request a new assistance position. The device could trigger this message when it has indication that the current available assistance position has an error which is larger than 150 km with the respect to the device’s current position.

The intent of this message is to trigger a D-GNSSNG-AIDP downlink message which updates the device’s assistance position with a new value. LoRa Cloud may infer this value from various sources, including but not limited to the gnss_assist_position API parameter and the WiFi position history.

bytes: 1:1: TAG=0x00 | 1:1: EXT_MRK=0x00 | 2:3:POS

Description of the fields:

POS

Coordinates of the current aiding position of the device. Encoded as in D-GNSSLOC-AIDP.

U-GNSSNG-APC1 - 0x01: Aiding Position Check Type 1

The purpose of the Aiding Position Check Type 1 message is to allow the device to request a new assistance position while simultaneously providing an autonomous scan result as an indication for its current position. The device could trigger this message when it has indication that the current available assistance position has an error which is larger than 150 km with the respect to the device’s current position.

The doppler observations contained in the NAV message will be used to calculate an updated assistance position and D-GNSSNG-AIDP downlink is triggered. In case the NAV message does not yield any result, the U-GNSSNG-APC1 message is treated as a Type 0 (U-GNSSNG-APC0) message.

bytes: 1:1: TAG=0x01 | 1:1: EXT_MRK=0x00 | 2:3:POS | 2:VL:NAV

Description of the fields:

POS

Coordinates of the current aiding position of the device. Encoded as in D-GNSSLOC-AIDP.

NAV

A message of type U-GNSSLOC-NAV from an autonomous scan which can be used to calculate a more accurate assistance position. Note, that U-GNSSLOC-REQAID is not an allowed value.

D-GNSSNG-AIDP - 0x00: Aiding position update

The aiding position downlink message is identical to D-GNSSLOC-AIDP. It can be sent in response to any U-GNSSNG-* uplink message.

bytes: 2:1: TAG=0x00 | 3:3: POS

Description of the fields:

POS

Coordinates of the new aiding position of the device. Encoded as in D-GNSSLOC-AIDP.

LoRa Edge Wi-Fi positioning protocol

The Wi-Fi positioning protocol messages consist of a single tag-value pair per message in uplink direction. Downlinks are not defined for this protocol.

bytes: 1:1:TAG | 2:VL: VALUE

The following tag-value pairs are defined:

Direction

Tag

Value

Value Length

Description

Uplink

0x00

U-WIFILOC-MAC

N*6 bytes

Wi-Fi AP list

Uplink

0x01

U-WIFILOC-MACRSSI

N*7 bytes

Wi-Fi AP list with RSSI

N: Number of scanned APs

U-WIFILOC-MAC - 0x00: Wi-Fi AP MAC List

bytes: 1:1: TAG=0x00 | 1:6: MAC | 1:6: MAC | 1:: ... | 1:6: MAC

Description of the fields:

MAC

MAC address of scanned AP. See MAC Address Encoding.

U-WIFILOC-MACRSSI - 0x01: Wi-Fi AP MAC List with RSSI

bytes: 1:1: TAG=0x01 | 1:1: RSSI | 1:6: MAC | 1:: ... | 1:1: RSSI | 1:6: MAC

Description of the fields:

RSSI

RSSI associated to AP in dB. 8-bit signed integer.

MAC

MAC address of scanned AP. See MAC Address Encoding.

MAC Address Encoding

A 48-bit MAC address denoted as M6:M5:M4:M3:M2:M1 is encoded in:

bytes: heading="MAC" 1:1: M6 | 1:1: M5 | 1:1: M4 | 1:1: M3 | 1:1: M2 | 1:1: M1

where

M6

Most significant byte of MAC address.

M1

Least significant byte of MAC address.