An Application Layer Interface for Non-IP device control (NIPC)
Bart Brinckman
Cisco Systems
Brussels
Belgium
bbrinckm@cisco.com
Rohit Mohan
Cisco Systems
170 West Tasman Drive
San Jose
95134
USA
rohitmo@cisco.com
Braeden Sanford
Philips
Cambridge
USA
braeden.sanford@philips.com
21 October 2024
Internet-Draft
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.
Introduction
Scope
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].

Gateway for non-IP Devices

    +-------------+              +---------+              +--------+
    | Application |<------------>| Gateway |<------------>| Non-IP |
    |    app      |   IP-based   |         |    Non-IP    | Device |
    +-------------+   Operation  +---------+   Operation  +--------+

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 specifia 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.
Non-IP Gateway functions
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 functions, so its goal is to proxy payloads between Non-IP and IP networks. It is not intended to be a middleware functioni that interprets, decodes or modifies these payloads.

Basic Architecture

                            +-----------------------------------+
                            |                                   |
    +-----------+   Request |  +---------+                      |
    | onboarding|------------->|  SCIM   |                      |
    |    app    |<-------------| Server  |                      |
    +-----------+  Ctrl Endpt  +---------+                      |
                            |                                   |
    +-----------+           |  +------------+  +-------+  +--+  |
    |  Control  |>...REST...|.>|            |..|  AP   |..|D |  |
    |     &     |           |  |   Gateway  |  +-------+  +--+  |
    | Telemetry |<...MQTT...|.<|            |                   |
    |    Apps   |           |  +------------+                   |
    +-----------+           |                                   |
                            |       Network Deployment          |
                            +-----------------------------------+

Figure 2 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.
Interaction flow
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:
1. Onboarding: Authorize an onboarding application against a SCIM server co-located with the gateway.
2. Control: Authorize applications that may control devices.
3. 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.i Subsequent operations are defined by NIPC.
1. 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).
2. An application authorized can receive streaming data on a pub/sub topic configured by the control interface (telemetry interface).
Terminology
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.
Architecture
Overview
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 registrationsr. 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 Operations
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.
Actions
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.
Registrations
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.
Extensions
The final set of operations are not fundamental NIPC operations, but are extensions. Extensions are compound API's. 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 is one operation. extension allows for extensions, either generic extensions that anre IANA registered, or vendor specific extensions
Events
Events are published over MQTT. Events can be normal sreaming data, but also broadcasts or connection events.
Protocols
NIPC actions, registrations and extensions are request/response APIs. They makes use of a JSON schema over RESTful HTTP[RFC9114].
NIPC events are encoded in CBOR ([RFC8949]) and delivered over MQTT.
Schema
Device schema
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:

Definition of an Object
Attribute | Req | Type | Example
id | T | uuid | 12345678-1234-5678-1234-56789abcdef4
type | T | enum | device, group
technology | F | enum | ble, zigbee
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:

Example device object

{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "type": "device",
  "technology": "ble",
}

Property mapping
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 Mapping

     - property
        |
        |> BLE
        |     - BLE property
        |
        |> Zigbee
              - Zigbee property

As shown in Figure 4, protocol-specific properties must be described in a protocol object, for example a "ble" or a "zigbee" object.

Protocol objects
Attribute | Req | Type | Example
ble | T | object | an object with BLE-specific attributes
zigbee | T | object | an object with Zigbee-specific attributes
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:

Example property mapping

{
  "propertyID": "temperature",
  "ble": {
    "serviceID": "12345678-1234-5678-1234-56789abcdef4",
    "characteristicID": "12345678-1234-5678-1234-56789abcdef4",
    "long": false
  }
}

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 API's as well, therefore there are a limited set of API's avaialbe that have protocol objects directly embedded in the API, in ordur to perform operations on properties without having to first register them.
Response
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:

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
Example success response:

Example success response

{
  "status": "SUCCESS",
  "requestID": "12345678-5678-1234-5578-abcdef1234",
  "id": "12345678-1234-5678-1234-56789abcdef4",
}

Failure responses additionally include an error code and optionally a reason, which contains a textual explanation of the error.
Failure response:

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"
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.
- reason is a human readable explanation of why the error occurred.
Example failure response:

Example failure response

{
  "status": "FAILURE",
  "reason": "Not Found",
  "errorCode": 12,
  "requestID": "12345678-5678-1234-5578-abcdef1234"
}

NIPC Actions
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.
Connections
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
Connection API
Connect to a device
Method: POST /action/connection
Description: Connect to a device
Parameters: None
Request Body:
- an Object, as defined in Table 1
- optionally a set of properties to be discovered. These are supplied in protocol objects, as defined in Table 2. 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:

Example Connection

{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "type": "device",
  "technology": "ble",
  "retries": 3,
  "retryMultipleAPs": true
}

where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in Table 1.
- "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:

Example Connection with explicit discovery of connections

{
  "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
}

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 Table 3 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 Figure 10.

BLE Services

    services
     - serviceID
        |
        |> characteristics
            - charactericID
            - flags
               |
               |> Descriptors
                   - descriptorID

Example of a BLE connection response with BLE discovered properties:

Example Connection response

{
  "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"
            }
          ]
        }
      ]
    }
  ]
}

where in the BLE protocol object:
- "id", "requestID" and "technology" are part of hte standard Table 3 definition
- "ble" protocol object conatins an Array of BLE services as shown in Figure 10
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Return active connections
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 (Figure 6)i or failure (Figure 7) 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:

Example 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"
    }
  ]
}

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.
Disconnect a device
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 Figure 6 for success response, and Figure 11 for failed responses.
Properties
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
Property API
Writing a value
Method: POST /action/property/
Description: Writes a value to a property
Parameters: None
Request Body:
- an Object, as defined in Table 1
- A propertyID to write to
- A value to be written
- optional parameters
Example body writing a property:

Example writing a property

{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "type": "device",
  "technology": "ble",
  "propertyID": "temperature",
  "value": "1",
  "forcedResponse": true
}

where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in Table 1
- "propertyID" is the ID of a previously registered property mapping
- "value" is the value to be written
- "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 Table 3 as well as the propertyID and the value written.
Example of a write property response:

Example write property response

{
  "status": "SUCCESS",
  "requestID": "12345678-5678-1234-5578-abcdef1234",
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "propertyID": "temperature",
  "value": "1"
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 definition
- "propertyID" is the ID of a previously registered property mapping
- "value" is the value to be written
- "propertyID" is the proper
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Updating a value
Method: PUT /action/property
Description: Updates a value of a property
Parameters: None
Request Body:
- an Object, as defined in Table 1
- A propertyID to write to
- A value to be written
- optional parameters
Example body updating a property:

Example updating a property

{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "type": "device",
  "technology": "ble",
  "propertyID": "temperature",
  "value": "1",
  "forcedResponse": true
}

where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in Table 1
- "propertyID" is the ID of a previously registered property mapping
- "value" is the value to be updated
- "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 Table 3 as well as the propertyID and the value updated.
Example of a write property response:

Example update property response

{
  "status": "SUCCESS",
  "requestID": "12345678-5678-1234-5578-abcdef1234",
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "propertyID": "temperature",
  "value": "1"
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 definition
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Read a property
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 Table 3 as well as the propertyID and the value read.
Example of a read property response:

Example read property response

{
  "status": "SUCCESS",
  "requestID": "12345678-5678-1234-5578-abcdef1234",
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "propertyID": "temperature",
  "value": "1"
}

A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Delete a property value
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 Table 3 as well as the propertyID and the value deleted.
Example of a delete property response:

Example delete property response

{
  "status": "SUCCESS",
  "requestID": "12345678-5678-1234-5578-abcdef1234",
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "propertyID": "temperature",
  "value": "1"
}

A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Subscriptions
/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
Property subscription API
Starting a subscription data stream
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 Table 1
- A propertyID for which to start the subscription
- optional parameters
Example body for starting a subscription of a property:

Example starting a subscription for a property

{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "type": "device",
  "technology": "ble",
  "propertyID": "temperature",
  "forcedAck": true
}

where-
- "id", "type" and "technology" are part of the object definition (device or group), as defined in Table 1
- "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 Table 3.
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Get status of a subscription data stream
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 Table 3.
A failure to find the subscription will generate a standard failed response. Please refer to Table 4 definition of failed response.
stop a subscription data stream
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 Table 3.
A failure to delete the subscription will generate a standard failed response. Please refer to Table 4 definition of failed response.
NIPC Registrations
NIPC allows an application to register properties to use in action API's. NIPC supports 2 types of registrations: Registrations for properties and registrations for events.
Event registration
/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
Event registration API
Registering an event
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:

Example 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"
}

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 hte 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 appplications 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 Table 3 as well as all the attributes that were configured from the request.
Example of a register event response:

Example 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"
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 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 appplications 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 Table 4 definition of failed response.
Updating a topic
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:

Example 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"
  }
}

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 hte 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 appplications 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 Table 3 as well as all the attributes that were configured from the request.
Example of an update register event response:

Example update 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"
  }
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 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 appplications 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 Table 4 definition of failed response.
Get configuration of one or more events
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 Table 3 with a "events" object containing an array of returned event names with attributes defined in Figure 22.
Example of a get event response:

Example 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"
    }
  ]
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 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 hte 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 appplications 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 Table 4 definition of failed response.
Delete one or more topics
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 Table 3 with a "events" object containing an array of returned event names with attributes defined in Figure 22.
Example of a delete event response:

Example 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"
    }
  ]
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 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 hte 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 appplications 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 Table 4 definition of failed response.
Property registration
/registration/property
The property registration API allows an application to register a property mapping against a protocol-specific property as decribed in Section 2.4.2
Operations:
- Register a property: POST
- Update a property: PUT
- Get a property: GET
- Delete a property: DELETE
Property registration API
Registering a property
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:

Example registering a property

{
  "propertyID": "temperature",
  "ble": {
    "serviceID": "12345678-1234-5678-1234-56789abcdef4",
    "characteristicID": "12345678-1234-5678-1234-56789abcdef4",
    "long": false
  }
}

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 Section 2.4.2
Response: Success responses include standard success response properties as defined in Table 3 as well as all the attributes that were configured from the request.
Example of a register property response:

Example 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
  }
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 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 Section 2.4.2
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Updating a property
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:

Example registering a property

{
  "propertyID": "temperature",
  "ble": {
    "serviceID": "12345678-1234-5678-1234-56789abcdef4",
    "characteristicID": "12345678-1234-5678-1234-56789abcdef4",
    "long": false
  }
}

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 Section 2.4.2
Response: Success responses include standard success response properties as defined in Table 3 as well as all the attributes that were configured from the request.
Example of an update property response:

Example 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
  }
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 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 Section 2.4.2
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Get property mapping of one or more properties
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 Table 3 with an array of properties, containing propertyID with protocol object containing a protocol-specific property mapping
Example of a get property response:

Example 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"
    }
  ]
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 definition
- "properties" is an array of properties
where a property-
- "id", "requestID" and "technology" are part of the standard Table 3 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 Section 2.4.2
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
Delete property mapping of one or more properties
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 Table 3 with an array of properties, containing propertyID with protocol object containing a protocol-specific
property mapping
Example of a delete property response:

Example 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"
    }
  ]
}

where-
- "id", "requestID" and "technology" are part of the standard Table 3 definition
- "properties" is an array of properties
where a property-
- "id", "requestID" and "technology" are part of the standard Table 3 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 Section 2.4.2
A failure will generate a standard failed response. Please refer to Table 4 definition of failed response.
NIPC Extensibility
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.
Protocol extensions
As described in Section 2.4.2 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 noew non-IP protocols can be supported by NIPC without a schema change.

Extended protocol mapping

     -  property
        |
        |> BLE
        |     - BLE  properties
        |
        |> Zigbee
        |     - Zigbee properties
        |
        |> New protocol
        |     -  New protocol properties

As shown in Figure 32, 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 Table 1
Furthermore, the protocol objects need to be extended with the new protocol as well. Protocol objects will be extended as follows:

Adding Protocol mappings
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
In the new protocol object, protocol specific properties can be added.
Protocol mappings need to be IANA registered.
API extensions
/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 Figure 38 below, we have defined a few example extensions.
Publish/Subscribe Interface
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].
CDDL Definition
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.

DataSubscription = {
  data: bytes,
  timestamp: float, ; epoch in seconds
  ? deviceId: text,
  ? apMacAddress: text,
  subscription
}

subscription = (
  bleSubscription: BleSubscription //
  bleAdvertisement: BleAdvertisement //
  bleConnectionStatus: BleConnectionStatus //
  zigbeeSubscription: ZigbeeSubscription //
  rawPayload: RawPayload
)

BleSubscription = {
  serviceId: text,
  characteristicId: text
}

BleAdvertisement = {
  macAddress: text,
  ? rssi: nint,
}

BleConnectionStatus = {
  macAddress: text,
  connected: bool,
  ? reason: int
}

ZigbeeSubscription = {
  endpointId: int,
  clusterId: int,
  attributeId: int
  attributeType: int
}

RawPayload = {
  contextId: text
}

CBOR Examples
This section contains a few examples of the DataSubscription struct depicted in CBOR diagnostic notation.

Onboarded BLE Device Advertisement

{
    "data": h'02011A020A0C16FF4C001007721F41B0392078',
    "deviceId": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "bleAdvertisement": {
        "macAddress": "C1:5C:00:00:00:01",
        "rssi": -25
    }
}

Non-onboarded BLE Device Advertisement

{
    "data": h'02011A020A0C16FF4C001007721F41B0392078',
    "timestamp": 1727484393,
    "bleAdvertisement": {
        "macAddress": "C1:5C:00:00:00:01",
        "rssi": -25
    }
}

BLE GATT Notification

{
    "data": h'434630374346303739453036',
    "deviceId": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "bleSubscription": {
        "serviceId": "a4e649f4-4be5-11e5-885d-feff819cdc9f",
        "characteristicId": "c4c1f6e2-4be5-11e5-885d-feff819cdc9f"
    }
}

BLE Connection status event

{
    "data": h'434630374346303739453036',
    "deviceId": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "bleConnectionStatus": {
        "macAddress": "C1:5C:00:00:00:01",
        "connected": true
    }
}

Zigbee Attribute Notification

{
    "data": h'434630374346303739453036',
    "deviceId": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "zigbeeSubscription": {
        "endpointId": 1,
        "clusterId": 6,
        "attributeId": 12,
        "type": 1
    }
}

Examples
This section contains a few examples on how applications can leverage NIPC operations to communicate with BLE and Zigbee devices.
BLE Advertisement
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 eventc with the device id to subscribe to advertisements POST /register/event
- Subscribe to the topic from the data receiver app MQTT subscribe topic
BLE Property Read/Write
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
Zigbee Property Read/Write
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
Security Considerations
TBD.
IANA Considerations
This section provides guidance to the Internet Assigned Numbers Authority (IANA) regarding registration of values related to NIPC, in accordance with [RFC8126].
Protocol mapping
API extensions

Normative References

Informative References
[BLE53]

Bluetooth Core Specification, Version 5.3
Bluetooth SIG
2021
[Zigbee22]

zigbee Specification, Version 22 1.0
Connectivity Standards Alliance
2017
[RFC7644]
[I-D.ietf-scim-device-model]
[RFC2119]
[RFC8174]
[I-D.ietf-asdf-sdf]
[RFC9114]
[RFC8949]
[RFC8610]
[RFC8126]
OpenAPI definition
The following non-normative model is provide for convenience of the implementor.

<CODE BEGINS>
file "openapi.yml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API
  description: |-
    There has been a large influx of non-IP devices supporting
    processes in manufacturing, healthcare, hospitality, retail, the
    home, and the office.  At the same time, wireless access points
    have been deployed nearly everywhere, many of which have radios
    that can transmit and receive different frame types, such as BLE,
    Zigbee. To integrate multiple of these use cases leveraging a
    single wireless infrastructure and avoid the need for parallel
    infrastructure, a Non IP device gateway function is necessary.
    The gateway provides the following functions:
       - authentication and authorization of application clients that
         will communicate with devices
       - APIs that onboard a device on the network (out of scope for
         this specification, but covered in SCIM for devices)
       - APIs that allow an app to set up a connection with a device
       - APIs that allow an app to exchange action with a device
       - APIs that allow a device to create registrations in the
         network for a device
    These collection of these APIs, in combination with the
    onboarding API (SCIM for devices) will allow an application to
    perform a complete set of operations on Non-IP devices.
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.3.5
externalDocs:
  description: NIPC IETF draft
  url: TBD
servers:
  - url: https://{gw_host}/nipc
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name: action
    description: APIs that allow apps to perform actions on devices.
  - name: registrations
    description: |-
      APIs that allow apps to register properties of devices.
  - name: extensions
    description: |-
      APIs that simplify application interaction by implementing one
      or more basic API's into a single API call.

paths:
### Action
  /action/connection:
    post:
      tags:
        - action
      summary: |-
        Connect a device to the network, optionally with service
        discovery
      description: |-
        Connect a device to the network, optionally with service
        discovery
      operationId: Connect
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Connection'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - action
      summary: |-
        Get connection state devices for a device or group of
        devices
      description: |-
        Get all connection status for connections made by control ap
        or connection status by object ID, multiple ids can be
        provided with comma separated strings, or a group id can be
        provided
      operationId: GetConnections
      parameters:
        - name: id
          in: query
          description: device or group ids that need to be filtered
          required: false
          explode: false
          schema:
            type: array
            items:
              type: string
              format: uuid
              example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiConnectionsResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    delete:
      tags:
        - action
      summary: Disconnect a device or group of devices
      description: |-
        Disconnect a device or device group by object ID, Multiple
        ids can be provided with comma separated strings, or a
        group id can be provided
      operationId: DeleteConnections
      parameters:
        - name: id
          in: query
          description: device or group ids that need to be filtered
          required: false
          explode: false
          schema:
            type: array
            items:
              type: string
              format: uuid
              example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiConnectionsResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/connection/id/{id}:
    post:
      tags:
        - action
      summary: |-
        Connect a device by device id (device technology needs to
        support connection)
      description: |-
        Connect a device by device id, full service discovery
        will be performed. Will fail if device has multiple
        technologies defined. Group ids will fail.
      operationId: CreateConnectionbyID
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - action
      summary: Get connection by id for a device
      description: |-
        Get connection by id for a device, success when device
        connected, failure when device not connected.
        Group ids will also fail.
      operationId: GetConnectionbyId
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    delete:
      tags:
        - action
      summary: Delete connection by id for a device
      description: |-
        Disconnect a device by id, success when device
        is disconnected, failure disconnect fails.
        Group ids will also fail.
      operationId: DeleteConnectionbyID
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/services/:
    get:
      tags:
        - action
      summary: Get all services for a device
      description: |-
        Get all services for a connected device, success
        when service discovery succeeds failure, failure when
        Service discovery fails. This updates cache for cached
        Services. Fails when using a group id.
      operationId: GetServicesbyId
      parameters:
        - name: id
          in: query
          description: device id that need to be filtered
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/services/discover:
    post:
      tags:
        - action
      summary: |-
        Selectively discover services on a device, limited
        to services described in the parameters
      description: |-
        Selectively discover services on a device, limited
        to services described in the parameters.
        Group ids will fail.
      operationId: GetSelectiveServices
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Service'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property:
    post:
      tags:
        - action
      summary: Write a value to an property on a device
      description: Write a value to an property on a device
      operationId: Write
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyValue'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyValueResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    put:
      tags:
        - action
      summary: Update a value of an property on a device
      description: Update a value of an property on a device
      operationId: Update
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyValue'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyValueResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/{property}:
    delete:
      tags:
        - action
      summary: Delete a value from an property on a device
      description: Delete a value to an property on a device
      operationId: Delete
      parameters:
      - name: id
        in: query
        description: device id that need to be filtered
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyValueResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - action
      summary: Read a value from an property on a device
      description: Read a value to an property on a device
      operationId: Read
      parameters:
      - name: id
        in: query
        description: device id that need to be filtered
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyValueResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/write:
    post:
      tags:
        - action
      summary: Write a value to an property using technology extensions
      description: |-
        Write a value to an property directly, addressing the property
        with technology-specific extensions, this does not require
        property registration. You cannot write to a group id.
      operationId: AttrWrite
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyValueRaw'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyValueResponseRaw'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/read:
    post:
      tags:
        - action
      summary: Read a value to an property using technology extensions
      description: |-
        Read a value to an property directly, addressing the property
        with technology-specific extensions, this does not require
        property registration. You cannot write to a group id.
      operationId: AttrRead
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyRaw'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyValueResponseRaw'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/subscription:
    post:
      tags:
        - action
      summary: |-
         Subscribe to streaming event action from an property on a device
      description: |-
        Subscribe to streaming event action from an property on a device
      operationId: Subscribe
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Subscription'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/subscription/{property}:
    delete:
      tags:
        - action
      summary: |-
        Unsubscribe to streaming event action from an property on a device
      description: |-
        Unsubscribe to streaming event action from an property on a device
      operationId: Unsubscribe
      parameters:
      - name: id
        in: query
        description: device id that need to be filtered
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - action
      summary: Get the status of an event subscription on a device
      description: Get the status of an event subscription on a device
      operationId: GetSubscription
      parameters:
      - name: id
        in: query
        description: device id that need to be filtered
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        explode: true
        schema:
          type: string
          example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/subscription/event/{event}:
    delete:
      tags:
        - action
      summary: delete all active subscriptions by event
      description: delete all active subscriptions by event
      operationId: deleteSubscriptionbyEvent
      parameters:
        - name: event
          in: path
          description: event that needs to be filtered
          required: true
          schema:
            type: string
            example: "enterprise/hospital/pulse_oximeter"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref:
                   '#/components/schemas/MultiSubscriptionResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - action
      summary: get all active subscriptions by event
      description: get all active subscriptions by event
      operationId: getSubsciptionsbyEvent
      parameters:
        - name: event
          in: path
          description: event that needs to be filtered
          required: true
          schema:
            type: string
            example: "enterprise/hospital/pulse_oximeter"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref:
                   '#/components/schemas/MultiSubscriptionResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref:
                   '#/components/schemas/MultiSubscriptionResponse'

  /action/property/subscription/id/{id}:
    delete:
      tags:
        - action
      summary: delete all event subscriptions by id
      description: delete all event subscriptions by id
      operationId: deleteSubscriptionbyID
      parameters:
        - name: id
          in: path
          description: object id that needs to be filtered
          required: true
          schema:
            type: string
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref:
                   '#/components/schemas/MultiSubscriptionResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - action
      summary: get all event subscriptions by object id
      description: get all event subscriptions by object id
      operationId: getSubscriptionbyID
      parameters:
        - name: id
          in: path
          description: object id that needs to be filtered
          required: true
          schema:
            type: string
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref:
                   '#/components/schemas/MultiSubscriptionResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/subscription/start:
    post:
      tags:
        - action
      summary: |-
         Subscribe to streaming action from an property on a device
         by directly addressing hte property (unregistered attr)
      description: |-
        Subscribe to streaming action from an property on a device
        by directly addressing hte property (unregistered attr)
      operationId: SubscriptionStart
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionRaw'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/property/subscription/stop:
    post:
      tags:
        - action
      summary: |-
         Stop streaming action from an property on a device
         by directly addressing hte property (unregistered attr)
      description: |-
        Stop streaming action from an property on a device
        by directly addressing hte property (unregistered attr)
      operationId: SubscriptionStop
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionRaw'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /action/broadcast:
    post:
      tags:
        - action
      summary: Broadcast to a device
      description: Broadcast to a device
      operationId: Broadcast
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Broadcast'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

### Registrations
  /registration/event:
    post:
      tags:
        - registrations
      summary: Register a publish/subscribe event
      description: Register a publish/subscribe event
      operationId: registerEvent
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Event'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    put:
      tags:
        - registrations
      summary: Update a publish/subscribe event
      description: Update a publish/subscribe event
      operationId: UpdateEvent
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Event'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    delete:
      tags:
        - registrations
      summary: unregister a publish/subscribe event
      description: |-
        unregister a publish/subscribe event, single topic,
        multiple events not allowed.
      operationId: unregisterEvent
      parameters:
        - name: event
          in: query
          description: event that need to be filtered
          required: false
          explode: false
          schema:
            type: string
            example: "enterprise/hospital/pulse_oximeter"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - registrations
      summary: get one or all publish/subscribe event
      description: |-
        get publish/subscribe event, if no topic is specified
        in query, all events will be returned
      operationId: getEvent
      parameters:
        - name: event
          in: query
          description: event that need to be filtered
          required: false
          explode: false
          schema:
            type: string
            example: "enterprise/hospital/pulse_oximeter"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiEventsResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /registration/event/{event}:
    delete:
      tags:
        - registrations
      summary: delete a publish/subscribe event by name
      description: unregister a publish/subscribe event by Name
      operationId: deleteEventbyName
      parameters:
        - name: event
          in: path
          description: event that needs to be filtered
          required: true
          schema:
            type: string
            example: "enterprise/hospital/pulse_oximeter"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - registrations
      summary: get a publish/subscribe event by name
      description: get a publish/subscribe event by name
      operationId: getEventbyName
      parameters:
        - name: event
          in: path
          description: event that needs to be filtered
          required: true
          schema:
            type: string
            example: "enterprise/hospital/pulse_oximeter"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /registration/event/data-app/{data-app}:
    delete:
      tags:
        - registrations
      summary: delete all publish/subscribe events by data-app
      description: |-
        unregister all publish/subscribe events by data-app
      operationId: deleteEventbyDataApp
      parameters:
        - name: data-app
          in: path
          description: action app that needs to be filtered
          required: true
          schema:
            type: string
            example: https://data-app-1
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiEventsResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - registrations
      summary: get all publish/subscribe events by data-app
      description: get all publish/subscribe events by data-app
      operationId: getEventbyDataApp
      parameters:
        - name: data-app
          in: path
          description: action app that needs to be filtered
          required: true
          schema:
            type: string
            example: https://data-app-1
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiEventsResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /registration/event/id/{id}:
    delete:
      tags:
        - registrations
      summary: delete all publish/subscribe events by object id
      description: unregister all publish/subscribe events by id
      operationId: deleteEventbyID
      parameters:
        - name: id
          in: path
          description: object id that needs to be filtered
          required: true
          schema:
            type: string
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiEventsResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - registrations
      summary: get all publish/subscribe events by object id
      description: get all publish/subscribe events by object id
      operationId: getEventbyID
      parameters:
        - name: id
          in: path
          description: object id that needs to be filtered
          required: true
          schema:
            type: string
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiEventsResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /registration/property:
    post:
      tags:
        - registrations
      summary: Register an property
      description: |-
        Register an property for use in action APIs
      operationId: registerProperty
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyRegistration'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyRegistrationResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    put:
      tags:
        - registrations
      summary: Update an property registration
      description: |-
        Update an existing property registration
      operationId: updatePropertyRegistration
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyRegistration'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyRegistrationResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    delete:
      tags:
        - registrations
      summary: Delete an property registration
      description: Delete an property registration
      operationId: deletePropertyRegistration
      parameters:
        - name: propertyname
          in: query
          description: property name that needs to be filtered
          required: false
          explode: false
          schema:
            type: string
            example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyRegistrationResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - registrations
      summary: list registered properties
      description: |-
        get a registered property by name of get all
        properties if no names supplied.
      operationId: getPropertyRegistration
      parameters:
        - name: propertyname
          in: query
          description: property name that needs to be filtered
          required: false
          explode: true
          schema:
            type: string
            example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiPropertyRegistrationResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /registration/property/{propertyname}:
    delete:
      tags:
        - registrations
      summary: delete an property registration by name
      description: delete an property registration by name
      operationId: deletePropertyRegistrationbyName
      parameters:
        - name: propertyname
          in: path
          description: property that needs to be filtered
          required: true
          schema:
            type: string
            example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyRegistrationResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - registrations
      summary: get an property registration by name
      description: get an property registration by name
      operationId: getAttirbuteRegistrationbyName
      parameters:
        - name: propertyname
          in: path
          description: property that needs to be filtered
          required: true
          schema:
            type: string
            example: "temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyRegistrationResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /registration/property/file:
    post:
      tags:
        - registrations
      summary: Register and upload a file for later use
      description: Register and upload a file for later use
      operationId: registerFile
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/File'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

### Extensions

  /extension/property/write/file:
    post:
      tags:
        - extensions
      summary: Write a file to an property across multiple writes
      description: |-
        Write a file to an property across multiple writes
      operationId: WriteFile
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyFile'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /extension/property/write/blob:
    post:
      tags:
        - extensions
      summary: |-
        Write a binary blob to an property across multiple writes
      description: |-
        Write a binary blob to an property across multiple writes
      operationId: WriteBlob
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyBlob'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /extension/property/read/conditional:
    post:
      tags:
        - extensions
      summary: |-
        Read a value from property on a device until it matches a
        specific value.
      description: |-
        Read a value from property on a device until it matches a
        specific value.
      operationId: ReadCond
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyConditional'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PropertyValueResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /extension/property/firmware:
    post:
      tags:
        - extensions
      summary: Write firmware to a device
      description: |-
        Write a file to an property across multiple writes
      operationId: WriteFirmware
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Firmware'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FirmwareResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - extensions
      summary: get the status of a firmware upgrade
      description: get the status of a firmware upgrade
      operationId: getFirmwareStatus
      parameters:
        - name: id
          in: query
          description: device id that needs to be filtered
          required: true
          schema:
            type: string
            example: "12345678-1234-5678-1234-56789abcdef4"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FirmwareResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /extension/bulk:
    post:
      tags:
        - extensions
      summary: Compound operations on a device
      description: Compound operations on a device
      operationId: Bulk
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Bulk'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

components:
  schemas:
# BLE objects
##  An array for BLE services
    BLEServiceslist:
      required:
        - services
      type: object
      properties:
        ble:
          type: array
          items:
            $ref: '#/components/schemas/BLEService'

## A BLE service with its characteristics
    BLEService:
      required:
        - serviceID
        - characteristics
      type: object
      properties:
        serviceID:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
        characteristics:
          type: array
          items:
            $ref: '#/components/schemas/BLECharacteristic'

## A BLE characteristics with its descriptors
    BLECharacteristic:
      required:
        - characteristicID
        - flags
        - descriptors
      type: object
      properties:
        characteristicID:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
        flags:
          type: array
          example:
          - read
          - write
          items:
            type: string
            enum:
              - read
              - write
              - notify
        descriptors:
          type: array
          items:
            $ref: '#/components/schemas/BLEDescriptor'

## A BLE descriptor
    BLEDescriptor:
      required:
        - descriptorID
      type: object
      properties:
        descriptorID:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4

## BLE service ID only
    BLEServiceID:
      type: object
      properties:
        serviceID:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4

## Properties that define a BLE property
    BLEProperties:
      required:
        - ble
      type: object
      properties:
        ble:
          required:
            - serviceID
            - characteristicID
          type: object
          properties:
            serviceID:
              type: string
              format: uuid
              example: 12345678-1234-5678-1234-56789abcdef4
            characteristicID:
              type: string
              format: uuid
              example: 12345678-1234-5678-1234-56789abcdef4
            long:
              type: boolean
              example: false

## Defines different types of BLE events
    BLEEvent:
      required:
        - ble
      type: object
      properties:
        ble:
          oneOf:
            - $ref: '#/components/schemas/BLESubEvent'
            - $ref: '#/components/schemas/BLEConnEvent'
            - $ref: '#/components/schemas/BLEAdvEvent'

## BLE Gatt Event definition
    BLESubEvent:
      required:
        - type
        - serviceID
        - characteristicID
      type: object
      properties:
        type:
          type: string
          example: gatt
          enum:
            - gatt
        serviceID:
          type: string
          example: 12345678-1234-5678-1234-56789abcdef0
        characteristicID:
          type: string
          example: 12345678-1234-5678-1234-56789abcdef1

## BLE Connection event Event definition
    BLEConnEvent:
      required:
        - type
      type: object
      properties:
        type:
          type: string
          example: connection_events
          enum:
            - connection_events

## BLE Advertisement Event definition
    BLEAdvEvent:
      required:
        - type
      type: object
      properties:
        type:
          type: string
          example: advertisements
          enum:
            - advertisements
        filterType:
          type: string
          example: deny
          enum:
            - deny
            - allow
        filters:
          type: array
          items:
            $ref: '#/components/schemas/BLEAdvertisement'

## BLE Advertisement properties
    BLEAdvertisement:
      type: object
      properties:
        adType:
          type: string
          example: ff
        adData:
          type: string
          example: 4c00*

## Properties that define a BLE broadcast
    BLEBroadcast:
      required:
        - ble
      type: object
      properties:
        ble:
          type: object
          required:
            - advertisement
          properties:
            advertisement:
              type: string
              format: byte
              example: AgEaAgoMFv9MABAHch9BsDkgeA==

# Zigbee objects
## An array for Zigbee Endpoints
    ZigbeeEndpointlist:
      required:
        - zigbee
      type: object
      properties:
        zigbee:
          type: array
          items:
            $ref: '#/components/schemas/ZigbeeEndpoint'

## A Zigbee endpoint with its clusters
    ZigbeeEndpoint:
      required:
        - endpointID
        - clusters
      type: object
      properties:
        endpointID:
          type: integer
          format: int32
          example: 10
        clusters:
          type: array
          items:
            $ref: '#/components/schemas/ZigbeeCluster'

## A Zigbee cluster with its properties
    ZigbeeCluster:
      required:
        - clusterID
        - properties
      type: object
      properties:
        clusterID:
          type: integer
          format: int32
          example: 0
        properties:
          type: array
          items:
            $ref: '#/components/schemas/ZigbeeProperty'

## A Zigbee property
    ZigbeeProperty:
      required:
        - propertyID
        - propertyType
      type: object
      properties:
        propertyID:
          type: integer
          format: int32
          example: 1
        propertyType:
          type: integer
          format: int32
          example: 32

## Properties that define a Zigbee property
    ZigbeeProperties:
      required:
        - zigbee
      type: object
      properties:
        zigbee:
          required:
            - endpointID
            - clusterID
            - propertyID
          type: object
          properties:
            endpointID:
              type: integer
              format: int32
              example: 1
            clusterID:
              type: integer
              format: int32
              example: 6
            propertyID:
              type: integer
              format: int32
              example: 16
            type:
              type: integer
              format: int32
              example: 1

## Properties that define a Zigbee broadcast
    ZigbeeBroadcast:
      required:
        - zigbee
      type: object
      properties:
        zigbee:
          required:
            - endpointID
            - clusterID
            - propertyID
            - value
          type: object
          properties:
            endpointID:
              type: integer
              format: int32
              example: 1
            clusterID:
              type: integer
              format: int32
              example: 6
            propertyID:
              type: integer
              format: int32
              example: 16
            type:
              type: integer
              format: int32
              example: 1
            value:
              type: integer
              format: int32
              example: 15

# Common objects
## A SCIM id, can be a  device or a group
    Id:
      required:
        - id
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4

## A SCIM object, can be a  device or a group
    Object:
      allOf:
        - $ref: '#/components/schemas/Id'
      type: object
      properties:
        type:
          type: string
          example: device
          enum:
            - device
            - group
        technology:
          type: string
          example: ble
          enum:
            - ble
            - zigbee

## A Service is a device with optional service IDs
    Service:
      allOf:
        - $ref: '#/components/schemas/Object'
      type: object
      properties:
        ble:
          type: object
          properties:
            services:
              type: array
              items:
                $ref: '#/components/schemas/BLEServiceID'
            cached:
              description: |-
                If we can cache information, then device doesn't need
                to be rediscovered before every connected.
              type: boolean
              default: false
            cacheIdlePurge:
              description: cache expiry period, when device allows
              type: integer
              example: 3600 # default 1 hour
            autoUpdate:
              description: |-
                autoupdate services if device supports it (default)
              type: boolean
              example: true
            bonding: #optional, by default defined in SCIM object
              type: string
              example: default
              enum:
                - default
                - none
                - justworks
                - passkey
                - oob

## A Connection
    Connection:
      allOf:
        - $ref: '#/components/schemas/Service'
      type: object
      properties:
        retries:
          type: integer
          format: int32
          example: 3
        retryMultipleAPs:
          type: boolean
          example: true

## A specific property of an Device
    PropertyRaw:
      allOf:
        - $ref: '#/components/schemas/Object'
      oneOf:
        - $ref: '#/components/schemas/BLEProperties'
        - $ref: '#/components/schemas/ZigbeeProperties'
      discriminator:
        propertyName: technology
        mapping:
          ble: '#/components/schemas/BLEProperties'
          zigbee: '#/components/schemas/ZigbeeProperties'

## A value of an property of an Device
    PropertyValueRaw:
      allOf:
        - $ref: '#/components/schemas/PropertyRaw'
      required:
        - value
      type: object
      properties:
        value:
          type: string
          format: byte
          example: 0001
        forcedResponse:
          description: do or do not wait for a response?
          type: boolean
          example: true

## An property ID
    PropertyID:
      required:
        - propertyID
      type: object
      properties:
        propertyID:
          type: string
          example: "temperature"

## A specific property of an Device
    Property:
      allOf:
        - $ref: '#/components/schemas/Object'
        - $ref: '#/components/schemas/PropertyID'

## A value of an property of an Device
    PropertyValue:
      allOf:
        - $ref: '#/components/schemas/Property'
      required:
        - value
      type: object
      properties:
        value:
          type: string
          format: byte
          example: 0001
        forcedResponse:
          description: do or do not wait for a response?
          type: boolean
          example: true

## An property registration
    PropertyRegistration:
      allOf:
        - $ref: '#/components/schemas/PropertyID'
      oneOf:
        - $ref: '#/components/schemas/BLEProperties'
        - $ref: '#/components/schemas/ZigbeeProperties'
      discriminator:
        propertyName: technology
        mapping:
          ble: '#/components/schemas/BLEProperties'
          zigbee: '#/components/schemas/ZigbeeProperties'

## A file-based property of an Device
    PropertyFile:
      allOf:
        - $ref: '#/components/schemas/Property'
      type: object
      properties:
        chunksize:
          type: integer
        forcedResponse:
          description: do or do not wait for a response?
          type: boolean
          example: true

## A binary blob-based property of an Device
    PropertyBlob:
      allOf:
        - $ref: '#/components/schemas/Property'
      required:
        - blob
      type: object
      properties:
        blob:
          type: string
          format: binary
        chunksize:
          type: integer
        forcedResponse:
          description: do or do not wait for a response?
          type: boolean
          example: true

## Conditional read of a value (read until specific value is read)
    PropertyConditional:
      allOf:
        - $ref: '#/components/schemas/Property'
      required:
        - value
      type: object
      properties:
        value:
          type: string
          format: byte
          example: 0001
        maxTime:
          description: |-
            maximum time the conditional read should run in seconds
            (default 10 sec, max 60 sec)
          type: integer
        maxRepeat:
          description: |-
           maximum time the conditional read should repeat
           (default 5, max 60)
          type: integer
        frequency:
          description: |-
            time between reads in seconds (default 1, max 60)
          type: integer

## A subscription property of an Device
    SubscriptionRaw:
      allOf:
        - $ref: '#/components/schemas/PropertyRaw'
      type: object
      properties:
        forcedAck:
          description: |-
            When not looking at device/property support MUST we
            ackhnowledge?
          type: boolean
          example: true

## A specific property of an Device
    Subscription:
      allOf:
        - $ref: '#/components/schemas/Object'
        - $ref: '#/components/schemas/PropertyID'
      type: object
      properties:
        forcedAck:
          description: |-
            When not looking at device/property support MUST we
            ackhnowledge?
          type: boolean
          example: true

## A broadcast
    Broadcast:
      allOf:
        - $ref: '#/components/schemas/Object'
      oneOf:
        - $ref: '#/components/schemas/BLEBroadcast'
        - $ref: '#/components/schemas/ZigbeeBroadcast'
      discriminator:
        propertyName: technology
        mapping:
          ble: '#/components/schemas/BLEBroadcast'
          zigbee: '#/components/schemas/ZigbeeBroadcast'
      required:
        - cycle
      type: object
      properties:
        cycle:
          type: string
          example: single
          enum:
            - single
            - repeat
        # broadcast time in ms
        broadcastTime:
          type: integer
          example: 3000
        # interval between broadcasts in ms
        broadcastInterval:
          type: integer
          example: 500
        # optional external broker config
        mqtt:
          type: object

## Event Name
    EventName:
      required:
        - event
      type: object
      properties:
        event:
          type: string
          example: enterprise/hospital/pulse_oximeter

## DataStream Event
    Event:
      allOf:
        - $ref: '#/components/schemas/EventName'
        - $ref: '#/components/schemas/PropertyID'
      oneOf:
        - $ref: '#/components/schemas/BLEEvent'
        - $ref: '#/components/schemas/ZigbeeProperties'
      discriminator:
        propertyName: technology
        mapping:
          ble: '#/components/schemas/BLEEvent'
          zigbee: '#/components/schemas/ZigbeeProperties'
      type: object
      properties:
        eventFormat:
          description: |-
            How is information decorated?  Default: device
            and property ids.
          type: string
          example: default
          enum:
            - default
            - payload
        replay:
          type: boolean
          example: false
          default: false
        id:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
        type:
          type: string
          example: device
          enum:
            - device
            - group
        dataApps:
          type: array
          items:
            type: object
            properties:
              dataAppID:
                type: string
                format: uuid
                example: 12345678-1234-5678-1234-56789abcdef4
              mqtt:
                type: object
                properties:
                  brokerURI:
                    type: string
                    example: mqtt.broker.com:8883
                  username:
                    type: string
                    example: user1
                  password:
                    type: string
                    example: password1
                  brokerCACert:
                    type: string
        technology:
          type: string
          example: ble
          enum:
            - ble
            - zigbee

## FileURL
    FileURL:
      required:
        - fileURL
      type: object
      properties:
        fileURL:
          type: string
          example: "https://domain.com/firmware.dat"

## FileBinary
    FileBin:
      required:
        - fileBin
      type: object
      properties:
        fileBin:
          type: string
          format: binary
          example: "firmware.dat"

## File
    File:
      allOf:
        - $ref: '#/components/schemas/PropertyID'
      oneOf:
        - $ref: '#/components/schemas/FileURL'
        - $ref: '#/components/schemas/FileBin'

## Firmware
    Firmware:
      allOf:
        - $ref: '#/components/schemas/Property'
      type: object
      properties:
        upgradeType:
          type: string
          enum:
            - nordics
            - silabs
            - wiliot

## Defines an operation in a bulk API
    Operation:
      required:
        - operation
      allOf:
        - type: object
          properties:
            path:
              type: string
              enum:
               - /action/connection
               - /action/property
               - /action/property/subscription
               - /extension/property/write/file
               - /extension/property/write/blob
               - /extension/property/read/conditional
            method:
              type: string
              enum:
               - POST
               - DELETE
               - GET
        - oneOf:
            - $ref: '#/components/schemas/Object'
            - $ref: '#/components/schemas/Property'
            - $ref: '#/components/schemas/PropertyValue'
            - $ref: '#/components/schemas/PropertyConditional'
            - $ref: '#/components/schemas/PropertyFile'
            - $ref: '#/components/schemas/PropertyBlob'
            - $ref: '#/components/schemas/Subscription'
          discriminator:
            propertyName: operation
            mapping:
              POST /action/connection:
                '#/components/schemas/Service'
              DELETE /action/connection:
                '#/components/schemas/Object'
              GET /action/connection:
                '#/components/schemas/Object'
              POST /action/property:
                '#/components/schemas/PropertyValue'
              DELETE /action/property:
                '#/components/schemas/Property'
              GET /action/property:
                '#/components/schemas/Property'
              POST /action/property/Subscription:
                '#/components/schemas/Subscription'
              DELETE /action/property/Subscription:
                '#/components/schemas/Subscription'
              GET /action/property/Subscription:
                '#/components/schemas/Subscription'
              POST /extension/property/read/conditional:
                '#/components/schemas/PropertyConditional'
              POST /extension/property/write/file:
                '#/components/schemas/PropertyFile'
              POST /extension/property/write/blob:
                '#/components/schemas/PropertyBlob'

## Bulk schema
    Bulk:
      allOf:
        - $ref: '#/components/schemas/Object'
      type: object
      properties:
        autoDisconnect:
          description: |-
            do we automatically disconnect after a RESTful operation?
          type: boolean
          example: true
          default: true
        operations:
          type: array
          items:
            $ref: '#/components/schemas/Operation'

# responses
## Baseline success reponse
    Success:
      required:
        - status
      type: object
      properties:
        status:
          type: string
          example: SUCCESS
          enum:
            - SUCCESS
        requestID:
          type: string
          example: 12345678-5678-1234-5578-abcdef1234

    SuccessResponse:
      allOf:
        - $ref: '#/components/schemas/Success'
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4

## Error 500 application Failure response
    FailureResponse:
      required:
        - status
        - errorCode
      type: object
      properties:
        status:
          type: string
          example: FAILURE
          enum:
            - FAILURE
        reason:
          type: string
          example: Not Found
        errorCode:
          type: integer
          format: int32
          example: 12
        requestID:
          type: string
          example: 12345678-5678-1234-5578-abcdef1234

## Response, success or failure
    Response:
      oneOf:
        - $ref: '#/components/schemas/SuccessResponse'
        - $ref: '#/components/schemas/FailureResponse'

 ## Returns discovered services
    PropertyResponse:
      allOf:
        - $ref: '#/components/schemas/SuccessResponse'
      oneOf:
        - $ref: '#/components/schemas/BLEServiceslist'
        - $ref: '#/components/schemas/ZigbeeEndpointlist'

## Response to multiple connections
    MultiConnectionsResponse:
      allOf:
        - $ref: '#/components/schemas/Success'
      required:
        - connections
      type: object
      properties:
        connections:
          type: array
          items:
            $ref: '#/components/schemas/Response'

## Returns an property value
    PropertyValueResponseRaw:
      allOf:
        - $ref: '#/components/schemas/SuccessResponse'
      required:
       - value
      type: object
      properties:
        value:
          type: string
          example: 01
          format: byte

## Returns an property value with ID
    PropertyValueResponse:
      allOf:
        - $ref: '#/components/schemas/SuccessResponse'
        - $ref: '#/components/schemas/PropertyID'
      required:
       - value
      type: object
      properties:
        value:
          type: string
          example: 01
          format: byte

## Returns an property registration
    PropertyRegistrationResponse:
      allOf:
        - $ref: '#/components/schemas/Success'
        - $ref: '#/components/schemas/PropertyRegistration'

## Returning multiple property registrations
    MultiPropertyRegistrationResponse:
      allOf:
        - $ref: '#/components/schemas/Success'
      required:
        - properties
      type: object
      properties:
        properties:
          type: array
          items:
            $ref: '#/components/schemas/PropertyRegistration'

## Returns a event
    EventResponse:
      allOf:
        - $ref: '#/components/schemas/SuccessResponse'
        - $ref: '#/components/schemas/Event'

## Returning multiple events
    MultiEventsResponse:
      allOf:
        - $ref: '#/components/schemas/Success'
      required:
        - events
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'

## Returning multiple subscriptions
    MultiSubscriptionResponse:
      allOf:
        - $ref: '#/components/schemas/Success'
      required:
        - subscriptions
      type: object
      properties:
        subscriptions:
          type: array
          items:
            $ref: '#/components/schemas/Subscription'

## Multiple returns for a bulk operation
    BulkResponse:
      allOf:
        - $ref: '#/components/schemas/SuccessResponse'
      type: object
      properties:
        operations:
          type: array
          items:
            $ref: '#/components/schemas/OperationResponse'

## Return ofr a firmware upgrade operation
    FirmwareResponse:
      allOf:
        - $ref: '#/components/schemas/SuccessResponse'
      type: object
      properties:
        upgradeStatus:
          type: string
          enum:
            - completed
            - in-progress
            - rolled-back
            - failed

## Return for an operation
    OperationResponse:
      required:
        - operation
      allOf:
        - type: object
          properties:
            operation:
              type: string
              enum:
               - /action/connection
               - /action/property
               - /action/property/subscription
               - /extension/property/write/file
               - /extension/property/write/blob
               - /extension/property/read/conditional
            type:
              type: string
              enum:
               - POST
               - DELETE
               - GET
        - oneOf:
            - $ref: '#/components/schemas/SuccessResponse'
            - $ref: '#/components/schemas/PropertyResponse'
            - $ref: '#/components/schemas/PropertyValueResponse'
          discriminator:
            propertyName: operation
            mapping:
              POST /action/connection:
                '#/components/schemas/ServiceResponse'
              DELETE /action/connection:
                '#/components/schemas/SuccessResponse'
              GET /action/connection:
                '#/components/schemas/SuccessResponse'
              POST /action/property:
                '#/components/schemas/PropertyValueResponse'
              DELETE /action/property:
                '#/components/schemas/PropertyValueResponse'
              GET /action/property:
                '#/components/schemas/PropertyValueResponse'
              POST /action/property/Subscription:
                '#/components/schemas/SuccessResponse'
              DELETE /action/property/Subscription:
                '#/components/schemas/SuccessResponse'
              GET /action/property/Subscription:
                '#/components/schemas/SuccessResponse'
              POST /extension/property/read/conditional:
                '#/components/schemas/PropertyValueResponse'
              POST /extension/property/write/file:
                '#/components/schemas/SuccessResponse'
              POST /extension/property/write/blob:
                '#/components/schemas/SuccessResponse'

 # API key authorization
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
# Apply the API key globally to all operations
security:
  - ApiKeyAuth: []
<CODE ENDS>