<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.1 (Ruby 2.6.10) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

<!ENTITY RFC7644 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7644.xml">
<!ENTITY I-D.ietf-scim-device-model SYSTEM "https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-scim-device-model.xml">
<!ENTITY RFC2119 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC8174 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
<!ENTITY I-D.ietf-asdf-sdf SYSTEM "https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-asdf-sdf.xml">
<!ENTITY RFC9114 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9114.xml">
<!ENTITY RFC7159 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7159.xml">
<!ENTITY RFC8949 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8949.xml">
<!ENTITY RFC3986 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml">
<!ENTITY RFC8615 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8615.xml">
<!ENTITY RFC9110 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9110.xml">
<!ENTITY RFC8610 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8610.xml">
<!ENTITY RFC8126 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8126.xml">
]>


<rfc ipr="trust200902" docName="draft-ietf-asdf-nipc-04" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="NIPC">An Application Layer Interface for Non-IP device control (NIPC)</title>

    <author initials="B." surname="Brinckman" fullname="Bart Brinckman">
      <organization>Cisco Systems</organization>
      <address>
        <postal>
          <city>Brussels</city>
          <country>Belgium</country>
        </postal>
        <email>bbrinckm@cisco.com</email>
      </address>
    </author>
    <author initials="R." surname="Mohan" fullname="Rohit Mohan">
      <organization>Cisco Systems</organization>
      <address>
        <postal>
          <street>170 West Tasman Drive</street>
          <city>San Jose</city>
          <code>95134</code>
          <country>USA</country>
        </postal>
        <email>rohitmo@cisco.com</email>
      </address>
    </author>
    <author initials="B." surname="Sanford" fullname="Braeden Sanford">
      <organization>Philips</organization>
      <address>
        <postal>
          <city>Cambridge</city>
          <country>USA</country>
        </postal>
        <email>braeden.sanford@philips.com</email>
      </address>
    </author>

    <date year="2025" month="April" day="07"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 60?>

<t>This memo specifies RESTful application layer interface for gateways 
providing operations against non-IP devices, as well as a CBOR-based 
publish-subscribe interface for streaming data. The described interfaces are
extensible. The specification also defines a protocol mapping function to
to map this interface to commonly used non-IP protocols.</t>



    </abstract>



  </front>

  <middle>


<?line 68?>

<section anchor="introduction"><name>Introduction</name>

<section anchor="scope"><name>Scope</name>

<t>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. With 
limited power budget, they may not be able to support the IP protocol on their
wired or wireless interfaces, hence they support protocols that require a lower
power budget. Promiment examples of such protocols are <xref target="BLE53"/> and
<xref target="Zigbee22"/>. These devices typically do require to communicate with devices
or applications that are connected to IP-based networking infrastructure. 
Therefore, applications on the IP network that need 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.</t>

<figure title="Gateway for non-IP Devices" anchor="gw"><artwork><![CDATA[
                                                               
    +-------------+              +---------+              +--------+
    | Application |<------------>| Gateway |<------------>| Non-IP |                     
    |    app      |   IP-based   |         |    Non-IP    | Device |
    +-------------+   Operation  +---------+   Operation  +--------+                 

]]></artwork></figure>

<t>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
(<xref target="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
vendor-specific implementations have proliferated. This results in parallel
infrastructure of both gateways and non-IP networks being deployed on a case
by case basis, each connecting separately into the IP network, with a distinct
set of APIs. At the same time, wireless access points supporting both IP-based 
wireless connectivity as well as non-IP based wireless technologies are
deployed ubiquitiously. Many of these wireless access points are equipped with
radios that can transmit and receive different frame types, such as <xref target="BLE53"/>
and <xref target="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. The specification aims to be
extensible, in order to support existing and future non-IP protocols.</t>

<t>A standardized Non-IP Gateway interface has following benefits:</t>

<t><list style="symbols">
  <t>Avoid the need for parallel Non-IP infrastructure.</t>
  <t>Avoid the need for applications to perform bespoke integrations for
different environments.</t>
  <t>Faster and more cost-effective adoption of Non-IP devices in IP network
environments.</t>
</list></t>

</section>
<section anchor="non-ip-gateway"><name>Non-IP Gateway</name>

<t>A non-IP gateway MUST provide at least following functions:</t>

<t><list style="symbols">
  <t>Authentication and authorization of application clients that
will leverage the gateway API to communicate with Non-IP devices.</t>
  <t>Access to a database of onboarded devices. Onboarding ensures that 
the Non-IP Gateway can identify a specific device and has sufficient context
about the device to service gateway API requests.</t>
  <t>The ability to consume an interaction model for a class of devices. This 
allows the gateway to understand how to interact with a device.</t>
  <t>An API that allows for bi-directional communication to non-IP devices.</t>
  <t>One or more channels to process requests, responses, and asymmetric
communications with the non-IP radio resources (Access Points)
at its disposal.</t>
  <t>The ability to stream telemetry received from non-IP devices in real-time
to applications on the IP network.</t>
</list></t>

<t>The definition of the onboarding function is out of scope of this document, but
can be provided by a provisioning interface such as <xref target="RFC7644"/> leveraging 
<xref target="I-D.ietf-scim-device-model"/>. NIPC performs operations on a device or group
object, hence it requires device onboarding to be performed prior to performing
a NIPC operation on a device. NIPC APIs will reference a device or group id 
generated at the time of onboarding as a unique identifier.</t>

<t>The Application gateway is a network function, so its goal is to proxy payloads 
between Non-IP and IP networks. It is not intended to be a middleware function
that interprets, decodes or modifies these payloads.</t>

<figure title="Basic Architecture" anchor="arch"><artwork><![CDATA[
                             +-----------------------------------+
                             |                                   |
    +-----------+   Request  |  +---------+                      |
    | onboarding|-------------->|  SCIM   |                      |
    |    app    |<--------------| Server  |                      |
    +-----------+  Ctrl Endpt|  +---------+                      |
                             |                                   |
    +-----------+            |  +------------+  +-------+  +--+  |
    |  Control  |>...REST....|.>|    NIPC    |..|  AP   |..|D |  |
    |     &     |            |  |   Gateway  |  +-------+  +--+  |
    | Telemetry |<..pub/sub..|.<|            |                   |
    |    Apps   |            |  +------------+                   |
    +-----------+            |                                   |
                             |       Network Deployment          |
                             +-----------------------------------+

]]></artwork></figure>

<t><xref target="arch"/> shows us applications, the NIPC 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 supports 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 &amp; AP).
The role of the application layer gateway is to provide a gateway functioni
to applications wishing to communicate with non-IP devices in the network
domain served by the gateway.
Applications implementing Non-IP Control can leverage RESTful interfaces
to communicate with Non-IP devices in the network domain and subscribe to
events levering a CBOR-based pub/sub interface.</t>

</section>
<section anchor="terminology"><name>Terminology</name>

<t>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 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all
capitals, as shown here.</t>

</section>
</section>
<section anchor="architecture"><name>Architecture</name>

<section anchor="overview"><name>Overview</name>

<t>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 provides a unified API to support those operations.</t>

<t>To perform NIPC operations on a device, the gateways needs 2 things:
1) Information about the instance of the device or thing: The device must be
onboarded on the gateway (e.g. by means of SCIM). This allows the NIPC Gateway
to retrieve the device object, identified by an id referenced in the path of 
the NIPC API.
2) Information about the interaction model: The Gateway must be able to perform
protocol-neutral operations, and hence requires a mapping of protocol-neutral
operations to protocol specific operations. These are supplied to the gateway
by means of an SDF model, described in <xref target="I-D.ietf-asdf-sdf"/>.</t>

<figure title="NIPC prerequisites" anchor="prereq"><artwork><![CDATA[
    +------------+   
    |    SCIM    |                      
    |   object   |           +----------------+          
    |    {id}    |---------->|                |
    +------------+           | NIPC Operation |
                             |    - Property  |
                             |    - Action    |
    +------------+           |    - Event     |
    |     SDF    |---------->|                |
    |    model   |           +----------------+
    |            |
    +------------+  

]]></artwork></figure>

<t>Once these 2 prerequisites have been fulfilled, applications that are
authorized can perform NIPC operations on device ids. NIPC operations
are operations on properties, or constitute actions or events on devices,
as per the affordances defined in an SDF model.</t>

</section>
<section anchor="onboarding"><name>Onboarding</name>

<t>In order to perform a NIPC operation on a device, the device has to have its 
identity declared to the NIPC gateway. We refer to this as 'onboarding'. Apart
from the device identity, it is also necessary that the device object contains
all required information to bootstrap trust with the device, as well as
establish connectivity, as NIPC operations assume that connectivity is there. 
Allthough onboarding could theoretically be performed in other ways, it is
strongly recommended to leverage <xref target="RFC7644"/> with
<xref target="I-D.ietf-scim-device-model"/>, as the SCIM device schema has been developed
to contain all nessary attributes and extensions to support NIPC.</t>

</section>
<section anchor="registrations"><name>Registrations</name>

<t>NIPC registration APIs allow applications to declare information that is not
related to a device instance. Registrations can be information about an
interaction model for a class of devices, or information about an application
that is required to interact with the gateway.</t>

<section anchor="sdf-model-registrations"><name>SDF model registrations</name>

<t>The SDF model for a class of devices determines how a gateway may interact with
these devices in a protocol-neutral way. In order to do that, the SDF model
must contain protocol mappings, mapping protocol-neutral SDF affordances
to protocol-specific ones. The SDF affordances supported by the device, as
well as its protcol-mappings, are provide to the gateway by means of an SDF
model registration. SDF models are described in <xref target="I-D.ietf-asdf-sdf"/>.</t>

</section>
<section anchor="data-application-registration"><name>Data application registration</name>

<t>An application authorized to perform NIPC operations on devices needs to be
able to define which applications can receive streaming event data from the
gateway. The data-app registration API allows mapping of an event to a data 
app as well as a protocol.</t>

</section>
</section>
<section anchor="protocolmap"><name>Protocol mapping</name>

<t>An SDF model can fully describe a thing, including all its SDF affordances. 
To leverage an SDF model to perform protocol specific operations on an
instance of that thing, a mapping of the SDF affordance to a protocol-specific
attribute is required. In NIPC, this is achieved through protocol mapping.</t>

<t>Protocol mapping is required to map a protocol agnostic affordance to a 
protocol-specific operation, as implementations of the same affordance will
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.</t>

<t>protocol mapping allows for integration of new protocols in NIPC, new mappings 
can be created without the need to update the base schema.</t>

<figure title="Property Mapping" anchor="propmap"><artwork><![CDATA[
     - protocolmap
        |
        |> ble
        |     - BLE property
        |
        |> zigbee
              - Zigbee property

]]></artwork></figure>

<t>As shown in <xref target="propmap"/>, protocol-specific properties must be embedded in a
protocolmap object, for example a "ble" or a "zigbee" object.</t>

<texttable title="Protocol objects" anchor="proobj">
      <ttcol align='left'>Attribute</ttcol>
      <ttcol align='left'>Req</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Example</ttcol>
      <c>ble</c>
      <c>T</c>
      <c>object</c>
      <c>an object with BLE-specific attributes</c>
      <c>zigbee</c>
      <c>T</c>
      <c>object</c>
      <c>an object with Zigbee-specific attributes</c>
</texttable>

<t>where-</t>

<t><list style="symbols">
  <t>"ble" is an object containing properties that are specific to the BLE
protocol.</t>
  <t>"zigbee" is an object containing properties that are specific to the
Zigbee protocol.</t>
  <t>Other protocol mapping objects can be added by creating a new protocol
object</t>
</list></t>

<t>Example property mapping:</t>

<figure title="Example property mapping" anchor="expropmap"><artwork><![CDATA[
"sdfObject": {
  "healthsensor": {
    "sdfProperty": {
      "heartrate": {
        "description": "The current measured heart rate",
        "type": "number",
        "unit": "beat/min",
        "observable": false,
        "writable": false,
        "protocolMap": {
          "ble": {
            "serviceID": "12345678-1234-5678-1234-56789abcdef4",
            "characteristicID": "12345678-1234-5678-1234-56789abcdef4"
          }
        }
      }
    }
  }
}
]]></artwork></figure>

<t>A protocol map is provided as part of the SDF model, in the SDF affordance 
definition. Alternatively, it can be provided directly in a NIPC API.</t>

</section>
<section anchor="nipc-ops"><name>NIPC Operations</name>

<t>NIPC operations are protocol-neutral operations on SDF affordances, more 
specifically properties, actions &amp; events. NIPC operations can happen against
affordances that were registered in an SDF model. If connection management is
required to execute a NIPC operation, it is assumed that the gateway implictly
establishes and tears down required connections.</t>

<section anchor="properties-apis"><name>Properties APIs</name>

<t>Property APIs allow applications perform operations on properties, such as to
read or write values to them.</t>

</section>
<section anchor="actions"><name>Actions</name>

<t>Action APIs perform actions on devices, such as enabling or disabling a feature
on a device.</t>

</section>
<section anchor="events"><name>Events</name>

<t>Event APIs allow apps to enable or disable event reporting on devices. Events
are reported over the events publish/subscribe interface.</t>

</section>
<section anchor="connection-management-for-nipc-operations"><name>Connection management for NIPC Operations</name>

<t>For protocols that require connection management before executing an operation,
a NIPC gateway can perform implicit connection management. When executing a 
NIP operation, a NIPC Gateway can set up a connection with a device as well as
tear down the connection after the operation has completed. A NIPC Gateway
should support explicit connection management as well. Explicit connection
management can be used by an app that wants to perform multiple NIPC operations
in a single connection. Explicit connection management can be performed by 
calling the /{id}/action/connection action API. When after establishing an
explicit connection to a device, an application calls a NIPC Operation, the
Gateway will leverage the exissting connection and will also not tear the
connection down after the operation completes. The app will have to explicitly
close the connection.</t>

</section>
<section anchor="action-apis-with-embedded-protocol-mapping"><name>Action APIs with embedded protocol mapping</name>

<t>Action APIs with embedded protocol mapping are APIs that perform actions on
devices, but do not use registered affordances. These APIs have embedded
protocol mappings. They require explicit connection management.</t>

</section>
<section anchor="extensions"><name>Extensions</name>

<t>Extensions are not part of the core NIPC API specification, but 
extensions to it. Extensions are compound APIs. They leverage basic NIPC operations
but combine multiple operations in to one API call for efficiency.
An example of this is the the bulk operation, allowing to send multiple
operations in one operation. Extensions can be generic, IANA registered 
extentions, or vendor specific extensions.</t>

</section>
</section>
<section anchor="events-publish-subscribe-interface"><name>Events publish subscribe interface</name>

<t>Events are published on a publish/subscribe interface. Events can be of
different types:</t>

<t><list style="symbols">
  <t>Streaming data from devices: Streaming data is activated/deactivated with the
NIPC events API</t>
  <t>Broadcasts from devices</t>
  <t>Connection events: Devices connecting &amp; disconnecting</t>
</list></t>

</section>
<section anchor="protocols"><name>Protocols</name>

<section anchor="nipc-apis"><name>NIPC APIs</name>

<t>NIPC is a protocol that is based on RESTful HTTP <xref target="RFC9114"/>. Along with HTTP
headers and URIs, NIPC uses JSON <xref target="RFC7159"/> payloads to convey NIPC 
operations, such as registrations, actions, event and property operations. This
is the case for both request and response parameters, as well as errors.
NIPC uses the standard JSON media type "application/json", except for the SDF 
model registration APIs, where the media type reflects the content as an SDF 
model, and hence is media type "application/sdf+json".</t>

</section>
<section anchor="nipc-publishsubscribe-events"><name>NIPC publish/subscribe events</name>

<t>NIPC publish/subscribe events are encoded in CBOR (<xref target="RFC8949"/>) and can be
delivered over either:</t>

<t><list style="symbols">
  <t>MQTT</t>
  <t>Webhook</t>
  <t>Websocket</t>
</list></t>

</section>
</section>
<section anchor="paths"><name>Paths</name>

<section anchor="general"><name>General</name>

<t>The NIPC HTTP protocol is described in terms of a path relative to a Base URI.
The Base URI MUST NOT contain a query string, as clients MAY append additional 
path information and query parameters as part of forming the request.  The base
URI is a URL that most often consists of the "https" protocol scheme, a domain
name, and an initial path <xref target="RFC3986"/>.  That initial path for NIPC is 
recommended to be /nipc.
For example:</t>

<figure><artwork><![CDATA[
  "https://example.com/nipc/"
]]></artwork></figure>

<t>Based on this a well_known URI <xref target="RFC8615"/> of nipc can be defined.</t>

<t>Additionally a version number may be added, for example:</t>

<figure><artwork><![CDATA[
  "https://example.com/nipc/v1/"
]]></artwork></figure>

</section>
<section anchor="nipc-registrations"><name>NIPC Registrations</name>

<t>Registrations leverage the base path + /registration. NIPC supports SDF model
registrations and data-app registrations.</t>

<t>paths:</t>

<t><list style="symbols">
  <t>/registration/model</t>
  <t>/registration/data-app</t>
</list></t>

</section>
<section anchor="nipc-operations"><name>NIPC Operations</name>

<t>Every NIPC Operations API pertains to either a device or group of devices, identified by
an id, hence the id will be reflected as the first parameter in the path. 
For example:</t>

<figure><artwork><![CDATA[
  "https://example.com/nipc/v1/{id}"
]]></artwork></figure>

<t>The second parameter in the path refers to the NIPC operation that the API will
perform on the device. This can be:</t>

<t><list style="symbols">
  <t>property</t>
  <t>event</t>
  <t>action</t>
  <t>extension</t>
</list></t>

<t>These are described in <xref target="nipc-ops"/>.</t>

<t>Every NIPC API response has a <spanx style="verb">X-Request-ID</spanx> header, which is a unique 
identifier for the request. Each successful response will have a HTTP 
status code of 200 OK.</t>

<t>A failure response will consist of a HTTP status code of 4xx or 5xx, and 
will contain an error code and reason field. The error codes and the 
appropriate error codes are described in <xref target="errorhandling"/>.</t>

<t>Failure response:</t>

<t>Example of a failure response:</t>

<figure title="Example failure response" anchor="failure"><artwork><![CDATA[
{
  "errorCode": 2000,
  "reason": "Generic error message"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"errorCode" is error code that indicates the type of error, 
as described in <xref target="errorcodes"/></t>
  <t>"reason" is a human-readable error message</t>
</list></t>

</section>
</section>
</section>
<section anchor="nipc-registrations-1"><name>NIPC Registrations</name>

<t>NIPC allows an application to register an SDF model for a class of devices,
as well as a data application that will receive streaming data from the 
gateway.</t>

<section anchor="sdf-model-registration-apis"><name>SDF model registration APIs</name>

<t>These APIs allow applications to register an SDF model for a class of devices.
These APIs use the <spanx style="verb">application/sdf+json</spanx> media type, as described in 
<xref section="7.1" sectionFormat="of" target="I-D.ietf-asdf-sdf"/>.</t>

<section anchor="register-an-sdf-model"><name>Register an sdf model</name>

<t>Method: <spanx style="verb">POST /registration/model</spanx></t>

<t>Description: Registers an SDF model for a class of devices</t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>an SDF model in JSON format, similar to the example in <xref target="thermometer-sdf"/>.</t>
</list></t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example register sdf model response" anchor="exregresp"><artwork><![CDATA[
{
  "sdfRef": "https://example.com/heartrate#/sdfObject/healthsensor"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfRef" is the reference to the top-level sdfThing or sdfObject 
 in the SDF model</t>
  <t>"id" is the id of the sdf model</t>
</list></t>

</section>
<section anchor="get-all-sdf-models"><name>Get all sdf models</name>

<t>Method: <spanx style="verb">GET /registration/model</spanx></t>

<t>Description: Gets all sdf models registered with the gateway</t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example get all sdf models response" anchor="exgetallresp"><artwork><![CDATA[
[
  {
    "sdfRef": "https://example.com/heartrate#/sdfObject/healthsensor"
  }
]
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfRef" is the reference to the top-level sdfThing or sdfObject 
 in the SDF model</t>
  <t>"id" is the id of the sdf model</t>
</list></t>

</section>
<section anchor="get-an-sdf-model"><name>Get an sdf model</name>

<t>Method: <spanx style="verb">GET /registration/model/{sdfRef}</spanx></t>

<t>Description: Gets an sdf model registered with the gateway</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>sdfRef: the reference to the top-level sdfThing or sdfObject 
 in the SDF model. This is a percent-encoded URL string.</t>
</list></t>

<t>Response:</t>

<t>The sdf model is returned in JSON format, similar to the example in 
<xref target="thermometer-sdf"/>.</t>

</section>
<section anchor="delete-an-sdf-model"><name>Delete an sdf model</name>

<t>Method: <spanx style="verb">DELETE /registration/model/{sdfRef}</spanx></t>

<t>Description: Deletes an sdf model registered with the gateway</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>sdfRef: the reference to the top-level sdfThing or sdfObject 
 in the SDF model. This is a percent-encoded URL string.</t>
</list></t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example delete sdf model response" anchor="exdelresp"><artwork><![CDATA[
{
  "sdfRef": "https://example.com/heartrate#/sdfObject/healthsensor"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfRef" is the reference to the top-level sdfThing or sdfObject 
 in the SDF model</t>
  <t>"id" is the id of the sdf model</t>
</list></t>

</section>
<section anchor="update-an-sdf-model"><name>Update an sdf model</name>

<t>Method: <spanx style="verb">PUT /registration/model/{sdfRef}</spanx></t>

<t>Description: Updates an sdf model registered with the gateway</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>sdfRef: the reference to the top-level sdfThing or sdfObject 
 in the SDF model. This is a percent-encoded URL string.</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>an SDF model in JSON format, similar to the example in <xref target="thermometer-sdf"/>.</t>
</list></t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example update sdf model response" anchor="exupresp"><artwork><![CDATA[
{
  "sdfRef": "https://example.com/heartrate#/sdfObject/healthsensor"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfRef" is the reference to the top-level sdfThing or sdfObject 
 in the SDF model</t>
  <t>"id" is the id of the sdf model</t>
</list></t>

</section>
</section>
<section anchor="data-application-registration-apis"><name>Data application registration APIs</name>

<t>These APIs allow applications to register a data application that will receive
streaming data from the gateway. These APIs operate on a data app ID.
This ID corresponds to the endpoint app ID of the telemetry endpoint app 
that is registered with the SCIM server. The endpoint app is defined in 
<xref section="6" sectionFormat="of" target="I-D.ietf-scim-device-model"/>.</t>

<section anchor="register-a-data-application"><name>Register a data application</name>

<t>Method: <spanx style="verb">POST /registration/data-app/{data-app-id}</spanx></t>

<t>Description: Registers a data application with the gateway</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>data-app-id: the id of the data application</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>events: a list of events that the data application wants to receive
streaming data for.</t>
</list></t>

<t>The request body also contains one of the following:</t>

<t><list style="symbols">
  <t>mqttClient: an empty object that denotes that the data application
is an MQTT client that will receive streaming data over MQTT</t>
  <t>mqttBroker: an object that contains the MQTT broker information
where the broker will publish the streaming data.</t>
  <t>webhook: an object that contains a webhook URL along with any 
 credentials that are required to authenticate the webhook. 
 The webhook URL is the endpoint where the streaming data will be sent.</t>
  <t>websocket: an object that contains a websocket URL along with any 
credentials that are required to authenticate the websocket. 
The websocket URL is the endpoint where the streaming data will be sent.</t>
</list></t>

<t>Example of a request body:</t>

<figure title="Example with mqttClient" anchor="exregmqttclientrsp"><artwork><![CDATA[
{
  "events": [
    "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
  ],
  "mqttClient": {}
}
]]></artwork></figure>

<t>Example of a request body for a data application that is an MQTT broker:</t>

<figure title="Example with mqttBroker" anchor="exregmqttbrokerrsp"><artwork><![CDATA[
{
  "events": [
    "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
  ],
  "mqttBroker": {
    "URI": "mqtt.example.com:1883",
    "username": "user",
    "password": "password"
  }
}
]]></artwork></figure>

<t>Response:</t>

<t>If successful, the response will be identical to the request body.</t>

</section>
<section anchor="update-a-data-application"><name>Update a data application</name>

<t>Method: <spanx style="verb">PUT /registration/data-app/{data-app-id}</spanx></t>

<t>Description: Updates a data application with the gateway</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>data-app-id: the id of the data application</t>
</list></t>

<t>Request Body: Same as the request body for the register data application API.</t>

<t>Response:</t>

<t>If successful, the response will be identical to the request body.</t>

</section>
<section anchor="get-a-data-application"><name>Get a data application</name>

<t>Method: <spanx style="verb">GET /registration/data-app/{data-app-id}</spanx></t>

<t>Description: Gets a data application registered with the gateway</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>data-app-id: the id of the data application</t>
</list></t>

<t>Response:</t>

<t>The response will be identical to the request body for the register data
application API.</t>

</section>
<section anchor="delete-a-data-application"><name>Delete a data application</name>

<t>Method: <spanx style="verb">DELETE /registration/data-app/{data-app-id}</spanx></t>

<t>Description: Deletes a data application registered with the gateway</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>data-app-id: the id of the data application</t>
</list></t>

<t>Response:</t>

<t>The response will be identical to the request body for the register data
application API.</t>

</section>
</section>
</section>
<section anchor="nipc-apis-1"><name>NIPC APIs</name>

<t>The primary goal of the NIPC APIs is to exchange data with a Non-IP device, by
means of reading, writing or streaming NIPC properties to applications.</t>

<t>The NIPC APIs are divided into 3 categories:</t>

<t><list style="symbols">
  <t>NIPC Property APIs: These APIs allow applications to get and update device 
properties.</t>
  <t>NIPC Event APIs: These APIs allow applications to enable or disable event reporting on devices.</t>
  <t>NIPC Action APIs: These APIs allow applications to perform actions on devices.</t>
  <t>NIPC Action APIs with embedded protocol mapping: These APIs allow applications to perform actions on devices, but do not use registered properties, events or actions.</t>
</list></t>

<t>An SDF model must be registered for the device in order to use these NIPC Property, Event and Action APIs.
The SDF model can be a top-level sdfThing with multiple sdfObjects or a top-level sdfObject.
These APIs depend on the SDF affordance (i.e. sdfProperty, sdfEvent and sdfAction) objects defined in the SDF model and a device ID that is defined in <xref target="I-D.ietf-scim-device-model"/>.
The SDF affordance can be referenced using the global name of the SDF affordance as described in <xref section="4" sectionFormat="of" target="I-D.ietf-asdf-sdf"/>.</t>

<t>The SDF global name will be used against the registered SDF model to 
determine the protocol-specific protocolMap that the NIPC API will operate on. 
The global name must be percent-encoded to be used in the URL as per <xref target="RFC3986"/>.</t>

<section anchor="nipc-property-apis"><name>NIPC Property APIs</name>

<t>These APIs allow applications to get and update device properties. 
These operations may require a connection to the device to be established. 
This connection can be established as part of the same API call implicitly.
If a connection is already active for this device, the existing connection will be leveraged without modifying it.</t>

<section anchor="write-a-value"><name>Write a value</name>

<t>Method: <spanx style="verb">POST /{id}/property/{property}</spanx></t>

<t>Description: Writes a value to a property on a device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
  <t>property: the property to write to</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>value: the bytes to be written in base64 encoding</t>
</list></t>

<t>Response:</t>

<t>Example of a write property response:</t>

<figure title="Example write property response" anchor="exwrresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature",
  "value": "dGVzdA=="
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"property" is the property that was written to</t>
  <t>"value" is the bytes that were written in base64 encoding</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="read-a-value"><name>Read a value</name>

<t>Method: <spanx style="verb">GET /{id}/property/{property}</spanx></t>

<t>Description: Reads a value from a property on a device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
  <t>property: the property to read from</t>
</list></t>

<t>Response:</t>

<t>Example of a read property response:</t>

<figure title="Example read property response" anchor="exreresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature",
  "value": "dGVzdA=="
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"property" is the property that was read from</t>
  <t>"value" is the bytes that were read in base64 encoding</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="write-multiple-values"><name>Write multiple values</name>

<t>Method: <spanx style="verb">PUT /{id}/property</spanx></t>

<t>Description: Write values to one or more properties on a device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>an array of properties to update, each containing a property and a value</t>
</list></t>

<t>Example body updating multiple properties:</t>

<figure title="Example updating multiple properties" anchor="exupmprop"><artwork><![CDATA[
{
  "properties": [
    {
      "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature",
      "value": "dGVzdA=="
    },
    {
      "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/humidity",
      "value": "eGVzdB=="
    }
  ]
}
]]></artwork></figure>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example update multiple properties response" anchor="exupmresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "properties": [
    {
      "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature",
      "value": "dGVzdA=="
    },
    {
      "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/humidity",
      "value": "eGVzdB=="
    }
  ]
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"properties" is an array of properties that were updated, each containing a property and a value</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="read-multiple-values"><name>Read multiple values</name>

<t>Method: <spanx style="verb">GET /{id}/property</spanx></t>

<t>Description: Read values from one or more properties on a device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>property: a comma separated list of properties to read</t>
</list></t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example read multiple properties response" anchor="exreadmresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "properties": [
    {
      "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature",
      "value": "dGVzdA=="
    },
    {
      "property": "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/humidity",
      "value": "eGVzdB=="
    }
  ]
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"properties" is an array of properties that were read, each containing a property and a value</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
</section>
<section anchor="nipc-event-apis"><name>NIPC Event APIs</name>

<t>These APIs allow applications to enable or disable event reporting on devices.
These operations may require a connection to the device to be established. This connection can be established as part of the same API call implicitly. If a connection is already active for this device, the existing connection will be leveraged without modifying it.</t>

<t>The event is a global name reference to an <spanx style="verb">sdfEvent</spanx>. 
If the data application registered for this event is an MQTT broker or 
client, the event will be used as the MQTT topic as well. 
When used as a topic, the event will be percent-encoded as per 
<xref target="RFC3986"/> since '/' and '#' have special meaning in MQTT.</t>

<t>The ID in the path is the id of the device or group of devices.
An event can be enabled on a group of devices if it is supported by the
underlying protocol. For example, if the underlying protocol is BLE, 
the event can be enabled on a group of devices if the event is an 
advertisement event or connection status event.</t>

<section anchor="enable-event-reporting"><name>Enable event reporting</name>

<t>Method: <spanx style="verb">POST /{id}/event/{event}</spanx></t>

<t>Description: Enables an event on a specific device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device or group of devices</t>
  <t>event: the event to enable</t>
</list></t>

<t>The event is a URL encoded string that is the absolute URI that is a global name reference to an <spanx style="verb">sdfEvent</spanx>.</t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example enable event response" anchor="exenableresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>id: the id of the device or group of devices</t>
  <t>"event" is the event that was enabled</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="disable-event-reporting"><name>Disable event reporting</name>

<t>Method: <spanx style="verb">DELETE /{id}/event/{event}</spanx></t>

<t>Description: Disables an event on a specific device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device or group of devices</t>
  <t>event: the event to disable</t>
</list></t>

<t>The event is a URL encoded string that is the absolute URI that is a global name reference to an <spanx style="verb">sdfEvent</spanx>.</t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example disable event response" anchor="exdisableresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>id: the id of the device or group of devices</t>
  <t>"event" is the event that was disabled</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="get-event-status"><name>Get event status</name>

<t>Method: <spanx style="verb">GET /{id}/event/{event}</spanx></t>

<t>Description: Get the status of an event on a specific device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device or group of devices</t>
  <t>event: the event to get the status of</t>
</list></t>

<t>The event is a URL encoded string that is the absolute URI that is a global name reference to an <spanx style="verb">sdfEvent</spanx>.</t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example get event status response" anchor="exgeteventresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>id: the id of the device or group of devices</t>
  <t>"event" is the event that was queried</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="get-status-of-multiple-events"><name>Get status of multiple events</name>

<t>Method: <spanx style="verb">GET /{id}/event</spanx></t>

<t>Description: Get the status of one or more events on a specific device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device or group of devices</t>
</list></t>

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>event: a comma separated list of events to get the status of</t>
</list></t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example get multiple events status response" anchor="exgetmresp"><artwork><![CDATA[
{
  "events": [
    {
      "id": "12345678-1234-5678-1234-56789abcdef4",
      "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
    }
  ]
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device or group of devices</t>
  <t>"events" is an array of events that were queried</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
</section>
<section anchor="nipc-action-apis"><name>NIPC Action APIs</name>

<t>These APIs allow applications to perform actions on devices. These operations may require a connection to the device to be established. This connection can be established as part of the same API call implicitly. If a connection is already active for this device, the existing connection will be leveraged without modifying it.</t>

<section anchor="perform-an-action"><name>Perform an action</name>

<t>Method: <spanx style="verb">PUT /{id}/action/{action}</spanx></t>

<t>Description: Perform an action on a specific device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
  <t>action: the action to perform</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>value: the bytes to be written in base64 encoding.</t>
</list></t>

<t>The request body is optional and can be empty if the underlying protocol 
allows an action without a value.</t>

<t>Example body of an action:</t>

<figure title="Example action" anchor="exaction"><artwork><![CDATA[
{
  "value": "dGVzdA=="
}
]]></artwork></figure>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example action response" anchor="exactionresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "action": "https://example.com/heartrate#/sdfObject/healthsensor/sdfAction/start"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"action" is the action that was performed</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
</section>
<section anchor="nipc-action-apis-with-embedded-protocol-mapping"><name>NIPC Action APIs with embedded protocol mapping</name>

<t>These APIs allow applications to perform actions on devices, but do not use registered properties, events or actions. These APIs do not perform an implicit connection, so a connection must be established before calling these APIs.</t>

<section anchor="connect-to-a-device"><name>Connect to a device</name>

<t>Method: <spanx style="verb">POST /{id}/action/connection</spanx></t>

<t>Description: Connect to a device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>Connection retry parameters</t>
  <t>A protocol map object. In the case of BLE,if no protocol map 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.</t>
</list></t>

<t>Example body of a connection without specific discovery of properties:</t>

<figure title="Example connection" anchor="exconn"><artwork><![CDATA[
{
  "retries": 3,
  "retryMultipleAPs": true
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"retries" defines the number of retries in case the operations does not 
succeed</t>
  <t>"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.</t>
</list></t>

<t>In case the application would like to discover specific properties of a device,
a protocol mapping can be added that defines what properties should be
discovered.</t>

<t>Example body of a BLE connection with specific discovery of properties:</t>

<figure title="Example connection with explicit discovery of connections" anchor="exconnprp"><artwork><![CDATA[
{
  "retries": 3,
  "retryMultipleAPs": true,
  "protocolMap": {
    "ble": {
      "services": [
        {
          "serviceID": "12345678-1234-5678-1234-56789abcdef4"
        }
      ],
      "cached": false,
      "cacheIdlePurge": 3600,
      "autoUpdate": true,
      "bonding": "default"
    }
  }
}
]]></artwork></figure>

<t>where in the BLE protocol object:</t>

<t><list style="symbols">
  <t>"services" is an array of services defined by their serviceIDs.</t>
  <t>"cached" refers to whether the services need to be cached for 
subsequent connects, in order not to perform service discovery on
each request.</t>
  <t>"cacheIdlepurge" defines how long the cache should be maintained 
before purging</t>
  <t>some devices support notifications on changes in services, 
"autoUpdate" allows the network to update services based on 
notification (on by default)</t>
  <t>"bonding" allows you to override the bonding method configured when 
onboarding the device</t>
</list></t>

<t>Response:</t>

<t>Success responses include a protocol mapping 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 <xref target="BLEservices"/>.</t>

<figure title="BLE Services" anchor="BLEservices"><artwork><![CDATA[
    services
     - serviceID
        |
        |> characteristics
            - charactericID
            - flags
               |
               |> Descriptors
                   - descriptorID
]]></artwork></figure>

<t>Example of a response:</t>

<figure title="Example connection response" anchor="exconnresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "protocolMap": {
    "ble": [
      {
        "serviceID": "12345678-1234-5678-1234-56789abcdef4",
        "characteristics": [
          {
            "characteristicID": "12345678-1234-5678-1234-56789abcdef4",
            "flags": [
              "read",
              "write"
            ],
            "descriptors": [
              {
                "descriptorID": "12345678-1234-5678-1234-56789abcdef4"
              }
            ]
          }
        ]
      }
    ]
  }
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"protocolMap" contains an Array of BLE services as shown in
   <xref target="BLEservices"/></t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/>
definition of failed response.</t>

</section>
<section anchor="update-a-connection"><name>Update a connection</name>

<t>Method: <spanx style="verb">PUT /{id}/action/connection</spanx></t>

<t>Description: Update cached ServiceMap for a device. Full service discovery will be performed, unless specific services are described in the API body.</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>A protocol map object. In the case of BLE,if no protocol map 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.</t>
</list></t>

<t>Example body of an update connection:</t>

<figure title="Example service discovery response" anchor="exupconn"><artwork><![CDATA[
{
  "protocolMap": {
    "ble": {
      "services": [
        {
          "serviceID": "12345678-1234-5678-1234-56789abcdef4"
        }
      ],
      "cached": false,
      "cacheIdlePurge": 3600,
      "autoUpdate": true
    }
  }
}
]]></artwork></figure>

<t>where in the BLE protocol object:</t>

<t><list style="symbols">
  <t>"services" is an array of services defined by their serviceIDs.</t>
  <t>"cached" refers to whether the services need to be cached for 
subsequent connects, in order not to perform service discovery on
each request.</t>
  <t>"cacheIdlepurge" defines how long the cache should be maintained 
before purging</t>
  <t>some devices support notifications on changes in services, 
"autoUpdate" allows the network to update services based on 
notification (on by default)</t>
</list></t>

<t>Response:</t>

<t>Success responses include a protocol mapping 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 <xref target="BLEservices"/>.</t>

<t>Example of a response:</t>

<figure title="Example connection response" anchor="exupconnresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "protocolMap": {
    "ble": [
      {
        "serviceID": "12345678-1234-5678-1234-56789abcdef4",
        "characteristics": [
          {
            "characteristicID": "12345678-1234-5678-1234-56789abcdef4",
            "flags": [
              "read",
              "write"
            ],
            "descriptors": [
              {
                "descriptorID": "12345678-1234-5678-1234-56789abcdef4"
              }
            ]
          }
        ]
      }
    ]
  }
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"protocolMap" contains an Array of BLE services as shown in
   <xref target="BLEservices"/></t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/>
definition of failed response.</t>

</section>
<section anchor="disconnect-from-a-device"><name>Disconnect from a device</name>

<t>Method: <spanx style="verb">DELETE /{id}/action/connection</spanx></t>

<t>Description: Disconnect from a device</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example disconnect response" anchor="exdisconnresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="get-connection-status"><name>Get connection status</name>

<t>Method: <spanx style="verb">GET /{id}/action/connection</spanx></t>

<t>Description: Get connection status for a device. Success when device(s) is/are connected, includes service map for the device if available. Failure when a device is not connected</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example connection status response" anchor="exconnstatresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "protocolMap": {
    "ble": [
      {
        "serviceID": "12345678-1234-5678-1234-56789abcdef4",
        "characteristics": [
          {
            "characteristicID": "12345678-1234-5678-1234-56789abcdef4",
            "flags": [
              "read",
              "write"
            ],
            "descriptors": [
              {
                "descriptorID": "12345678-1234-5678-1234-56789abcdef4"
              }
            ]
          }
        ]
      }
    ]
  }
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"protocolMap" contains an Array of BLE services as shown in
   <xref target="BLEservices"/></t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="write-a-value-using-protocol-mapping"><name>Write a value using protocol mapping</name>

<t>Method: <spanx style="verb">POST /{id}/action/property/write</spanx></t>

<t>Description: Writes a value to a property on a device using protocol mapping</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>value: the bytes to be written in base64 encoding</t>
  <t>protocolMap: the protocol mapping for the property</t>
</list></t>

<t>Example body of a write property:</t>

<figure title="Example write property" anchor="exwriteprop"><artwork><![CDATA[
{
  "value": "dGVzdA==",
  "protocolMap": {
    "ble": {
      "serviceID": "12345678-1234-5678-1234-56789abcdef4",
      "characteristicID": "12345678-1234-5678-1234-56789abcdef4"
    }
  }
}
]]></artwork></figure>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example write property response" anchor="exwritepropresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "value": "dGVzdA==",
  "protocolMap": {
    "ble": {
      "serviceID": "12345678-1234-5678-1234-56789abcdef4",
      "characteristicID": "12345678-1234-5678-1234-56789abcdef4"
    }
  }
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"value" is the bytes that were written in base64 encoding</t>
  <t>"protocolMap" is the protocol mapping for the property</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="read-a-value-using-protocol-mapping"><name>Read a value using protocol mapping</name>

<t>Method: <spanx style="verb">POST /{id}/action/property/read</spanx></t>

<t>Description: Reads a value from a property on a device using protocol mapping</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>protocolMap: the protocol mapping for the property</t>
</list></t>

<t>Example body of a read property:</t>

<figure title="Example read property" anchor="exreadprop"><artwork><![CDATA[
{
  "protocolMap": {
    "ble": {
      "serviceID": "12345678-1234-5678-1234-56789abcdef4",
      "characteristicID": "12345678-1234-5678-1234-56789abcdef4"
    }
  }
}
]]></artwork></figure>

<t>Response:</t>

<t>Example of a response:</t>

<figure title="Example read property response" anchor="exreadpropresp"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "value": "dGVzdA==",
  "protocolMap": {
    "ble": {
      "serviceID": "12345678-1234-5678-1234-56789abcdef4",
      "characteristicID": "12345678-1234-5678-1234-56789abcdef4"
    }
  }
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"value" is the bytes that were read in base64 encoding</t>
  <t>"protocolMap" is the protocol mapping for the property</t>
</list></t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
<section anchor="broadcast-to-a-device"><name>Broadcast to a device</name>

<t>Method: <spanx style="verb">POST /{id}/action/broadcast</spanx></t>

<t>Description: Broadcast a payload to a device. The broadcast is performed on the AP where the device was last seen</t>

<t>Parameters:</t>

<t><list style="symbols">
  <t>id: the id of the device</t>
</list></t>

<t>Request Body:</t>

<t>An example body of a broadcast:</t>

<figure title="Example broadcast" anchor="exbroadcast"><artwork><![CDATA[
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "protocolMap": {
    "ble": {}
  },
  "cycle": "single",
  "broadcastTime": 3000,
  "broadcastInterval": 500,
  "payload": "AgEaAgoMFv9MABAHch9BsDkgeA=="
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"id" is the id of the device</t>
  <t>"protocolMap" is the protocol mapping for the property to identify the protocol to be used</t>
  <t>"cycle" is the broadcast cycle, either "single" or "repeat"</t>
  <t>"broadcastTime" is the time in milliseconds for the broadcast to run</t>
  <t>"broadcastInterval" is the time in milliseconds between each broadcast</t>
  <t>"payload" is the bytes to be broadcast in base64 encoding</t>
</list></t>

<t>Response:</t>

<t>This API responds with a HTTP 200 OK status code and an empty body when successful.</t>

<t>A failure will generate a standard failed response. Please refer to <xref target="failure"/> definition of failed response.</t>

</section>
</section>
</section>
<section anchor="nipc-extensibility"><name>NIPC Extensibility</name>

<t>NIPC is extensible in two ways:</t>

<t><list style="symbols">
  <t>Protocol mapping: New protocol mapping can extend NIPC with support
for new non-IP protocols</t>
  <t>API extensions: API extensions leverage compound statements of basic NIPC
action APIs to simplify common operations for applications.</t>
</list></t>

<section anchor="protocol-extensions"><name>Protocol extensions</name>

<t>As described in <xref target="protocolmap"/> NIPC supports mapping protocol specific
mapping to NIPC properties. BLE and Zigbee are used as examples, but protocol
mapping is extensible to other protocols, so now non-IP protocols can be 
supported by NIPC without a schema change.</t>

<t>The protocol objects need to be extended with the new
protocol as well. Protocol objects will be extended as follows:</t>

<texttable title="Adding Protocol mappings" anchor="newprotext">
      <ttcol align='left'>Attribute</ttcol>
      <ttcol align='left'>Req</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Example</ttcol>
      <c>ble</c>
      <c>T</c>
      <c>object</c>
      <c>an object with BLE-specific properties</c>
      <c>zigbee</c>
      <c>T</c>
      <c>object</c>
      <c>an object with Zigbee-specific properties</c>
      <c>newProtocol</c>
      <c>T</c>
      <c>object</c>
      <c>an object with newProtocol-specific props</c>
</texttable>

<t>In the new protocol object, protocol specific properties can be added.</t>

<t>Protocol mappings need to be IANA registered.</t>

</section>
<section anchor="api-extensions"><name>API extensions</name>

<t>/extension</t>

<t>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 <xref target="NIPCextensions"/> below, we have defined a few example 
extensions.</t>

</section>
</section>
<section anchor="errorhandling"><name>NIPC Error Handling</name>

<t>The error codes in the NIPC APIs can be generic or specific to the API. 
The generic error codes reuse the HTTP status codes defined in <xref target="RFC9110"/>.
The error codes for the action APIs are divided into the following
categories:</t>

<t><list style="symbols">
  <t>1000-1099 (Generic): Broadly applicable errors, including 
authorization, invalid identifiers, and generic failures.</t>
  <t>1100-1199 (Property APIs): Errors related to property APIs
(read/write).</t>
  <t>1200-1299 (Event APIs): Errors related to event APIs
(enable/disable).</t>
  <t>1300-1399 (BLE-Specific): Errors specific to BLE operations,
including connection management and service discovery.</t>
  <t>1400-1499 (Zigbee-Specific): Errors specific to Zigbee operations.</t>
  <t>1500-1599 (Broadcast APIs): Errors related to broadcasting data.</t>
</list></t>

<t>The specific error codes are defined in the table below:</t>

<texttable title="Error Codes" anchor="errorcodes">
      <ttcol align='left'>Error Code</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Category</ttcol>
      <c>1000</c>
      <c>Generic catch-all error code for any API</c>
      <c>Generic</c>
      <c>1001</c>
      <c>Application not authorized to access the device</c>
      <c>Generic</c>
      <c>1002</c>
      <c>Invalid device ID or gateway doesn't recognize the ID</c>
      <c>Generic</c>
      <c>1003</c>
      <c>Invalid SDF URL or SDF affordance not found</c>
      <c>Generic</c>
      <c>1004</c>
      <c>Operation was not executed since the previous operation failed</c>
      <c>Generic</c>
      <c>1100</c>
      <c>Property not readable</c>
      <c>Property APIs</c>
      <c>1101</c>
      <c>Property not writable</c>
      <c>Property APIs</c>
      <c>1200</c>
      <c>Event already enabled</c>
      <c>Event APIs</c>
      <c>1201</c>
      <c>Event not enabled</c>
      <c>Event APIs</c>
      <c>1202</c>
      <c>Event not registered for any data application</c>
      <c>Event APIs</c>
      <c>1300</c>
      <c>Device already connected</c>
      <c>BLE-Specific</c>
      <c>1301</c>
      <c>No connection found for device</c>
      <c>BLE-Specific</c>
      <c>1302</c>
      <c>BLE connection timeout</c>
      <c>BLE-Specific</c>
      <c>1303</c>
      <c>BLE bonding failed</c>
      <c>BLE-Specific</c>
      <c>1304</c>
      <c>BLE connection failed</c>
      <c>BLE-Specific</c>
      <c>1305</c>
      <c>BLE service discovery failed</c>
      <c>BLE-Specific</c>
      <c>1306</c>
      <c>Invalid BLE service or characteristic ID</c>
      <c>BLE-Specific</c>
      <c>1400</c>
      <c>Zigbee connection timeout</c>
      <c>Zigbee-Specific</c>
      <c>1401</c>
      <c>Invalid Zigbee endpoint or cluster ID</c>
      <c>Zigbee-Specific</c>
      <c>1500</c>
      <c>Invalid broadcast data</c>
      <c>Broadcast APIs</c>
</texttable>

<t>The appropriate HTTP status code is returned in the response.</t>

</section>
<section anchor="publishsubscribe-interface"><name>Publish/Subscribe Interface</name>

<t>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/data-app API.</t>

<t>In this memo, we propose the data format to be CBOR <xref target="RFC8949"/>.</t>

<section anchor="cddl-definition"><name>CDDL Definition</name>

<t>We have a CDDL <xref target="RFC8610"/> definition where we define the
DataSubscription struct that will be used by all the messages published 
to the MQTT broker.</t>

<t>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.</t>

<t>Other fields in the CDDL such as apMacAddress and rssi can be optionally
included but these fields can expose the underlying network topology.</t>

<t>Each message also has a subscription choice group that will define the
type of data that is being published.</t>

<t>Each MQTT message can be a collection of DataSubscription structs. This
collection is represented as DataBatch in the CDDL.</t>

<figure><sourcecode type="CDDL"><![CDATA[
DataBatch = [* DataSubscription]

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
}
]]></sourcecode></figure>

</section>
<section anchor="cbor-examples"><name>CBOR Examples</name>

<t>This section contains a few examples of the DataSubscription struct 
depicted in CBOR diagnostic notation.</t>

<figure title="Onboarded BLE Device Advertisement"><artwork><![CDATA[
[
  {
    "data": h'02011A020A0C16FF4C001007721F41B0392078',
    "deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "bleAdvertisement": {
        "macAddress": "C1:5C:00:00:00:01",
        "rssi": -25
    }
  }
]
]]></artwork></figure>

<figure title="Non-onboarded BLE Device Advertisement"><artwork><![CDATA[
[
  {
    "data": h'02011A020A0C16FF4C001007721F41B0392078',
    "timestamp": 1727484393,
    "bleAdvertisement": {
        "macAddress": "C1:5C:00:00:00:01",
        "rssi": -25
    }
  }
]
]]></artwork></figure>

<figure title="BLE GATT Notification"><artwork><![CDATA[
[
  {
    "data": h'434630374346303739453036',
    "deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "bleSubscription": {
        "serviceID": "a4e649f4-4be5-11e5-885d-feff819cdc9f",
        "characteristicID": "c4c1f6e2-4be5-11e5-885d-feff819cdc9f"
    }
  }
]
]]></artwork></figure>

<figure title="BLE Connection status event"><artwork><![CDATA[
[
  {
    "deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "bleConnectionStatus": {
        "macAddress": "C1:5C:00:00:00:01",
        "connected": true
    }
  }
]
]]></artwork></figure>

<figure title="Zigbee Attribute Notification"><artwork><![CDATA[
[
  {
    "data": h'434630374346303739453036',
    "deviceID": "75fde96d-886f-4ac0-a1d5-df79f76e7c9c",
    "timestamp": 1727484393,
    "zigbeeSubscription": {
        "endpointID": 1,
        "clusterID": 6,
        "attributeID": 12,
        "type": 1
    }
  }
]
]]></artwork></figure>

</section>
</section>
<section anchor="examples"><name>Examples</name>

<t>This section contains a few examples on how applications can leverage 
NIPC operations to communicate with BLE and Zigbee devices.</t>

<section anchor="property-readwrite"><name>Property Read/Write</name>

<t>In this example, we will connect to a device and read and write from a
property.</t>

<t>The sequence of operations for this are:</t>

<t><list style="symbols">
  <t>Onboard a device using the SCIM Interface (out of scope of this
memo)</t>
  <t>Register an SDF model for the device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /registration/model
Content-Type: application/sdf+json
Accept: application/json
Host: localhost
    
{ ... }

HTTP/1.1 200 OK
content-type: application/json
x-request-id: 1f1c5a37-e21c-4edc-aeb0-65b9d747fe07

{
  "sdfRef": "https://example.com/thermometer#/sdfThing/thermometer"
}
]]></artwork></figure>
  <vspace blankLines='1'/>
Request Body: JSON object with the SDF model, from <xref target="thermometer-sdf"/></t>
  <t>Read a property from the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
GET /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Fdevice_name
Accept: application/json
Host: localhost
    
HTTP/1.1 200 OK
content-type: application/json
x-request-id: 7b821223-2ef4-4b7e-8802-efab7e1801ea
    
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "value": "dGVzdA==",
  "sdfRef": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name"
}
]]></artwork></figure>
  </t>
  <t>Write to a property on the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
PUT /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Fdevice_name
Content-Type: application/json
Accept: application/json
Host: localhost
    
{
  "value": "dGVzdA=="
}
    
HTTP/1.1 200 OK
content-type: application/json
x-request-id: 7b821223-2ef4-4b7e-8802-efab7e1801ea
    
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "value": "dGVzdA==",
  "sdfRef": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name"
}
]]></artwork></figure>
  </t>
</list></t>

</section>
<section anchor="enabling-an-event"><name>Enabling an Event</name>

<t>In this example, we will onboard a device, and setup an advertisement
subscription event for that device.</t>

<t>The sequence of operations for this are:</t>

<t><list style="symbols">
  <t>Onboard a device and endpoint app using the SCIM Interface (out of scope of this
   memo)</t>
  <t>Register an SDF model for the device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /registration/model
Content-Type: application/sdf+json
Accept: application/json
Host: localhost
    
{ ... }

HTTP/1.1 200 OK
content-type: application/json
x-request-id: 1f1c5a37-e21c-4edc-aeb0-65b9d747fe07

{
  "sdfRef": "https://example.com/thermometer#/sdfThing/thermometer"
}
]]></artwork></figure>
  <vspace blankLines='1'/>
Request Body: JSON object with the SDF model, from <xref target="thermometer-sdf"/></t>
  <t>Register the data app with the event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /registration/data-app/23456789-1234-5678-1234-56789abcdef4
Content-Type: application/json
Accept: application/json
Host: localhost

{
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEvent/isPresent"
  ],
  "mqttClient": {}
}

HTTP/1.1 200 OK
content-type: application/json
x-request-id: 3a7d9ad6-562e-44ac-b119-cfe1d0e7b74e

{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEvent/isPresent"
  ]
}
]]></artwork></figure>
  </t>
  <t>Enable the advertisement event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /12345678-1234-5678-1234-56789abcdef4/event/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfEvent%2FisPresent
Content-Type: application/json
Accept: application/json
Host: localhost
Content-Length: 0
    
HTTP/1.1 200 OK
content-type: application/json
x-request-id: 1f1c5a37-e21c-4edc-aeb0-65b9d747fe07

{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "event": "https://example.com/thermometer#/sdfThing/thermometer/sdfEvent/isPresent"
}
]]></artwork></figure>
  </t>
</list></t>

</section>
<section anchor="property-readwrite-with-explicit-connection"><name>Property read/write with explicit connection</name>

<t>In this example, we will connect to a device explicitly and read and 
write from a property.
The sequence of operations for this are:</t>

<t><list style="symbols">
  <t>Onboard a device using the SCIM Interface (out of scope of this
memo)</t>
  <t>Connect to the device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /12345678-1234-5678-1234-56789abcdef4/action/connection
Content-Type: application/json
Accept: application/json
Host: localhost
    
{
  "retries": 3,
  "retryMultipleAPs": true,
  "protocolMap": {
    "ble": {
      "services": [
        {
          "serviceID": "1800"
        },
        {
          "serviceID": "1801"
        }
      ],
      "cached": false,
      "cacheIdlePurge": 3600,
      "autoUpdate": true,
      "bonding": "default"
    }
  }
}

HTTP/1.1 200 OK
content-type: application/json
x-request-id: 7b821223-2ef4-4b7e-8802-efab7e1801ea
    
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "protocolMap": {
    "ble": [
      {
        "serviceID": "1800",
        "characteristics": [
          {
            "characteristicID": "2A00",
            "flags": [
              "read",
              "write"
            ],
            "descriptors": [
              {
                "descriptorID": "2901"
              }
            ]
          }
        ]
      }
    ]
  }
}
]]></artwork></figure>
  </t>
  <t>Read a property from the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /12345678-1234-5678-1234-56789abcdef4/action/property/read
Content-Type: application/json
Accept: application/json
Host: localhost

{
  "protocolMap": {
    "ble": {
      "serviceID": "1800",
      "characteristicID": "2A00"
    }
  }
}
    
HTTP/1.1 200 OK
content-type: application/json
x-request-id: 7b821223-2ef4-4b7e-8802-efab7e1801ea
    
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "value": "dGVzdA==",
  "protocolMap": {
    "ble": {
      "serviceID": "1800",
      "characteristicID": "2A00"
    }
  }
}
]]></artwork></figure>
  </t>
  <t>Write to a property on the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /12345678-1234-5678-1234-56789abcdef4/action/property/write
Content-Type: application/json
Accept: application/json
Host: localhost
    
{
  "value": "dGVzdA==",
  "protocolMap": {
    "ble": {
      "serviceID": "1800",
      "characteristicID": "2A00"
    }
  }
}
    
HTTP/1.1 200 OK
content-type: application/json
x-request-id: 7b821223-2ef4-4b7e-8802-efab7e1801ea
    
{
  "id": "12345678-1234-5678-1234-56789abcdef4",
  "value": "dGVzdA==",
  "protocolMap": {
    "ble": {
      "serviceID": "1800",
      "characteristicID": "2A00"
    }
  }
}
]]></artwork></figure>
  </t>
  <t>Disconnect from the device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
DELETE /12345678-1234-5678-1234-56789abcdef4/action/connection
Accept: application/json
Host: localhost
    
HTTP/1.1 200 OK
content-type: application/json
x-request-id: 7b821223-2ef4-4b7e-8802-efab7e1801ea
    
{
  "id": "12345678-1234-5678-1234-56789abcdef4"
}
]]></artwork></figure>
  </t>
</list></t>

</section>
</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<section anchor="api-authorization"><name>API authorization</name>

<t>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:</t>

<t><list style="numbers">
  <t>Onboarding: Authorize an onboarding application against a SCIM server
co-located with the gateway.</t>
  <t>Control: Authorize applications that may control devices.</t>
  <t>Data: Authorize applications that may receive telemetry.<br />
It is possible to further refine roles down to an API basis.</t>
</list></t>

</section>
</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<t>This section provides guidance to the Internet Assigned Numbers Authority
(IANA) regarding registration of values related to NIPC, in accordance
with <xref target="RFC8126"/>.</t>

<section anchor="protocol-mapping"><name>Protocol mapping</name>

</section>
<section anchor="api-extensions-1"><name>API extensions</name>

</section>
<section anchor="wellknown-uri"><name>well_known URI</name>

</section>
</section>


  </middle>

  <back>


    <references title='Normative References' anchor="sec-normative-references">

&RFC7644;
&I-D.ietf-scim-device-model;
&RFC2119;
&RFC8174;
&I-D.ietf-asdf-sdf;
&RFC9114;
&RFC7159;
&RFC8949;
&RFC3986;
&RFC8615;
&RFC9110;
&RFC8610;
&RFC8126;


    </references>

    <references title='Informative References' anchor="sec-informative-references">

<reference anchor="BLE53" >
  <front>
    <title>Bluetooth Core Specification, Version 5.3</title>
    <author >
      <organization>Bluetooth SIG</organization>
    </author>
    <date year="2021"/>
  </front>
</reference>
<reference anchor="Zigbee22" >
  <front>
    <title>zigbee Specification, Version 22 1.0</title>
    <author >
      <organization>Connectivity Standards Alliance</organization>
    </author>
    <date year="2017"/>
  </front>
</reference>
<reference anchor="Gatt-REST-API" target="https://www.bluetooth.com/bluetooth-resources/gatt-rest-api/">
  <front>
    <title>A RESTful API used to access data in devices using the functionality defined in the Bluetooth GATT profile</title>
    <author >
      <organization>Bluetooth SIG</organization>
    </author>
    <date year="2017"/>
  </front>
</reference>


    </references>


<?line 2203?>

<section anchor="openapi-definition"><name>OpenAPI definition</name>

<t>The following non-normative model is provide for convenience of
the implementor.</t>

<figure anchor="openAPI"><artwork><![CDATA[
<CODE BEGINS>
file "openapi.yml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API
  description: |-
    This API specifies RESTful application layer interface for gateways providing operations against non-IP devices. The described interface is extensible. The examples includes leverage Bluetooth Low Energy and Zigbee as they are commonly deployed.
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-04"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name: NIPC property APIs
    description: |-
      APIs that allow apps to get and update device properties. If the underlying protocol requires connection management, it will be performed as part of the API call.
  - name: NIPC event APIs
    description: |-
      APIs that allow apps to enable or disable event reporting on devices. If the underlying protocol requires connection management, it will be performed as part of the API call.
  - name: NIPC action APIs
    description: |-
      APIs that perform actions on devices.
  - name: NIPC action APIs with embedded protocol mapping
    description: |-
      APIs that perform actions on devices, but do not use registered properties, events or actions. These APIs have embedded protocol mappings
  - name: NIPC registration APIs
    description: |-
      APIs that register sdf models or data applications

paths:
### NIPC Property APIs
  /{id}/property/{property}:
    put:
      tags:
        - NIPC property APIs
      summary: Write a value to a property on a device
      description: |-
        Write a value to a property on a device. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. Id cannot be a group-id.
      operationId: UpdateProperty
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        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: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Value'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValue'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/PropertyErrorCodes'

    get:
      tags:
        - NIPC property APIs
      summary: Read a value from a property on a device
      description: |-
        Read a value to a property on a device. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. Id cannot be a group-id.
      operationId: GetProperty
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        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: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValue'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/PropertyErrorCodes'

  /{id}/property:
    put:
      tags:
        - NIPC property APIs
      summary: Update a value of one or more properties on a device
      description: |-
        Write a value to a property or multiple properties to a device. If underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. 
      operationId: UpdateProperties
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyValueArray'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValueResponseArray'
        '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:
        - NIPC property APIs
      summary: Read a value from one or multiple properties on a device
      description: |-
        Read a value to a property or multiple properties from a device. If underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. 
      operationId: GetProperties
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: query
        description: properties that needs to be filtered, multiple values are comma-separated
        required: true
        explode: false
        schema:
          type: array
          items:
            type: string
            example: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValueResponseArray'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/PropertyErrorCodes'
 
 ### NIPC Event APIs
  /{id}/event/{event}:
    post:
      tags:
        - NIPC event APIs
      summary: Enable an event on a specific device
      description: |-
        Enable an event on a specific device or for a group of devices. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it.
      operationId: EnableEvent
      parameters:
      - name: id
        in: path
        description: device id or group id
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: event
        in: path
        description: event that needs to be enabled
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/Event'                  
                
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request 
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/EventErrorCodes'
  
    delete:
      tags:
        - NIPC event APIs
      summary: Disable an event on a specific device
      description: |-
        Disable an event on a specific device or a group of devices. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. 
      operationId: DisableEvent
      parameters:
      - name: id
        in: path
        description: device id or group id
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: event
        in: path
        description: event that needs to be disabled
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'  
                  - $ref: '#/components/schemas/Event' 
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/EventErrorCodes'
                
    get:
      tags:
        - NIPC event APIs
      summary: Get status of an event on a specific device
      description: |-
        Get status of an event on a specific device or a groupd of devices. Success is event is active, failure if event not active.
      operationId: GetEvent
      parameters:
      - name: id
        in: path
        description: device id or group id
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: event
        in: path
        description: event that needs to be filtered
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/Event' 
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/EventErrorCodes'

  /{id}/event:
    get:
      tags:
        - NIPC event APIs
      summary: Get status of events on a device or group of devices
      description: |-
        Get status of an event or multiple events on a specific device or group of devices.
      operationId: GetEvents
      parameters:
      - name: id
        in: path
        description: device or group id that needs to be filtered
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: event
        in: query
        description: events that needs to be filtered, multiple values are comma-separated
        explode: false
        required: true
        schema:
          type: array
          items:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventStatusResponseArray'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/EventErrorCodes'

### NIPC action APIs
  /{id}/action/{action}:
    put:
      tags:
        - NIPC action APIs
      summary: Perform an action on a device
      description: |-
        Perform an action on a device. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. Id cannot be a group-id.
      operationId: ActionProperty
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: action
        in: path
        description: action that needs to be performed
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfAction/start"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Value'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/ActionValue'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/PropertyErrorCodes'   
                  
  /{id}/action/broadcast:
    post:
      tags:
        - NIPC action APIs with embedded protocol mapping
      summary: Broadcast to a device
      description: |-
        Broadcast a payload to a device. The broadcast is performed on the AP where the device was last seen
      operationId: ActionBroadcast
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered, group id not allowed
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Broadcast'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/BroadcastErrorCodes'
                  
  /{id}/action/connection:
    post:
      tags:
        - NIPC action APIs with embedded protocol mapping
      summary: Connect a device
      description: |-
        Connect a device. 3 retries by default, optionally retry policy can be defined in the API body. If the protocol requires service discovery, full service discovery will be performed, unless specific services are described in the API body.
      operationId: ActionCreateConnection
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered, group id not allowed
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - $ref: '#/components/schemas/Connection'
                - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceList'
        required: false
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/ConnectionErrorCodes'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ErrorCodes'
  
    put:
      tags:
        - NIPC action APIs with embedded protocol mapping
      summary: Update cached ServiceMap for a device.
      description: |-
        Update cached ServiceMap for a device. Full service discovery will be performed, unless specific services are described in the API body.
      operationId: ActionUpdateServiceMap
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered, group id not allowed
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceList'
        required: false
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/ConnectionErrorCodes'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ErrorCodes'
  
    delete:
      tags:
        - NIPC action APIs with embedded protocol mapping
      summary: Disconnect a device 
      description: |-
        Disconnect a device.
      operationId: ActionDeleteConnection
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered, group id not allowed
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/ConnectionErrorCodes'
                  
    get:
      tags:
        - NIPC action APIs with embedded protocol mapping
      summary: Get connection state for a device
      description: |-
        Get connection status for a device. Success when device(s) is/are connected, includes service map for the device if available. Failure when a device is not connected
      operationId: ActionGetConnection
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered, group id not allowed
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/ConnectionErrorCodes'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ErrorCodes'
 
  /{id}/action/property/write:
    post:
      tags:
        - NIPC action APIs with embedded protocol mapping
      summary: Write a value to an property using protocol mapping
      description: |-
        Write a value to an unregistered property, embedding property protocol mapping in the API, this does not require
        property registration. You cannot write to a group id.
      operationId: ActionPropWrite
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered, group id not allowed
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/Value' 
                - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/Value'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/PropertyErrorCodes'
                
  /{id}/action/property/read:
    post:
      tags:
        - NIPC action APIs with embedded protocol mapping
      summary: Write a value to an property using protocol mapping
      description: |-
        Read a value from an unregistered property, embedding property protocol mapping in the API, this does not require
        property registration. You cannot read from a group id.
      operationId: ActionPropRead
      parameters:
        - name: id
          in: path
          description: device id that need to be filtered, group id not allowed
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/Value'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse' 
                  - $ref: '#/components/schemas/PropertyErrorCodes'


### Registrations
  /registration/model:
    post:
      tags:
        - NIPC registration APIs
      summary: Register an sdfObject
      description: |-
        Register an sdfObject, including Properties, Events and actions
      operationId: registerSdfObject
      requestBody:
        content:
          application/sdf+json:
            schema:
              $ref: '#/components/schemas/SdfModel'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfReference'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - NIPC registration APIs
      summary: Get all registered sdfRefs
      description: |-
        Get all registered sdfRefs for a device or group
      operationId: getSdfRefs
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                type: array
                items:
                  allOf:
                    - $ref: '#/components/schemas/SdfReference'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'


  /registration/model/{sdfRef}:
    put:
      tags:
        - NIPC registration APIs
      summary: Update an SDF model
      description: |-
        Update an SDF model, including Properties, Events and actions
      operationId: updateSdf
      parameters:
        - name: sdfRef
          in: path
          description: sdfRef can be a reference to an sdfThing or sdfObject
          required: true
          schema:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healthsensor"
      requestBody:
        content:
          application/sdf+json:
            schema:
              $ref: '#/components/schemas/SdfModel'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfReference'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'
 
    delete:
      tags:
        - NIPC registration APIs
      summary: Delete an sdfObject
      description: |-
        Delete an sdfObject, including Properties, Events and actions
      operationId: deleteSdfObject
      parameters:
        - name: sdfRef
          in: path
          description: sdfObject name
          required: true
          schema:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healthsensor"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfReference'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - NIPC registration APIs
      summary: get a registered sdfObject
      description: |-
        Get an sdfObject, including Properties, Events and actions
      operationId: getSdfObject
      parameters:
        - name: sdfRef
          in: path
          description: sdfObject name
          required: true
          schema:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healthsensor"
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfModel'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

  /registration/data-app/{data-app}:
    post:
      tags:
        - NIPC registration APIs
      summary: Register a dataApp
      description: |-
        Register a dataApp that is able to receive device data. 
      operationId: registerDataApp
      parameters:
        - name: data-app
          in: path
          description: id of the data app that will be registered
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DataApp'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

    put:
      tags:
        - NIPC registration APIs
      summary: Update registration of a dataApp
      description: |-
        Update registration of a dataApp that is able to receive device data. 
      operationId: UpdateDataApp
      parameters:
        - name: data-app
          in: path
          description: id of the data app that will be updated
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DataApp'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'
                  
    delete:
      tags:
        - NIPC registration APIs
      summary: Delete registration of a dataApp
      description: |-
        Delete registration of a dataApp that is able to receive device data. 
      operationId: DeleteDataApp
      parameters:
        - name: data-app
          in: path
          description: id of the data app that will be updated
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'
  
    get:
      tags:
        - NIPC registration APIs
      summary: Get registration of a dataApp
      description: |-
        Get registrationdetails of a dataApp that is able to receive device data. 
      operationId: GetDataApp
      parameters:
        - name: data-app
          in: path
          description: id of the data app that will be updated
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

components:
  schemas:
# Base objects
## A SCIM id, can be a device or a group
    Id:
      required:
        - id
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: A SCIM-generated UUID, can be a device or group
          example: 12345678-1234-5678-1234-56789abcdef4
          
## A property
    Property:
      required:
        - property
      type: object
      properties:
        property:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"

    Action:
      required:
        - action
      type: object
      properties:
        action:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermostat/sdfAction/start"

## A value 
    Value:
      required:
        - value
      type: object
      properties:
        value:
          type: string
          format: byte
          example: dGVzdA==

## A value of an property of an Device
    PropertyValue:
      allOf:
        - $ref: '#/components/schemas/Property'
        - $ref: '#/components/schemas/Value'

    ActionValue:
      allOf:
        - $ref: '#/components/schemas/Action'
        - $ref: '#/components/schemas/Value'

## An array of Property values
    PropertyValueArray:
      type: object
      properties:
        properties:
          type: array
          items:
            $ref: '#/components/schemas/PropertyValue'

## Event
    Event:
      required:
        - event
      type: object
      properties:
        event:
          type: string
          description: percent-encoded JSON pointer to the SDF event object
          example: https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected
            
## A Connection
    Connection:
      type: object
      properties:
        retries:
          type: integer
          format: int32
          example: 3
        retryMultipleAPs:
          type: boolean
          example: true
        
## A broadcast
    Broadcast:
      allOf:
        - $ref: '#/components/schemas/Id'
        - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Broadcast'
      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
        payload:
          type: string
          format: byte
          example: AgEaAgoMFv9MABAHch9BsDkgeA==
          
 ## DataApp
    DataApp:
      oneOf:
        - $ref: '#/components/schemas/DataAppMqttClient'
        - $ref: '#/components/schemas/DataAppMqttBroker'
        - $ref: '#/components/schemas/DataAppWebhook'
        - $ref: '#/components/schemas/DataAppWebsocket'
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'


    DataAppMqttClient:
      type: object
      properties: 
        mqttClient:
          type: object

    DataAppMqttBroker:
      type: object
      properties: 
        mqttBroker:
          type: object
          properties: 
            URI: 
              type: string
              example: mqtt.broker.com:8883
            username:
              type: string
              example: user1
            password: 
              type: string
              example: password1
            brokerCACert: 
              type: string         
      
    DataAppWebhook:
      type: object
      properties: 
        webhook:
          type: object
          properties: 
            URI: 
              type: string
              example: webhook.com:443
            apiKey:
              type: string
              example: fjelk-3dl33f-2wdsd
            serverCACert: 
              type: string 
          
    DataAppWebsocket:
      type: object
      properties: 
        websocket:
          type: object
          properties: 
            URI: 
              type: string
              example: websocket.com:443
            apiKey:
              type: string
              example: fjelk-3dl33f-2wdsd
            serverCACert: 
              type: string 

 ## sdfObject registration definition
    SdfReference:
      type: object
      description: SDF URL referring to the sdfobject
      properties: 
        sdfRef:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor"
    
    SdfModel:
      allOf:
        - type: object
          description: Sample SDF model
          properties:
            namespace:
              type: object
              additionalProperties:
                type: string
              example:
                heartrate: https://example.com/heartrate
            defaultNamespace:
              type: string
              example: heartrate
        - oneOf:
          - $ref: '#/components/schemas/SdfThing'
          - $ref: '#/components/schemas/SdfObject'

    SdfThing:
      type: object
      description: Sample SDF thing
      properties:
        sdfThing:
          additionalProperties:
            anyOf:
                - $ref: '#/components/schemas/SdfProperty'
                - $ref: '#/components/schemas/SdfEvent'
                - $ref: '#/components/schemas/SdfAction'
                - $ref: '#/components/schemas/SdfObject'
          example:
            multipleSensor:
              sdfEvent:
                isPresent:
                  sdfOutputData:
                    protocolMap:
                      ble:
                        type: advertisement
              sdfObject:
                healthsensor:
                  sdfProperty:
                    heartrate:
                      protocolMap:
                        ble:
                          serviceID: 12345678-1234-5678-1234-56789abcdef4
                          characteristicID: 12345678-1234-5678-1234-56789abcdef4
                  sdfEvent:
                    fallDetected:
                      sdfOutputData:
                        protocolMap:
                          ble:
                            serviceID: 12345678-1234-5678-1234-56789abcdef4
                            characteristicID: 12345678-1234-5678-1234-56789abcdef4
                  sdfAction:
                    start:
                      protocolMap:
                        ble:
                          serviceID: 12345678-1234-5678-1234-56789abcdef4
                          characteristicID: 12345678-1234-5678-1234-56789abcdef4

    SdfObject:
      type: object
      description: Sample SDF object
      properties:
        sdfObject:
          additionalProperties:
            anyOf:
              - $ref: '#/components/schemas/SdfProperty'
              - $ref: '#/components/schemas/SdfEvent'
              - $ref: '#/components/schemas/SdfAction'
          example:
            healthsensor:
              sdfProperty:
                heartrate:
                  protocolMap:
                    ble:
                      serviceID: 12345678-1234-5678-1234-56789abcdef4
                      characteristicID: 12345678-1234-5678-1234-56789abcdef4
              sdfEvent:
                fallDetected:
                  sdfOutputData:
                    protocolMap:
                      ble:
                        serviceID: 12345678-1234-5678-1234-56789abcdef4
                        characteristicID: 12345678-1234-5678-1234-56789abcdef4
              sdfAction:
                start:
                  protocolMap:
                    ble:
                      serviceID: 12345678-1234-5678-1234-56789abcdef4
                      characteristicID: 12345678-1234-5678-1234-56789abcdef4

    SdfProperty:
      type: object
      description: Sample SDF property
      properties:
        sdfProperty:
          additionalProperties: 
            allOf:
              - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
          example:
            heartrate:
              protocolMap:
                ble:
                  serviceID: 12345678-1234-5678-1234-56789abcdef4
                  characteristicID: 12345678-1234-5678-1234-56789abcdef4
          
    SdfEvent:
      type: object
      description: Sample SDF property
      properties:
        sdfEvent:
          additionalProperties: #example, this will be the registered event
            type: object
            properties:
              sdfOutputData:
                allOf:
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Event'
          example:
            fallDetected:
              sdfOutputData:
                protocolMap:
                  ble:
                    serviceID: 12345678-1234-5678-1234-56789abcdef4
                    characteristicID: 12345678-1234-5678-1234-56789abcdef4
    
    SdfAction:
      type: object
      description: Sample SDF property
      properties:
        sdfAction:
          additionalProperties: 
            allOf:
              - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
          example:
            start:
              protocolMap:
                ble:
                  serviceID: 12345678-1234-5678-1234-56789abcdef4
                  characteristicID: 12345678-1234-5678-1234-56789abcdef4

# responses

## Error 500 application Failure response
    FailureResponse:
      type: object
      properties:
        reason:
          type: string
          example: Bad request
        errorCode:
          type: integer
          format: int32
          enum: 
            - 1000 # Generic catch-all error code for any API
            - 1001 # Application not authorized to access the device
            - 1002 # Invalid device ID or gateway doesn't recognize the ID
            - 1003 # Invalid SDF URL or SDF affordance not found
            - 1004 # Operation was not executed since the previous operation failed

    PropertyErrorCodes:
      type: integer
      format: int32
      enum:
        - 1100 # Property not readable
        - 1101 # Property not writable

    EventErrorCodes:
      type: integer
      format: int32
      enum:
        - 1200 # Event already enabled
        - 1201 # Event not enabled
        - 1202 # Event not registered for any data application

    ConnectionErrorCodes:
      type: integer
      format: int32
      enum:
        - 1300 # Device already connected
        - 1301 # No connection found for device
        - 1302 # BLE connection timeout
        - 1303 # BLE bonding failed
        - 1304 # BLE connection failed
        - 1305 # BLE service discovery failed
        - 1306 # Invalid BLE service or characteristic ID
        - 1400 # Zigbee connection timeout
        - 1401 # Invalid Zigbee endpoint or cluster ID

    BroadcastErrorCodes:
      type: integer
      format: int32
      enum:
        - 1500 # Invalid broadcast data        

## Property operations responses
    
    PropertyValueResponseArrayItem:
      oneOf:
        - $ref: '#/components/schemas/PropertyValue'
        - $ref: '#/components/schemas/FailureResponse'
    
    PropertyValueResponseArray:
      type: object
      properties:
        properties:
          type: array
          items:
              $ref: '#/components/schemas/PropertyValueResponseArrayItem'

## Event operations responses
    EventStatusResponseArrayItem:
      allOf:
        - $ref: '#/components/schemas/Id'
        - $ref: '#/components/schemas/Event' 
      oneOf:
        - $ref: '#/components/schemas/FailureResponse'

    EventStatusResponseArray:
      type: object
      properties:
        events:
          type: array
          items:
              $ref: '#/components/schemas/EventStatusResponseArrayItem'

<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="protocol-mapping-1"><name>Protocol mapping</name>

<t>NIPC requires that a protocol mapping be provided as part of the sdf
model for a device or have one provided using the NIPC action APIs with 
embedded protocol mapping. The protocol mapping is a JSON object that 
describes the underlying technology used to communicate with the device 
along with any additional information needed to communicate with the 
device.</t>

<t>The JSON format of the protocol mapping is provided as a non-normative
OpenAPI model for the convenience of the implementor.</t>

<section anchor="protocol-mapping-openapi-model"><name>Protocol mapping OpenAPI model</name>

<figure anchor="protocolmapmodel"><artwork><![CDATA[
<CODE BEGINS>
file "ProtocolMap.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) Protocol Mapping
  description: |-
    Non IP Device Control (NIPC) Protocol Mapping. When adding a new protocol mapping pls add a reference to the protocol map for all the schemas in this file.
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

components:
  schemas:
# Protocol Mapping
## Protocol Map for Service Discovery
    ProtocolMap-ServiceList:
      type: object
      properties:
        protocolMap:
          oneOf:
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/ProtocolMap-BLE-ServiceList'

## Protocol Map for Service Discovery result
    ProtocolMap-ServiceMap:
      type: object
      properties:
        protocolMap:
          oneOf:
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/ProtocolMap-BLE-ServiceMap'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/ProtocolMap-Zigbee-ServiceMap'
        
## Protocol Map for Error Codes
    ProtocolMap-ErrorCodes:
      type: object
      properties:
        protocolMap:
          oneOf:  
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/ProtocolMap-BLE-ErrorCodes'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/ProtocolMap-Zigbee-ErrorCodes'

## Protocol Map for Broadcasts
    ProtocolMap-Broadcast:
      type: object
      properties:
        protocolMap:
          oneOf:  
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/ProtocolMap-BLE-Broadcast'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/ProtocolMap-Zigbee-Broadcast'

## Protocol Map for a property
    ProtocolMap-Property:
      type: object
      properties:
        protocolMap:
          oneOf:  
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/ProtocolMap-BLE-Propmap'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/ProtocolMap-Zigbee-Propmap'

## Protocol Map for an event
    ProtocolMap-Event:
      type: object
      properties:
        protocolMap:
          oneOf:  
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/ProtocolMap-BLE-Event'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/ProtocolMap-Zigbee-Event'
 
<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="protocol-map-for-ble"><name>Protocol map for BLE</name>

<figure anchor="protocolmapble"><artwork><![CDATA[
<CODE BEGINS>
file "ProtocolMap-BLE.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) BLE Protocol Mapping
  description: |-
    Non IP Device Control (NIPC) BLE Protocol Mapping. 
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

components:
  schemas:
# BLE Protocol Mapping
## A Service is a device with optional service IDs
    ProtocolMap-BLE-ServiceList:
      type: object
      properties:
        ble:
          type: object
          properties:
            services:
              type: array
              items:
                type: object
                properties:
                  serviceID:
                    type: string
                    format: uuid
                    example: 12345678-1234-5678-1234-56789abcdef4
            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

##  Protocol Mapping for BLE Service Map
    ProtocolMap-BLE-ServiceMap:
      required:
        - services
      type: object
      properties:
        ble:
          type: array
          items:
            $ref: '#/components/schemas/ProtocolMap-BLE-Service'

    ProtocolMap-BLE-Service:
      required:
        - serviceID
        - characteristics
      type: object
      properties:
        serviceID:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
        characteristics:
          type: array
          items:
            $ref: '#/components/schemas/ProtocolMap-BLE-Characteristic'

    ProtocolMap-BLE-Characteristic:
      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/ProtocolMap-BLE-Descriptor'

    ProtocolMap-BLE-Descriptor:
      required:
        - descriptorID
      type: object
      properties:
        descriptorID:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4

##  Protocol Mapping for BLE Broadcast
    ProtocolMap-BLE-Broadcast:
      required:
        - ble
      type: object
      properties:
        ble:
          type: object

## Protocol Mapping for BLE Property
    ProtocolMap-BLE-Propmap:
      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
              
## Defines different types of BLE events
    ProtocolMap-BLE-Event:
      required:
        - ble
      type: object
      properties:
        ble:
          required:
            - type
          type: object
          properties:
            type:
              type: string
              example: gatt
              enum:
                - gatt
                - connection_events
                - advertisements
            serviceID:
              type: string
              example: 12345678-1234-5678-1234-56789abcdef0
            characteristicID:
              type: string
              example: 12345678-1234-5678-1234-56789abcdef1

## BLE Error codes
    ProtocolMap-BLE-ErrorCodes:
      type: object
      properties:
        errorCode:
          type: integer
          format: int32
          enum:
            - 1011 # BLE bonding failed
            - 1013 # BLE service discovery failed
<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="protocol-map-for-zigbee"><name>Protocol map for Zigbee</name>

<figure anchor="protocolmapzigbee"><artwork><![CDATA[
<CODE BEGINS>
file "ProtocolMap-Zigbee.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) Zigbee Protocol Mapping
  description: |-
    Non IP Device Control (NIPC) Zigbee Protocol Mapping. 
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

components:
  schemas:
# Zigbee Protocol Mapping
##  Protocol Mapping for Zigbee Service Map
    ProtocolMap-Zigbee-ServiceMap:
      required:
        - zigbee
      type: object
      properties:
        zigbee:
          type: array
          items:
            $ref: '#/components/schemas/ProtocolMap-Zigbee-Endpoint'

    ProtocolMap-Zigbee-Endpoint:
      required:
        - endpointID
        - clusters
      type: object
      properties:
        endpointID:
          type: integer
          format: int32
          example: 10
        clusters:
          type: array
          items:
            $ref: '#/components/schemas/ProtocolMap-Zigbee-Cluster'

    ProtocolMap-Zigbee-Cluster:
      required:
        - clusterID
        - properties
      type: object
      properties:
        clusterID:
          type: integer
          format: int32
          example: 0
        properties:
          type: array
          items:
            $ref: '#/components/schemas/ProtocolMap-Zigbee-Property'

    ProtocolMap-Zigbee-Property:
      required:
        - propertyID
        - propertyType
      type: object
      properties:
        propertyID:
          type: integer
          format: int32
          example: 1
        propertyType:
          type: integer
          format: int32
          example: 32
          
## Protocol Mapping for Zigbee broadcast
    ProtocolMap-Zigbee-Broadcast:
      required:
        - zigbee
      type: object
      properties:
        zigbee:
          type: object

## Protocol mapping for Zigbee property
    ProtocolMap-Zigbee-Propmap:
      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

    ProtocolMap-Zigbee-Event:
      allOf:  
        - $ref: '#/components/schemas/ProtocolMap-Zigbee-Propmap'

## Zigbee Error codes
    ProtocolMap-Zigbee-ErrorCodes:
      type: object
      properties:
        errorCode:
          type: integer
          format: int32
          enum:
            - 1021 # Zigbee join failed
<CODE ENDS>
]]></artwork></figure>

</section>
</section>
<section anchor="NIPCextensions"><name>NIPC API extensions</name>

<t>The following OpenAPI models define a few example extensions to the 
NIPC API.</t>

<section anchor="nipc-api-write-binary-blob-extension"><name>NIPC API write binary blob extension</name>

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-Blob.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API write binary blob extension
  description: |-
    Non IP Device Control (NIPC) API write binary blob extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-04"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing one or more basic APIs into a single API call.

paths:
### Extensions
  /{id}/extension/property/{property}/blob:
    put:
      tags:
        - NIPC API extensions
      summary: Write a binary blob to a property on a device
      description: |-
        Write a binary blob to a property on a device. Will chunk up the binary blob and perform multiple writes. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. Id cannot be a group-id.
      operationId: writeBlob
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        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: "bin_blob"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-Blob'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '../NIPC.yaml#/components/schemas/Property'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'

components:
  schemas:
# Extensions
## A binary blob Extension
    Extension-Blob:
      required:
        - blob
      type: object
      properties:
        blob:
          type: string
          format: byte
        chunksize:
          type: integer
<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="nipc-api-bulk-operations-extension"><name>NIPC API bulk operations extension</name>

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-Bulk.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API bulk extension
  description: |-
    Non IP Device Control (NIPC) API bulk extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-04"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing one or more basic APIs into a single API call.

paths:
### Extensions
  /{id}/extension/bulk:
    post:
      tags:
        - NIPC API extensions
      summary: Compound operations on a device
      description: Compound operations on a device
      operationId: Bulk
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-Bulk'
            examples:
              bulkRequest:
                $ref: '#/components/examples/bulkRequest'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Extension-BulkResponse'
              examples:
                bulkResponse:
                  $ref: '#/components/examples/bulkResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
              examples:
                errorBulkResponse:
                  $ref: '#/components/examples/errorBulkResponse'
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'

components:
  schemas:
# Extensions
## Bulk schema Extension
    Extension-Bulk:
      type: object
      properties:
        operations:
          type: array
          items:
            $ref: '#/components/schemas/Extension-BulkOperation'

## Extension that defines an operation in a bulk API
    Extension-BulkOperation:
      required:
        - method
        - path
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
               - POST
               - PUT
               - GET
            path:
              type: string
              enum:
                - /{id}/property/{property}
                - /{id}/action/{action}
                - /{id}/extension/property/{property}/read/conditional
              example: /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              type: object
              oneOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value'
                - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-ConditionalRead'


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

## Return for an operation
    Extension-OperationResponse:
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
               - POST
               - PUT
               - GET
            path:
              type: string
              enum:
                - /{id}/property/{property}
                - /{id}/action/{action}
                - /{id}/extension/property/{property}/read/conditional'
              example: /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              anyOf:
                - allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyValue'
                - allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '../NIPC.yaml#/components/schemas/ActionValue'
                - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'

  examples:
    bulkRequest:
      summary: Bulk request example
      value:
        operations:
          - method: GET
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
          - method: PUT
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              value: dGVzdA==
          - method: POST
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/extension/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature/read/conditional
            data:
              value: dGVzdA==
              maxRepeat: 5
              frequency: 1
    bulkResponse:
      summary: Bulk response example
      value:
        operations:
          - method: GET
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              id: 12345678-1234-5678-1234-56789abcdef4
              property: >-
                https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
              value: dGVzdA==
          - method: PUT
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              id: 12345678-1234-5678-1234-56789abcdef4
              property: >-
                https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
              value: dGVzdA==
          - method: POST
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/extension/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature/read/conditional
            response:
              id: 12345678-1234-5678-1234-56789abcdef4
              property: >-
                https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
              value: dGVzdA==
    errorBulkResponse:
      summary: Error Bulk response example
      value:
        operations:
          - method: GET
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              reason: Property not readable
              errorCode: 1100
          - method: PUT
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              reason: >-
                Operation was not executed since the previous 
                operation failed
              errorCode: 1004
          - method: POST
            path: >-
              /12345678-1234-5678-1234-56789abcdef4/extension/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature/read/conditional
            response:
              reason: >-
                Operation was not executed since the previous 
                operation failed
              errorCode: 1004
<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="nipc-api-write-file-extension"><name>NIPC API write file extension</name>

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-File.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API write file extension
  description: |-
    Non IP Device Control (NIPC) API write file extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-04"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing one or more basic APIs into a single API call.

paths:
### Extensions
  /{id}/extension/property/{property}/file:
    put:
      tags:
        - NIPC API extensions
      summary: Write a file to a property on a device
      description: |-
        Write a file to a property on a device. Will chunk up the file and perform multiple writes. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. Id cannot be a group-id.
      operationId: writeFile
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        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: "firmware"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-File'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '../NIPC.yaml#/components/schemas/Property'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'

components:
  schemas:
# Extensions
## A File Extension
    Extension-File:
      required:
        - fileURL
      type: object
      properties:
        fileURL:
          type: string
          example: "https://domain.com/firmware.dat"
        chunksize:
          type: integer
<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="nipc-api-firmware-update-extension"><name>NIPC API firmware update extension</name>

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-Firmware.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API firmware upgrade extension
  description: |-
    Non IP Device Control (NIPC) API firmware upgrade extension, requires the file extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-04"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing one or more basic APIs into a single API call.

paths:
### Extensions
  /{id}/extension/firmware:
    put:
      tags:
        - NIPC API extensions
      summary: Upgrade the firmware of a device
      description: |-
        Update the firmware of a device. Will perform all operations required to upgrade the firmware. Id cannot be a group-id.
      operationId: upgradeFirmware
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: './Extension-File.yaml#/components/schemas/Extension-File'
                - $ref: '#/components/schemas/Extension-Firmware'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '#/components/schemas/Extension-UpgradeStatus'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  
    get:
      tags:
        - NIPC API extensions
      summary: Get the status of a firmware upgrade of a device
      description: |-
        Get the status of a firmware upgrade of a device. REturns success when ongoing or completed, with a reason. Returns failure when upgrade has failed. Id cannot be a group-id.
      operationId: upgradeFirmwareStatus
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '#/components/schemas/Extension-UpgradeStatus'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
  
components:
  schemas:
# Extensions
## a Firmware Extension
    Extension-Firmware:
      type: object
      properties:
        firmware:
          type: string
          enum:
            - nordic
            - silabs

## Firmware upgrade status extension
    Extension-UpgradeStatus:
      type: object
      properties:
        upgradeStatus:
          type: string
          enum:
            - started
            - completed
            - in progress
            - rolled-back
            - failed




<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="nipc-api-conditional-read-extension"><name>NIPC API conditional read extension</name>

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-ReadConditional.yaml"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API read conditional extension
  description: |-
    Non IP Device Control (NIPC) API read conditional extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-04"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing one or more basic APIs into a single API call.

paths:
### Extensions
  /{id}/extension/property/{property}/read/conditional:
    post:
      tags:
        - NIPC API extensions
      summary: Conditional read of a property
      description: Conditional read of a property
      operationId: conditionalRead
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        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: "#/sdfObject/thermostat/sdfProperty/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-ConditionalRead'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyValue'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'

components:
  schemas:
# Extensions
    Extension-ConditionalRead:
      allOf:
        - $ref: '../NIPC.yaml#/components/schemas/Value'
        - type: object
          properties:
            maxRepeat:
              description: |-
                maximum time the conditional read should repeat
                (default 5, max 60)
              type: integer
              example: 5
            frequency:
              description: |-
                time between reads in seconds (default 1, max 60)
              type: integer
              example: 1
<CODE ENDS>
]]></artwork></figure>

</section>
</section>
<section anchor="thermometer-sdf"><name>Example SDF model with protocol mappings for BLE</name>

<figure title="Example SDF model with protocol mappings for BLE"><artwork><![CDATA[
<CODE BEGINS>
file "thermometer.sdf.json"
{
    "namespace": {
        "thermometer": "https://example.com/thermometer"
    },
    "defaultNamespace": "thermometer",
    "sdfThing": {
        "thermometer": {
            "sdfObject": {
                "health_thermometer": {
                    "description": "Health Thermometer",
                    "sdfProperty": {
                        "temperature_type": {
                            "description": "Temperature Type",
                            "observable": false,
                            "writable": false,
                            "readable": true,
                            "protocolMap": {
                                "ble": {
                                    "serviceID": "1809",
                                    "characteristicID": "2A1D"
                                }
                            }
                        },
                        "measurement_interval": {
                            "description": "Measurement Interval",
                            "observable": false,
                            "writable": false,
                            "readable": true,
                            "protocolMap": {
                                "ble": {
                                    "serviceID": "1809",
                                    "characteristicID": "2A21"
                                }
                            }
                        }
                    },
                    "sdfEvent": {
                        "temperature_measurement": {
                            "description": "Temperature Measurement",
                            "sdfOutputData": {
                                "protocolMap": {
                                    "ble": {
                                        "type": "gatt",
                                        "serviceID": "1809",
                                        "characteristicID": "2A1C"
                                    }
                                }
                            }
                        },
                        "intermediate_temperature": {
                            "description": "Intermediate Temperature",
                            "sdfOutputData": {
                                "protocolMap": {
                                    "ble": {
                                        "type": "gatt",
                                        "serviceID": "1809",
                                        "characteristicID": "2A1E"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "description": "Generic Access, Device Information",
            "sdfProperty": {
                "device_name": {
                    "description": "Device Name",
                    "observable": false,
                    "writable": true,
                    "readable": true,
                    "protocolMap": {
                        "ble": {
                            "serviceID": "1800",
                            "characteristicID": "2A00"
                        }
                    }
                },
                "appearance": {
                    "description": "Appearance",
                    "observable": false,
                    "writable": false,
                    "readable": true,
                    "protocolMap": {
                        "ble": {
                            "serviceID": "1800",
                            "characteristicID": "2A01"
                        }
                    }
                },
                "manufacturer_name_string": {
                    "description": "Manufacturer Name String",
                    "observable": false,
                    "writable": false,
                    "readable": true,
                    "protocolMap": {
                        "ble": {
                            "serviceID": "180A",
                            "characteristicID": "2A29"
                        }
                    }
                },
                "model_number_string": {
                    "description": "Model Number String",
                    "observable": false,
                    "writable": false,
                    "readable": true,
                    "protocolMap": {
                        "ble": {
                            "serviceID": "180A",
                            "characteristicID": "2A24"
                        }
                    }
                },
                "hardware_revision_string": {
                    "description": "Hardware Revision String",
                    "observable": false,
                    "writable": false,
                    "readable": true,
                    "protocolMap": {
                        "ble": {
                            "serviceID": "180A",
                            "characteristicID": "2A27"
                        }
                    }
                },
                "firmware_revision_string": {
                    "description": "Firmware Revision String",
                    "observable": false,
                    "writable": false,
                    "readable": true,
                    "protocolMap": {
                        "ble": {
                            "serviceID": "180A",
                            "characteristicID": "2A26"
                        }
                    }
                },
                "system_id": {
                    "description": "System ID",
                    "observable": false,
                    "writable": false,
                    "readable": true,
                    "protocolMap": {
                        "ble": {
                            "serviceID": "180A",
                            "characteristicID": "2A23"
                        }
                    }
                }
            },
            "sdfEvent": {
                "isPresent": {
                    "description": "BLE advertisements",
                    "sdfOutputData": {
                        "protocolMap": {
                            "ble": {
                                "type": "advertisements"
                            }
                        }
                    }
                },
                "isConnected": {
                    "description": "BLE connection events",
                    "sdfOutputData": {
                        "protocolMap": {
                            "ble": {
                                "type": "connection_events"
                            }
                        }
                    }
                }
            }
        }
    }
}
<CODE ENDS>
]]></artwork></figure>

</section>


  </back>

<!-- ##markdown-source:
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
j2Ts3jLSciYYYi0qJ5jDEoVrYbm0sJTBqGtp+ceWlh4xN6O8vMfScC0MJwlD
94ceTHMeN8vFVyBfZEpTrIG7hHScA5IlIyNHSMpdTzdRqDWKKRJPm7ocadKX
78inSS+bgnHWYmZpMXMfomvWYuabi5m1kPlDCZnA8Vjur1TGqNs75hTSsFMj
CxYUNtappN2PR/7ULLRJMmT1J3eWBPkKTPeryJYJ53RyLVZ0RtdwGDcnkr7y
Gd1aiN19aAXhlCsDrE/UfgQxpA/T3OutLJtkwpIb/nfG+5LVe7KWmHqvLqam
6qvZI2Umtv0jOv/muTZxQKDXNydmlLyhyc4zHQeSGmuSV98wv0+GHRNCBxS7
vFxfiPzeJfXXNDeZctZXOb4fYe8JnxFeZ3ZV3utSsjMG0MyZvsJSCEwxWusm
xhRFwLQJhSrX6dzjwKw6phouJirSuT5k+q6D97JkqlUBFAuSD7BBEceK9Xtk
qO69UYh6xahHiCwjSn1ytFG++Emz0fJqkKff10UJvUx/LPmy5sfT0fzN+LGm
yUmHTXVubEyDO2fHKs/6jJy4+nlb7AqZ4hzzHMq8WZtWsWN6fQ1TgJW7VvkM
ufqwrhVO6fmAX2ibrm7I1WrLb4r+GKymes35WrqnTTARB3gAph2WKmk6OcTs
pG3uaJpFwiEVDzcFDNeS4VtLhjC99m3xydvTLGB9V+qW7Y6iRthCpGKppLXt
63A4aNLD1EctmYrvdeKXTLa79QcTTfeDi0+xfFa0vPDr2kb6LmSy2fSThfLK
KMQTdTmHQ3VOeS4v2XPRDWGIU942UFXZPGtvSfnZgIiX304A8wjNyNYC+FsL
4LW0XEvLtbS8Z6v5Y0jLGe4oLC4wrcIPOnRminj0NJkgqo5o9GtbcV5RtWbu
d8rc11z3ztD89bguPZoWQ7g4b8SAQCtMAWMDY8cGmMIoPe3HRcWIUNHpVxex
ylmOtViSosPRatQaeZgulqAsjqE0SKwTnaQvwkvAfki1FuQ6MGjN3GVMgobc
zLlh+Gu2vWbb35yfrHXytXS4Pzp5UDmscsv03fmBVT3lY2oSaHHJ4QYQsyeR
TMU4rZfJuN6Uo5R9cJfVziwnlowxjLKYRY7k17pjDcMul9EW/5mNVZjflam0
qGTBlGC/X3WtxLWs+pbHUX7eMHlfc6RVnR+sbB+r8KA/VoTEdxyBV4m98zRb
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

-->

</rfc>

