title: An Application Layer Interface for Non-IP device control (NIPC) abbrev: NIPC docname: draft-ietf-asdf-nipc-03 submissionType: IETF category: std
ipr: trust200902 keyword: Internet-Draft
stand_alone: no pi: [toc, sortrefs, symrefs]
ins: B. Brinckman
name: Bart Brinckman
org: Cisco Systems
city: Brussels
country: Belgium
email: [email protected]
- ins: R. Mohan name: Rohit Mohan org: Cisco Systems street: 170 West Tasman Drive code: 95134 city: San Jose country: USA email: [email protected]
- ins: B. Sanford name: Braeden Sanford org: Philips city: Cambridge country: USA email: [email protected]
informative: BLE53: title: Bluetooth Core Specification, Version 5.3 author: - org: Bluetooth SIG date: 2021 Zigbee22: title: zigbee Specification, Version 22 1.0 author: - org: Connectivity Standards Alliance date: 2017
--- abstract
This memo specifies RESTful application layer interface for gateways providing operations against non-IP devices. The described interface is extensible. This memo initially describes Bluetooth Low Energy and Zigbee as they are the most commonly deployed.
--- middle
Low-power sensors, actuators and other connected devices introduced in environments and use cases such as building management, healthcare, workplaces, manufacturing, logistics and hospitality are often battery-powered. Often they do not support wireless of wired interfaces that support the IP protocol. Most of these environments however mainly support IP-based networking infrastructure. Therefore, applications on the IP network that aim to communicate or receive telemetry from these non-IP low-power devices must do so through a gateway function on the IP network. This gateway functions then translates the communication to the non-IP protocol that the low-power device supports. Promiment examples of such protocols are {{BLE53}} and {{Zigbee22}}.
+-------------+ +---------+ +--------+
| Application |<------------>| Gateway |<------------>| Non-IP |
| app | IP-based | | Non-IP | Device |
+-------------+ Operation +---------+ Operation +--------+
{: #gw title="Gateway for non-IP Devices"}
There have been efforts to define Gateway functions for devices that support a particular protocol, such as a BLE GATT REST API for BLE Gateways ({{https://www.bluetooth.com/bluetooth-resources/gatt-rest-api/}}), however they have been limited to a single protocol or a particular use case. In absence of an open standard describing how applications on an IP network communicate with non-IP devices, bespoke and vendors specific implementations have proliferated. This results in parallel infrastructure of both gateways and non-IP networks being deployed on a case by case basis, each connecting separately into the IP network, with a distinct set of APIs. At the same time, wireless access points supporting IP-based wireless connectivity are deployed ubiquitiously. Many of these wireless access points are equipped with multiple wireless radios, of different types. These radios can transmit and receive different frame types, such as {{BLE53}} and {{Zigbee22}}. This specification aims to define a Gateway API for these Non-IP protocols that can be leveraged by this wireless infrastructure in order to connect Non-IP devices into IP networks.
A standardized Non-IP Gateway interface has following benefits:
- Avoid the need for parallel Non-IP infrastructure.
- Avoid the need for applications to perform bespoke integrations for different environments.
- Faster and more cost-effective adoption of Non-IP devices in IP network environments.
A non-IP gateway MUST provide at least following functions:
- Authentication and authorization of application clients that will leverage the gateway API to communicate with Non-IP devices.
- The ability to onboard Non-IP devices on the Non-IP Gateway. Onboarding ensures that the Non-IP Gateway can identify a device and has sufficient context about the device to service gateway API requests. It also ensures segmentation of devices that were onboarded by particular applications.
- A persistent inventory of onboarded devices mapping to the application that onboarded them and the access point/radio that is serving them.
- An API that allows for bi-directional communication to non-IP devices.
- One or more channels to process requests, responses, and asymmetric communications with the non-IP radio resources (Access Points) in its inventory.
- The ability to stream telemetry received from non-IP devices in real-time to applications on the IP network.
The onboarding function is out of scope of this document, but can be provided by a provisioning interface such as {{!RFC7644}} leveraging {{!I-D.ietf-scim-device-model}}. All other defined functions are supported by Non IP-Control (NIPC).
The Application gateway is a network function, so its goal is to proxy payloads between Non-IP and IP networks. It is not intended to be a middleware function that interprets, decodes or modifies these payloads.
+-----------------------------------+
| |
+-----------+ Request | +---------+ |
| onboarding|------------->| SCIM | |
| app |<-------------| Server | |
+-----------+ Ctrl Endpt +---------+ |
| |
+-----------+ | +------------+ +-------+ +--+ |
| Control |>...REST...|.>| |..| AP |..|D | |
| & | | | Gateway | +-------+ +--+ |
| Telemetry |<...MQTT...|.<| | |
| Apps | | +------------+ |
+-----------+ | |
| Network Deployment |
+-----------------------------------+
{: #arch title="Basic Architecture"}
{{arch}} shows us applications, the application layer gateway (ALG), an access point (AP), and a device (D). The applications, application layer gateway and access point are deployed on an IP-Network. The AP also has a Non-IP interface, which it uses to communicate with the device. The Application is deployed in a different administrative domain than the network elements (ALG & AP). The role of the ALG is to provide a gateway function to applications wishing to communicate with non-IP devices in the network domain served by the ALG. Applications implementing Non-IP Control can leverage RESTful interfaces to communicate with Non-IP devices in the network domain and subscribe to events levering MQTT.
In order to enable a network wishing to offer NIPC ALG functions, the network administrator authorizes application(s) to perform operations on the Gateway. This happens out of band and may be accomplished by means of exchanging tokens or public keys. Authorization can be role-based. The 3 primary roles are:
- Onboarding: Authorize an onboarding application against a SCIM server co-located with the gateway.
- Control: Authorize applications that may control devices.
- Data: Authorize applications that may receive telemetry.
It is possible to further refine roles down to an API basis.
Applications can perform the API requests they were authorized for. In order for application to perform a NIPC operation on a device, the device must be first onboarded, for example by means of SCIM.
Previous steps are prerequisites and not within the scope of this specification, but are provided for context. Subsequent operations are defined by NIPC.
- An application authorized for Control can perform NIPC calls to the gateway in order to establish bi-directional communication to one or more devices. Optionally, also set up a publish/subcribe topic to receive streaming data from a device (telemetry interface).
- An application authorized can receive streaming data on a pub/sub topic configured by the control interface (telemetry interface).
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 {{!RFC2119}} {{!RFC8174}} when, and only when, they appear in all capitals, as shown here.
Non-IP protocols, such as BLE or Zigbee, typically define a number of basic operations that are similar across protocols. Examples of this are read and write data. NIPC leverages a unified API to support those operations.
NIPC defines actions, which are implemented as REST over HTTP request-response APIs. NIPC Also defines events, which are implemented as MQTT topics.
In case NIPC is not leveraged in combination with a data model such as ASDF {{!I-D.ietf-asdf-sdf}}, which can define the properties of a devices, NIPC also support registrations. Registrations perform mapping of properties to protocol-specific attributes.
All operations pertain to a devices or a group of devices, which are addressed by UUIDs. These UUID's were generated at time of onboarding and returned to the application, for example in a SCIM response.
NIPC adheres to nomenclature defined by Semantic Definition Format (SDF) for Data and Interactions of Things {{!I-D.ietf-asdf-sdf}}. Therefore NIPC defines actions and events on properties.
NIPC supports 3 types of actions:
- connection: Allows an application to establish to manage connections with a device (if so required by the technology).
- property: Allows applications to read or write device properties. In case the property supports streaming data, a subscription property can be managed.
- broadcast: This allows the application to send a broadcast message to a device or group of devices.
In absence of a model such as SDF that defines device properties, NIPC allows an application to register them. NIPC defines 2 types of registrations:
- property: Manage registrations of properties and their protocol mappings. For example, a property called temperature can be mapped to a BLE Service Characteristic.
- event: Manage registrations of events and their MQTT properties such as MQTT topic definition.
The final set of operations are not fundamental NIPC operations, but are extensions. Extensions are compound APIs. They leverage basic NIPC operations but combine multiple operations in to one API call for efficiency. An example of this is the the bulk operation, allowing to send multiple operations in one operation. Extension allows for extensions, either generic extensions that are IANA registered, or vendor specific extensions
Events are published over MQTT. Events can be normal sreaming data, but also broadcasts or connection events.
NIPC actions, registrations and extensions are request/response APIs. They make use of a JSON schema over RESTful HTTP{{!RFC9114}}.
NIPC events are encoded in CBOR ({{!RFC8949}}) and delivered over MQTT.
Most operations (except registations) are executed against a device or a group. NIPC operations refer to either of these as "Object" with an ID as an identifier. The common schema for Object is defined as follows:
| Attribute | Req | Type | Example | +---------------+-----+---------+--------------------------------------| | id | T | uuid | 12345678-1234-5678-1234-56789abcdef4 | | type | T | enum | device, group | | technology | F | enum | ble, zigbee | {: #objectdef title="Definition of an Object"}
where-
- id is the unique uuid of the device. This is generated when registering the device, for example against a SCIM server. As such this ID is known both to the application as well as the NIPC Server.
- type is either "group" or "device".
- technology is the radio technology supported by the device. The mappings defined in this spec are "ble" or "zigbee". Mappings are extendable to new technologies.
Example device object:
{
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"technology": "ble",
}
{: #exdevobj title="Example device object"}
An object can support one or more communications protocols. Even though Non-IP communications protocols all perform operations on properties, implementations differ between protocols. For example BLE will address a property as a service characteristic, while a property in Zigbee is addressed as a property in a cluster of an endpoint.
In order for NIPC to support protocol-agnostic APIs, a property mapping is required between a NIPC property and a protocol-specific property. A property mapping can be done by means of a property registration API.
Property mapping allows for integration of new protocols in NIPC, new mappings can be created without the need to update the base schema.
- property
|
|> BLE
| - BLE property
|
|> Zigbee
- Zigbee property
{: #propmap title="Property Mapping"}
As shown in {{propmap}}, protocol-specific properties must be described in a protocol object, for example a "ble" or a "zigbee" object.
| Attribute | Req | Type | Example | +-----------+-----+---------+------------------------------------------| | ble | T | object | an object with BLE-specific attributes | | zigbee | T | object | an object with Zigbee-specific attributes| {: #proobj title="Protocol objects"}
where-
- "ble" is an object containing properties that are specific to the BLE protocol.
- "zigbee" is an object containing properties that are specific to the Zigbee protocol.
- Other protocol mapping objects can be added by creating a new protocol object
Example property mapping:
{
"propertyID": "temperature",
"ble": {
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"long": false
}
}
{: #expropmap title="Example property mapping"}
Protocol mapping allows applications to perform a one-time registration to a propertyID for a property, and leverage the propertyID in all API calls that perform an operation on this property. It might be useful for applications to directly use protocol objects in action APIs as well, therefore there are a limited set of APIs available that have protocol objects directly embedded in the API, in order to perform operations on properties without having to first register them.
As most operations have a common base schema, based on a device ID and a property, so do responses. Every NIPC API returns a status in the response, as well as a requestID, which allows for tracking and logging of requests and responses. If the operation was performed on a device or group, the ID is also returned. If the operation is to read or write a property, the resulting value is also returned.
Success response:
| Attribute | Req | Type | Example | +---------------+-----+---------+--------------------------------------| | status | T | enum | SUCCESS | | id | F | uuid | 12345678-1234-5678-1234-56789abcdef4 | | requestID | F | uuid | abcd0987-1234-5678-1234-56789abcdef4 | {: #success title="Success response"}
Example success response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
}
{: #exsuccess title="Example success response"}
Failure responses additionally include an error code and optionally a reason, which contains a textual explanation of the error.
Failure response:
| Attribute | Req | Type | Example | +---------------+-----+---------+--------------------------------------| | status | T | enum | SUCCESS | | id | F | uuid | 12345678-1234-5678-1234-56789abcdef4 | | requestID | F | uuid | abcd0987-1234-5678-1234-56789abcdef4 | | errorCode | T | int | 12 | | reason | T | string | "Not Found" | {: #failure title="Failure response"}
where-
- status is the status of the request, either "SUCCESS" or "FAILURE". In case of failure an error code and reason are added.
- id is the id the operation was executed against, found in the request
- requestID is a correlation ID that can be used for end-to-end tracing.
- errorCode is a numerical value representing the error. The various codes are defined in {{errorhandling}}.
- reason is a human readable explanation of why the error occurred.
Example failure response:
{
"status": "FAILURE",
"reason": "Not Found",
"errorCode": 12,
"requestID": "12345678-5678-1234-5578-abcdef1234"
}
{: #exfail title="Example failure response"}
The primary goal of NIPC actions is to exchange data with a Non-IP device, by means of reading, writing or streaming NIPC properties to applications. An explicit connection may be required, which is also an action. An application may also want to transmit a broadcast.
A connection is an operation that establishes or tears down an association or connection with a device. Optionally during connection setup properties supported by a device can be discovered.
/action/connection
The connection API allows an application to request to connect to a device.
Operations:
- Connect to a device: POST
- Return active connections: GET
- Disconnect a device: DELETE
Method: POST /action/connection
Description: Connect to a device
Parameters: None
Request Body:
- an Object, as defined in {{objectdef}}
- optionally a set of properties to be discovered. These are supplied in protocol objects, as defined in {{proobj}}. In the case of BLE, if no protocol object is included, service discovery is performed to discover all supported properties when connecting to a device. Optionally, service discovery may be limited to properties defined in the "ble" protocol extension. The services to be discovered can be added in an array. Property discover can be buffered across connections, so the API also supports caching parameters.
- Connection retry parameters
Example body of a connection without specific discovery of properties:
{
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"technology": "ble",
"retries": 3,
"retryMultipleAPs": true
}
{: #exconn title="Example Connection"}
where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in {{objectdef}}.
- "retries" defines the number of retries in case the operations does not succeed
- "retryMultipleAPs" can be used in case there is an infrastructure with multiple access points or radios that can reach the device. If set to "true" a different access point may be used for retries.
In case the application would like to discover specific properties of a device, a protocol object can be added that defines what properties should be discovered.
Example body of a BLE connection with specific discovery of properties:
{
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"technology": "ble",
"ble": {
"services": [
{
"serviceID": "12345678-1234-5678-1234-56789abcdef4"
}
],
"cached": false,
"cacheIdlePurge": 3600,
"autoUpdate": true,
"bonding": "default"
},
"retries": 3,
"retryMultipleAPs": true
}
{: #exconnprp title="Example Connection with explicit discovery of connections"}
where in the BLE protocol object:
- "services" is an array of services defined by their serviceIDs.
- "cached" refers to whether the services need to be cached for subsequent connects, in order not to perform service discovery on each request.
- "cacheIdlepurge" defines how long the cache should be maintained before purging
- some devices support notifications on changes in services, "autoUpdate" allows the network to update services based on notification (on by default)
- "bonding" allows you to override the bonding method configured when onboarding the device
Response: Success responses include standard success response properties as defined in {{success}} as well as a protocol object with an array of discovered properties, as defined in the specific protocol. For example, for BLE, this is an array of supported services, which in turn contains an array of charateristics, which in turn contains an array of descriptors, as shown in {{BLEservices}}.
services
- serviceID
|
|> characteristics
- charactericID
- flags
|
|> Descriptors
- descriptorID
{: #BLEservices title="BLE Services"}
Example of a BLE connection response with BLE discovered properties:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
"ble": [
{
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristics": [
{
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"flags": [
"read",
"write"
],
"descriptors": [
{
"descriptorID": "12345678-1234-5678-1234-56789abcdef4"
}
]
}
]
}
]
}
{: #exconnresp title="Example Connection response"}
where in the BLE protocol object:
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "ble" protocol object contains an Array of BLE services as shown in {{BLEservices}}
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: GET /action/connection
Description: Returns one or more active connections, based on ids provided in parameters (none = return all connections).
Parameters, in query: One of following options-
- None: return all active connections for this application
- single id: return connection status for this id
- comma separated ids: return connection status for multiple ids
Response: A standard success ({{exsuccess}}) or failure ({{exfail}}) response, including an array of device objects and their connection status. Success if the device is connected, failure if the device is not connected.
Example get connection response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"connections": [
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4"
},
{
"status": "FAILURE",
"reason": "Not Found",
"errorCode": 12,
"requestID": "12345678-5678-1234-5578-abcdef1234"
}
]
}
{: #exgetresp title="Example Connection response"}
In this example, status of 2 connections was requested. The request was successfully executed, 1 of the 2 connections was found active, the other one not.
Method: DELETE /action/connection
Description: Disconnect one or more devices, based on ids provided in parameters
Parameters, in query: One of following options-
- None: Disconnect all devices for connections this application made
- single id: disconnect device with id
- comma separated ids: disconnect multiple devices with ids
Response: The response for the DELETE function is the same as the response for the GET function. See {{exsuccess}} for success response, and {{exconnresp}} for failed responses.
Property APIs allow applictions to read and write property values from/to devices.
/action/property
Operations:
- Write value: POST
- Update value: PUT
- Read value: GET
- Delete value: DELETE
Method: POST /action/property/
Description: Writes a value to a property
Parameters: None
Request Body:
- an Object, as defined in {{objectdef}}
- A propertyID to write to
- A value to be written
- optional parameters
Example body writing a property:
{
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"technology": "ble",
"propertyID": "temperature",
"value": "dGVzdA==",
"forcedResponse": true
}
{: #exwrite title="Example writing a property"}
where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in {{objectdef}}
- "propertyID" is the ID of a previously registered property mapping
- "value" is the bytes to be written in base64 encoding
- "forcedresponse" requests a specific response behavior of the device that is not the default
Response: Success responses include standard success response properties as defined in {{success}} as well as the propertyID and the value written.
Example of a write property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
"propertyID": "temperature",
"value": "dGVzdA=="
}
{: #exwrresp title="Example write property response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "propertyID" is the ID of a previously registered property mapping
- "value" is the bytes to be written in base64 encoding
- "propertyID" is the ID of the property
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: PUT /action/property
Description: Updates a value of a property
Parameters: None
Request Body:
- an Object, as defined in {{objectdef}}
- A propertyID to write to
- A value to be written
- optional parameters
Example body updating a property:
{
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"technology": "ble",
"propertyID": "temperature",
"value": "dGVzdA==",
"forcedResponse": true
}
{: #exupd title="Example updating a property"}
where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in {{objectdef}}
- "propertyID" is the ID of a previously registered property mapping
- "value" is the value to be updated in base64 encoding
- "forcedresponse" requests a specific response behavior of the device that is not the default
Response: Success responses include standard success response properties as defined in {{success}} as well as the propertyID and the value updated.
Example of a write property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
"propertyID": "temperature",
"value": "dGVzdA=="
}
{: #exupresp title="Example update property response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: GET /action/property/{property}
Description: Read a property from a device
Parameters, in path: A propertyID {property} that needs to be read.
Parameters, in query: An id of a device on which the property has to be read.
Response: Success responses include standard success response properties as defined in {{success}} as well as the propertyID and the value read.
Example of a read property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
"propertyID": "temperature",
"value": "dGVzdA=="
}
{: #exreresp title="Example read property response"}
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: DELETE /action/property/{property}
Description: Delete a property value from a device
Parameters, in path: A propertyID {property} that needs to be deleted..
Parameters, in query: An id of a device on which the property has to be deleted.
Response: Success responses include standard success response properties as defined in {{success}} as well as the propertyID and the value deleted.
Example of a delete property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
"propertyID": "temperature",
"value": "dGVzdA=="
}
{: #exdelresp title="Example delete property response"}
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
/action/property/subscription
Subscriptions are properties that deliver a data stream instead of a single value. The property subscription API allows an application to manage these data streams.
Operations:
- Start a subscription data stream: POST
- Get status of a subscription data stream: GET
- Stop a subscription data stream: DELETE
Method: POST /action/property/subscription
Description: Start a subcription data stream pertaining to a specific property
Parameters: None
Request Body:
- an Object, as defined in {{objectdef}}
- A propertyID for which to start the subscription
- optional parameters
Example body for starting a subscription of a property:
{
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"technology": "ble",
"propertyID": "temperature",
"forcedAck": true
}
{: #exstartsub title="Example starting a subscription for a property"}
where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in {{objectdef}}
- "propertyID" is the ID of a previously registered property mapping
- "forcedAck" requests a specific response behavior of the device that is not the default
Response: Success responses is a standard success response when the subscription is started, as defined in {{success}}.
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: GET /action/property/subscription/{property}
Description: Gets the status of a subscription data stream, success if active, failure if not active
Parameters, in path: A propertyID {property} for the subscription.
Parameters, in query: An id of a device on which the subscription has to be started.
Response: Success responses is a standard success response when the subscription is started, as defined in {{success}}.
A failure to find the subscription will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: DELETE /action/property/subscription/{property}
Description: stops a subscription data stream
Parameters, in path: A propertyID {property} for the subscription.
Parameters, in query: An id of a device on which the subscription has to be started.
Response: Success response is a standard success response when the subscription is deleted, as defined in {{success}}.
A failure to delete the subscription will generate a standard failed response. Please refer to {{failure}} definition of failed response.
NIPC allows an application to register properties to use in action APIs. NIPC supports 2 types of registrations: Registrations for properties and registrations for events.
/registration/event
The event registration API allows an application to register an event for a data application to a specified property. This event is mapped to an MQTT pub/sub topic. By activating a subscription on one or more device(s) for that property, streaming data will get published to the associated pub/sub topic on MQTT.
Operations:
- Register an event: POST
- Update an event: PUT
- Get configuration of one or more events: GET
- Delete an event: DELETE
Method: POST /registration/event
Description: Register an event to a property
Parameters: None
Request Body:
- An event name that matches to an MQTT pub/sub topic
- The data format the event should be delivered in
- The device or group id the event is valid for
- Whether the event needs to be cached for replay
- the data applications that can consume the events
Example body registering an event:
{
"event": "enterprise/hospital/pulse_oximeter",
"eventFormat": "default",
"replay": false,
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"propertyID": "temperature"
}
{: #exregeve title="Example registering an event"}
where-
- "event" is the event identifier, which also maps to the MQTT topic name
- "eventFormat" is the format the data stream is delivered in, either default (decorated with id and property) or just the payload
- "replay" defines whether the event should be cached for replay or not
- "id" is the id of the device or group the event is valid for
- "type" is the type if the id, either device or group
- "dataApps" is an array of data applications that can subscribe to the event
- "propertyID" is the propertyID that will be used in action APIs to activate this event
The dataApps array consists of following-
- "dataAppID" is the identity of the data application either configured administratively or through SCIM.
- "mqtt" optional MQTT broker connection parameters, in case an external MQTT needs to be configured
Response: Success responses include standard success response properties as defined in {{success}} as well as all the attributes that were configured from the request.
Example of a register event response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
"event": "enterprise/hospital/pulse_oximeter",
"eventFormat": "default",
"replay": false,
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"propertyID": "temperature"
}
{: #exregeveresp title="Example register event response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "event" is the event identifier, which also maps to the MQTT topic name
- "eventFormat" is the format the data stream is delivered in, either default (decorated with id and property) or just the payload
- "replay" defines whether the event should be cached for replay or not
- "dataApps" is an array of data applications that can subscribe to the event
- "propertyID" is the propertyID that will be used in action APIs to activate this event
The dataApps array consists of following-
- "dataAppID" is the identity of the data application either configured administratively or through SCIM.
- "mqtt" optional MQTT broker connection parameters, in case an external MQTT needs to be configured
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: PUT /registration/event
Description: Update an existing event
Parameters: None
Request Body:
- An event name that matches to an MQTT pub/sub topic
- The data format the event should be delivered in
- The device or group id the event is valid for
- Whether the event needs to be cached for replay
- the data applications that can consume the events
Example body updating an event:
{
"event": "enterprise/hospital/pulse_oximeter",
"eventFormat": "default",
"replay": false,
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"propertyID": "temperature"
"ble": {
"type": "gatt",
"serviceID": "12345678-1234-5678-1234-56789abcdef0",
"characteristicID": "12345678-1234-5678-1234-56789abcdef1"
}
}
{: #exupdeve title="Example updating an event"}
where-
- "event" is the event identifier, which also maps to the MQTT topic name
- "eventFormat" is the format the data stream is delivered in, either default (decorated with id and property) or just the payload
- "replay" defines whether the event should be cached for replay or not
- "id" is the id of the device or group the event is valid for
- "type" is the type if the id, either device or group
- "dataApps" is an array of data applications that can subscribe to the event
- "propertyID" is the propertyID that will be used in action APIs to activate this event
The dataApps array consists of following-
- "dataAppID" is the identity of the data application either configured administratively or through SCIM.
- "mqtt" optional MQTT broker connection parameters, in case an external MQTT needs to be configured
The propertyID gets mapped to a protocol-specific property with a property mapping, through a protocol object-
Response: Success responses include standard success response properties as defined in {{success}} as well as all the attributes that were configured from the request.
Example of an update register event response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"id": "12345678-1234-5678-1234-56789abcdef4",
"event": "enterprise/hospital/pulse_oximeter",
"eventFormat": "default",
"replay": false,
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"propertyID": "temperature"
"ble": {
"type": "gatt",
"serviceID": "12345678-1234-5678-1234-56789abcdef0",
"characteristicID": "12345678-1234-5678-1234-56789abcdef1"
}
}
{: #exupdeveresp title="Example update event response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "event" is the event identifier, which also maps to the MQTT topic name
- "eventFormat" is the format the data stream is delivered in, either default (decorated with id and property) or just the payload
- "replay" defines whether the event should be cached for replay or not
- "dataApps" is an array of data applications that can subscribe to the event
- "propertyID" is the propertyID that will be used in action APIs to activate this event
The dataApps array consists of following-
- "dataAppID" is the identity of the data application either configured administratively or through SCIM.
- "mqtt" optional MQTT broker connection parameters, in case an external MQTT needs to be configured
The propertyID gets mapped to a protocol-specific property with a property mapping, through a protocol object-
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: GET /registration/event
Description: Gets the configuration of one or more events
Parameters: An event name. Multiple events can be added by comma-separated attributes. If no parameters are present, all events are returned.
Response: A success response as in {{success}} with a "events" object containing an array of returned event names with attributes defined in {{exupdeve}}.
Example of a get event response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"events": [
{
"ble": {
"type": "gatt",
"serviceID": "12345678-1234-5678-1234-56789abcdef0",
"characteristicID": "12345678-1234-5678-1234-56789abcdef1"
},
"event": "enterprise/hospital/pulse_oximeter",
"propertyID": "temperature",
"eventFormat": "default",
"replay": false,
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"technology": "ble"
},
{
"zigbee": {
"endpointID": 1,
"clusterID": 6,
"propertyID": 16,
"type": 1
},
"event": "enterprise/hospital/pulse_oximeter",
"propertyID": "temperature",
"eventFormat": "default",
"replay": false,
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"technology": "ble"
}
]
}
{: #exgeteveresp title="Example get event response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "events" is an array of events
where an event-
- "event" is the event identifier, which also maps to the MQTT topic name
- "eventFormat" is the format the data stream is delivered in, either default (decorated with id and property) or just the payload
- "replay" defines whether the event should be cached for replay or not
- "id" is the id of the device or group the event is valid for
- "type" is the type if the id, either device or group
- "dataApps" is an array of data applications that can subscribe to the event
- "propertyID" is the propertyID that will be used in action APIs to activate this event
The dataApps array consists of following-
- "dataAppID" is the identity of the data application either configured administratively or through SCIM.
- "mqtt" optional MQTT broker connection parameters, in case an external MQTT needs to be configured
The propertyID gets mapped to a protocol-specific property with a property mapping, through a protocol object-
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: DELETE /registration/event
Description: Delete one or more events
Parameters: An event name. Multiple events can be added by comma-separated attributes. If no parameters are present, all events are returned.
Response: A success response as in {{success}} with a "events" object containing an array of returned event names with attributes defined in {{exupdeve}}.
Example of a delete event response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"events": [
{
"ble": {
"type": "gatt",
"serviceID": "12345678-1234-5678-1234-56789abcdef0",
"characteristicID": "12345678-1234-5678-1234-56789abcdef1"
},
"event": "enterprise/hospital/pulse_oximeter",
"propertyID": "temperature",
"eventFormat": "default",
"replay": false,
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"technology": "ble"
},
{
"zigbee": {
"endpointID": 1,
"clusterID": 6,
"propertyID": 16,
"type": 1
},
"event": "enterprise/hospital/pulse_oximeter",
"propertyID": "temperature",
"eventFormat": "default",
"replay": false,
"id": "12345678-1234-5678-1234-56789abcdef4",
"type": "device",
"dataApps": [
{
"dataAppID": "12345678-1234-5678-1234-56789abcdef4",
"mqtt": {
"brokerURI": "mqtt.broker.com:8883",
"username": "user1",
"password": "password1",
"brokerCACert": "string"
}
}
],
"technology": "ble"
}
]
}
{: #exdeleveresp title="Example delete event response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "events" is an array of events
where an event-
- "event" is the event identifier, which also maps to the MQTT topic name
- "eventFormat" is the format the data stream is delivered in, either default (decorated with id and property) or just the payload
- "replay" defines whether the event should be cached for replay or not
- "id" is the id of the device or group the event is valid for
- "type" is the type if the id, either device or group
- "dataApps" is an array of data applications that can subscribe to the event
- "propertyID" is the propertyID that will be used in action APIs to activate this event
The dataApps array consists of following-
- "dataAppID" is the identity of the data application either configured administratively or through SCIM.
- "mqtt" optional MQTT broker connection parameters, in case an external MQTT needs to be configured
The propertyID gets mapped to a protocol-specific property with a property mapping, through a protocol object-
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
/registration/property
The property registration API allows an application to register a property mapping against a protocol-specific property as decribed in {{propertymap}}
Operations:
- Register a property: POST
- Update a property: PUT
- Get a property: GET
- Delete a property: DELETE
Method: POST /registration/property
Description: Register a property mapping to a protocol-specific property
Parameters: None
Request Body:
- a property ID
- a protocol object containing a protocol mapping
Example body registering a property:
{
"propertyID": "temperature",
"ble": {
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"long": false
}
}
{: #exregprop title="Example registering a property"}
where-
- "propertyID" is the propertyID that will be used in action APIs to refer to this property mapping
- A protocol object with a protocol-specific property map, as decribed in {{propertymap}}
Response: Success responses include standard success response properties as defined in {{success}} as well as all the attributes that were configured from the request.
Example of a register property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"propertyID": "temperature",
"ble": {
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"long": false
}
}
{: #exregpropresp title="Example register property response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "propertyID" is the propertyID that will be used in action APIs to refer to this property mapping
- A protocol object with a protocol-specific property map, as decribed in {{propertymap}}
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: PUT /registration/property
Description: Update a property mapping to a protocol-specific property
Parameters: None
Request Body:
- a property ID
- a protocol object containing a protocol mapping
Example body updating a property:
{
"propertyID": "temperature",
"ble": {
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"long": false
}
}
{: #exupdprop title="Example registering a property"}
where-
- "propertyID" is the propertyID that will be used in action APIs to refer to this property mapping
- A protocol object with a protocol-specific property map, as decribed in {{propertymap}}
Response: Success responses include standard success response properties as defined in {{success}} as well as all the attributes that were configured from the request.
Example of an update property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"propertyID": "temperature",
"ble": {
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"long": false
}
}
{: #exupdpropresp title="Example register property response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "propertyID" is the propertyID that will be used in action APIs to refer to this property mapping
- A protocol object with a protocol-specific property map, as decribed in {{propertymap}}
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: GET /registration/property
Description: Gets the property mapping of one or more properties
Parameters: A property name. Multiple properties can be added by comma-separated parameters. If no parameters are present, all properties are returned.
Response: A success response as in {{success}} with an array of properties, containing propertyID with protocol object containing a protocol-specific property mapping
Example of a get property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"properties": [
{
"ble": {
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"long": false
},
"propertyID": "temperature"
},
{
"zigbee": {
"endpointID": 1,
"clusterID": 6,
"propertyID": 16,
"type": 1
},
"propertyID": "temperature"
}
]
}
{: #exgetpropresp title="Example get property response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "properties" is an array of properties
where a property-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "propertyID" is the propertyID that will be used in action APIs to refer to this property mapping
- A protocol object with a protocol-specific property map, as decribed in {{propertymap}}
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
Method: DELETE /registration/property
Description: Deletes the property mapping of one or more properties
Parameters: A property name. Multiple properties can be added by comma-separated parameters. If no parameters are present, all properties are deleted.
Response: A success response as in {{success}} with an array of properties,
containing propertyID with protocol object containing a protocol-specific
property mapping
Example of a delete property response:
{
"status": "SUCCESS",
"requestID": "12345678-5678-1234-5578-abcdef1234",
"properties": [
{
"ble": {
"serviceID": "12345678-1234-5678-1234-56789abcdef4",
"characteristicID": "12345678-1234-5678-1234-56789abcdef4",
"long": false
},
"propertyID": "temperature"
},
{
"zigbee": {
"endpointID": 1,
"clusterID": 6,
"propertyID": 16,
"type": 1
},
"propertyID": "temperature"
}
]
}
{: #exdelpropresp title="Example delete property response"}
where-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "properties" is an array of properties
where a property-
- "id", "requestID" and "technology" are part of the standard {{success}} definition
- "propertyID" is the propertyID that will be used in action APIs to refer to this property mapping
- A protocol object with a protocol-specific property map, as decribed in {{propertymap}}
A failure will generate a standard failed response. Please refer to {{failure}} definition of failed response.
NIPC is extensible in two ways:
- Protocol mapping: New protocol mapping can extend NIPC with support for new non-IP protocols
- API extensions: API extensions leverage compound statements of basic NIPC action APIs to simplify common operations for applications.
As described in {{propertymap}} NIPC supports mapping protocol specific mapping to NIPC properties. BLE and Zigbee are used as examples, but protocol mapping is extensible to other protocols, so now non-IP protocols can be supported by NIPC without a schema change.
- property
|
|> BLE
| - BLE properties
|
|> Zigbee
| - Zigbee properties
|
|> New protocol
| - New protocol properties
{: #extprotmap title="Extended protocol mapping"}
As shown in {{extprotmap}}, a protocol mapping can be added by adding a new technology specific extension to the schema.
This is performed by adding the new protocol to the technology enum in the base object definition {{objectdef}}
Furthermore, the protocol objects need to be extended with the new protocol as well. Protocol objects will be extended as follows:
| Attribute | Req | Type | Example | +------------+-----+--------+------------------------------------------| | ble | T | object | an object with BLE-specific properties | | zigbee | T | object | an object with Zigbee-specific properties| | newProtocol| T | object | an object with newProtocol-specific props| {: #newprotext title="Adding Protocol mappings"}
In the new protocol object, protocol specific properties can be added.
Protocol mappings need to be IANA registered.
/extension
The extension APIs allow for extensibility of the APIs, either IANA registered extensions or vendor-specific extensions. Extension APIs must leverage the basic NIPC defined APIs and combine them in compound statements in order to streamline application operation against devices, make operations more expediant and convenient in one API call. In principle they do not add any basic functionality. In the OpenAPI model {{openAPI}} below, we have defined a few example extensions.
{: #errorhandling}
The error codes in the NIPC APIs can be generic or specific to the API. The generic error codes reuse the HTTP status codes defined in {{!RFC9110}}. The error codes for the action APIs are divided into the following categories:
- 1000-1099: Errors related to Connection APIs
- 1100-1199: Errors related to Property APIs
- 1200-1299: Errors related to Subscription APIs
- 1300-1399: Errors related to Broadcast APIs
The error codes for the registration APIs are further divided into the following categories:
- 1400-1499: Errors related to Event Registration APIs
- 1500-1599: Errors related to Property Registration APIs
For errors that are not specific to any API, the error codes have a value of 2000 or higher.
The error codes are also categorized according to the technology:
- xx00 - xx09: Generic
- xx10 - xx19: BLE
- xx20 - xx29: Zigbee
- xx30 - xx99: Reserved for future use
The specific error codes are defined in the table below:
Error Code | Description | Category |
---|---|---|
1000 | Device already connected | action/connection |
1001 | No connection found for device | action/connection |
1010 | BLE connection timeout | action/connection/ble |
1011 | BLE bonding failed | action/connection/ble |
1012 | BLE connection failed | action/connection/ble |
1013 | BLE service discovery failed | action/connection/ble |
1020 | Zigbee connection timeout | action/connection/zigbee |
1100 | Property not writeable | action/property |
1101 | Property not readable | action/property |
1110 | Invalid BLE service or characteristic ID | action/property/ble |
1120 | Invalid Zigbee endpoint or cluster ID | action/property/zigbee |
1200 | Subscription not found | action/subscription |
1201 | Subscription already started | action/subscription |
1210 | Invalid BLE service or characteristic ID | action/subscription/ble |
1220 | Invalid Zigbee endpoint or cluster ID | action/subscription/zigbee |
1300 | Invalid broadcast data | action/broadcast |
1400 | Invalid event identifier | registration/event |
1500 | Invalid property identifier | registration/property |
2000 | Generic catch-all error code for any API | generic |
2001 | Invalid device ID or gateway doesn't recognize the ID | generic |
2002 | Property not found | generic |
{: #errorcodes title="Error Codes"} |
The appropriate HTTP status code is returned in the response.
The publish/subscribe interface, or data streaming interface, is an MQTT publishing interface. Pub/sub topics can be created and managed by means of the /registration/event NIPC element.
In this memo, we propose the data format to be CBOR {{!RFC8949}}.
We have a CDDL {{!RFC8610}} definition where we define the DataSubscription struct that will be used by all the messages published to the MQTT broker.
The DataSubscription struct is a CBOR map that will contain the raw data in bytes and a timestamp of the data. Optionally, the message will also have a deviceID that corresponds to the SCIM ID of the device if the payload is associated to a known device.
Other fields in the CDDL such as apMacAddress and rssi can be optionally included but these fields can expose the underlying network topology.
Each message also has a subscription choice group that will define the type of data that is being published.
{::include data_subscription.cddl}
{:cddl}
This section contains a few examples of the DataSubscription struct depicted in CBOR diagnostic notation.
{
"data": h'02011A020A0C16FF4C001007721F41B0392078',
"deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
"timestamp": 1727484393,
"bleAdvertisement": {
"macAddress": "C1:5C:00:00:00:01",
"rssi": -25
}
}
{: title="Onboarded BLE Device Advertisement" }
{
"data": h'02011A020A0C16FF4C001007721F41B0392078',
"timestamp": 1727484393,
"bleAdvertisement": {
"macAddress": "C1:5C:00:00:00:01",
"rssi": -25
}
}
{: title="Non-onboarded BLE Device Advertisement" }
{
"data": h'434630374346303739453036',
"deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
"timestamp": 1727484393,
"bleSubscription": {
"serviceID": "a4e649f4-4be5-11e5-885d-feff819cdc9f",
"characteristicID": "c4c1f6e2-4be5-11e5-885d-feff819cdc9f"
}
}
{: title="BLE GATT Notification" }
{
"deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
"timestamp": 1727484393,
"bleConnectionStatus": {
"macAddress": "C1:5C:00:00:00:01",
"connected": true
}
}
{: title="BLE Connection status event" }
{
"data": h'434630374346303739453036',
"deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
"timestamp": 1727484393,
"zigbeeSubscription": {
"endpointID": 1,
"clusterID": 6,
"attributeID": 12,
"type": 1
}
}
{: title="Zigbee Attribute Notification" }
This section contains a few examples on how applications can leverage NIPC operations to communicate with BLE and Zigbee devices.
In this example, we will onboard a device, and setup an advertisement subscription event for that device.
The sequence of operations for this are:
- Onboard a device using the SCIM Interface (out of scope of this memo)
- Register an event with the device id to subscribe to advertisements POST /register/event
- Subscribe to the topic from the data receiver app MQTT subscribe topic
In this example, we will connect to a BLE device and read and write from a property.
The sequence of operations for this are:
- Onboard a device using the SCIM Interface (out of scope of this memo)
- Connect to the BLE device POST /action/connection
- Read a property from the BLE device GET /action/property
- Write to a property on the BLE device POST /action/property
- Disconnect from the BLE device DELETE /action/connection
In this example, we will connect a zigbee device to a Zigbee mesh and read and write from a property
The sequence of operations for this are:
- Onboard a device using the SCIM Interface (out of scope of this memo)
- Connect the Zigbee device POST /action/connection
- Read a property from the Zigbee device GET /action/property
- Write to a property on the Zigbee device POST /action/property
- Disconnect from the Zigbee device DELETE /action/connection
TBD.
This section provides guidance to the Internet Assigned Numbers Authority (IANA) regarding registration of values related to NIPC, in accordance with {{!RFC8126}}.
--- back
The following non-normative model is provide for convenience of the implementor.
<CODE BEGINS>
file "openapi.yml"
{::include nipc-openapi/NIPC_REST.yaml}
<CODE ENDS>
{: #openAPI}