<?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.29 (Ruby 3.4.7) -->


<!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 I-D.ietf-asdf-sdf SYSTEM "https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-asdf-sdf.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-protocol-mapping SYSTEM "https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-asdf-sdf-protocol-mapping.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 RFC6570 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6570.xml">
<!ENTITY RFC9562 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9562.xml">
<!ENTITY RFC9457 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9457.xml">
<!ENTITY RFC7468 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7468.xml">
<!ENTITY RFC4648 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.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">
<!ENTITY RFC8615 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8615.xml">
]>


<rfc ipr="trust200902" docName="draft-ietf-asdf-nipc-14" 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="November" day="02"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 61?>

<t>This memo describes an API that allows applications to perform operations against a gateway serving one or more devices described by an SDF model. The document describes a RESTful application layer interface to perform operations on those devices, as well as a CBOR-based publish-subscribe interface for streaming data.</t>



    </abstract>



  </front>

  <middle>


<?line 65?>

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

<section anchor="motivation"><name>Motivation</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. Prominent examples of such protocols are <xref target="BLE53"/> and
<xref target="Zigbee22"/>. These devices typically need 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 function 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"><artset><artwork  type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="688" viewBox="0 0 688 144" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
<path d="M 8,48 L 8,96" fill="none" stroke="black"/>
<path d="M 120,48 L 120,96" fill="none" stroke="black"/>
<path d="M 240,48 L 240,96" fill="none" stroke="black"/>
<path d="M 320,48 L 320,96" fill="none" stroke="black"/>
<path d="M 440,48 L 440,96" fill="none" stroke="black"/>
<path d="M 512,48 L 512,96" fill="none" stroke="black"/>
<path d="M 8,48 L 120,48" fill="none" stroke="black"/>
<path d="M 240,48 L 320,48" fill="none" stroke="black"/>
<path d="M 440,48 L 512,48" fill="none" stroke="black"/>
<path d="M 128,64 L 232,64" fill="none" stroke="black"/>
<path d="M 328,64 L 432,64" fill="none" stroke="black"/>
<path d="M 8,96 L 120,96" fill="none" stroke="black"/>
<path d="M 240,96 L 320,96" fill="none" stroke="black"/>
<path d="M 440,96 L 512,96" fill="none" stroke="black"/>
<polygon class="arrowhead" points="440,64 428,58.4 428,69.6" fill="black" transform="rotate(0,432,64)"/>
<polygon class="arrowhead" points="336,64 324,58.4 324,69.6" fill="black" transform="rotate(180,328,64)"/>
<polygon class="arrowhead" points="240,64 228,58.4 228,69.6" fill="black" transform="rotate(0,232,64)"/>
<polygon class="arrowhead" points="136,64 124,58.4 124,69.6" fill="black" transform="rotate(180,128,64)"/>
<g class="text">
<text x="64" y="68">Application</text>
<text x="280" y="68">Gateway</text>
<text x="476" y="68">Non-IP</text>
<text x="180" y="84">IP-based</text>
<text x="380" y="84">Non-IP</text>
<text x="476" y="84">Device</text>
<text x="184" y="100">Operation</text>
<text x="384" y="100">Operation</text>
</g>
</svg>
</artwork><artwork  type="ascii-art"><![CDATA[
                                                               
    +-------------+              +---------+              +--------+
    | Application |<------------>| Gateway |<------------>| Non-IP |                     
    |             |   IP-based   |         |    Non-IP    | Device |
    +-------------+   Operation  +---------+   Operation  +--------+                 

]]></artwork></artset></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. The implication of this is
that every use case deployment requires implementation of a new API, and possibly
requires its own gateway, which results in proliferation of network infrastructure.
This specification aims to define a Gateway API for these Non-IP protocols
that can be leveraged by a Network Gateway connected to a wireless network. 
The API aims to enable a Gateway to support any non-IP protocol. The gateway
can simultaneously support multiple applications and multiple non-IP protocols
as well as different versions of the same protocol. The specification is
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 applications to perform new and bespoke integrations for
different environments.</t>
  <t>Avoid having to deploy multiple Gateway functions to support multiple non-IP use cases.</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 is an application layer gateway that allows Applications on IP networks to communicate with Non-IP devices leveraging NIPC APIs.
NIPC APIs consist of reading or writing properties of devices, performing actions on devices, as well as enabling or disabling events on devices.</t>

<t>In order to perform NIPC operations on a device, 2 prerequisites must be fulfilled:
- The device must be onboarded on the gateway. Onboarding declares a device instance to the gateway. This allows the NIPC Gateway to retrieve the device object, identified by an id referenced in the path of the NIPC API. 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"/>.
- An interaction model for the class of devices must be registered with the gateway. This allows the gateway to understand how to interact with the device in a protocol-neutral way. The interaction model is provided to the gateway by means of an SDF model, described in <xref target="I-D.ietf-asdf-sdf"/>.</t>

<t>A non-IP gateway provides 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.</t>
  <t>The ability to consume an interaction model for a class of devices.</t>
  <t>An API that allows for reading or writing properties of devices, performing actions on devices, as well as enabling or disabling events on devices.</t>
  <t>The ability to manage connections to Non-IP devices, either implicitly
when performing a NIPC operation, or explicitly by means of a connection
management API.</t>
  <t>The ability to stream events from Non-IP devices to applications on the IP network
by means of a publish/subscribe interface.</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>
</list></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"><artset><artwork  type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="288" width="560" viewBox="0 0 560 288" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
<path d="M 8,64 L 8,112" fill="none" stroke="black"/>
<path d="M 8,144 L 8,224" fill="none" stroke="black"/>
<path d="M 104,64 L 104,112" fill="none" stroke="black"/>
<path d="M 104,144 L 104,224" fill="none" stroke="black"/>
<path d="M 208,32 L 208,72" fill="none" stroke="black"/>
<path d="M 208,104 L 208,152" fill="none" stroke="black"/>
<path d="M 208,200 L 208,256" fill="none" stroke="black"/>
<path d="M 232,64 L 232,112" fill="none" stroke="black"/>
<path d="M 232,144 L 232,208" fill="none" stroke="black"/>
<path d="M 312,64 L 312,112" fill="none" stroke="black"/>
<path d="M 336,144 L 336,208" fill="none" stroke="black"/>
<path d="M 368,144 L 368,176" fill="none" stroke="black"/>
<path d="M 432,144 L 432,176" fill="none" stroke="black"/>
<path d="M 464,144 L 464,176" fill="none" stroke="black"/>
<path d="M 536,144 L 536,176" fill="none" stroke="black"/>
<path d="M 552,32 L 552,256" fill="none" stroke="black"/>
<path d="M 208,32 L 552,32" fill="none" stroke="black"/>
<path d="M 8,64 L 104,64" fill="none" stroke="black"/>
<path d="M 232,64 L 312,64" fill="none" stroke="black"/>
<path d="M 104,80 L 224,80" fill="none" stroke="black"/>
<path d="M 112,96 L 232,96" fill="none" stroke="black"/>
<path d="M 8,112 L 104,112" fill="none" stroke="black"/>
<path d="M 232,112 L 312,112" fill="none" stroke="black"/>
<path d="M 8,144 L 104,144" fill="none" stroke="black"/>
<path d="M 232,144 L 336,144" fill="none" stroke="black"/>
<path d="M 368,144 L 432,144" fill="none" stroke="black"/>
<path d="M 464,144 L 536,144" fill="none" stroke="black"/>
<path d="M 104,160 L 136,160" fill="none" stroke="black"/>
<path d="M 176,160 L 224,160" fill="none" stroke="black"/>
<path d="M 336,160 L 360,160" fill="none" stroke="black"/>
<path d="M 432,160 L 456,160" fill="none" stroke="black"/>
<path d="M 368,176 L 432,176" fill="none" stroke="black"/>
<path d="M 464,176 L 536,176" fill="none" stroke="black"/>
<path d="M 112,192 L 128,192" fill="none" stroke="black"/>
<path d="M 192,192 L 232,192" fill="none" stroke="black"/>
<path d="M 232,208 L 336,208" fill="none" stroke="black"/>
<path d="M 8,224 L 104,224" fill="none" stroke="black"/>
<path d="M 208,256 L 552,256" fill="none" stroke="black"/>
<polygon class="arrowhead" points="464,160 452,154.4 452,165.6" fill="black" transform="rotate(0,456,160)"/>
<polygon class="arrowhead" points="368,160 356,154.4 356,165.6" fill="black" transform="rotate(0,360,160)"/>
<polygon class="arrowhead" points="232,160 220,154.4 220,165.6" fill="black" transform="rotate(0,224,160)"/>
<polygon class="arrowhead" points="232,80 220,74.4 220,85.6" fill="black" transform="rotate(0,224,80)"/>
<polygon class="arrowhead" points="120,192 108,186.4 108,197.6" fill="black" transform="rotate(180,112,192)"/>
<polygon class="arrowhead" points="120,96 108,90.4 108,101.6" fill="black" transform="rotate(180,112,96)"/>
<g class="text">
<text x="160" y="68">Request</text>
<text x="60" y="84">onboarding</text>
<text x="268" y="84">SCIM</text>
<text x="56" y="100">app</text>
<text x="268" y="100">Server</text>
<text x="140" y="116">Ctrl</text>
<text x="184" y="116">Endpt</text>
<text x="56" y="164">Control</text>
<text x="156" y="164">REST</text>
<text x="284" y="164">NIPC</text>
<text x="396" y="164">AP</text>
<text x="500" y="164">Device</text>
<text x="56" y="180">&amp;</text>
<text x="208" y="180">|</text>
<text x="288" y="180">Gateway</text>
<text x="56" y="196">Telemetry</text>
<text x="160" y="196">pub/sub</text>
<text x="60" y="212">Apps</text>
<text x="336" y="244">Network</text>
<text x="412" y="244">Deployment</text>
</g>
</svg>
</artwork><artwork  type="ascii-art"><![CDATA[
                         +------------------------------------------+
                         |                                          |
+-----------+   Request  |  +---------+                             |
| onboarding+-------------->|  SCIM   |                             |
|    app    |<--------------+ Server  |                             |
+-----------+  Ctrl Endpt|  +---------+                             |
                         |                                          |
+-----------+            |  +------------+   +-------+   +--------+ |
|  Control  +----REST------>|    NIPC    +-->|  AP   +-->| Device | |
|     &     |            |  |   Gateway  |   +-------+   +--------+ |
| Telemetry |<--pub/sub-----+            |                          |
|    Apps   |            |  +------------+                          |
+-----------+            |                                          |
                         |            Network Deployment            |
                         +------------------------------------------+

]]></artwork></artset></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 leveraging 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 anchor="glossary"><name>Glossary</name>

<t><list style="symbols">
  <t>NIPC: Non-IP Control, the application layer interface defined in this
document.</t>
  <t>NIPC Gateway: An application layer gateway that implements the NIPC
interface.</t>
  <t>SDF: Semantic Device Format, a standardized format to describe devices
and their interaction models, as defined in <xref target="I-D.ietf-asdf-sdf"/>.</t>
  <t>SDF Affordance: An interaction point on a device as defined in an SDF
model. Examples of affordances are properties, actions &amp; events.</t>
  <t>SDF Global Name: Absolute URI (with fragment) identifying an SDF affordance.</t>
  <t>SCIM: System for Cross-domain Identity Management, a standardized
protocol to manage identity information, as defined in <xref target="RFC7644"/>.</t>
  <t>ALG: Application Layer Gateway.</t>
  <t>Non-IP Device: Device using a non-IP protocol (e.g. BLE, Zigbee) requiring a gateway for IP interaction.</t>
  <t>Protocol Mapping / sdfProtocolMap: Mapping from protocol-neutral SDF affordances to protocol-specific operations.</t>
  <t>BLE: Bluetooth Low Energy protocol.</t>
  <t>Zigbee: Low-power mesh networking protocol.</t>
  <t>GATT: Generic Attribute Profile used in BLE for services/characteristics/descriptors.</t>
  <t>Service (BLE): Top-level GATT grouping of characteristics.</t>
  <t>Characteristic (BLE): GATT data element supporting read/write/notify.</t>
  <t>Descriptor (BLE): Metadata element attached to a characteristic.</t>
  <t>Bonding (BLE): Procedure to establish trusted, reusable security keys.</t>
  <t>Service Discovery (BLE): Procedure to enumerate GATT services/characteristics/descriptors.</t>
  <t>Device Onboarding: Registration of a device identity and metadata before NIPC operations.</t>
  <t>Device ID / Group ID: UUID identifying a device or a group of devices.</t>
  <t>UUID: Universally unique identifier (128-bit).</t>
  <t>Data Application / Data App: Registered application receiving streamed event data.</t>
  <t>MQTT: Publish/subscribe messaging protocol used for streaming.</t>
  <t>Webhook: HTTP callback endpoint for push delivery.</t>
  <t>Websocket: Bidirectional TCP-based message channel over HTTP.</t>
  <t>Publish/Subscribe Interface: Streaming channel for events (CBOR-encoded payloads).</t>
  <t>CBOR: Concise Binary Object Representation; compact binary data format.</t>
  <t>CDDL: Concise Data Definition Language; schema language for CBOR data.</t>
  <t>JSON: JavaScript Object Notation; text encoding used for API payloads.</t>
  <t>Access Point (AP): Network element with non-IP radio interface communicating with devices.</t>
</list></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 gateway has 2 prerequisites:</t>

<t><list style="numbers" type="1">
  <t>Information about the instance of the device or thing: The device must be
onboarded on the gateway (e.g. by means of SCIM with <xref target="I-D.ietf-scim-device-model"/>). 
This allows the NIPC Gateway to retrieve the device object, identified by an ID
referenced in the path of the NIPC API.</t>
  <t>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>
</list></t>

<figure title="NIPC prerequisites" anchor="prereq"><artset><artwork  type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="432" viewBox="0 0 432 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
<path d="M 8,32 L 8,96" fill="none" stroke="black"/>
<path d="M 8,144 L 8,192" fill="none" stroke="black"/>
<path d="M 112,32 L 112,96" fill="none" stroke="black"/>
<path d="M 112,144 L 112,192" fill="none" stroke="black"/>
<path d="M 208,64 L 208,176" fill="none" stroke="black"/>
<path d="M 344,64 L 344,176" fill="none" stroke="black"/>
<path d="M 8,32 L 112,32" fill="none" stroke="black"/>
<path d="M 208,64 L 344,64" fill="none" stroke="black"/>
<path d="M 112,80 L 200,80" fill="none" stroke="black"/>
<path d="M 8,96 L 112,96" fill="none" stroke="black"/>
<path d="M 8,144 L 112,144" fill="none" stroke="black"/>
<path d="M 112,160 L 200,160" fill="none" stroke="black"/>
<path d="M 208,176 L 344,176" fill="none" stroke="black"/>
<path d="M 8,192 L 112,192" fill="none" stroke="black"/>
<polygon class="arrowhead" points="208,160 196,154.4 196,165.6" fill="black" transform="rotate(0,200,160)"/>
<polygon class="arrowhead" points="208,80 196,74.4 196,85.6" fill="black" transform="rotate(0,200,80)"/>
<g class="text">
<text x="60" y="52">SCIM</text>
<text x="60" y="68">object</text>
<text x="60" y="84">{ID}</text>
<text x="236" y="100">NIPC</text>
<text x="296" y="100">Operation</text>
<text x="248" y="116">-</text>
<text x="292" y="116">Property</text>
<text x="248" y="132">-</text>
<text x="284" y="132">Action</text>
<text x="248" y="148">-</text>
<text x="280" y="148">Event</text>
<text x="64" y="164">SDF</text>
<text x="64" y="180">model</text>
</g>
</svg>
</artwork><artwork  type="ascii-art"><![CDATA[
    +------------+   
    |    SCIM    |                      
    |   object   |           +----------------+          
    |    {ID}    +---------->|                |
    +------------+           | NIPC Operation |
                             |    - Property  |
                             |    - Action    |
    +------------+           |    - Event     |
    |     SDF    +---------->|                |
    |    model   |           +----------------+
    +------------+  

]]></artwork></artset></figure>

<t>Once these 2 prerequisites have been fulfilled, applications that are
authorized can perform NIPC operations on device IDs. Please review <xref target="security-considerations"/> for more information on authorization. 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 can be set up without explicitly calling an API.
Although onboarding could theoretically be performed in different 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 necessary attributes and extensions to support NIPC.</t>

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

<t>NIPC registration APIs allow applications to declare information about a device class, or an application authorization. These APIs do
not perform any operations on a specific device.
NIPC supports 2 types of registrations:
- Registering an SDF model for a class of devices.
- Registering an authorization for a data application. This authorizes an application to receive streaming event data from devices.
Optionally a pointer to the model and the data-app registration can be included in the SCIM object for the device.
See <xref target="I-D.ietf-scim-device-model"/> and <xref target="I-D.ietf-asdf-sdf-protocol-mapping"/> for more information.</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 as defined in <xref target="I-D.ietf-asdf-sdf-protocol-mapping"/>. 
The SDF affordances supported by the device, as well as its protocol-mappings,
are provided 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-registrations"><name>Data application registrations</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 registrations API allows mapping of an event to a data 
app as well as a protocol.</t>

</section>
</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 implicitly
establishes and tears down required connections.</t>

<t>The NIPC APIs that perform NIPC operations are organized in 3 main categories:</t>

<t><list style="symbols">
  <t>Properties APIs: These APIs allow applications to perform operations on properties, such as to read or write values to them.</t>
  <t>Actions APIs: These APIs perform actions on devices, such as enabling or disabling a feature on a device.</t>
  <t>Events APIs: These APIs allow apps to enable or disable event reporting on devices. Events are reported over the events publish/subscribe interface.</t>
</list></t>

<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 will perform implicit connection management. When executing a 
NIPC 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
may 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 APIs in <xref target="nipc-connection-management-apis"/>. After establishing an
explicit connection to a device, an application calls a NIPC Operation, the
Gateway will leverage the existing 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="extensions"><name>Extensions</name>

<t>NIPC is extendable as a NIPC gateway may want to provide a way to execute a
complex set of NIPC operations in a single API call, or may want to perform
an operation that can deliver an outcome more efficiently than a NIPC API. 
An example of an extension that uses compound operation is the bulk API.</t>

<t>Extensions must leverage the /extensions path element. In order to assure
inter-operability, extensions must be IANA registered in the registry in <xref target="iana-api-ext"/>.</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 JSON media type "application/nipc+json" that is registered in
<xref target="iana-media-types"/>, except for the SDF model registrations APIs, 
where the media type reflects the content as an SDF 
model, and hence is media type "application/sdf+json".
The NIPC property APIs also support the use of other media types to 
describe the content of the property.</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>

<t>CBOR was selected for the publish/subscribe interface as Non-IP payloads are typically binary. CBOR encodes binary payloads efficiently, and is more compact than JSON, therefore reducing the amount of data that needs to be transmitted to the application.</t>

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

<section anchor="paths-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>Additionally a version number may be added, for example:</t>

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

<t>After the base or version number, the path must contain a collection identifier.
The collection identifier can be one of the following:</t>

<t><list style="symbols">
  <t>/registrations: for NIPC registration APIs</t>
  <t>/devices: for NIPC operations on devices</t>
  <t>/groups: for NIPC operations on groups of devices</t>
  <t>/extensions: for NIPC extension APIs</t>
</list></t>

<t>The well-known URI <spanx style="verb">/.well-known/nipc</spanx> defined in <xref target="iana-well-known"/> can
be used to discover the base path of the NIPC APIs and the supported versions
and extensions. The response to a GET request on this URI MUST be a JSON
document that contains the base path, and optionally the supported versions and<br />
extension APIs. The paths MUST be a URI template as defined in <xref target="RFC6570"/>.
The following is an example of a template defining the NIPC base path as well
as supported extensions on a server.</t>

<figure title="Example response for /.well-known/nipc" anchor="ex-wellknown"><sourcecode type="json"><![CDATA[
{
  "base_path": "/nipc",
  "versions": [
    "/v1"
  ],
  "extensions": [
    "/extensions/{id}/bulk",
    "/extensions/{id}/properties/blob",
    "/extensions/{id}/properties/file",
    "/extensions/{id}/properties/read/conditional",
    "/extensions/{id}/events/conditional",
    "/extensions/{id}/properties/write"
  ]
}
]]></sourcecode></figure>

<t>A formal CBOR definition of the well-known response is as follows:</t>

<figure><sourcecode type="CDDL"><![CDATA[
NipcWellKnown = {
  base_path: text,
  ? versions: [* uri / text],
  ? extensions: [* uri / text]
}
]]></sourcecode></figure>

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

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

<t>paths:</t>

<t><list style="symbols">
  <t>/registrations/models</t>
  <t>/registrations/data-apps</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>properties</t>
  <t>events</t>
  <t>actions</t>
  <t>extensions</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-registrations-1"><name>SDF model registrations</name>

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

<t>The SDF model can be registered by means of a registrations API POST with 
the SDF model in the body of the request. A registered SDF model can be 
fetched by a registrations 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 name for the SDF affordance the operation 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, adhering to the <xref target="RFC9562"/>.</t>

<texttable title="Definition of a device or group of devices" anchor="devicedef">
      <ttcol align='left'>Attribute</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Example</ttcol>
      <c>id</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 onboarding
the device, for example by a SCIM server. This identifier is returned to the application.
As such, this ID is a common identifier, known both to the application as well as the NIPC Server.
If the server is not collocated with the SCIM server, the NIPC server will have to retrieve the device object from the SCIM server by means of the ID.</t>

</section>
</section>
<section anchor="sdf-name"><name>SDF Name</name>

<t>NIPC operations happen against SDF affordances and are referenced with an
global sdfName, 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="Example SDF names for NIPC operations" anchor="nipcopsdef">
      <ttcol align='left'>NIPC Operation</ttcol>
      <ttcol align='left'>Example SDF Name used in the API</ttcol>
      <c>Property</c>
      <c>https://example.com/heartrate#/<br />sdfObject/thermostat/sdfProperty/temperature</c>
      <c>Event</c>
      <c>https://example.com/heartrate#<br />/sdfObject/healthsensor/sdfEvent/fallDetected</c>
      <c>Action</c>
      <c>https://example.com/heartrate#/<br />sdfObject/thermostat/sdfAction/resetThermostat</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 extensions API to get the
execution status for the request. If a callback URL 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[
=============== NOTE: '\\' line wrapping per RFC 8792 ===============

{
  "type": "https://www.iana.org/assignments/nipc-problem-types#inval\
\id-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-registrations-apis"><name>SDF model registrations 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 /registrations/models</spanx></t>

<t>Description: Registers one or more SDF models for a class of devices</t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>an SDF document in JSON format containing one or more sdfThings or sdfObjects, similar to the example in <xref target="thermometer-sdf"/>.</t>
</list></t>

<t>Response:</t>

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

<figure title="Example of a response to an SDF model registration" anchor="exregresp"><artwork><![CDATA[
[
 {
  "sdfName": "https://example.com/heartrate#/sdfObject/healthsensor"
 }
]
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfName" is the name of the top-level sdfThing or sdfObject 
 in the SDF model</t>
</list></t>

<t>The <spanx style="verb">sdfName</spanx> in the response is wrapped in an object to allow for future
extensions to the response.</t>

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

<t>Method: <spanx style="verb">GET /registrations/models</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"
 },
 {
  "sdfName": "https://example.com/thermometer#/sdfObject/thermometer"
 }
]
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"sdfName" is the name of 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 /registrations/models{?sdfName}</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>sdfName: the name of 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 /registrations/models{?sdfName}</spanx></t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>sdfName: the name of 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 name of 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 /registrations/models{?sdfName}</spanx></t>

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

<t>Query Parameters:</t>

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

</section>
</section>
<section anchor="data-application-registrations-apis"><name>Data application registrations 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>

<t>Apart from the endpoint app ID, the API also registers the protocol the data-app supports. These can be one of the following:</t>

<t><list style="symbols">
  <t>mqttClient: The data-app is an MQTT client, which means that the gateway is an MQTT broker.</t>
  <t>mqttBroker: The data-app is an MQTT broker. The registration API has to include the MQTT broker configuration data, such as the URI, credentials and MQTT topic to publish to.</t>
  <t>webhook: The data-app supports a webhook the gateway can publish to. The registration API has to include the webhook URI &amp; credentials.</t>
  <t>websocket: The data-app supports a websocket interface. The registration API has to include the websocket URI &amp; credentials.</t>
</list></t>

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

<t>Method: <spanx style="verb">POST /registrations/data-apps{?dataAppId}</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: a boolean 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 base64-encoded CA certificate of the MQTT broker (optional)</t>
      <t>customTopic: By default, the topic will be composed of <spanx style="verb">data-app/&lt;dataAppId&gt;/&lt;namespace&gt;/&lt;json_pointer_to_sdf_event&gt;</spanx>, as described in <xref target="nipc-event-apis"/>.
You can configure a 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. The URL MUST include the scheme used by the webhook server (e.g., "https://"). It is up to the implementation to support different schemes. If a scheme is not supported, the NIPC gateway MUST return an error response with type
"https://www.iana.org/assignments/nipc-problem-types#unsupported-uri-scheme".</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. Each header is represented as a key-value pair in the object.</t>
      <t>serverCACert: the CA certificate of the webhook server, encoded as per <xref target="RFC7468"/> and newlines encoded as '\n' (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. The URL MUST include the scheme used by the websocket server (e.g., "wss://"). It is up to the implementation to support different schemes. If a scheme is not supported, the NIPC gateway MUST return an error response with type
"https://www.iana.org/assignments/nipc-problem-types#unsupported-uri-scheme".</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. Each header is represented as a key-value pair in the object.</t>
      <t>serverCACert: the CA certificate of the websocket server, encoded as per <xref target="RFC7468"/> and newlines encoded as '\n' (optional)</t>
    </list></t>
</list></t>

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

<figure title="Example with mqttClient" anchor="exregmqttclientrsp"><artwork><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

{
  "events": [
    {
      "event": "https://example.com/heartrate#/sdfObject/healthsenso\
r/sdfEvent/fallDetected"
    }
  ],
  "mqttClient": true
}
]]></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[
=============== NOTE: '\' line wrapping per RFC 8792 ================

{
  "events": [
    {
      "event": "https://example.com/heartrate#/sdfObject/healthsenso\
r/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 /registrations/data-apps{?dataAppId}</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 /registrations/data-apps{?dataAppId}</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 /registrations/data-apps{?dataAppId}</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  perform operations on SDF Affordances, such as properties, events &amp; actions.This allows a user of the NIPC API to get or update properties of devices, perform actions on devices, and consume events from devices.</t>

<t>The NIPC APIs consist of three main collections which reflect SDF Affordances as defined in <xref section="1.2" sectionFormat="of" target="I-D.ietf-asdf-sdf"/>:</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>
</list></t>

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

<t>The SDF global name will be used against the registered SDF model to 
determine the protocol-specific protocolmap that the NIPC API will operate on. 
The SDF global name is also percent-encoded as per <xref section="2.1" sectionFormat="of" target="RFC3986"/>.</t>

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

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

<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/nipc+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{?propertyName}</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>Query Parameters:</t>

<t><list style="symbols">
  <t>propertyName: a single property to update. If this parameter is
provided, the request body can contain any content type payload 
with the value to write to the property. If this parameter is not
provided, the request body MUST contain an application/nipc+json payload
with an array of properties to update, each containing a property and a
value.</t>
</list></t>

<t>Request Body:</t>

<t><list style="symbols">
  <t>If the query parameter propertyName is provided, the request body
can contain any content type payload with the value to write to the property.
The value is encoded as per the content type of the payload.</t>
</list></t>

<t>or</t>

<t><list style="symbols">
  <t>an array of properties to update, each containing a property and a value.
The value is the raw binary data, encoded in base64 with padding as per 
<xref section="5" sectionFormat="of" target="RFC4648"/>.</t>
</list></t>

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

<figure title="Example updating multiple properties" anchor="exupmprop"><sourcecode type="json"><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

[
  {
    "property": "https://example.com/heartrate#/sdfObject/thermostat\
/sdfProperty/temperature",
    "value": "dGVzdA=="
  },
  {
    "property": "https://example.com/heartrate#/sdfObject/thermostat\
/sdfProperty/humidity",
    "value": "eGVzdB=="
  }
]
]]></sourcecode></figure>

<t>Response:</t>

<t>If the Accept header is set to <spanx style="verb">application/nipc+json</spanx>, the response will be
an array with a status field set to 200 for each property that was updated, 
or a problem type object for each property that failed to update.</t>

<t>If the Accept header is set to any other media type and the propertyName query parameter is provided, the response will be 204 No Content with no body.</t>

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

<figure title="Example update multiple properties response" anchor="exupmresp"><artwork><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

[
  {
    "status": 200
  },
  {
    "type": "https://www.iana.org/assignments/nipc-problem-types#inv\
alid-property",
    "status": 400,
    "title": "Invalid Property",
    "detail": "Property https://example.com/heartrate#/sdfObject/the\
rmostat/sdfProperty/temperature does not exist or is not writable"
  }
]
]]></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{?propertyName*}</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: The property to read. This can be a single property or multiple
properties. If multiple properties are provided, the request body MUST
contain an application/nipc+json payload with an array of properties to read.</t>
</list></t>

<t>Response:</t>

<t>If the Accept header is set to <spanx style="verb">application/nipc+json</spanx>, the response will be
an array of properties, each containing a property and a value. The value is
the raw binary data read from the property, encoded in base64 with padding as per <xref section="5" sectionFormat="of" target="RFC4648"/>.</t>

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

<figure title="Example read multiple properties response" anchor="exreadmresp"><artwork><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

[
  {
    "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 the global name of 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[
=============== NOTE: '\' line wrapping per RFC 8792 ================

data-app/<dataAppId>/<namespace>/<json_pointer_to_sdf_event>

data-app/12345678-1234-5678-1234-56789abcdef4/thermometer/sdfThing/\
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{?eventName}</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 the global
name of 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[
=============== NOTE: '\' line wrapping per RFC 8792 ================

HTTP/1.1 201 Created
Location: /devices/12345678-1234-5678-1234-56789abcdef4/events?insta\
nceId=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{?instanceId}</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-status-of-one-or-more-events"><name>Get status of one or more events</name>

<t>Method: <spanx style="verb">GET /devices/{id}/events{?instanceId*}</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[
=============== NOTE: '\' line wrapping per RFC 8792 ================

[
  {
    "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 the global
name of 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[
=============== NOTE: '\' line wrapping per RFC 8792 ================

HTTP/1.1 201 Created
Location: /groups/12345678-1234-5678-1234-56789abcdef4/events?instan\
ceId=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{?instanceId}</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 200 with a list of the event status for the group of devices.
If the event was successfully disabled on a device, the response will contain
the device ID and SDF event name for that device. If the event could not be disabled
on a device, the response will contain a problem type error response for that device.</t>

<figure><artwork><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

[
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef4"
  },
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef5"
  },
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef6"
  },
  {
    "type": "https://www.iana.org/assignments/nipc-problem-types#eve\
nt-not-enabled",
    "status": 400,
    "title": "Event Not Enabled",
    "deviceId": "12345678-1234-5678-1234-56789abcdef7",
    "detail": "Failed to disable the event for device 12345678-1234-\
5678-1234-56789abcdef7"
  }
]
]]></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{?instanceId}</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: The instance ID of the event to get the status for</t>
</list></t>

<t>Response:</t>

<t>Returns HTTP status code 200 with a list of the event status for the group of devices.
If the event was successfully enabled on a device, the response will contain
the device ID and SDF event name for that device. If the event could not be enabled
on a device, the response will contain a problem type error response for that device.</t>

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

<figure title="Example get multiple group events status response" anchor="exgetmgevntsresp"><artwork><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

[
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef4"
  },
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef5"
  },
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef6"
  },
  {
    "type": "https://www.iana.org/assignments/nipc-problem-types#eve\
nt-not-enabled",
    "status": 400,
    "title": "Event Not Enabled",
    "deviceId": "12345678-1234-5678-1234-56789abcdef7",
    "detail": "Failed to disable the event for device 12345678-1234-\
5678-1234-56789abcdef7"
  }
]
]]></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{?actionName}</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 may contain a value. The media type of the value can be defined by the underlying protocol, for example it could be octet-stream for binary data.</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[
=============== NOTE: '\' line wrapping per RFC 8792 ================

HTTP/1.1 202 Accepted
Location: /devices/12345678-1234-5678-1234-56789abcdef4/actions?inst\
anceId=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{?instanceId}</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-connection-management-apis"><name>NIPC explicit connections management APIs</name>

<t>Many protocols do not require connection management, so for these protocols, these APIs will not apply.
NIPC Gateways perform implicit connection management for protocols that require connection management (such as BLE), so in principle the user of the NIPC API does not have to perform connection management. In some cases however, a user might want to keep a connection open, perform an action, evaluate the result and perform a second action based on that result. In this case it is useful to perform explicit connection management so the connection remains established to execute subsequent actions.  These APIs allow applications to explicitly manage device connections.
The examples in this section will be based on BLE, which requires connection management.</t>

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

<t>Method: <spanx style="verb">POST /devices/{id}/connections</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 discovery 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 operation 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,
  "sdfProtocolMap": {
    "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 (in seconds) 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 characteristics, 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
            - characteristicID
            - 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",
  "sdfProtocolMap": {
    "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>"sdfProtocolMap" 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}/connections</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 discovery 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[
{
  "sdfProtocolMap": {
    "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 characteristics, 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",
  "sdfProtocolMap": {
    "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>"sdfProtocolMap" 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}/connections</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}/connections</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",
  "sdfProtocolMap": {
    "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>"sdfProtocolMap" 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>NIPC supports mapping protocol specific properties to NIPC properties
as described in <xref target="I-D.ietf-asdf-sdf-protocol-mapping"/>.
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'>Type</ttcol>
      <ttcol align='left'>Example</ttcol>
      <c>ble</c>
      <c>object</c>
      <c>an object with BLE-specific properties</c>
      <c>zigbee</c>
      <c>object</c>
      <c>an object with Zigbee-specific properties</c>
      <c>newProtocol</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>

</section>
<section anchor="apiextensions"><name>API extensions</name>

<t>/extensions</t>

<t>The extension APIs allow for extensibility of the APIs. Extensions must be IANA registered.
Extension APIs can leverage the basic NIPC defined APIs and combine them in 
compound statements in order to streamline application operation against
devices, make operations more expedient and convenient in one API call. An example of this is the bulk API extension.
They can also introduce new functionality that is specific to a use case or protocol, such as the BLE transmit API.
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 types in the NIPC APIs use URI-based error type identifiers 
as defined in <xref target="iana-problem-details"/>. The error types 
can be generic or specific to the API category. The error types 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 types are defined in the table below:</t>

<texttable title="Error Codes" anchor="errorcodes">
      <ttcol align='left'>Error Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Category</ttcol>
      <c>invalid-id</c>
      <c>Invalid device ID or gateway doesn't recognize the ID</c>
      <c>Generic</c>
      <c>invalid-sdf-url</c>
      <c>Invalid SDF URL or SDF affordance not found</c>
      <c>Generic</c>
      <c>extension-operation-not-executed</c>
      <c>Operation was not executed since the previous operation failed</c>
      <c>Generic</c>
      <c>sdf-model-already-registered</c>
      <c>SDF model already registered</c>
      <c>Generic</c>
      <c>sdf-model-in-use</c>
      <c>SDF model in use</c>
      <c>Generic</c>
      <c>unsupported-uri-scheme</c>
      <c>Unsupported URI scheme</c>
      <c>Generic</c>
      <c>property-not-readable</c>
      <c>Property not readable</c>
      <c>Property APIs</c>
      <c>property-not-writable</c>
      <c>Property not writable</c>
      <c>Property APIs</c>
      <c>event-already-enabled</c>
      <c>Event already enabled</c>
      <c>Event APIs</c>
      <c>event-not-enabled</c>
      <c>Event not enabled</c>
      <c>Event APIs</c>
      <c>event-not-registered</c>
      <c>Event not registered for any data application</c>
      <c>Event APIs</c>
      <c>protocolmap-ble-already-connected</c>
      <c>Device already connected</c>
      <c>Protocol specific</c>
      <c>protocolmap-ble-no-connection</c>
      <c>No connection found for device</c>
      <c>Protocol specific</c>
      <c>protocolmap-ble-connection-timeout</c>
      <c>BLE connection timeout</c>
      <c>Protocol specific</c>
      <c>protocolmap-ble-bonding-failed</c>
      <c>BLE bonding failed</c>
      <c>Protocol specific</c>
      <c>protocolmap-ble-connection-failed</c>
      <c>BLE connection failed</c>
      <c>Protocol specific</c>
      <c>protocolmap-ble-service-discovery-failed</c>
      <c>BLE service discovery failed</c>
      <c>Protocol specific</c>
      <c>protocolmap-ble-invalid-service-or-characteristic</c>
      <c>Invalid BLE service or characteristic ID</c>
      <c>Protocol specific</c>
      <c>protocolmap-zigbee-connection-timeout</c>
      <c>Zigbee connection timeout</c>
      <c>Protocol specific</c>
      <c>protocolmap-zigbee-invalid-endpoint-or-cluster</c>
      <c>Invalid Zigbee endpoint or cluster ID</c>
      <c>Protocol specific</c>
      <c>extension-transmit-invalid-data</c>
      <c>Invalid transmit data</c>
      <c>Transmit APIs</c>
      <c>extension-firmware-rollback</c>
      <c>Firmware rollback</c>
      <c>Extension APIs</c>
      <c>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 /registrations/data-apps 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[
start = DataBatch

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[
============== NOTE: '\' line wrapping per RFC 8792 ==============

POST /registrations/models
Content-Type: application/sdf+json
Accept: application/nipc+json
Host: localhost

{ ... }

HTTP/1.1 200 OK
content-type: application/nipc+json

[
  {
    "sdfName": "https://example.com/thermometer#/sdfThing/thermom\
eter"
  }
]
]]></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[
============== NOTE: '\' line wrapping per RFC 8792 ==============

GET /devices/12345678-1234-5678-1234-56789abcdef4/properties?prop\
ertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2F\
thermometer%2FsdfProperty%2Fdevice_name
Accept: application/nipc+json
Host: localhost

HTTP/1.1 200 OK
content-type: application/nipc+json

[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermo\
meter/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
]]></artwork></figure>
  </t>
  <t>Write to a property on the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

PUT /devices/12345678-1234-5678-1234-56789abcdef4/properties
Content-Type: application/nipc+json
Host: localhost

[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermo\
meter/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]

HTTP/1.1 200 OK
content-type: application/nipc+json

[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermo\
meter/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
]]></artwork></figure>
  </t>
</list></t>

</section>
<section anchor="enabling-an-event-on-a-device"><name>Enabling an Event on a Device</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[
============== NOTE: '\' line wrapping per RFC 8792 ==============

POST /registrations/models
Content-Type: application/sdf+json
Accept: application/nipc+json
Host: localhost

{ ... }

HTTP/1.1 200 OK
content-type: application/nipc+json

[
  {
    "sdfName": "https://example.com/thermometer#/sdfThing/thermom\
eter"
  }
]
]]></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[
============== NOTE: '\' line wrapping per RFC 8792 ==============

POST /registrations/data-apps?dataAppId=23456789-1234-5678-1234-5\
6789abcdef4
Content-Type: application/nipc+json
Accept: application/nipc+json
Host: localhost

{
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEve\
nt/isPresent"
  ],
  "mqttClient": true
}

HTTP/1.1 200 OK
content-type: application/nipc+json

{
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEve\
nt/isPresent"
  ],
  "mqttClient": true
}
]]></artwork></figure>
  </t>
  <t>Enable the advertisement event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

POST /devices/12345678-1234-5678-1234-56789abcdef4/events?eventNa\
me=https%23%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermo\
meter%2FsdfEvent%2FisPresent
Host: localhost
Content-Length: 0

HTTP/1.1 201 Created
Location: /devices/12345678-1234-5678-1234-56789abcdef4/events?in\
stanceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>
  </t>
  <t>Check the status of the event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

GET /devices/12345678-1234-5678-1234-56789abcdef4/events?instance\
Id=87654321-4321-8765-4321-fedcba9876543
Host: localhost

HTTP/1.1 200 OK
content-type: application/nipc+json

{
  "event": "https://example.com/thermometer#/sdfThing/thermometer\
/sdfEvent/isPresent"
}
]]></artwork></figure>
  </t>
</list></t>

</section>
<section anchor="enabling-an-event-on-a-group-of-devices"><name>Enabling an Event on a Group of Devices</name>

<t>In this example, we will enable an advertisement subscription event
for a group of devices.</t>

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

<t><list style="symbols">
  <t>Onboard devices and endpoint app using the SCIM Interface (out of scope of this
   memo)</t>
  <t>Register an SDF model for the devices  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

POST /registrations/models
Content-Type: application/sdf+json
Accept: application/nipc+json
Host: localhost

{ ... }

HTTP/1.1 200 OK
content-type: application/nipc+json

[
  {
    "sdfName": "https://example.com/thermometer#/sdfThing/thermom\
eter"
  }
]
]]></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[
============== NOTE: '\' line wrapping per RFC 8792 ==============

POST /registrations/data-apps?dataAppId=23456789-1234-5678-1234-5\
6789abcdef4
Content-Type: application/nipc+json
Accept: application/nipc+json
Host: localhost

{
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEve\
nt/isPresent"
  ],
  "mqttClient": true
}

HTTP/1.1 200 OK
content-type: application/nipc+json

{
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEve\
nt/isPresent"
  ],
  "mqttClient": true
}
]]></artwork></figure>
  </t>
  <t>Enable the advertisement event on a group of devices  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

POST /groups/87654321-4321-8765-4321-fedcba9876543/events?eventNa\
me=https%23%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermo\
meter%2FsdfEvent%2FisPresent
Host: localhost
Content-Length: 0

HTTP/1.1 201 Created
Location: /groups/87654321-4321-8765-4321-fedcba9876543/events?in\
stanceId=11223344-5566-7788-99aa-bbccddeeff00
]]></artwork></figure>
  </t>
  <t>Check the status of the event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

GET /groups/87654321-4321-8765-4321-fedcba9876543/events?instance\
Id=11223344-5566-7788-99aa-bbccddeeff00
Host: localhost

HTTP/1.1 200 OK
content-type: application/nipc+json

[
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsen\
sor/sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef4"
  },
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsen\
sor/sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef5"
  },
  {
    "event": "https://example.com/heartrate#/sdfObject/healthsen\
sor/sdfEvent/fallDetected",
    "deviceId": "12345678-1234-5678-1234-56789abcdef6"
  },
  {
    "type": "https://www.iana.org/assignments/nipc-problem-types\
#event-not-enabled",
    "status": 400,
    "title": "Event Not Enabled",
    "deviceId": "12345678-1234-5678-1234-56789abcdef7",
    "detail": "Failed to disable the event for device 12345678-1\
234-5678-1234-56789abcdef7"
  }
]
]]></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" type="1">
  <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="iana-media-types"><name>Media Type Registration</name>

<t>This document registers the "application/nipc+json" media type 
for messages of the NIPC APIs defined in this document carrying
parameters encoded in JSON.</t>

<t>Type name: application</t>

<t>Subtype name: nipc+json</t>

<t>Required parameters: none</t>

<t>Optional parameters: none</t>

<t>Encoding considerations: Encoding considerations are identical to those specified for the "application/json" media type.</t>

<t>Security considerations: See the <xref target="security-considerations"/> section of this document.</t>

<t>Interoperability considerations: none</t>

<t>Published specification: This document, the NIPC API specification.</t>

<t>Applications that use this media type:</t>

<t>Fragment identifier considerations: none</t>

<t>Additional information:</t>

<t><list style="symbols">
  <t>Deprecated alias names for this type: none</t>
  <t>Magic number(s): none</t>
  <t>File extension(s): none</t>
  <t>Macintosh file type code(s): none</t>
</list></t>

<t>Person &amp; email address to contact for further information:</t>

<t>Intended usage: LIMITED USE</t>

<t>Restrictions on usage: To be used for NIPC APIs as defined in this document.</t>

<t>Author:</t>

<t>Change controller: IETF</t>

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

<t>IANA is requested to create a new registry called "NIPC API extensions".</t>

<t>The registry must contain following attributes:</t>

<t><list style="symbols">
  <t>Extension URI</t>
  <t>Extension name</t>
  <t>Description</t>
  <t>Openapi model describing the extension. This model must be reviewed by an expert.</t>
</list></t>

<t>Following API extensions are described in this document:</t>

<texttable>
      <ttcol align='left'>Extension URI</ttcol>
      <ttcol align='left'>Extension name</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Model reference</ttcol>
      <c>/extensions/{id}/bulk</c>
      <c>Bulk API</c>
      <c>Call multiple NIPC's in a single request</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extensions/{id}/properties/file</c>
      <c>File write API</c>
      <c>Write a file with multiple property ops</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extensions/{id}/properties/blob</c>
      <c>Binary write API</c>
      <c>Write a binary blob with multiple property ops</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extensions/{id}/properties/read/conditional</c>
      <c>Read conditional API</c>
      <c>Read a property until a condition is fulfilled</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extensions/{id}/events/conditional</c>
      <c>Event conditional API</c>
      <c>Enable an event until a condition is fulfilled</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extensions/{id}/transmit</c>
      <c>Transmit API</c>
      <c>Transmits a payload to a device</c>
      <c><xref target="NIPCextensions"/></c>
</texttable>

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

<t>IANA is requested to register the following well-known URI in the "Well-Known URIs" registry as defined by <xref target="RFC8615"/>:</t>

<texttable>
      <ttcol align='left'>URI Suffix</ttcol>
      <ttcol align='left'>Change Controller</ttcol>
      <ttcol align='left'>Specification Document</ttcol>
      <c>nipc</c>
      <c>IETF</c>
      <c>This document, <xref target="paths-general"></xref></c>
</texttable>

<t>The well-known URI for NIPC is:</t>

<figure><artwork><![CDATA[
/.well-known/nipc
]]></artwork></figure>

</section>
<section anchor="iana-problem-details"><name>Problem Details for NIPC APIs</name>

<t>IANA is requested to create a new registry, the "NIPC Problem Type" registry, 
with following URL: <eref target="https://www.iana.org/assignments/nipc-problem-types"></eref>.</t>

<t>Registrations MUST use the prefix <eref target="&quot;https://iana.org/assignments/nipc-problem-types#&quot;"></eref> for the type URI.</t>

<t>The registration requests MUST use the template defined in <xref section="4.2" sectionFormat="of" target="RFC9457"/>.</t>

<t>IANA is requested to register the following URIs in the "NIPC Problem Type" 
registry:</t>

<texttable>
      <ttcol align='left'>Problem Type URI</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Reference</ttcol>
      <c>https://www.iana.org/assignments/nipc-problem-types#invalid-id</c>
      <c>Invalid device ID or gateway doesn't recognize the ID</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#invalid-sdf-url</c>
      <c>Invalid SDF URL or SDF affordance not found</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#extension-operation-not-executed</c>
      <c>Operation was not executed since the previous operation failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#sdf-model-already-registered</c>
      <c>SDF model already registered</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#sdf-model-in-use</c>
      <c>SDF model in use</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#unsupported-uri-scheme</c>
      <c>Unsupported URI scheme</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#property-not-readable</c>
      <c>Property not readable</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#property-read-failed</c>
      <c>Property read failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#property-not-writable</c>
      <c>Property not writable</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#property-write-failed</c>
      <c>Property write failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#event-already-enabled</c>
      <c>Event already enabled</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#event-not-enabled</c>
      <c>Event not enabled</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#event-not-registered</c>
      <c>Event not registered for any data application</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-ble-already-connected</c>
      <c>Device already connected</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-ble-no-connection</c>
      <c>No connection found for device</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-ble-connection-timeout</c>
      <c>BLE connection timeout</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-ble-bonding-failed</c>
      <c>BLE bonding failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-ble-connection-failed</c>
      <c>BLE connection failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-ble-service-discovery-failed</c>
      <c>BLE service discovery failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-ble-invalid-service-or-characteristic</c>
      <c>Invalid BLE service or characteristic ID</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-zigbee-connection-timeout</c>
      <c>Zigbee connection timeout</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#protocolmap-zigbee-invalid-endpoint-or-cluster</c>
      <c>Invalid Zigbee endpoint or cluster ID</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#extension-broadcast-invalid-data</c>
      <c>Invalid transmit data</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#extension-firmware-rollback</c>
      <c>Firmware rollback</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/nipc-problem-types#extension-firmware-update-failed</c>
      <c>Firmware update failed</c>
      <c>This document</c>
</texttable>

<t>Each Problem Type URI is intended for use as the "type" member in Problem Details responses as described.</t>

</section>
</section>


  </middle>

  <back>


<references title='References' anchor="sec-combined-references">

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

&RFC7644;
&I-D.ietf-scim-device-model;
&I-D.ietf-asdf-sdf;
&RFC2119;
&RFC8174;
&I-D.ietf-asdf-sdf-protocol-mapping;
&RFC9114;
&RFC7159;
&RFC8949;
&RFC3986;
&RFC6570;
&RFC9562;
&RFC9457;
&RFC7468;
&RFC4648;
&RFC8610;
&RFC8126;
&RFC8615;


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

</references>


<?line 2457?>

<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"
=============== NOTE: '\\' line wrapping per RFC 8792 ===============

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
\2/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.14.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-14"
    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
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be written to.
        required: false
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/temperature"
      requestBody:
        description: |-
          The value to be written to the property or properties.
          If multiple properties are specified, the request body
          should be application/nipc+json.
        content:
          application/nipc+json:
            schema:
              $ref: '#/components/schemas/PropertyValueArray'
          "*/*":
            schema:
              description: |-
                Any other content type, such as 
                application/octet-stream, application/json that will 
                be written to the device.
        required: true
      responses:
        '204':
          description: |-
            Success, no content, used for a single property write
        '200':
          description: Success, used for multiple property writes
          content:
            application/nipc+json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/PropertyValueRespons\
\eArray'
        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/therm\
\ostat/sdfProperty/temperature"
      responses:
        '200':
          description: Success
          content:
            application/nipc+json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValueReadRes\
\ponseArray'
            "*/*":
              schema:
                type: string
                description: |-
                  Any other content type, such as
                  application/octet-stream, application/json that 
                  will be read from the device.
        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/healths\
\ensor/sdfEvent/fallDetected"
      responses:
        '201':
          description: Success
          headers:
            Location:
              description: Location of the created event
              schema:
                type: string
                format: uri
                example: "/devices/{id}/events?instanceId={instanceI\
\d}"
        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 disab\
\led
        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 devi\
\ce
      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/nipc+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/healths\
\ensor/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 disab\
\led
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, event disabled
          content:
            application/nipc+json:
              schema:
                $ref: '#/components/schemas/GroupEventStatusResponse\
\Array'
        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 devi\
\ces.
      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: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, events retrieved
          content:
            application/nipc+json:
              schema:
                $ref: '#/components/schemas/GroupEventStatusResponse\
\Array'
        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.
      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/healths\
\ensor/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={instance\
\Id}"
        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/nipc+json:
              schema:
                $ref: '#/components/schemas/ActionResponse'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
               
  /devices/{id}/connections:
    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/nipc+json:
            schema:
              anyOf:
                - $ref: '#/components/schemas/Connection'
                - $ref: './protocolmaps/ProtocolMap.yaml#/components\
\/schemas/ProtocolMap-ServiceList'
        required: false
      responses:
        '200':
          description: Success
          content:
            application/nipc+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/componen\
\ts/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/nipc+json:
            schema:
              $ref: './protocolmaps/ProtocolMap.yaml#/components/sch\
\emas/ProtocolMap-ServiceList'
        required: false
      responses:
        '200':
          description: Success
          content:
            application/nipc+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/componen\
\ts/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/nipc+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/nipc+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/componen\
\ts/schemas/ProtocolMap-ServiceMap'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'


### Registrations
  /registrations/models:
    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/nipc+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/healt\
\hsensor"
      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/healt\
\hsensor"
      requestBody:
        content:
          application/sdf+json:
            schema:
              $ref: '#/components/schemas/SdfModel'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/nipc+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: query
          description: sdfObject name
          required: true
          schema:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healt\
\hsensor"
      responses:
        '200':
          description: Success
          content:
            application/nipc+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfReference'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

  /registrations/data-apps:
    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/nipc+json:
            schema:
              $ref: '#/components/schemas/DataApp'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/nipc+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 dev\
\ice data. 
      operationId: UpdateDataApp
      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
      requestBody:
        content:
          application/nipc+json:
            schema:
              $ref: '#/components/schemas/DataApp'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/nipc+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: 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/nipc+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/nipc+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/thermos\
\tat/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/healthse\
\nsor/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: boolean

    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/healths\
\ensor"
    
    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:
                    sdfProtocolMap:
                      ble:
                        type: advertisement
              sdfObject:
                healthsensor:
                  sdfProperty:
                    heartrate:
                      sdfProtocolMap:
                        ble:
                          serviceID: 12345678-1234-5678-1234-56789ab\
\cdef4
                          characteristicID: 12345678-1234-5678-1234-\
\56789abcdef4
                  sdfEvent:
                    fallDetected:
                      sdfOutputData:
                        sdfProtocolMap:
                          ble:
                            serviceID: 12345678-1234-5678-1234-56789\
\abcdef4
                            characteristicID: 12345678-1234-5678-123\
\4-56789abcdef4
                  sdfAction:
                    start:
                      sdfProtocolMap:
                        ble:
                          serviceID: 12345678-1234-5678-1234-56789ab\
\cdef4
                          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:
                  sdfProtocolMap:
                    ble:
                      serviceID: 12345678-1234-5678-1234-56789abcdef4
                      characteristicID: 12345678-1234-5678-1234-5678\
\9abcdef4
              sdfEvent:
                fallDetected:
                  sdfOutputData:
                    sdfProtocolMap:
                      ble:
                        serviceID: 12345678-1234-5678-1234-56789abcd\
\ef4
                        characteristicID: 12345678-1234-5678-1234-56\
\789abcdef4
              sdfAction:
                start:
                  sdfProtocolMap:
                    ble:
                      serviceID: 12345678-1234-5678-1234-56789abcdef4
                      characteristicID: 12345678-1234-5678-1234-5678\
\9abcdef4

    SdfProperty:
      type: object
      description: Sample SDF property
      properties:
        sdfProperty:
          additionalProperties: 
            allOf:
              - $ref: './protocolmaps/ProtocolMap.yaml#/components/s\
\chemas/ProtocolMap-Property'
          example:
            heartrate:
              sdfProtocolMap:
                ble:
                  serviceID: 12345678-1234-5678-1234-56789abcdef4
                  characteristicID: 12345678-1234-5678-1234-56789abc\
\def4
          
    SdfEvent:
      type: object
      description: Sample SDF property
      properties:
        sdfEvent:
          additionalProperties: #example, this will be the registere\
\d event
            type: object
            properties:
              sdfOutputData:
                allOf:
                  - $ref: './protocolmaps/ProtocolMap.yaml#/componen\
\ts/schemas/ProtocolMap-Event'
          example:
            fallDetected:
              sdfOutputData:
                sdfProtocolMap:
                  ble:
                    serviceID: 12345678-1234-5678-1234-56789abcdef4
                    characteristicID: 12345678-1234-5678-1234-56789a\
\bcdef4
    
    SdfAction:
      type: object
      description: Sample SDF property
      properties:
        sdfAction:
          additionalProperties: 
            allOf:
              - $ref: './protocolmaps/ProtocolMap.yaml#/components/s\
\chemas/ProtocolMap-Property'
          example:
            start:
              sdfProtocolMap:
                ble:
                  serviceID: 12345678-1234-5678-1234-56789abcdef4
                  characteristicID: 12345678-1234-5678-1234-56789abc\
\def4

# 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/nipc-problem-types#in\
\valid-id
            - https://www.iana.org/assignments/nipc-problem-types#in\
\valid-sdf-url
            - https://www.iana.org/assignments/nipc-problem-types#ex\
\tension-operation-not-executed
            - https://www.iana.org/assignments/nipc-problem-types#sd\
\f-model-already-registered
            - https://www.iana.org/assignments/nipc-problem-types#sd\
\f-model-in-use
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\operty-not-readable
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\operty-read-failed
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\operty-not-writable
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\operty-write-failed
            - https://www.iana.org/assignments/nipc-problem-types#ev\
\ent-already-enabled
            - https://www.iana.org/assignments/nipc-problem-types#ev\
\ent-not-enabled
            - https://www.iana.org/assignments/nipc-problem-types#ev\
\ent-not-registered
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-ble-already-connected
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-ble-no-connection
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-ble-connection-timeout
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-ble-bonding-failed
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-ble-connection-failed
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-ble-service-discovery-failed
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-ble-invalid-service-or-characteristic
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-zigbee-connection-timeout
            - https://www.iana.org/assignments/nipc-problem-types#pr\
\otocolmap-zigbee-invalid-endpoint-or-cluster
            - https://www.iana.org/assignments/nipc-problem-types#ex\
\tension-broadcast-invalid-data
            - https://www.iana.org/assignments/nipc-problem-types#ex\
\tension-firmware-rollback
            - https://www.iana.org/assignments/nipc-problem-types#ex\
\tension-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'

    PropertyValueReadResponseArrayItem:
      oneOf:
        - $ref: '#/components/schemas/PropertyValue'
        - $ref: '#/components/schemas/FailureResponse'
    
    PropertyValueReadResponseArray:
      type: array
      items:
        allOf:
          - $ref: '#/components/schemas/PropertyValueReadResponseArr\
\ayItem'

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

    GroupEventStatusResponse:
      type: object
      oneOf:
        - allOf:
          - $ref: '#/components/schemas/Event'
          - type: object
            properties:
              deviceId:
                type: string
                format: uuid
                example: 12345678-1234-5678-1234-56789abcdef4
        - $ref: '#/components/schemas/FailureResponse'

    GroupEventStatusResponseArray:
      type: array
      items:
          $ref: '#/components/schemas/GroupEventStatusResponse'
    
<CODE ENDS>
]]></artwork></figure>

</section>
<section anchor="protocol-mapping"><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"
=============== NOTE: '\' line wrapping per RFC 8792 ================

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.10.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

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

## Protocol Map for Service Discovery result
    ProtocolMap-ServiceMap:
      type: object
      properties:
        sdfProtocolMap:
          oneOf:
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/Prot\
ocolMap-BLE-ServiceMap'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/P\
rotocolMap-Zigbee-ServiceMap'

## Protocol Map for Broadcasts
    ProtocolMap-Broadcast:
      type: object
      properties:
        sdfProtocolMap:
          oneOf:  
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/Prot\
ocolMap-BLE-Broadcast'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/P\
rotocolMap-Zigbee-Broadcast'

## Protocol Map for a property
    ProtocolMap-Property:
      type: object
      properties:
        sdfProtocolMap:
          oneOf:  
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/Prot\
ocolMap-BLE-Propmap'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/P\
rotocolMap-Zigbee-Propmap'

## Protocol Map for an event
    ProtocolMap-Event:
      type: object
      properties:
        sdfProtocolMap:
          oneOf:  
            - $ref: './ProtocolMap-BLE.yaml#/components/schemas/Prot\
ocolMap-BLE-Event'
            - $ref: './ProtocolMap-Zigbee.yaml#/components/schemas/P\
rotocolMap-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"
=============== NOTE: '\' line wrapping per RFC 8792 ================

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.10.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

components:
  schemas:
# BLE Protocol Mapping
## A Service is a device with optional service IDs
    ProtocolMap-BLE-ServiceList:
      type: object
      properties:
        ble:
          type: object
          properties:
            services:
              type: array
              items:
                type: object
                properties:
                  serviceID:
                    type: string
                    format: uuid
                    example: 12345678-1234-5678-1234-56789abcdef4
            cached:
              description: |-
                If we can cache information, then device doesn't need
                to be rediscovered before every connected.
              type: boolean
              default: false
            cacheIdlePurge:
              description: cache expiry period, when device allows
              type: integer
              example: 3600 # default 1 hour
            autoUpdate:
              description: |-
                autoupdate services if device supports it (default)
              type: boolean
              example: true
            bonding: #optional, by default defined in SCIM object 
              type: string
              example: default
              enum:
                - default 
                - none
                - justworks
                - passkey
                - oob

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

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

    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
          properties:
            connectable:
              type: boolean

## 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
<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.10.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

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

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

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

    ProtocolMap-Zigbee-Property:
      required:
        - attributeID
        - propertyType
      type: object
      properties:
        attributeID:
          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
            - attributeID
          type: object
          properties:
            endpointID:
              type: integer
              format: int32
              example: 1
            clusterID:
              type: integer
              format: int32
              example: 6
            attributeID:
              type: integer
              format: int32
              example: 16
            type:
              type: integer
              format: int32
              example: 1

    ProtocolMap-Zigbee-Event:
      allOf:  
        - $ref: '#/components/schemas/ProtocolMap-Zigbee-Propmap'
<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"
=============== NOTE: '\' line wrapping per RFC 8792 ================

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
2/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.14.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-14"
    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/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: query
        description: |-
          The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
tat/sdfProperty/firmware"
      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/FailureRespo\
nse' 

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"
=============== NOTE: '\' line wrapping per RFC 8792 ================

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
2/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.14.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-14"
    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"
              firmwareUpgradeRequest:
                $ref: "#/components/examples/firmwareUpgradeRequest"
        required: true
      responses:
        "202":
          description: Accepted
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/bulk/status?instanceId=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the bulk status response
        "401":
          description: Unauthorized
        "405":
          description: Invalid request
        "500":
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: "../NIPC.yaml#/components/schemas/FailureRespo\
nse"
      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-Bulk\
Response"
              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: instanceId
          in: query
          description: Instance 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-BulkRespon\
se"
              examples:
                bulkResponse:
                  $ref: "#/components/examples/bulkResponse"
                firmwareUpgradeResponse:
                  $ref: "#/components/examples/firmwareUpgradeRespon\
se"
                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: instanceId
          in: query
          description: Instance 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-Async.yaml#/components/schema\
s/Extension-StatusResponse"
        "303":
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/bulk?instanceId=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the bulk response
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "./Extension-Async.yaml#/components/schema\
s/Extension-StatusResponse"
              examples:
                successExample:
                  summary: Success
                  value:
                    status: COMPLETED

components:
  schemas:
    # Extensions
    ## Bulk schema Extension
    Extension-Bulk:
      allOf:
        - $ref: "./Extension-Async.yaml#/components/schemas/Extensio\
n-Callback"
        - type: object
          properties:
            operations:
              type: array
              items:
                $ref: "#/components/schemas/Extension-BulkOperation"
            trigger:
              type: string
              description: |-
                When to trigger the operations. If not specified, th\
e operations are triggered immediately.
              default: immediate
              enum:
                - immediate
                - advertisement

    ## 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={propertyNam\
e}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?prope\
rtyName={propertyName}
                - /extensions/{id}/events/conditional?eventName={eve\
ntName}
                - /extensions/{id}/properties/file?propertyName={pro\
pertyName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4\
/properties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%\
2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              type: object
              oneOf:
                - $ref: "../NIPC.yaml#/components/schemas/Value"
                - $ref: "./Extension-ReadConditional.yaml#/component\
s/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={propertyNam\
e}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?prope\
rtyName={propertyName}
                - /extensions/{id}/events/conditional?eventName={eve\
ntName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4\
/properties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%\
2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              anyOf:
                - $ref: "../NIPC.yaml#/components/schemas/Value"
                - $ref: "../NIPC.yaml#/components/schemas/SuccessRes\
ponse"
                - $ref: "../NIPC.yaml#/components/schemas/FailureRes\
ponse"

  examples:
    bulkRequest:
      summary: Bulk request example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2Ftemperature
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              value: dGVzdA==
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/p\
roperties/read/conditional?propertyName=https%3A%2F%2Fexample.com%2F\
thermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              value: dGVzdA==
              maxRepeat: 5
              retryTime: 1
    bulkResponse:
      summary: Bulk response example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              value: dGVzdA==
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              status: 200
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/p\
roperties/read/conditional?propertyName=https%3A%2F%2Fexample.com%2F\
thermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              value: dGVzdA==
    errorBulkResponse:
      summary: Error Bulk response example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              type: https://www.iana.org/assignments/nipc-problem-ty\
pes#property-not-readable
              status: 400
              title: Property not readable
              detail: Property https://example.com/thermometer#/sdfT\
hing/thermometer/sdfProperty/temperature is not readable
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              type: https://www.iana.org/assignments/nipc-problem-ty\
pes#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/p\
roperties/read/conditional?propertyName=https%3A%2F%2Fexample.com%2F\
thermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              type: https://www.iana.org/assignments/nipc-problem-ty\
pes#extension-operation-not-executed
              status: 400
              title: Operation not executed
              detail: Operation was not executed since the previous \
operation failed
    firmwareUpgradeRequest:
      summary: Firmware upgrade request example
      value:
        operations:
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2FstartOTA
            data:
              value: dGVzdA==
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/e\
vents/conditional?eventName=https%3A%2F%2Fexample.com%2Fthermometer%\
23%2FsdfThing%2Fthermometer%2FsdfEvent%2FotaStarted
            data:
              value: MQ==
              timeout: 5
          - method: PUT
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/p\
roperties/file?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%\
23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ffirmware
            data:
              fileURL: https://example.com/firmware.bin
              chunkSize: 20
              sha256Checksum: abcdef1234567890abcdef1234567890abcdef\
1234567890abcdef1234567890
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2FfinishOTA
            data:
              value: dGVzdA==
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/p\
roperties/read/conditional?propertyName=https%3A%2F%2Fexample.com%2F\
thermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2FupdateStatus
            data:
              value: MQ==
              maxRepeat: 5
              retryTime: 1
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2FactivateOTA
            data:
              value: dGVzdA==
    firmwareUpgradeResponse:
      summary: Firmware upgrade response example
      value:
        operations:
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2FstartOTA
            response:
              status: 200
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/e\
vents/conditional?eventName=https%3A%2F%2Fexample.com%2Fthermometer%\
23%2FsdfThing%2Fthermometer%2FsdfEvent%2FotaStarted
            response:
              value: MQ==
          - method: PUT
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/p\
roperties/file?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%\
23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ffirmware
            response:
              status: 204
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2FfinishOTA
            response:
              status: 200
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/p\
roperties/read/conditional?propertyName=https%3A%2F%2Fexample.com%2F\
thermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2FupdateStatus
            response:
              value: MQ==
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/prop\
erties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%2Fsdf\
Thing%2Fthermometer%2FsdfProperty%2FactivateOTA
            data:
              status: 200
<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"
=============== NOTE: '\\' line wrapping per RFC 8792 ===============

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
\2/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.14.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-14"
    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/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: query
        description: |-
          The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/firmware"
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/Extension-File'
                - $ref: './Extension-Async.yaml#/components/schemas/\
\Extension-Callback'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
\cdef4/properties/file/status?propertyName=https%3A%2F%2Fexample.com\
\%2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2Ffirmware&i\
\nstanceId=12345678-1234-5678-1234-56789abcdef4
              description: |-
                URL to get the file write status
            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/FailureRespo\
\nse'
      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/Fa\
\ilureResponse'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          property: https://example.com/heartrate#/s\
\dfObject/thermostat/sdfProperty/firmware
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          status: 400
                          type: https://www.iana.org/assignments/nip\
\c-problem-types#invalid-id
                          title: Invalid ID
                          detail: "Invalid request"
                          property: https://example.com/heartrate#/s\
\dfObject/thermostat/sdfProperty/firmware
              responses:
                '200':
                  description: Success
    get:
      tags:
        - NIPC API extensions
      summary: Get the status of a file write operation
      description: |-
        Get the status of a file write operation. This will return
        the status of the file write operation, including any errors
        that may have occurred.
      operationId: getFileWriteStatus
      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 written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/firmware"
      - name: instanceId
        in: query
        description: |-
          The Instance ID for the file write operation.
        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/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureRespo\
\nse'
  /extensions/{id}/properties/file/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get the status of a file write operation
      description: |-
        Get the status of a file write operation. This will return
        the status of the file write operation, including any errors
        that may have occurred.
      operationId: getFileWriteStatus
      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 written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/firmware"
      - name: instanceId
        in: query
        description: |-
          The Instance ID for the file write operation.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, returns the status of the file write\
\ operation.
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
\tension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
\cdef4/properties/file?propertyName=https%3A%2F%2Fexample.com%2Fhear\
\trate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2Ffirmware&instance\
\Id=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the file write response
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
\tension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

components:
  schemas:
# Extensions
## A File Extension
    Extension-File:
      required:
        - fileURL
      type: object
      properties:
        fileURL:
          type: string
          example: "https://domain.com/firmware.dat"
          description: |-
            URL to the firmware file. 
            The HTTP method is assumed to be a GET.
        chunkSize:
          type: integer
        sha256Checksum:
          type: string
          description: firmware checksum
        headers:
          type: object
          additionalProperties:
            type: string
          example:
            x-api-key: fjelk-3dl33f-2wdsd
<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"
=============== NOTE: '\' line wrapping per RFC 8792 ================

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
2/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.14.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-14"
    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
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/properties/read/conditional/status?propertyName=https%3A%2F%2F\
example.com%2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2F\
temperature&instanceId=12345678-1234-5678-1234-56789abcdef4
              description: |-
                URL to get the conditional read status
            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/FailureRespo\
nse'
      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/Fa\
ilureResponse'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          property: https://example.com/heartrate#/s\
dfObject/thermostat/sdfProperty/temperature
                          value: dGVzdA==
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          status: 400
                          type: https://www.iana.org/assignments/nip\
c-problem-types#invalid-id
                          title: Invalid ID
                          detail: "Invalid request"
                          property: https://example.com/heartrate#/s\
dfObject/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: instanceId
        in: query
        description: |-
          Instance 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/FailureR\
esponse'
  /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: instanceId
        in: query
        description: Instance 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:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/properties/read/conditional?propertyName=https%3A%2F%2Fexample\
.com%2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2Ftempera\
ture&instanceId=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the conditional read response
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

components:
  schemas:
# Extensions
    Extension-ConditionalRead:
      allOf:
        - $ref: '../NIPC.yaml#/components/schemas/Value'
        - $ref: './Extension-Async.yaml#/components/schemas/Extensio\
n-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-conditional-event-extension"><name>NIPC API conditional event extension</name>

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-EventConditional.yaml"
=============== NOTE: '\' line wrapping per RFC 8792 ================

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
2/schema
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API event conditional extension
  description: |-
    Non IP Device Control (NIPC) API event conditional extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.14.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-14"
    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}/events/conditional:
    post:
      tags:
        - NIPC API extensions
      summary: Enable an event until a condition is met
      description: Enable an event until a condition is met
      operationId: conditionalEvent
      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: eventName
        in: query
        description: |-
          The SDF event name that needs to be enabled.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfEvent/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-ConditionalEvent'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/events/conditional/status?eventName=https%3A%2F%2Fexample.com%\
2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfEvent%2Ftemperature&ins\
tanceId=12345678-1234-5678-1234-56789abcdef4
              description: |-
                URL to get the conditional event status
            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/FailureRespo\
nse'
      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/Fa\
ilureResponse'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          event: https://example.com/heartrate#/sdfO\
bject/thermostat/sdfEvent/temperature
                          value: dGVzdA==
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          status: 400
                          type: https://www.iana.org/assignments/nip\
c-problem-types#invalid-id
                          title: Invalid ID
                          detail: "Invalid request"
                          event: https://example.com/heartrate#/sdfO\
bject/thermostat/sdfEvent/temperature
                          value: dGVzdA==
                          
              responses:
                '200':
                  description: Success
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional event response
      description: Conditional event response
      operationId: getConditionalEvent
      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: eventName
        in: query
        description: |-
          The name of the SDF event that is enabled.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfEvent/temperature"
      - name: instanceId
        in: query
        description: |-
          Instance ID of the conditional event 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 event value
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureR\
esponse'
  /extensions/{id}/events/conditional/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional event status
      description: Conditional event status
      operationId: getConditionalEventStatus
      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: eventName
        in: query
        description: |-
          The name of the SDF event that is enabled.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfEvent/temperature"
      - name: instanceId
        in: query
        description: Instance ID of the conditional event operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/events/conditional?eventName=https%3A%2F%2Fexample.com%2Fheart\
rate%23%2FsdfObject%2Fthermostat%2FsdfEvent%2Ftemperature&instanceId\
=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the conditional event response
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

components:
  schemas:
# Extensions
    Extension-ConditionalEvent:
      allOf:
        - $ref: './Extension-Async.yaml#/components/schemas/Extensio\
n-Callback'
        - $ref: '../NIPC.yaml#/components/schemas/Value'
        - type: object
          properties:
            timeout:
              description: |-
                Time in seconds to keep the event enabled.
                If the event condition is not met within this time,
                the event will be disabled and marked as failed.
              type: integer
              example: 5
<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"
=============== NOTE: '\' line wrapping per RFC 8792 ================

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
2/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.14.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-14"
    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}/transmit:
    post:
      tags:
        - NIPC API extensions
      summary: Transmit to a device
      description: |-
        Transmit a payload to a device. The transmission is performe\
d on the AP where the device was last seen
      operationId: ActionTransmit
      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/FailureRespo\
nse'
   
  /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#/component\
s/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/FailureRespo\
nse'
                
  /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/sc\
hemas/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/FailureRespo\
nse'

components:
  schemas:
    Transmit:
      allOf:
        - $ref: '../protocolmaps/ProtocolMap.yaml#/components/schema\
s/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,
              "sdfProtocolMap": {
                "ble": {
                  "serviceID": "1809",
                  "characteristicID": "2A1D"
                }
              }
            },
            "measurement_interval": {
              "description": "Measurement Interval",
              "observable": false,
              "writable": false,
              "readable": true,
              "sdfProtocolMap": {
                "ble": {
                  "serviceID": "1809",
                  "characteristicID": "2A21"
                }
              }
            }
          },
          "sdfEvent": {
            "temperature_measurement": {
              "description": "Temperature Measurement",
              "sdfOutputData": {
                "sdfProtocolMap": {
                  "ble": {
                    "type": "gatt",
                    "serviceID": "1809",
                    "characteristicID": "2A1C"
                  }
                }
              }
            },
            "intermediate_temperature": {
              "description": "Intermediate Temperature",
              "sdfOutputData": {
                "sdfProtocolMap": {
                  "ble": {
                    "type": "gatt",
                    "serviceID": "1809",
                    "characteristicID": "2A1E"
                  }
                }
              }
            }
          }
        }
      },
      "description": "Generic Access, Device Information",
      "sdfProperty": {
        "device_name": {
          "description": "Device Name",
          "observable": false,
          "writable": true,
          "readable": true,
          "sdfProtocolMap": {
            "ble": {
              "serviceID": "1800",
              "characteristicID": "2A00"
            }
          }
        },
        "appearance": {
          "description": "Appearance",
          "observable": false,
          "writable": false,
          "readable": true,
          "sdfProtocolMap": {
            "ble": {
              "serviceID": "1800",
              "characteristicID": "2A01"
            }
          }
        },
        "manufacturer_name_string": {
          "description": "Manufacturer Name String",
          "observable": false,
          "writable": false,
          "readable": true,
          "sdfProtocolMap": {
            "ble": {
              "serviceID": "180A",
              "characteristicID": "2A29"
            }
          }
        },
        "model_number_string": {
          "description": "Model Number String",
          "observable": false,
          "writable": false,
          "readable": true,
          "sdfProtocolMap": {
            "ble": {
              "serviceID": "180A",
              "characteristicID": "2A24"
            }
          }
        },
        "hardware_revision_string": {
          "description": "Hardware Revision String",
          "observable": false,
          "writable": false,
          "readable": true,
          "sdfProtocolMap": {
            "ble": {
              "serviceID": "180A",
              "characteristicID": "2A27"
            }
          }
        },
        "firmware_revision_string": {
          "description": "Firmware Revision String",
          "observable": false,
          "writable": false,
          "readable": true,
          "sdfProtocolMap": {
            "ble": {
              "serviceID": "180A",
              "characteristicID": "2A26"
            }
          }
        },
        "system_id": {
          "description": "System ID",
          "observable": false,
          "writable": false,
          "readable": true,
          "sdfProtocolMap": {
            "ble": {
              "serviceID": "180A",
              "characteristicID": "2A23"
            }
          }
        }
      },
      "sdfEvent": {
        "isPresent": {
          "description": "BLE advertisements",
          "sdfOutputData": {
            "sdfProtocolMap": {
              "ble": {
                "type": "advertisements"
              }
            }
          }
        },
        "isConnected": {
          "description": "BLE connection events",
          "sdfOutputData": {
            "sdfProtocolMap": {
              "ble": {
                "type": "connection_events"
              }
            }
          }
        }
      }
    }
  }
}
<CODE ENDS>
]]></artwork></figure>

</section>


  </back>

<!-- ##markdown-source:
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
6qYp+epXQofVdn1Z6Gv3Zv1cg1sgGwMMfOh1XIGyn29dDz7pffaTo9pdvvhF
Teazf7+rR6Rmt/+DXC0OjLU1pLWq3nvLWadLZFzbtm0UcwlfEyUL/KSMrbOo
LNRBdHfv+d7R3qJA5T6/cbg2n9YlHdXPlaMF8/CdqyFvgw2uL3qq3kyHUT0a
HLxZ+GBxh98mDtRIFPrKp+WpuqJ8cG0oNpv6MGzGO/yVMGxOUNziAnMLGT6o
k+HtQDcZj81bEuSj+iZru1xzDNJMWQe1DKJzCfG7Gko6G6vzQuDxrfXdILBy
7zRNHCceS4R/4Ajw3pzzAUXWm9WXJr2qLeNkJcq0oF6cxLajtRUSaAonKXPj
HMe00/8tih2y1fXc2EL2OEK/VWXLkysHvvKoBruZ9/tZ+h6vaLj3J/Stvnf1
tjLVuN5wktNARRrTgFYjVChGyfFMNcDerZC0E3LtXA0HWUxqeTTmywzqAE4L
67sSAlCkOOEzSUx15AMqBnXwC87SKZeF6ab1SqQvtBz82Z6mmokku2qYC79i
hx8sMLhq7Bm+pGFWDvQcPVM7y1z8gn9uT6f7wwoXMmqnh2C0ZkG6/544x8hN
aGXKVeYi4Q9ROFZmS+X2bXJXVCYm0V5CyMKwYo9IM3XdJkZh8lGgI6zdDL0H
kpdkH8kIU2GgXwpPCXYoLeKG+VHyz/LJnW9CIZ9M8lEP3UNraX4VL0n7IFp+
z6omgLq7UM852FDOyEl5Al3mTh3ExZ6cXIGPQ1P4tRlQ44mWPOQbaaem1oSV
4tjqQvUwjfKcy/MSLVXfFumBv+xs78RZ0dM+aw+2dJa4ne1wgNeqI1Wvr7Ka
8I7cOdxVfQ5meZGeHiFt6oVPKJ9ZNBurGwsmWeJmQ9cLFFkzCt/JgVv7iz4P
f137i779hb9RAPlNpXr4rUh/A7ngN0L2v76r2qGUyxQ9l8hB5S/2X+mM6J1Q
XvRp5Vl7SGpln/GpvWiL4NZhWmSRyefOZcbknLHGpu86uZsdwO3sqEV4FdYd
OaT4uchWmhcbZC4tRrYi5+y9LgJbPTJRxq7JD9imwuymr+NK7YbKyYDSrq0a
EXTlrpRgmE1F1ilVYbMys5jYMx4pV1dmalxlE9euwdbVmDA3mrK6MUQXZDIx
W1cqeD7Y4IyfS90VzCZ6Ap1ZlnR4cisCUhUMRmmCa4mRRIyxb1uusxJaEFVT
1HeHR1YzhdJ8MwSIFbkla0rkTfWSZHW71g33IpBC1CUbiZUqDyT7akboGdah
GHmgPYn2puTlycK5L5vC+EmKO/aqDlhS2ahUrNzWg0cqx8okPhtTghPrxdtv
J7erR1MkkMbDqcUI7/G81OnkLvl8HpWElSUeUNPnwkdUNS0d0rP85ohe9oiq
cLhrPqTOvn3xY+qMvpyDWrZkGIlz7p3wIlfCcifMArKO67gQpKLfL2sqeRvU
eC+tUPefdWSJEY1hqCKbxR4TC6gi+BqLvlnV2EI4Z3X0uQGENem4QrEWuDrs
Dwpw1gVgKB57BSgojouPutagvY1Hj+5JiIyI5Pgi/i2/i6CNv+u/1TNL+MXH
/HWNpEqc1uf6vWbwN+21WsNnxwa4T6XDMdPdaKZqN7i+In1xVh5EY3O3ZdBD
7rfEQtuoJ1fttK3UZG2s/QpKcniIWpWypVTORXFiHPmrk+OEEK8tB5arg9u6
ZWoCteeuqRWo+cKpupTLmMYXArlzobQYTPw7EVR3wr5QagKe/1qpFfz03dKP
CkI748URmWATcr+hanqVIFYuX1STRMstgWLlp7Czaylr1J8l4qlrJ9GOyO5R
HlbcJ2FJ6lahuaykv6bkZKgrXtqVFk3i9iNnpZbfX3GSxbFKP6YjpXNd45vi
1cqLr8TBigV9o7tZ4wSjUISmcGDnkWiR1YzuyWGFCj7K0V9VXVGgMsV42Dm7
Zdc1GcUCkkU9ScX0KMo/e8G8bGbvqJCQ3p1Xfj8eT8Vau3C3clzKVRkhAauK
CSCQWdNk0dzqXd00RL6LKEqXqfNiGRcfjiFyGvATN4NrTMkWrIA8J9vfnaQb
d0PLxX41FNmG62aJ2/rdskOwuXBzarcBpREBz0HL5ruc7XKiQxPspoM5uKoO
ET8O57Av8NzWQdUoJ8diq94zTPbE7l6IIGmwEnli0zsnRo6zq6gcqM5Fk0kn
Kr9gZKM2RWsKROOZOzsrg6g9K0kYDe8N0MxY0YVktZvsCWflqDBJKp2j3+KO
0n/0rWMfqj6c8M1z7Y3vpLJTrESC9kirNXkeh1LzwGqhEMJ6yc4HQsYGBI0k
/7ISSFK8kzM6wQ+9Oc85O5TEABLSmtzgvpxrFIQL85CA66HOeE0FWZV3f9eB
Z6WGvZ2RR6d42uFMPB0KymOCgW7ogaX6RwMKA2P4a9OHVQgFNyGgfIN8Whw/
Sp0N6d2qw8ed5EvA1BNdj5rDRpUDIld0U1p8LFU+KIxjlQUTuzCLhZIB2/al
6QrZBFbE4ZtCnzhRkeQiIsCsGnElyZ1EOAgFzhqusEhnQ5WpKpTj2m6EHZgB
xri2s0T3KyXb1JvCWTfLWodiDOVcBRe/SKYkr5fIr6U8nrbHpi1TmMjjIKjI
cElVeFOvVoQ+9qi2p9Qz+fB0rijkU3R4yUpG6G7FpFOROp1deLUq6pVNSPZ2
SVYkvhXQYiqbf2BcTmyq9ksnmfJOA01286ZCVjszl9CL5jInMyV8M8uic1VO
RLZBwwWkRrRpWa62kYEesTnqi1bl8biBLVCRlaXURc7O2AXmq0vjW5k2kG4L
ZH1Pw+8ledl0hm87I0guMB6IO4D/AALzIq8ORgFhZWoEjujMJiWrdhIxRUpo
7VPMIIWd8zLYxKNZ331hfFsPth4R4xPDBmEQzRRb6/NvVtJzsrksySCFJihl
BBJYLGSBKnTE4NugLiZSrEFMYaH34bP//H24/fPPZANava4ZnMxOk2ECvZWH
j3H4J2p4jz/ubHqKM/G6dNXsjWOGYsMI4gzzSssajXlCASHnMEBX1Q00YquI
Jomcoygn1ePm+joHfCOKG9LK2WxzdQLgYAcknqubAHWuTHp/T2uMl+FbHUWk
5y6OyjEUboo/nf7JITlleuQhQSWtf3N9K3yZilAiVcrElNTsAbj8E6PDnwD6
JVS+YqDV2wCjpzr6QKyWBlTxVr6Iq4NSGxNypUXrRc7W22BexLOEZlXispDw
o8bccM4aXCc9p6zWidI6iMqG7+UEOoe8Pg4ljoAQ8zMFO0KSkFFyMFiVXuWs
mFgJXedI1eK5uFB9fP4cuDmfyk3FXws4ar0oSFbRVqLgP3t8taBrJQqSJegL
CINlWfDoxBUDUfdxkgZ5pEWcokRKu/YdlHJ8SGNXp6gR2uhWu6XcNk9mo0WU
LyWugRk4A7eWbRy5JvDINTR/474qnbQVd5oknS9On28kGn2pFg29tDZzCEx7
Snuu/dWrsoZGIGqg1GpJLH5eOISY3jUYJbVLvwa1LduGpUaK5TLXwhy1UAGK
ZVqmKJv1cgxT5KwSLM8whWSrjWFKgUqhSsmcCst5Jzbgd5K+A9MQWUnrVMsy
M/KlXSLjLo8nkKKdU+ngy6+HyUhlxyiXSQpmEyDn43OnmnhoJc5ZxbY4Gc+L
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

-->

</rfc>

