<?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 RFC9457 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9457.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-08" 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="July" day="01"/>

    
    
    <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 function
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 fully describes 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="protmap"><artwork><![CDATA[
     - protocolmap
        |
        |> ble
        |     - BLE property
        |
        |> zigbee
              - Zigbee property

]]></artwork></figure>

<t>As shown in <xref target="protmap"/>, 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 protocol mapping:</t>

<figure title="Example property mapping" anchor="exprotmap"><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 /devices/{id}/manage/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="management-apis"><name>Management APIs</name>

<t>Management APIs are APIs that perform device connection management and
protocol-specific operations, 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>

</section>
</section>
<section anchor="schema"><name>Schema</name>

<t>The NIPC schema leans heavily on the SDF schema, as defined in
<xref target="I-D.ietf-asdf-sdf"/>. NIPC operations map directly to SDF affordances.</t>

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

<t>In order to perform a NIPC operation on a device, an SDF interaction model 
needs to be declared that provides protcol mappings for the SDF affordances
the operations will be performed on.</t>

<t>The SDF model can be registered by means of a registration API POST with 
the SDF model in the body of hte request. A registered SDF model can be 
fetched by a registration API GET with an sdfReference.</t>

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

<t>NIPC operations require 2 key parameters:
1) A device ID identifying the device the operation should be executed on
2) an SDF reference for the SDF affordance the operations pertains to</t>

<section anchor="device-id"><name>Device ID</name>

<t>All NIPC operations are executed against a device or a group of devices.
Devices or groups of devices are identified by a unique uuid.</t>

<texttable title="Definition of a device our group of devices" anchor="devicedef">
      <ttcol align='left'>Attribute</ttcol>
      <ttcol align='left'>Req</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Example</ttcol>
      <c>id</c>
      <c>T</c>
      <c>uuid</c>
      <c>12345678-1234-5678-1234-56789abcdef4</c>
</texttable>

<t>Id is the unique uuid of the device. This id is generated when registering
the device, for example against a SCIM server. As such, this id is a common
identifier, known both to the application as well as the NIPC Server.</t>

</section>
</section>
<section anchor="sdfreferences"><name>SDFReferences</name>

<t>NIPC operations happen against SDF affordances and are referenced with an
sdfReference, which is the full path including the namespace.</t>

<t>The operations are either Properties, Events or Actions and their references
are of type string</t>

<t>For example:</t>

<texttable title="Definition of a NIPC operation on a property" anchor="nipcopsdef">
      <ttcol align='left'>Attribute</ttcol>
      <ttcol align='left'>Req</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Example</ttcol>
      <c>Property</c>
      <c>T</c>
      <c>string</c>
      <c>https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature</c>
</texttable>

</section>
<section anchor="responses"><name>Responses</name>

<t>A NIPC Gateway will respond to a NIPC operation request synchronously, and
provide the result of the completed operation in the HTTP response.</t>

<t>The exception to the above are NIPC extensions, <xref target="apiextensions"/>. These contain 
compound statements, and thus require the gateway to execute multiple
NIPC operations. In this case the NIPC gateway will return HTTP status
code 202 after receiving the request and verifying it is able to execute it.
The client can then perform an HTTP GET of the extension API to get the
execution status for the request. If a callback URL was address was defined in
the request, the NIPC Gateway can optionally perform a callback with a
response to the compound request after the compound statement completes.</t>

<t>Actions also follow an asynchronous pattern, returning HTTP status code 202
when the action is accepted, along with a Location header pointing to the
action instance for status tracking.</t>

<t>A failure response will consist of a HTTP status code of 4xx or 5xx, and 
will follow the <xref target="RFC9457"/> Problem Details format with <spanx style="verb">application/problem+json</spanx>
media type. The response will contain a <spanx style="verb">type</spanx> field with a URI identifying
the error type, and a human-readable <spanx style="verb">detail</spanx> field. The <spanx style="verb">type</spanx> field
is a URI and is 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[
{
  "type": "https://www.iana.org/assignments/http-problem-types#nipc-invalid-id",
  "status": 400,
  "title": "Invalid Device ID",
  "detail": "Device ID 12345678-1234-5678-1234-56789abcdef4 does not exist or is not a device"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"type" is a URI identifying the specific error type</t>
  <t>"status" is the HTTP status code</t>
  <t>"title" is a brief, human-readable summary of the error type</t>
  <t>"detail" is a human-readable explanation specific to this occurrence</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[
[
  {
    "sdfName": "https://example.com/heartrate#/sdfObject/healthsensor"
  }
]
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfName" is the reference to the top-level sdfThing or sdfObject 
 in 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[
[
  {
    "sdfName": "https://example.com/heartrate#/sdfObject/healthsensor"
  }
]
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfName" is the reference to the top-level sdfThing or sdfObject 
 in 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</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>sdfName: the reference to the top-level sdfThing or sdfObject 
 in the SDF model.</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</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>sdfName: the reference to the top-level sdfThing or sdfObject 
 in the SDF model.</t>
</list></t>

<t>Response:</t>

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

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

<t>where-</t>

<t><list style="symbols">
  <t>"sdfName" is the reference to the top-level sdfThing or sdfObject 
 in 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</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>sdfName: the reference to the top-level sdfThing or sdfObject 
 in the SDF model.</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[
{
  "sdfName": "https://example.com/heartrate#/sdfObject/healthsensor"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfName" is the reference to the top-level sdfThing or sdfObject 
 in 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</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>dataAppId: 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.
  <list style="symbols">
      <t>URI: the URI of the MQTT broker</t>
      <t>username: the username to authenticate with the MQTT broker</t>
      <t>password: the password to authenticate with the MQTT broker</t>
      <t>brokerCACert: the CA certificate of the MQTT broker (optional)</t>
      <t>customTopic: the custom topic to publish the streaming data to
(optional)</t>
    </list></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.
  <list style="symbols">
      <t>URI: the webhook URL</t>
      <t>headers: An object that contains the headers to be sent with the webhook
request. The headers can contain any authentication information
required by the webhook server.</t>
      <t>serverCACert: the CA certificate of the webhook server (optional)</t>
    </list></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.
  <list style="symbols">
      <t>URI: the websocket URL</t>
      <t>headers: An object that contains the headers to be sent with the websocket
request. The headers can contain any authentication information
required by the websocket server.</t>
      <t>serverCACert: the CA certificate of the websocket server (optional)</t>
    </list></t>
</list></t>

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

<figure title="Example with mqttClient" anchor="exregmqttclientrsp"><artwork><![CDATA[
{
  "events": [
    {
      "event": "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": [
    {
      "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
    }
  ],
  "mqttBroker": {
    "URI": "mqtt.example.com:1883",
    "username": "user",
    "password": "password",
    "customTopic": "custom/topic",
  }
}
]]></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</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>dataAppId: 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</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>dataAppId: 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</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>dataAppId: 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 Management APIs: These APIs allow
applications to manage device connections and perform protocol-specific
operations.</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.</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 willi
be leveraged without modifying it.</t>

<t>These APIs support multiple media types based on Content-Type and Accept
headers to accommodate different data formats.</t>

<t>When using <spanx style="verb">application/octet-stream</spanx>, the raw binary data is sent 
directly in the request/response body.
When using <spanx style="verb">application/json</spanx>, the request and response bodies follow 
the format shown in the examples above, with binary data encoded as 
base64 in the "value" field. 
For other content types, the data is transmitted according to the 
specific format requirements of that media type.</t>

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

<t>Method: <spanx style="verb">PUT /devices/{id}/properties</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[
[
  {
    "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[
[
  {
    "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>"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 /devices/{id}/properties</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>propertyName: 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[
[
  {
    "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>"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>
<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>.</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>

<t>If the data application registered for this event is an MQTT broker or 
client, the event is used to construct the MQTT topic for the event.
The topic is constructed using the data application ID, the default 
namespace for the event, and the event itself. For example, if the data 
application ID is <spanx style="verb">"12345678-1234-5678-1234-56789abcdef4"</spanx> 
and the event is 
<spanx style="verb">"https://example.com/thermometer#/sdfThing/thermometer/sdfEvent/isPresent"</spanx>,
the topic will be:</t>

<figure><artwork><![CDATA[
data-app/<dataAppId>/<namespace>/<json_pointer_to_sdf_event>

data-app/12345678-1234-5678-1234-56789abcdef4/thermometer/sdfObject/thermometer/sdfEvent/isPresent
]]></artwork></figure>

<t>A data application can subscribe to this topic using the topic or it 
can use MQTT wildcards to subscribe to <spanx style="verb">data-app/+/temperature/#</spanx> to 
receive all events for the <spanx style="verb">temperature</spanx> namespace.</t>

<t>If a custom topic is provided for an MQTT broker, the custom topic is
used as the MQTT topic instead.</t>

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

<t>Method: <spanx style="verb">POST /devices/{id}/events</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</t>
</list></t>

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>eventName: the event to enable</t>
</list></t>

<t>The eventName 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>Returns HTTP status code 201 Created with a Location header pointing to the created event instance.</t>

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

<figure><artwork><![CDATA[
HTTP/1.1 201 Created
Location: /devices/12345678-1234-5678-1234-56789abcdef4/events?instanceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>

<t>The Location header contains the URI for the created event instance, which can be used to check status or disable the event.</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 /devices/{id}/events</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>
</list></t>

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>instanceId: the instance ID of the event to disable (obtained from the Location header when the event was enabled)</t>
</list></t>

<t>Response:</t>

<t>Returns HTTP status code 204 No Content on successful disable.</t>

<figure><artwork><![CDATA[
HTTP/1.1 204 No Content
]]></artwork></figure>

<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 /devices/{id}/events</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>
</list></t>

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>instanceId: the instance ID of the event to query</t>
</list></t>

<t>Response:</t>

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

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

<t>where "event" is the event URI that was enabled for this instance.</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 /devices/{id}/events</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>instanceId: a comma separated list of event instance IDs to filter by (optional)</t>
</list></t>

<t>Response:</t>

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

<figure title="Example get multiple events status response" anchor="exgetmresp"><artwork><![CDATA[
[
  {
    "instanceId": "87654321-4321-8765-4321-fedcba9876543",
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
  }
]
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"instanceId" is the unique instance ID for each enabled event</t>
  <t>"event" is the event URI for each enabled event</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="enable-event-reporting-on-a-group-of-devices"><name>Enable event reporting on a group of devices</name>

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

<t>Description: Enables an event on a group of devices</t>

<t>Parameters:</t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>eventName: the event to enable</t>
</list></t>

<t>The eventName 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>Returns HTTP status code 201 Created with a Location header pointing to the created event instance.</t>

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

<figure><artwork><![CDATA[
HTTP/1.1 201 Created
Location: /groups/12345678-1234-5678-1234-56789abcdef4/events?instanceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>

<t>The Location header contains the URI for the created event instance, which can be used to check status or disable the event.</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-on-a-group-of-devices"><name>Disable event reporting on a group of devices</name>

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

<t>Description: Disables an event on a group of devices</t>

<t>Parameters:</t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>instanceId: the instance ID of the event to disable (obtained from the Location header when the event was enabled)</t>
</list></t>

<t>Response:</t>

<t>Returns HTTP status code 204 No Content on successful disable.</t>

<figure><artwork><![CDATA[
HTTP/1.1 204 No Content
]]></artwork></figure>

<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-on-a-group-of-devices"><name>Get event status on a group of devices</name>

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

<t>Description: Get the status of an event on a group of devices</t>

<t>Parameters:</t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>instanceId: the instance ID of the event to check</t>
</list></t>

<t>Response:</t>

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

<figure title="Example get group event status response" anchor="exgetgevntresp"><artwork><![CDATA[
{
  "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
}
]]></artwork></figure>

<t>where "event" is the event URI that was enabled for this instance.</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-on-a-group-of-devices"><name>Get status of multiple events on a group of devices</name>

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>instanceId: a comma separated list of event instance IDs to filter by (optional)</t>
</list></t>

<t>Response:</t>

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

<figure title="Example get multiple group events status response" anchor="exgetmgevntsresp"><artwork><![CDATA[
[
  {
    "instanceId": "87654321-4321-8765-4321-fedcba9876543",
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
  }
]
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"instanceId" is the unique instance ID for each enabled event</t>
  <t>"event" is the event URI for each enabled event</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">POST /devices/{id}/actions</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>
</list></t>

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>actionName: the action to perform</t>
</list></t>

<t>Request Body:</t>

<t>The request body is optional and can contain binary data if the underlying protocol 
allows an action with a value.</t>

<t>Response:</t>

<t>Actions are performed asynchronously. A successful request returns HTTP status code 202 Accepted 
with a Location header pointing to the action instance for status checking.</t>

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

<figure><artwork><![CDATA[
HTTP/1.1 202 Accepted
Location: /devices/12345678-1234-5678-1234-56789abcdef4/actions?instanceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>

<t>The Location header contains the URI for the action instance, which can be used to check the action status.</t>

</section>
<section anchor="check-action-status"><name>Check action status</name>

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

<t>Description: Check the status of an action on a specific 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>instanceId: the instance ID of the action (obtained from the Location header)</t>
</list></t>

<t>Response:</t>

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

<figure title="Example action status response" anchor="exactionstatusresp"><artwork><![CDATA[
{
  "status": "COMPLETED"
}
]]></artwork></figure>

<t>where "status" indicates the current state of the action (e.g., "IN_PROGRESS" or "COMPLETED").</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-management-apis"><name>NIPC Management APIs</name>

<t>These APIs allow applications to manage device connections, 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 /devices/{id}/manage/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 /devices/{id}/manage/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 /devices/{id}/manage/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>Returns HTTP status code 200 OK with device ID on successful disconnect.</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 "id" is the id of the device.</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 /devices/{id}/manage/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>
</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
properties 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="apiextensions"><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>

<t>The extensions can contain long running operations, such as firmware updates,
or other bulk operations that can be performed on a device. For long 
running operations, the extension API will return a 202 Accepted status 
code and a location header with the URL to check the status of the operation.
The status of the operation can be checked by calling the status extension API
with the same device ID. The status extension API will return a 200 OK status code
when the operation is in progress. When the operation is complete, 
the status extension API will return a 303 See Other status code with a 
location header with the URL to check the status of the operation.
The GET operation on the extension API will return a 200 OK status code
with the actual response once the operation is complete.</t>

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

<t>The error codes in the NIPC APIs use URI-based error type identifiers 
as defined in <xref target="RFC9457"/> Problem Details for HTTP APIs. The error codes 
can be generic or specific to the API category. The error codes are 
organized into the following categories:</t>

<t><list style="symbols">
  <t>Generic: Broadly applicable errors, including authorization, 
invalid identifiers, and generic failures.</t>
  <t>Property APIs: Errors related to property APIs (read/write).</t>
  <t>Event APIs: Errors related to event APIs (enable/disable).</t>
  <t>Protocol specific: Errors related to protocol-specific operations.</t>
  <t>Extension APIs: Errors related to extension APIs.</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>nipc-invalid-id</c>
      <c>Invalid device ID or gateway doesn't recognize the ID</c>
      <c>Generic</c>
      <c>nipc-invalid-sdf-url</c>
      <c>Invalid SDF URL or SDF affordance not found</c>
      <c>Generic</c>
      <c>nipc-extension-operation-not-executed</c>
      <c>Operation was not executed since the previous operation failed</c>
      <c>Generic</c>
      <c>nipc-sdf-model-already-registered</c>
      <c>SDF model already registered</c>
      <c>Generic</c>
      <c>nipc-sdf-model-in-use</c>
      <c>SDF model in use</c>
      <c>Generic</c>
      <c>nipc-property-not-readable</c>
      <c>Property not readable</c>
      <c>Property APIs</c>
      <c>nipc-property-not-writable</c>
      <c>Property not writable</c>
      <c>Property APIs</c>
      <c>nipc-event-already-enabled</c>
      <c>Event already enabled</c>
      <c>Event APIs</c>
      <c>nipc-event-not-enabled</c>
      <c>Event not enabled</c>
      <c>Event APIs</c>
      <c>nipc-event-not-registered</c>
      <c>Event not registered for any data application</c>
      <c>Event APIs</c>
      <c>nipc-protocolmap-ble-already-connected</c>
      <c>Device already connected</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-ble-no-connection</c>
      <c>No connection found for device</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-ble-connection-timeout</c>
      <c>BLE connection timeout</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-ble-bonding-failed</c>
      <c>BLE bonding failed</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-ble-connection-failed</c>
      <c>BLE connection failed</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-ble-service-discovery-failed</c>
      <c>BLE service discovery failed</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-ble-invalid-service-or-characteristic</c>
      <c>Invalid BLE service or characteristic ID</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-zigbee-connection-timeout</c>
      <c>Zigbee connection timeout</c>
      <c>Protocol specific</c>
      <c>nipc-protocolmap-zigbee-invalid-endpoint-or-cluster</c>
      <c>Invalid Zigbee endpoint or cluster ID</c>
      <c>Protocol specific</c>
      <c>nipc-extension-broadcast-invalid-data</c>
      <c>Invalid transmit data</c>
      <c>Transmit APIs</c>
      <c>nipc-extension-firmware-rollback</c>
      <c>Firmware rollback</c>
      <c>Extension APIs</c>
      <c>nipc-extension-firmware-update-failed</c>
      <c>Firmware update failed</c>
      <c>Extension 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

{
  "sdfName": "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 /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/device_name
Accept: application/json
Host: localhost
    
HTTP/1.1 200 OK
content-type: application/json
    
[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
]]></artwork></figure>
  </t>
  <t>Write to a property on the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
PUT /devices/12345678-1234-5678-1234-56789abcdef4/properties
Content-Type: application/json
Host: localhost
    
[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
    
HTTP/1.1 200 OK
content-type: application/json
    
[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
]]></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

[
  {
    "sdfName": "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?dataAppId=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

{
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEvent/isPresent"
  ],
  "mqttClient": {}
}
]]></artwork></figure>
  </t>
  <t>Enable the advertisement event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
POST /devices/12345678-1234-5678-1234-56789abcdef4/events?eventName=https://example.com/thermometer%23/sdfThing/thermometer/sdfEvent/isPresent
Host: localhost
Content-Length: 0
    
HTTP/1.1 201 Created
Location: /devices/12345678-1234-5678-1234-56789abcdef4/events?instanceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>
  </t>
  <t>Check the status of the event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
GET /devices/12345678-1234-5678-1234-56789abcdef4/events?instanceId=87654321-4321-8765-4321-fedcba9876543
Host: localhost
    
HTTP/1.1 200 OK
content-type: application/json
    
{
  "event": "https://example.com/thermometer#/sdfThing/thermometer/sdfEvent/isPresent"
}
]]></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"><name>API extensions</name>

</section>
<section anchor="well-known-uris"><name>Well-known URIs</name>

</section>
<section anchor="problem-details-for-http-apis"><name>Problem Details for HTTP APIs</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;
&RFC9457;
&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 2114?>

<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"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
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.4
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-07"
    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 management APIs
    description: |-
      APIs that manage device connections.
  - name: NIPC registration APIs
    description: |-
      APIs that register sdf models or data applications

paths:
### NIPC Property APIs
  /devices/{id}/properties:
    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: The ID of the device. 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
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/PropertyValueResponseArray'
        default:
          description: Error response
          content:
            application/problem+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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: Properties to be read
        required: true
        allowReserved: true
        schema:
          type: array
          items:
            type: string
            example: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValueResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
 
 ### NIPC Event APIs
  /devices/{id}/events:
    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: eventName
        in: query
        description: event that needs to be enabled
        required: true
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '201':
          description: Success
          headers:
            Location:
              description: Location of the created event
              schema:
                type: string
                format: uri
                example: "/devices/{id}/events?instanceId={instanceId}"
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    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: instanceId
        in: query
        description: instance id of the event that needs to be disabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
               
    get:
      tags:
        - NIPC event APIs
      summary: Get status of events on a device
      description: |-
        Get status of an event or multiple events on a specific device
      operationId: GetEvents
      parameters:
      - name: id
        in: path
        description: The ID of the device.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: Instance ID of the events that need to be filtered
        required: false
        schema:
          type: array
          items:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventStatusResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /groups/{id}/events:
    post:
      tags:
        - NIPC event APIs
      summary: Enable an event on a group of devices
      description: |-
        Enable an event on 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: EnableGroupEvent
      parameters:
      - name: id
        in: path
        description: group id for which the event needs to be enabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: eventName
        in: query
        description: event that needs to be enabled
        required: true
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '201':
          description: Success, event enabled
          headers:
            Location:
              description: Location of the created event
              schema:
                type: string
                format: uri
                example: "/groups/{id}/events?instanceId={instanceId}"
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
    delete:
      tags:
        - NIPC event APIs
      summary: Disable an event on a group of devices
      description: |-
        Disable an event on 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: DisableGroupEvent
      parameters:
      - name: id
        in: path
        description: group id for which the event needs to be disabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: instance id of the event that needs to be disabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
    get:
      tags:
        - NIPC event APIs
      summary: Get status of events on a group of devices
      description: |-
        Get status of an event or multiple events on a group of devices.
      operationId: GetGroupEvents
      parameters:
      - name: id
        in: path
        description: group id of the SCIM group
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: Instance IDs of the events that need to be filtered
        required: false
        schema:
          type: array
          items:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, events retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventStatusResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

### NIPC action APIs
  /devices/{id}/actions:
    post:
      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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: actionName
        in: query
        description: action that needs to be performed
        required: true
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfAction/start"
      requestBody:
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
        required: false
      responses:
        '202':
          description: Accepted, action is being performed
          headers:
            Location:
              description: Location of the action
              schema:
                type: string
                format: uri
                example: "/devices/{id}/actions?instanceId={instanceId}"
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
    get:
      tags:
        - NIPC action APIs
      summary: Get status of an action on a device
      description: |-
        Get status of an action on a specific device or a group of devices. Success is action is active, failure if action not active.
      operationId: GetAction
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: instance id of the action that needs to be checked
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, action is active
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionResponse'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
               
  /devices/{id}/manage/connection:
    post:
      tags:
        - NIPC management APIs
      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: The ID of the device. Group ID is 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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
  
    put:
      tags:
        - NIPC management APIs
      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: The ID of the device. Group ID is 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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
  
    delete:
      tags:
        - NIPC management APIs
      summary: Disconnect a device 
      description: |-
        Disconnect a device.
      operationId: ActionDeleteConnection
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
                  
    get:
      tags:
        - NIPC management APIs
      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: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'


### 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
          content:
            application/json:
              schema:
                type: array
                items:
                  allOf:
                    - $ref: '#/components/schemas/SdfReference'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - NIPC registration APIs
      summary: Get all registered SDF model names
      description: |-
        Get all registered SDF model names.
      operationId: getSdfRefs
      parameters:
        - name: sdfName
          in: query
          description: sdfName can be a reference to an sdfThing or sdfObject
          required: false
          allowReserved: true
          schema:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healthsensor"
      responses:
        '200':
          description: Success
          content:
            application/sdf+json:
              schema:
                $ref: '#/components/schemas/SdfModel'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'
    put:
      tags:
        - NIPC registration APIs
      summary: Update an SDF model
      description: |-
        Update an SDF model, including Properties, Events and actions
      operationId: updateSdf
      parameters:
        - name: sdfName
          in: query
          description: sdfName can be a reference to an sdfThing or sdfObject
          required: true
          allowReserved: 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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfReference'
        default:
          description: Error response
          content:
            application/problem+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: sdfName
          in: path
          description: sdfObject name
          required: true
          schema:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healthsensor"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfReference'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

  /registration/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: dataAppId
          in: query
          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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+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: dataAppId
          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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+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: dataAppId
          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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+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: dataAppId
          in: query
          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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+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"

    ActionResponse:
      required:
        - action
      type: object
      properties:
        status:
          type: string
          example: COMPLETED
          description: Status of the action, can be IN_PROGRESS or COMPLETED

## 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'

## An array of Property values
    PropertyValueArray:
      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

    InstanceId:
      type: object
      properties:
        instanceId:
          type: string
          format: uuid
          description: A SCIM-generated UUID for the event instance
          example: 12345678-1234-5678-1234-56789abcdef4
            
## A Connection
    Connection:
      type: object
      properties:
        retries:
          type: integer
          format: int32
          example: 3
        retryMultipleAPs:
          type: boolean
          example: true
          
 ## 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
          required:
            - URI
            - username
            - password
          properties: 
            URI: 
              type: string
              example: mqtt.broker.com:8883
            username:
              type: string
              example: user1
            password: 
              type: string
              example: password1
            brokerCACert:
              description: PEM encoded CA certificate
              type: string
            customTopic:
              type: string
              description: custom MQTT topic to publish to
              example: custom/topic
      
    DataAppWebhook:
      type: object
      properties: 
        webhook:
          type: object
          properties: 
            URI: 
              type: string
              example: webhook.com:443
            headers:
              type: object
              additionalProperties:
                type: string
              example:
                x-api-key: fjelk-3dl33f-2wdsd
            serverCACert: 
              type: string 
          
    DataAppWebsocket:
      type: object
      properties: 
        websocket:
          type: object
          properties: 
            URI: 
              type: string
              example: websocket.com:443
            headers:
              type: object
              additionalProperties:
                type: string
              example:
                x-api-key: fjelk-3dl33f-2wdsd
            serverCACert: 
              type: string 

 ## sdfObject registration definition
    SdfReference:
      type: object
      description: SDF URL referring to the sdfobject
      properties: 
        sdfName:
          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

    SuccessResponse:
      type: object
      properties:
        status:
          type: integer
          format: int32
          example: 200
          description: HTTP status code

## Error 500 application Failure response
    FailureResponse:
      type: object
      properties:
        type:
          type: string
          description: URI to the error type
          enum:
            - https://www.iana.org/assignments/http-problem-types#nipc-invalid-id
            - https://www.iana.org/assignments/http-problem-types#nipc-invalid-sdf-url
            - https://www.iana.org/assignments/http-problem-types#nipc-extension-operation-not-executed
            - https://www.iana.org/assignments/http-problem-types#nipc-sdf-model-already-registered
            - https://www.iana.org/assignments/http-problem-types#nipc-sdf-model-in-use
            - https://www.iana.org/assignments/http-problem-types#nipc-property-not-readable
            - https://www.iana.org/assignments/http-problem-types#nipc-property-not-writable
            - https://www.iana.org/assignments/http-problem-types#nipc-event-already-enabled
            - https://www.iana.org/assignments/http-problem-types#nipc-event-not-enabled
            - https://www.iana.org/assignments/http-problem-types#nipc-event-not-registered
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-already-connected
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-no-connection
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-connection-timeout
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-bonding-failed
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-connection-failed
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-service-discovery-failed
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-invalid-service-or-characteristic
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-zigbee-connection-timeout
            - https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-zigbee-invalid-endpoint-or-cluster
            - https://www.iana.org/assignments/http-problem-types#nipc-extension-broadcast-invalid-data
            - https://www.iana.org/assignments/http-problem-types#nipc-extension-firmware-rollback
            - https://www.iana.org/assignments/http-problem-types#nipc-extension-firmware-update-failed
            - about:blank
        status:
          type: integer
          format: int32
          example: 400
          description: HTTP status code
        title:
          type: string
          example: Invalid Device ID
          description: Human-readable error title
        detail:
          type: string
          example: Device ID 12345678-1234-5678-1234-56789abcdef4 does not exist or is not a device
          description: Human-readable error message  

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

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

    EventStatusResponseArray:
      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.4
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.4
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:
        nipcStatus:
          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.4
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:
        nipcStatus:
          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"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
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.4
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-07"
    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
  /extensions/{id}/properties/{propertyName}/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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: path
        description: The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "bin_blob"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-Blob'
        required: true
      responses:
        '204':
          description: Success, no content
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 

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"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
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.4
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-07"
    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
  /extensions/{id}/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: The ID of the device. 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:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
              description: URL to get the bulk status response
              example: /extensions/12345678-1234-5678-1234-56789abcdef4/bulk/status?requestId=12345678-1234-5678-1234-56789abcdef4
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
      callbacks:
        bulkEvent:
          '{$request.body#/callback.url}':
            post:
              description: Callback for bulk response
              operationId: bulkCallback
              requestBody:
                content:
                  application/json:
                    schema:
                      allOf:
                        - $ref: '../NIPC.yaml#/components/schemas/Id'
                        - $ref: '#/components/schemas/Extension-BulkResponse'
              responses:
                '200':
                  description: OK
                '400':
                  description: Bad request
                '401':
                  description: Unauthorized
                '405':
                  description: Invalid request
                '500':
                  description: Server-side failure
    get:
      tags:
        - NIPC API extensions
      summary: Get Bulk response
      description: Get Bulk response
      operationId: getBulkResponse
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the bulk operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '#/components/schemas/Extension-BulkResponse'
              examples:
                bulkResponse:
                  $ref: '#/components/examples/bulkResponse'
                errorBulkResponse:
                  $ref: '#/components/examples/errorBulkResponse'
                
  /extensions/{id}/bulk/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Bulk status
      description: Get Bulk status
      operationId: getBulkStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the bulk operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
              description: URL to get the bulk response
              example: /extensions/12345678-1234-5678-1234-56789abcdef4/bulk?requestId=12345678-1234-5678-1234-56789abcdef4
          content:
            application/json:
              schema:
                allOf:
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
              examples:
                successExample:
                  summary: Success
                  value:
                    status: COMPLETED

components:
  schemas:
# Extensions
## Bulk schema Extension
    Extension-Bulk:
      allOf:
        - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-Callback'
        - 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:
                - /devices/{id}/properties?propertyName={propertyName}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?propertyName={propertyName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            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:
                - /devices/{id}/properties?propertyName={propertyName}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?propertyName={propertyName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              anyOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value'
                - $ref: '../NIPC.yaml#/components/schemas/SuccessResponse'
                - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'

  examples:
    bulkRequest:
      summary: Bulk request example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            data:
              value: dGVzdA==
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/read/conditional?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            data:
              value: dGVzdA==
              maxRepeat: 5
              retryTime: 1
    bulkResponse:
      summary: Bulk response example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              value: dGVzdA==
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              status: 200
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/read/conditional?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              value: dGVzdA==
    errorBulkResponse:
      summary: Error Bulk response example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-property-not-readable
              status: 400
              title: Property not readable
              detail: Property https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/temperature is not readable
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-extension-operation-not-executed
              status: 400
              title: Operation not executed
              detail: Operation was not executed since the previous operation failed
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/read/conditional?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-extension-operation-not-executed
              status: 400
              title: Operation not executed
              detail: Operation was not executed since the previous operation failed
<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"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
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.4
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-07"
    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
  /extensions/{id}/properties/{propertyName}/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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: path
        description: The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "firmware"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-File'
        required: true
      responses:
        '204':
          description: Success, no content
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 

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"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
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.4
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-07"
    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
  /extensions/{id}/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: The ID of the device. 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'
                - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-Callback'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
              description: Location of the resource
              example: /12345678-1234-5678-1234-56789abcdef4/extension/firmware/status?requestId=12345678-1234-5678-1234-56789abcdef4
        default:
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
      callbacks:
        bulkEvent:
          '{$request.body#/callback.url}':
            post:
              description: Callback for bulk response
              operationId: bulkCallback
              requestBody:
                content:
                  application/json:
                    schema:
                      anyOf:
                        - $ref: '../NIPC.yaml#/components/schemas/Id'
                        - allOf:
                          - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                          - $ref: '#/components/schemas/ExtensionErrorCodes'
              responses:
                '200':
                  description: OK
                '400':
                  description: Bad request
                '401':
                  description: Unauthorized
                '405':
                  description: Invalid request
                '500':
                  description: Server-side failure
                  
    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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the firmware upgrade operation
        required: true
        schema:
          type: string
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
            Location:
              schema:
                type: string
              description: Location of the resource
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/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: '../NIPC.yaml#/components/schemas/FailureResponse'
                  - $ref: '#/components/schemas/ExtensionErrorCodes'
  /extensions/{id}/firmware/status:
    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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the firmware upgrade operation
        required: true
        schema:
          type: string
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
              description: URL to get the firmware response
              example: /12345678-1234-5678-1234-56789abcdef4/extension/firmware?requestId=12345678-1234-5678-1234-56789abcdef4
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

components:
  schemas:
# Extensions
## a Firmware Extension
    Extension-Firmware:
      type: object
      properties:
        firmware:
          type: string
          enum:
            - nordic
            - silabs

    ExtensionErrorCodes:
      type: object
      properties:
        nipcStatus:
          type: integer
          format: int32
          enum:
            - 1600 # Firmware rollback
            - 1601 # Firmware update 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"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
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.4
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-07"
    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
  /extensions/{id}/properties/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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: The SDF property name that needs to be read conditionally.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-ConditionalRead'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
              description: URL to get the conditional read status
              example: /12345678-1234-5678-1234-56789abcdef4/extension/property/temperature/read/conditional/status?requestId=12345678-1234-5678-1234-56789abcdef4
            Retry-After:
              schema:
                type: integer
              description: Time in seconds to wait before retrying
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
      callbacks:
        callbackEvent:
          "{$request.body#/callback.url}":
            post:
              requestBody:
                content:
                  application/json:
                    schema:
                      anyOf:
                        - allOf:
                          - $ref: '../NIPC.yaml#/components/schemas/Id'
                          - $ref: '../NIPC.yaml#/components/schemas/PropertyValue'
                        - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          property: https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature
                          value: dGVzdA==
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          status: 400
                          nipcStatus: 1000
                          detail: "Invalid request"
                          property: https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature
                          value: dGVzdA==
                          
              responses:
                '200':
                  description: Success
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional read response of a property
      description: Conditional read response of a property
      operationId: getConditionalRead
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: The SDF property name that needs to be read conditionally.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - name: requestId
        in: query
        description: Request ID of the conditional read operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Value'
            application/octet-stream:
              schema:
                type: string
                format: binary
              description: Binary data of the property value
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
  /extensions/{id}/properties/read/conditional/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional read status of a property
      description: Conditional read status of a property
      operationId: getConditionalReadStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: The SDF property name that needs to be read conditionally.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - name: requestId
        in: query
        description: Request ID of the conditional read operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Extension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
              description: URL to get the conditional read response
              example: /12345678-1234-5678-1234-56789abcdef4/extension/property/temperature/read/conditional?requestId=12345678-1234-5678-1234-56789abcdef4
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Extension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

components:
  schemas:
# Extensions
    Extension-Callback:
      type: object
      properties:
        callback:
          type: object
          properties:
            url:
              description: |-
                URL to send the callback to
                (default is the same as the request URL)
              type: string
              example: "http://localhost:8080/callback"
            headers:
              description: |-
                Headers to include in the callback
                (default is empty)
              type: object
              example:
                x-api-key: "1234567890"
              additionalProperties:
                type: string

    Extension-StatusResponse:
      type: object
      properties:
        status:
          description: |-
            Status of the callback
          type: string
          enum:
            - IN_PROGRESS
            - COMPLETED

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

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

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-Property.yaml"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
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.4
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-07"
    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
  /extensions/{id}/manage/transmit:
    post:
      tags:
        - NIPC API extensions
      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: The ID of the device. 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/Transmit'
        required: true
      responses:
        '200':
          description: Success
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
   
  /extensions/{id}/properties/write:
    post:
      tags:
        - NIPC API extensions
      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: The ID of the device. 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: '../NIPC.yaml#/components/schemas/Value' 
                - $ref: '../protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
        required: true
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                
  /extensions/{id}/properties/read:
    post:
      tags:
        - NIPC API extensions
      summary: Read 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: The ID of the device. Group ID is 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
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Value'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'

components:
  schemas:
    Transmit:
      allOf:
        - $ref: '../protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Broadcast'
      required:
        - cycle
      type: object
      properties:
        cycle:
          type: string
          example: single
          enum:
            - single
            - repeat
        # transmit time in ms
        transmitTime:
          type: integer
          example: 3000
        # interval between transmits in ms
        transmitInterval:
          type: integer
          example: 500
        payload:
          type: string
          format: byte
          example: AgEaAgoMFv9MABAHch9BsDkgeA==
<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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
MA2BeFEV92lKFTBVqVa0tkrCnrKFUqPFEjPz8dE/0OGw24uBIa407IDtCxN4
7b7JgFGD3pi6+9YPn6yS/+ZuKdyyMzwkKLIKDNzjU65QXIIGvHn8qG4pj51e
L99K8qado5ruB2k6joKkrpsSU4k1TnybB5bfVZ9wsLoTCmn7VleM70oxrIav
svRjlC3Y8LdocJamHxdvlafDj5Ge5iKHvQbqHTItzc0whA6S1jYYUHbDPFP4
Z1JpWWldHohBf5OB3JYNrfGnSm55t359f1B6Msux+K1jRyWWKsjzizSzCUbt
rPAHOq1UQmpJp6GPCK6oP6AlIS3dfvHixWPnWzW3MrPepXNsu+W8VEu60VxV
Y7dLnvzuzi7ApTxJt4DX/ltfXT+7O/4Q4ThCISbqOpfhLC/SyUk6jYcLgMOZ
BHfhv/33kxO49qAjqmGP5eTzM/i1aencbINayDc2RgtNWBSdL9xmDU0bm+PP
TfFOhiace/LERbna7DONU8OfIAyp4nkwPqqhYQvMq9Lmj14wjXsfo8ttf/T3
aPyx9zgcP3486j26CHNX2cB1pQUP20BivyttIpPoG2yj27AFWnexkTz4n3Mr
iacw3jCO6o9yPsSas7LdOFq22JXzgCX+9f0b9uijEYVXhiHnI4b49dyNcF11
uFGrfGtCGmqkr4a9d5dNY1ccNksLdTaGXKWnwbDhovrMuKYhNkdicRqKiu5d
+0raj2O1516Zr+3gbkTeot8t0oKRQszsqofOWG62uzgzi6vVpZS67raNN8qa
cWxURi1pM5qaCoe7cLudeXk65u1AFSmcvlQi3GM6uBV9rUy8Cqs4P8qivPYV
NTucFdMZWRjqPvB1gpu3wbT+A+Dk6k6S+hGxIzzH/c0pILM6d4ZB7XHUtKph
/mUdZ6UDOc8NE+ywvDkL9FXU5sHeDWR592d4FmTBsIgyTLU5vEWHzfiAP7Y2
pWlhHVADfzrBby4ElwnD5UJxx1GplF5jFspvGrHUreCezwWuhfk69rrDf8OL
4cbXws0uhRtcCbWUvY3ItRK4VuI2F/9acG85eLeUY9hMyOYRsc9wty3rfC4L
Uk3EqpFQfbVIoghT+XAsQJpKhs8G4lR3+mrJkytu1trJlxZuX0fHmkhLPYVo
3fiGTb/9ht8az9W2OyRh6XteITj1G/5AQC4Z2ZW3DEr5VlBwtTZTo2DbJCLP
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

-->

</rfc>

