<?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.4) -->


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

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


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

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

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

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 60?>

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



    </abstract>



  </front>

  <middle>


<?line 68?>

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

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

<t>Low-power sensors, actuators and other connected devices introduced in
environments and use cases such as building management, healthcare, workplaces,
manufacturing, logistics and hospitality are often battery-powered. With 
limited power budget, they may not be able to support the IP protocol on their
wired or wireless interfaces, hence they support protocols that require a lower
power budget. Promiment examples of such protocols are <xref target="BLE53"/> and
<xref target="Zigbee22"/>. These devices typically do require to communicate with devices
or applications that are connected to IP-based networking infrastructure. 
Therefore, applications on the IP network that need to communicate or receive
telemetry from these non-IP low-power devices must do so through a gateway 
function on the IP network. This gateway functions then translates the 
communication to the non-IP protocol that the low-power device supports.</t>

<figure title="Gateway for non-IP Devices" anchor="gw"><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="56" y="84">app</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 |                     
    |    app      |   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. This results in parallel
infrastructure of both gateways and non-IP networks being deployed on a case
by case basis, each connecting separately into the IP network, with a distinct
set of APIs. At the same time, wireless access points supporting both IP-based 
wireless connectivity as well as non-IP based wireless technologies are
deployed ubiquitiously. Many of these wireless access points are equipped with
radios that can transmit and receive different frame types, such as <xref target="BLE53"/>
and <xref target="Zigbee22"/>. This specification aims to define a Gateway API for these 
Non-IP protocols that can be leveraged by this wireless infrastructure in order
to connect Non-IP devices into IP networks. The specification aims to be
extensible, in order to support existing and future non-IP protocols.</t>

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

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

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

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

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

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

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

<figure title="Basic Architecture" anchor="arch"><artset><artwork  type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="304" width="560" viewBox="0 0 560 304" 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 levering a CBOR-based pub/sub interface.</t>

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

<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP
14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all
capitals, as shown here.</t>

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

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

<t>Non-IP protocols, such as BLE or Zigbee, typically define a number of basic
operations that are similar across protocols. Examples of this are read and 
write data. NIPC provides a unified API to support those operations.</t>

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

<figure title="NIPC prerequisites" anchor="prereq"><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. NIPC operations
are operations on properties, or constitute actions or events on devices,
as per the affordances defined in an SDF model.</t>

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

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

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

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

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

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

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

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

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

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

<t>Protocol mapping is required to map a protocol agnostic affordance to a 
protocol-specific operation, as implementations of the same affordance will
differ between protocols. For example BLE will address a property as a service
characteristic, while a property in Zigbee is addressed as a property in a
cluster of an endpoint.</t>

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

<figure title="Property Mapping" anchor="protmap"><artset><artwork  type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="208" width="256" viewBox="0 0 256 208" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
<path d="M 24,48 L 24,128" fill="none" stroke="black"/>
<path d="M 96,80 L 96,96" fill="none" stroke="black"/>
<path d="M 96,144 L 96,160" fill="none" stroke="black"/>
<path d="M 24,64 L 72,64" fill="none" stroke="black"/>
<path d="M 96,96 L 120,96" fill="none" stroke="black"/>
<path d="M 24,128 L 72,128" fill="none" stroke="black"/>
<path d="M 96,160 L 120,160" fill="none" stroke="black"/>
<polygon class="arrowhead" points="128,160 116,154.4 116,165.6" fill="black" transform="rotate(0,120,160)"/>
<polygon class="arrowhead" points="128,96 116,90.4 116,101.6" fill="black" transform="rotate(0,120,96)"/>
<polygon class="arrowhead" points="80,128 68,122.4 68,133.6" fill="black" transform="rotate(0,72,128)"/>
<polygon class="arrowhead" points="80,64 68,58.4 68,69.6" fill="black" transform="rotate(0,72,64)"/>
<g class="text">
<text x="48" y="36">protocolmap</text>
<text x="96" y="68">ble</text>
<text x="144" y="100">BLE</text>
<text x="196" y="100">property</text>
<text x="108" y="132">zigbee</text>
<text x="156" y="164">Zigbee</text>
<text x="220" y="164">property</text>
</g>
</svg>
</artwork><artwork  type="ascii-art"><![CDATA[
  protocolmap
    |
    +-----> ble
    |        |
    |        +--> BLE property
    |
    +-----> zigbee
             |
             +--> Zigbee property

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

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

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

<t>where-</t>

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

<t>Example protocol mapping:</t>

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

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

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

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

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

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

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

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

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

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

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

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

</section>
<section anchor="management-apis"><name>Management APIs</name>

<t>Management APIs are APIs that perform device connection management and
protocol-specific operations, but do not use registered affordances. These APIs have embedded
protocol mappings. They require explicit connection management.</t>

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

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

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

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

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

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

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

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

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

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

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

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

<section anchor="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>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 
extension APIs. The paths can 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/v1/",
  "extensions": [
    "/extensions/{id}/bulk",
    "/extensions/{id}/firmware",
    "/extensions/{id}/properties/blob",
    "/extensions/{id}/properties/file",
    "/extensions/{id}/properties/read/conditional",
    "/extensions/{id}/properties/write"
  ]
}
]]></sourcecode></figure>

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

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

<t>paths:</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>For example:</t>

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

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

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

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

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

<t>A failure response will consist of a HTTP status code of 4xx or 5xx, and 
will follow the <xref target="RFC9457"/> Problem Details format with <spanx style="verb">application/problem+json</spanx>
media type. The response will contain a <spanx style="verb">type</spanx> field with a URI identifying
the error type, and a human-readable <spanx style="verb">detail</spanx> field. The <spanx style="verb">type</spanx> field
is a URI and is described in <xref target="errorhandling"/>.</t>

<t>Failure response:</t>

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

<figure title="Example failure response" anchor="failure"><artwork><![CDATA[
{
  "type": "https://www.iana.org/assignments/http-problem-types#nipc-invalid-id",
  "status": 400,
  "title": "Invalid Device ID",
  "detail": "Device ID 12345678-1234-5678-1234-56789abcdef4 does not exist or is not a device"
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <t>"type" is a URI identifying the specific error type</t>
  <t>"status" is the HTTP status code</t>
  <t>"title" is a brief, human-readable summary of the error type</t>
  <t>"detail" is a human-readable explanation specific to this occurrence</t>
</list></t>

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

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

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

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

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

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

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Query Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

<t>Query Parameters:</t>

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

<t>Request Body:</t>

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

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

<t><list style="symbols">
  <t>mqttClient: an empty object that denotes that the data application
is an MQTT client that will receive streaming data over MQTT</t>
  <t>mqttBroker: an object that contains the MQTT broker information
where the broker will publish the streaming data.
  <list style="symbols">
      <t>URI: the URI of the MQTT broker</t>
      <t>username: the username to authenticate with the MQTT broker</t>
      <t>password: the password to authenticate with the MQTT broker</t>
      <t>brokerCACert: the CA certificate of the MQTT broker (optional)</t>
      <t>customTopic: the custom topic to publish the streaming data to
(optional)</t>
    </list></t>
  <t>webhook: an object that contains a webhook URL along with any 
 credentials that are required to authenticate the webhook. 
 The webhook URL is the endpoint where the streaming data will be sent.
  <list style="symbols">
      <t>URI: the webhook URL</t>
      <t>headers: An object that contains the headers to be sent with the webhook
request. The headers can contain any authentication information
required by the webhook server.</t>
      <t>serverCACert: the CA certificate of the webhook server (optional)</t>
    </list></t>
  <t>websocket: an object that contains a websocket URL along with any 
credentials that are required to authenticate the websocket. 
The websocket URL is the endpoint where the streaming data will be sent.
  <list style="symbols">
      <t>URI: the websocket URL</t>
      <t>headers: An object that contains the headers to be sent with the websocket
request. The headers can contain any authentication information
required by the websocket server.</t>
      <t>serverCACert: the CA certificate of the websocket server (optional)</t>
    </list></t>
</list></t>

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

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

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

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

<t>Response:</t>

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

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

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

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

<t>Query Parameters:</t>

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

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

<t>Response:</t>

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

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

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

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t><list style="symbols">
  <t>NIPC Property APIs: These APIs allow applications to get and update device 
properties.</t>
  <t>NIPC Event APIs: These APIs allow applications to enable or disable event
reporting on devices.</t>
  <t>NIPC Action APIs: These APIs allow applications to perform actions on
devices.</t>
  <t>NIPC Management APIs: These APIs allow
applications to manage device connections and perform protocol-specific
operations.</t>
</list></t>

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

<t>The SDF global name will be used against the registered SDF model to 
determine the protocol-specific protocolMap that the NIPC API will operate on.</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>The event is a global name reference to an <spanx style="verb">sdfEvent</spanx>.</t>

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

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

<t>Response:</t>

<t>Returns HTTP status code 201 Created with a Location header pointing to the created event instance.</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where "event" is the event URI that was enabled for this instance.</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

<t><list style="symbols">
  <t>"instanceId" is the unique instance ID for each enabled event</t>
  <t>"event" is the event URI for each enabled event</t>
</list></t>

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

</section>
<section anchor="enable-event-reporting-on-a-group-of-devices"><name>Enable event reporting on a group of devices</name>

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

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

<t>Response:</t>

<t>Returns HTTP status code 201 Created with a Location header pointing to the created event instance.</t>

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

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

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

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

</section>
<section anchor="disable-event-reporting-on-a-group-of-devices"><name>Disable event reporting on a group of devices</name>

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

</section>
<section anchor="get-event-status-on-a-group-of-devices"><name>Get event status on a group of devices</name>

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where "event" is the event URI that was enabled for this instance.</t>

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

</section>
<section anchor="get-status-of-multiple-events-on-a-group-of-devices"><name>Get status of multiple events on a group of devices</name>

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

<t><list style="symbols">
  <t>"instanceId" is the unique instance ID for each enabled event</t>
  <t>"event" is the event URI for each enabled event</t>
</list></t>

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

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

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

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

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

<t>Description: Check the status of an action on a specific device</t>

<t>Parameters:</t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>instanceId: the instance ID of the action (obtained from the Location header)</t>
</list></t>

<t>Response:</t>

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

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

<t>where "status" indicates the current state of the action (e.g., "IN_PROGRESS" or "COMPLETED").</t>

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

<t><list style="symbols">
  <t>Connection retry parameters</t>
  <t>A protocol map object. In the case of BLE, if no protocol map is included,
service discovery is performed to discover all supported properties when
connecting to a device. Optionally, service discovery may be limited to
properties defined in the "ble" protocol extension. The services to be 
discovered can be added in an array. Property discover can be buffered
across connections, so the API also supports caching parameters.</t>
</list></t>

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

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

<t>where-</t>

<t><list style="symbols">
  <t>"retries" defines the number of retries in case the operations does not 
succeed</t>
  <t>"retryMultipleAPs" can be used in case there is an infrastructure with 
multiple access points or radios that can reach the device. If set to "true"
a different access point may be used for retries.</t>
</list></t>

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

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

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

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

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

<t>Response:</t>

<t>Success responses include a protocol mapping with an array of 
discovered properties, as defined in the specific protocol.
For example, for BLE, this is an array of supported services, which in turn
contains an array of charateristics, which in turn contains an array of
descriptors, as shown in <xref target="BLEservices"/>.</t>

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

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

<t><list style="symbols">
  <t>A protocol map object. In the case of BLE, if no protocol map is included,
service discovery is performed to discover all supported properties when
connecting to a device. Optionally, service discovery may be limited to
properties defined in the "ble" protocol extension. The services to be 
discovered can be added in an array. Property discover can be buffered
across connections, so the API also supports caching parameters.</t>
</list></t>

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

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

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

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

<t>Response:</t>

<t>Success responses include a protocol mapping with an array of 
discovered properties, as defined in the specific protocol.
For example, for BLE, this is an array of supported services, which in turn
contains an array of charateristics, which in turn contains an array of
descriptors, as shown in <xref target="BLEservices"/>.</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

<t>Returns HTTP status code 200 OK with device ID on successful disconnect.</t>

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

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

<t>where "id" is the id of the device.</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

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

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

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

<t>Protocol mappings need to be IANA registered, see <xref target="iana-prot-map"/>.</t>

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

<t>/extension</t>

<t>The extension APIs allow for extensibility of the APIs, either IANA 
registered extensions (<xref target="iana-api-ext"/>) or vendor-specific extensions.
Extension APIs must leverage the basic NIPC defined APIs and combine them in 
compound statements in order to streamline application operation against
devices, make operations more expediant and convenient in one API call.
In principle they do not add any basic functionality. In
the OpenAPI model <xref target="NIPCextensions"/> below, we have defined a few example 
extensions.</t>

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

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

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

<t><list style="symbols">
  <t>Generic: Broadly applicable errors, including authorization, 
invalid identifiers, and generic failures.</t>
  <t>Property APIs: Errors related to property APIs (read/write).</t>
  <t>Event APIs: Errors related to event APIs (enable/disable).</t>
  <t>Protocol specific: Errors related to protocol-specific operations.</t>
  <t>Extension APIs: Errors related to extension APIs.</t>
</list></t>

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

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

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

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

<t>The publish/subscribe interface, or data streaming interface, is an MQTT
publishing interface. Pub/sub topics can be created and managed by means
of the /registration/data-app API.</t>

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

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

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

<t>The DataSubscription struct is a CBOR map that will contain the raw data
in bytes and a timestamp of the data. Optionally, the message will also
have a deviceID that corresponds to the SCIM ID of the device if the 
payload is associated to a known device.</t>

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

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

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

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

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

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

BleSubscription = {
  serviceID: text,
  characteristicID: text
}

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

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

ZigbeeSubscription = {
  endpointID: int,
  clusterID: int,
  attributeID: int
  attributeType: int
}

RawPayload = {
  contextID: text
}
]]></sourcecode></figure>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

{
  "sdfName": "https://example.com/thermometer#/sdfThing/thermometer"
}
]]></artwork></figure>
  <vspace blankLines='1'/>
Request Body: JSON object with the SDF model, from <xref target="thermometer-sdf"/></t>
  <t>Read a property from the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
GET /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/device_name
Accept: application/json
Host: localhost
    
HTTP/1.1 200 OK
content-type: application/json
    
[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
]]></artwork></figure>
  </t>
  <t>Write to a property on the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
PUT /devices/12345678-1234-5678-1234-56789abcdef4/properties
Content-Type: application/json
Host: localhost
    
[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
    
HTTP/1.1 200 OK
content-type: application/json
    
[
  {
    "property": "https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/device_name",
    "value": "dGVzdA=="
  }
]
]]></artwork></figure>
  </t>
</list></t>

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

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

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

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

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

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

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

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

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

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

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

<t>In order to enable a network wishing to offer NIPC ALG functions, the network
administrator authorizes application(s) to perform operations on the Gateway.
This happens out of band and may be accomplished by means of exchanging tokens
or public keys.
Authorization can be role-based. The 3 primary roles are:</t>

<t><list style="numbers" 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-prot-map"><name>Protocol mapping</name>

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

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

<t><list style="symbols">
  <t>Protocol map name</t>
  <t>Protocol name</t>
  <t>Description</t>
  <t>Reference of the document describing the protocol mapping. This document 
must be an RFC.</t>
</list></t>

<t>Following protocol mappings are described in this document:</t>

<texttable>
      <ttcol align='left'>Protocol map</ttcol>
      <ttcol align='left'>Protocol Name</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Reference</ttcol>
      <c>ble</c>
      <c>Bluetooth Low Energy (BLE)</c>
      <c>Protocol mapping for BLE devices</c>
      <c>This document</c>
      <c>zigbee</c>
      <c>Zigbee</c>
      <c>Protocol mapping for Zigbee devices</c>
      <c>This document</c>
</texttable>

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

<t>IANA is requested to create a new registry called "NIPC API extensions". 
Registering extensions is optional, extensions can be generally
available (IANA registered), or vendor-specific (not IANA registered).</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>/extension/{id}/bulk</c>
      <c>Bulk API</c>
      <c>Call multiple NIPC's in a single request</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extension/{id}/properties/file</c>
      <c>File write API</c>
      <c>Write a file with multiple property ops</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extension/{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}/firmware</c>
      <c>Firmware upgrade API</c>
      <c>Firmware upgrade API, leveraging mutiple opsed</c>
      <c><xref target="NIPCextensions"/></c>
      <c>/extensions/{id}/manage/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="problem-details-for-http-apis"><name>Problem Details for HTTP APIs</name>

<t>This document registers new Problem Details types in the "HTTP Problem Type" registry established by <xref target="RFC9457"/>.</t>

<t>IANA is requested to register the following URIs in the "HTTP 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/http-problem-types#nipc-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/http-problem-types#nipc-invalid-sdf-url</c>
      <c>Invalid SDF URL or SDF affordance not found</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-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/http-problem-types#nipc-sdf-model-already-registered</c>
      <c>SDF model already registered</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-sdf-model-in-use</c>
      <c>SDF model in use</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-property-not-readable</c>
      <c>Property not readable</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-property-not-writable</c>
      <c>Property not writable</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-event-already-enabled</c>
      <c>Event already enabled</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-event-not-enabled</c>
      <c>Event not enabled</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-event-not-registered</c>
      <c>Event not registered for any data application</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-already-connected</c>
      <c>Device already connected</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-no-connection</c>
      <c>No connection found for device</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-connection-timeout</c>
      <c>BLE connection timeout</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-bonding-failed</c>
      <c>BLE bonding failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-connection-failed</c>
      <c>BLE connection failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-protocolmap-ble-service-discovery-failed</c>
      <c>BLE service discovery failed</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-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/http-problem-types#nipc-protocolmap-zigbee-connection-timeout</c>
      <c>Zigbee connection timeout</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-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/http-problem-types#nipc-extension-broadcast-invalid-data</c>
      <c>Invalid transmit data</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-extension-firmware-rollback</c>
      <c>Firmware rollback</c>
      <c>This document</c>
      <c>https://www.iana.org/assignments/http-problem-types#nipc-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;
&RFC2119;
&RFC8174;
&I-D.ietf-asdf-sdf;
&RFC9114;
&RFC7159;
&RFC8949;
&RFC3986;
&RFC6570;
&RFC9457;
&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 2214?>

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

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

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

paths:
### NIPC Property APIs
  /devices/{id}/properties:
    put:
      tags:
        - NIPC property APIs
      summary: Update a value of one or more properties on a device
      description: |-
        Write a value to a property or multiple properties to a device. If underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. 
      operationId: UpdateProperties
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyValueArray'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/PropertyValueResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    get:
      tags:
        - NIPC property APIs
      summary: Read a value from one or multiple properties on a device
      description: |-
        Read a value to a property or multiple properties from a device. If underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. 
      operationId: GetProperties
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: Properties to be read
        required: true
        allowReserved: true
        schema:
          type: array
          items:
            type: string
            example: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValueResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
 
 ### NIPC Event APIs
  /devices/{id}/events:
    post:
      tags:
        - NIPC event APIs
      summary: Enable an event on a specific device
      description: |-
        Enable an event on a specific device or for a group of devices. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it.
      operationId: EnableEvent
      parameters:
      - name: id
        in: path
        description: device id or group id
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: eventName
        in: query
        description: event that needs to be enabled
        required: true
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '201':
          description: Success
          headers:
            Location:
              description: Location of the created event
              schema:
                type: string
                format: uri
                example: "/devices/{id}/events?instanceId={instanceId}"
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    delete:
      tags:
        - NIPC event APIs
      summary: Disable an event on a specific device
      description: |-
        Disable an event on a specific device or a group of devices. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. 
      operationId: DisableEvent
      parameters:
      - name: id
        in: path
        description: device id or group id
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: instance id of the event that needs to be disabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
               
    get:
      tags:
        - NIPC event APIs
      summary: Get status of events on a device
      description: |-
        Get status of an event or multiple events on a specific device
      operationId: GetEvents
      parameters:
      - name: id
        in: path
        description: The ID of the device.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: Instance ID of the events that need to be filtered
        required: false
        schema:
          type: array
          items:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventStatusResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

  /groups/{id}/events:
    post:
      tags:
        - NIPC event APIs
      summary: Enable an event on a group of devices
      description: |-
        Enable an event on a group of devices. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it.
      operationId: EnableGroupEvent
      parameters:
      - name: id
        in: path
        description: group id for which the event needs to be enabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: eventName
        in: query
        description: event that needs to be enabled
        required: true
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected"
      responses:
        '201':
          description: Success, event enabled
          headers:
            Location:
              description: Location of the created event
              schema:
                type: string
                format: uri
                example: "/groups/{id}/events?instanceId={instanceId}"
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
    delete:
      tags:
        - NIPC event APIs
      summary: Disable an event on a group of devices
      description: |-
        Disable an event on a group of devices. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it.
      operationId: DisableGroupEvent
      parameters:
      - name: id
        in: path
        description: group id for which the event needs to be disabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: instance id of the event that needs to be disabled
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
    get:
      tags:
        - NIPC event APIs
      summary: Get status of events on a group of devices
      description: |-
        Get status of an event or multiple events on a group of devices.
      operationId: GetGroupEvents
      parameters:
      - name: id
        in: path
        description: group id of the SCIM group
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: Instance IDs of the events that need to be filtered
        required: false
        schema:
          type: array
          items:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, events retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventStatusResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

### NIPC action APIs
  /devices/{id}/actions:
    post:
      tags:
        - NIPC action APIs
      summary: Perform an action on a device
      description: |-
        Perform an action on a device. If the underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. Id cannot be a group-id.
      operationId: ActionProperty
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: actionName
        in: query
        description: action that needs to be performed
        required: true
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/healthsensor/sdfAction/start"
      requestBody:
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
        required: false
      responses:
        '202':
          description: Accepted, action is being performed
          headers:
            Location:
              description: Location of the action
              schema:
                type: string
                format: uri
                example: "/devices/{id}/actions?instanceId={instanceId}"
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
    get:
      tags:
        - NIPC action APIs
      summary: Get status of an action on a device
      description: |-
        Get status of an action on a specific device or a group of devices. Success is action is active, failure if action not active.
      operationId: GetAction
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: instance id of the action that needs to be checked
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, action is active
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionResponse'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
               
  /devices/{id}/manage/connection:
    post:
      tags:
        - NIPC management APIs
      summary: Connect a device
      description: |-
        Connect a device. 3 retries by default, optionally retry policy can be defined in the API body. If the protocol requires service discovery, full service discovery will be performed, unless specific services are described in the API body.
      operationId: ActionCreateConnection
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - $ref: '#/components/schemas/Connection'
                - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceList'
        required: false
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
  
    put:
      tags:
        - NIPC management APIs
      summary: Update cached ServiceMap for a device.
      description: |-
        Update cached ServiceMap for a device. Full service discovery will be performed, unless specific services are described in the API body.
      operationId: ActionUpdateServiceMap
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceList'
        required: false
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
  
    delete:
      tags:
        - NIPC management APIs
      summary: Disconnect a device 
      description: |-
        Disconnect a device.
      operationId: ActionDeleteConnection
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'
                  
    get:
      tags:
        - NIPC management APIs
      summary: Get connection state for a device
      description: |-
        Get connection status for a device. Success when device(s) is/are connected, includes service map for the device if available. Failure when a device is not connected
      operationId: ActionGetConnection
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Id'
                  - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-ServiceMap'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'


### Registrations
  /registration/model:
    post:
      tags:
        - NIPC registration APIs
      summary: Register an sdfObject
      description: |-
        Register an sdfObject, including Properties, Events and actions
      operationId: registerSdfObject
      requestBody:
        content:
          application/sdf+json:
            schema:
              $ref: '#/components/schemas/SdfModel'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  allOf:
                    - $ref: '#/components/schemas/SdfReference'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

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

  /registration/data-app:
    post:
      tags:
        - NIPC registration APIs
      summary: Register a dataApp
      description: |-
        Register a dataApp that is able to receive device data. 
      operationId: registerDataApp
      parameters:
        - name: dataAppId
          in: query
          description: id of the data app that will be registered
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DataApp'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

    put:
      tags:
        - NIPC registration APIs
      summary: Update registration of a dataApp
      description: |-
        Update registration of a dataApp that is able to receive device data. 
      operationId: UpdateDataApp
      parameters:
        - name: dataAppId
          in: path
          description: id of the data app that will be updated
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DataApp'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'
                  
    delete:
      tags:
        - NIPC registration APIs
      summary: Delete registration of a dataApp
      description: |-
        Delete registration of a dataApp that is able to receive device data. 
      operationId: DeleteDataApp
      parameters:
        - name: dataAppId
          in: path
          description: id of the data app that will be updated
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'
  
    get:
      tags:
        - NIPC registration APIs
      summary: Get registration of a dataApp
      description: |-
        Get registrationdetails of a dataApp that is able to receive device data. 
      operationId: GetDataApp
      parameters:
        - name: dataAppId
          in: query
          description: id of the data app that will be updated
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

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

## A property
    Property:
      required:
        - property
      type: object
      properties:
        property:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"

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

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

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

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

## Event
    Event:
      required:
        - event
      type: object
      properties:
        event:
          type: string
          description: percent-encoded JSON pointer to the SDF event object
          example: https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected

    InstanceId:
      type: object
      properties:
        instanceId:
          type: string
          format: uuid
          description: A SCIM-generated UUID for the event instance
          example: 12345678-1234-5678-1234-56789abcdef4
            
## A Connection
    Connection:
      type: object
      properties:
        retries:
          type: integer
          format: int32
          example: 3
        retryMultipleAPs:
          type: boolean
          example: true
          
 ## DataApp
    DataApp:
      oneOf:
        - $ref: '#/components/schemas/DataAppMqttClient'
        - $ref: '#/components/schemas/DataAppMqttBroker'
        - $ref: '#/components/schemas/DataAppWebhook'
        - $ref: '#/components/schemas/DataAppWebsocket'
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'


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

    DataAppMqttBroker:
      type: object
      properties: 
        mqttBroker:
          type: object
          required:
            - URI
            - username
            - password
          properties: 
            URI: 
              type: string
              example: mqtt.broker.com:8883
            username:
              type: string
              example: user1
            password: 
              type: string
              example: password1
            brokerCACert:
              description: PEM encoded CA certificate
              type: string
            customTopic:
              type: string
              description: custom MQTT topic to publish to
              example: custom/topic
      
    DataAppWebhook:
      type: object
      properties: 
        webhook:
          type: object
          properties: 
            URI: 
              type: string
              example: webhook.com:443
            headers:
              type: object
              additionalProperties:
                type: string
              example:
                x-api-key: fjelk-3dl33f-2wdsd
            serverCACert: 
              type: string 
          
    DataAppWebsocket:
      type: object
      properties: 
        websocket:
          type: object
          properties: 
            URI: 
              type: string
              example: websocket.com:443
            headers:
              type: object
              additionalProperties:
                type: string
              example:
                x-api-key: fjelk-3dl33f-2wdsd
            serverCACert: 
              type: string 

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

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

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

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

# responses

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ProtocolMap-BLE-Characteristic:
      required:
        - characteristicID
        - flags
        - descriptors
      type: object
      properties:
        characteristicID:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
        flags:
          type: array
          example:
          - read
          - write
          items:
            type: string
            enum:
              - read
              - write
              - notify
        descriptors:
          type: array
          items:
            $ref: '#/components/schemas/ProtocolMap-BLE-Descriptor'

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

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

## Protocol Mapping for BLE Property
    ProtocolMap-BLE-Propmap:
      required:
        - ble
      type: object
      properties:
        ble:
          required:
            - serviceID
            - characteristicID
          type: object
          properties:
            serviceID:
              type: string
              format: uuid
              example: 12345678-1234-5678-1234-56789abcdef4
            characteristicID:
              type: string
              format: uuid
              example: 12345678-1234-5678-1234-56789abcdef4
              
## Defines different types of BLE events
    ProtocolMap-BLE-Event:
      required:
        - ble
      type: object
      properties:
        ble:
          required:
            - type
          type: object
          properties:
            type:
              type: string
              example: gatt
              enum:
                - gatt
                - connection_events
                - advertisements
            serviceID:
              type: string
              example: 12345678-1234-5678-1234-56789abcdef0
            characteristicID:
              type: string
              example: 12345678-1234-5678-1234-56789abcdef1

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

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

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

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

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

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

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

## Protocol mapping for Zigbee property
    ProtocolMap-Zigbee-Propmap:
      required:
        - zigbee
      type: object
      properties:
        zigbee:
          required:
            - endpointID
            - clusterID
            - propertyID
          type: object
          properties:
            endpointID:
              type: integer
              format: int32
              example: 1
            clusterID:
              type: integer
              format: int32
              example: 6
            propertyID:
              type: integer
              format: int32
              example: 16
            type:
              type: integer
              format: int32
              example: 1

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

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

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

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

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

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-Blob.yaml"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API write binary blob extension
  description: |-
    Non IP Device Control (NIPC) API write binary blob extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.9.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-09"
    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/thermostat/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/FailureResponse' 

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

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

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

paths:
### Extensions
  /extensions/{id}/bulk:
    post:
      tags:
        - NIPC API extensions
      summary: Compound operations on a device
      description: Compound operations on a device
      operationId: Bulk
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-Bulk'
            examples:
              bulkRequest:
                $ref: '#/components/examples/bulkRequest'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
              description: URL to get the bulk status response
              example: /extensions/12345678-1234-5678-1234-56789abcdef4/bulk/status?requestId=12345678-1234-5678-1234-56789abcdef4
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
      callbacks:
        bulkEvent:
          '{$request.body#/callback.url}':
            post:
              description: Callback for bulk response
              operationId: bulkCallback
              requestBody:
                content:
                  application/json:
                    schema:
                      allOf:
                        - $ref: '../NIPC.yaml#/components/schemas/Id'
                        - $ref: '#/components/schemas/Extension-BulkResponse'
              responses:
                '200':
                  description: OK
                '400':
                  description: Bad request
                '401':
                  description: Unauthorized
                '405':
                  description: Invalid request
                '500':
                  description: Server-side failure
    get:
      tags:
        - NIPC API extensions
      summary: Get Bulk response
      description: Get Bulk response
      operationId: getBulkResponse
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the bulk operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '#/components/schemas/Extension-BulkResponse'
              examples:
                bulkResponse:
                  $ref: '#/components/examples/bulkResponse'
                errorBulkResponse:
                  $ref: '#/components/examples/errorBulkResponse'
                
  /extensions/{id}/bulk/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Bulk status
      description: Get Bulk status
      operationId: getBulkStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the bulk operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
              description: URL to get the bulk response
              example: /extensions/12345678-1234-5678-1234-56789abcdef4/bulk?requestId=12345678-1234-5678-1234-56789abcdef4
          content:
            application/json:
              schema:
                allOf:
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
              examples:
                successExample:
                  summary: Success
                  value:
                    status: COMPLETED

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

## Extension that defines an operation in a bulk API
    Extension-BulkOperation:
      required:
        - method
        - path
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
               - POST
               - PUT
               - GET
            path:
              type: string
              enum:
                - /devices/{id}/properties?propertyName={propertyName}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?propertyName={propertyName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            data:
              type: object
              oneOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value'
                - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-ConditionalRead'


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

## Return for an operation
    Extension-OperationResponse:
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
               - POST
               - PUT
               - GET
            path:
              type: string
              enum:
                - /devices/{id}/properties?propertyName={propertyName}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?propertyName={propertyName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              anyOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value'
                - $ref: '../NIPC.yaml#/components/schemas/SuccessResponse'
                - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'

  examples:
    bulkRequest:
      summary: Bulk request example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            data:
              value: dGVzdA==
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/read/conditional?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            data:
              value: dGVzdA==
              maxRepeat: 5
              retryTime: 1
    bulkResponse:
      summary: Bulk response example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              value: dGVzdA==
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              status: 200
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/read/conditional?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              value: dGVzdA==
    errorBulkResponse:
      summary: Error Bulk response example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-property-not-readable
              status: 400
              title: Property not readable
              detail: Property https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/temperature is not readable
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-extension-operation-not-executed
              status: 400
              title: Operation not executed
              detail: Operation was not executed since the previous operation failed
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/read/conditional?propertyName=https://example.com/thermometer%23/sdfThing/thermometer/sdfProperty/temperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-extension-operation-not-executed
              status: 400
              title: Operation not executed
              detail: Operation was not executed since the previous operation failed
<CODE ENDS>
]]></artwork></figure>

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

<figure><artwork><![CDATA[
<CODE BEGINS>
file "Extension-File.yaml"
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API write file extension
  description: |-
    Non IP Device Control (NIPC) API write file extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.9.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-09"
    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/thermostat/sdfProperty/firmware"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-File'
        required: true
      responses:
        '204':
          description: Success, no content
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 

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

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

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

paths:
### Extensions
  /extensions/{id}/firmware:
    put:
      tags:
        - NIPC API extensions
      summary: Upgrade the firmware of a device
      description: |-
        Update the firmware of a device. Will perform all operations required to upgrade the firmware. Id cannot be a group-id.
      operationId: upgradeFirmware
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: './Extension-File.yaml#/components/schemas/Extension-File'
                - $ref: '#/components/schemas/Extension-Firmware'
                - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-Callback'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
              description: Location of the resource
              example: /12345678-1234-5678-1234-56789abcdef4/extension/firmware/status?requestId=12345678-1234-5678-1234-56789abcdef4
        default:
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
      callbacks:
        bulkEvent:
          '{$request.body#/callback.url}':
            post:
              description: Callback for bulk response
              operationId: bulkCallback
              requestBody:
                content:
                  application/json:
                    schema:
                      anyOf:
                        - $ref: '../NIPC.yaml#/components/schemas/Id'
                        - allOf:
                          - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                          - $ref: '#/components/schemas/ExtensionErrorCodes'
              responses:
                '200':
                  description: OK
                '400':
                  description: Bad request
                '401':
                  description: Unauthorized
                '405':
                  description: Invalid request
                '500':
                  description: Server-side failure
                  
    get:
      tags:
        - NIPC API extensions
      summary: Get the status of a firmware upgrade of a device
      description: |-
        Get the status of a firmware upgrade of a device. Returns success when ongoing or completed, with a reason. Returns failure when upgrade has failed. Id cannot be a group-id.
      operationId: upgradeFirmwareStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the firmware upgrade operation
        required: true
        schema:
          type: string
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
            Location:
              schema:
                type: string
              description: Location of the resource
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/Id'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                  - $ref: '#/components/schemas/ExtensionErrorCodes'
  /extensions/{id}/firmware/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get the status of a firmware upgrade of a device
      description: |-
        Get the status of a firmware upgrade of a device. REturns success when ongoing or completed, with a reason. Returns failure when upgrade has failed. Id cannot be a group-id.
      operationId: upgradeFirmwareStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: requestId
        in: query
        description: Request ID of the firmware upgrade operation
        required: true
        schema:
          type: string
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
              description: URL to get the firmware response
              example: /12345678-1234-5678-1234-56789abcdef4/extension/firmware?requestId=12345678-1234-5678-1234-56789abcdef4
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

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

    ExtensionErrorCodes:
      type: object
      properties:
        nipcStatus:
          type: integer
          format: int32
          enum:
            - 1600 # Firmware rollback
            - 1601 # Firmware update failed
<CODE ENDS>
]]></artwork></figure>

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

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

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

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

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

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

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

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

paths:
### Extensions
  /extensions/{id}/manage/transmit:
    post:
      tags:
        - NIPC API extensions
      summary: Broadcast to a device
      description: |-
        Broadcast a payload to a device. The broadcast is performed on the AP where the device was last seen
      operationId: ActionBroadcast
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Transmit'
        required: true
      responses:
        '200':
          description: Success
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
   
  /extensions/{id}/properties/write:
    post:
      tags:
        - NIPC API extensions
      summary: Write a value to an property using protocol mapping
      description: |-
        Write a value to an unregistered property, embedding property protocol mapping in the API, this does not require
        property registration. You cannot write to a group id.
      operationId: ActionPropWrite
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value' 
                - $ref: '../protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
        required: true
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                
  /extensions/{id}/properties/read:
    post:
      tags:
        - NIPC API extensions
      summary: Read a value to an property using protocol mapping
      description: |-
        Read a value from an unregistered property, embedding property protocol mapping in the API, this does not require
        property registration. You cannot read from a group id.
      operationId: ActionPropRead
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '../protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Property'
        required: true
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '../NIPC.yaml#/components/schemas/Value'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'

components:
  schemas:
    Transmit:
      allOf:
        - $ref: '../protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Broadcast'
      required:
        - cycle
      type: object
      properties:
        cycle:
          type: string
          example: single
          enum:
            - single
            - repeat
        # transmit time in ms
        transmitTime:
          type: integer
          example: 3000
        # interval between transmits in ms
        transmitInterval:
          type: integer
          example: 500
        payload:
          type: string
          format: byte
          example: AgEaAgoMFv9MABAHch9BsDkgeA==
<CODE ENDS>
]]></artwork></figure>

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

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

</section>


  </back>

<!-- ##markdown-source:
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
whWur0gtV0EnmxhExSK6SU3tXwcusX5In5NGvbhO/5UeqoM0SVjrdl6xFVEy
7rKVjjmf1FGxI/uDOxrm39Gwb4uGWQTnHcxmBz1/OQyyma6ZJm4WLnOa7z/e
eNwme0T+Aarqb5PIeCOy4lWFxO8FDxwY1txWOZss9poK1llUW6wbNZ9Uartb
rfnSsIvNdzQjMPWnt81GBK35ay7nfk3AKmHSTsi3pHeZUQ3WO0otkUegO+Ny
oAaVXIjqJStvQwnTCRIzO4ywDvgowvVdA2ndZZvdBm7f0zS0Hlg3bdeaj02A
5L7rgVgfOlIXUdP3Dw+Ojmue/lrz8NWe+xBXc90JQLfrzFdUXCv+aluIf76w
/7pc2A3r3fP1v/I/uAvz79oOWrw80KcA8EyfliXmZmi2mmAngt0EhzrrMxua
idf7P48er6v6j/ZzxwIN54nQ11WzwbVUUy6kJVtHTUozhmRXkYQSlraUcbwu
uTKfY2sspQ6n/43yYckiAECSS76oGu6uXvrRvH43S2w9wVuJ37uZn6ZGVu5T
WOo7WqHK6NS0uErjxlvkjkTdkaivTKKyBml/UfXa69OiRR005o1evqu6RMYu
21pje9O8qag8WXyVZvJNiTmtp02Kb9mqP023HknM/Msk4tuYf/09zFvnh6/+
449w++ef69dbJpSy4GWFxc5U5fYAAX/T4Pd30SxCZcrT0iu467Pz43iqg1Dq
NJPlE8Rv/4xHqJnOdkLDb/TYNa1Zye1uAbDv9Ngts/GNOnh9ktiP8+48NYKV
mdEbLMZl0NctYEKDs+ejmjwp8xs6kWIi5tsFwLq3FKiUJaFm8O+XrFxz65eq
VdcBC7QYKCVdantRaGA+PgtypwE6L44iyd0PW5POc0utVsnh8Sejon/iPV/g
M87he+QKvqS7+Eus/HD73MVrF3St2MZKX3eu43eu4zcS1IiYxgBaTVAjYe51
oxnbO6kLY6QWd/GL14tfRPKq9Nt3HiV38Yu3MH4RUfQufvFm4hcRto0+By9j
4ydRZwBHAvzru9fqAulmMZNGV8LpMAXWJiGUVmg6AAZjzeDltYMbVb++5Idf
mluVad0+jtVa2UkWhCvgW5t77Nn1De9Y2zvW9kZZW4WHq+BpfxVUZrQV/E7H
XblZrkfR2FrYWMVFIltpRVMqGot8wrxmHsuxd9KDokh3TN6XicNs8H+s9XrR
uo2lOKBKlwtbMwbcoCtOxXPw+wj3VP0qXIcFpPNs1Oy320mFqYmPJlzXDPNU
98C3ya5KR3ehl9cPvaz3klG/VYVeLojwvJYrTIdO22lRU4XPu3jPG433dH/0
6PqBU1QImqPriYeqyBvd+bJluxuId2Wuwga4qlmanKTEymLWTKT5cDn1pFg5
mjfh4JqWAh9uqcY4DXIxmVyLm7sLBbvBULAqYqw8LOxWxH99Vcbpq/Ae9sVW
od0LafafL53GCgKTO1zxV7raG7UAK47e/bqX0N7dJXR3CX3Tl1A1lvLLRCJX
q5muMJ3CXSizjaELw5mvqBb5diKabyc6OdtwvYjoHXXR1HzUEhMdh1cqryeD
XzmgOvDVFdVi27RtBktYL91mpmmVutaULkjSLIxHpYd5PAmGuedO8DbWXeCK
3Bq0WVqjAaPPNu3PxJDazU/Qcuckd+Fl7a91p+d2mWFpVfYyr22Gbe3xztJ6
Z2m9ESfCsve1GF+vm5a2dPxJGnIqOVWy0nZo4QgxIzdu/E58+aLOb2ViNTlf
CAmCGHA3eKpX4CDXwQfO8vu/PW5wlXwHrWD75mytJeGiwgg42dHU78oixqxm
qysk7ZpmWfy9w8jU/vbYKvHYDWD1JcXcExfDAYsTP49wznTAzoIY9TjjlKQy
GNoG+rfu1ygd1RiK1aOKsXit1Vi8tthYfKvNuSs0xLZZfJfpR5HQhnwLy3fY
yULcLOLyb7Ggq75bmACMfy0iL/+uJfjyT5GordpgzGVcupvC2OrW1BR9r34s
xrVl5eSfBuXLal3v6qg3C8nmQDn7ZwnO/uZG66cqZm6tZMBZ++a2E38VkndN
Pwn78Fzf/lJh8HWk+fKyQWvTcsbVnTs54U5OWFpOWKEFqMICf1/Zab+WYaiG
fF0rj5Q9m3RUREUfwBwFlUxjVxCQrBJeVGesTRp4wZXIUFWmEEgfMboLLLS7
KXdRiWn/4eu7GCyjuVqxw0Dl1rHN/UtdVy0NF1xWd5b5uyvr7sr63hOq/ym8
DCootWpvg06qwG/GFeHOVWAJVwFsWo1iWtLgPio1a2ja1Bx/aKNsOxKWD6H6
ySnJoyTkY6ICWYq08u0D4fjwnib/Q7y+glw8c5mGQ38PSw3bMuk6odlb6+va
Lrr108ZPG1rN6ipEasnI4qX+ws1wuXEymsxD0nrbi25dMZzq4rx+bbV5r6Mm
HP+9H8zi/scIcHxNYerzjbLOJwgVzThs2O0KbEt46J7RJbExr7h+tIH3SHOY
DeBcwrdl/+37w3cHr97tHR2V3lin0l1piWtVPTbWN1hSOutKFFdQ+MAkJ10S
uaFhPJ1P/SKeRg2Gr9N0PsFrD7tvxvSnPezL39yoR/V6e5I+x25GVZNPdcnV
0CqGUXEWRQnNPrcNVHqum9ea6+YiJyLNp1uCWifvIcUl37kN3bkN3bkNrc5t
iJNircNeJPk0LlbiKvQiS4NwFADrQrPrFIBh2gT+LDifwF926wFJ+kP9ETAP
kqkhCv2UWY7tQwylyCJLEUIJEyfYIAeyJ4M5CpptgrceXV3fFb1MrWamRjez
Gu1MoyxeL380soMNEvntS83Qxg0cC25eya1mCS337VK+XscKX3fQLS0rZZdb
yUlXGQJJeKTzmpgrfp47af2mABGDn4tyDto9zpMsOolzOI5w2FX3PbjQhhFw
9DwGD1keTEkjsArJGRimkcp4TDikB9Z98FhMIQb+f6ZzFYTFuUCJKFEolt8Q
isUkBRkWWswdSbml2V66iSzVYCW7B4VwgG/kYUN/vAlmrW446iPN1H7JFHrf
D5VzfgtIXqZl2GtSPBSGV0rwnA7HWTq9RRSP5BCeU1eS1+qPcUfxvgQT9XXJ
0lJuBbcuuLSkpvpOiGWTxh07PXYkv1YN3/WwSstY962jUM5bOjof6aTHXZX8
2GQZWyxLy/abGpVp5SN8WFL03fOV2MzaNSC9U4Pd6l1ZWdekSNPze2x7ON5j
tQBcD1p5pzrOGwbclwZLDfrUGlPk7yUsvsPzIqrrdftkL9g+Sd+8/PT8zfaL
7V9Gp89f5LsfTyJ0e6xTFfpixiKj/jQNowlnTyhfc1w88sXrPd+72PLvWVUi
+nk4vmzTKVrfDuDbAZ7ANe+Cpr+Gt1M+C0bR2pZ/oVdkt1lrSORsf0INL3vc
pdCQt1bPTn/ymap40TbwhYOPa9qjoPKKXp9GwaQ4fd/Whf7Womo4v1+oKV68
pWlWGloODI2980qMCfc9YlPr13VzOraq1hxjB/Uz0s3TIWoNUQsIrcfBJI8W
NED5bonPVcmcNb4UF3w9M5Rw4cqpAfe8+EP6OGdl8P4uAmrzp43nC4CjG45O
A1Q5RhnmtR9x+0fbm7tt7tL8q1bJ7Pb2snlma9MoyGF7Uen5XpG9pfHkjenE
V6TwDlfMxyvGlUebN4grtW8aMAhJEUUZdadDFr5dixxZKLcI05Bmz4vZvNgN
iqDb7i6LDtRoGZSgBkKT106CYtEinHZXRSdq3EB+dhajFP7a0WrxF1cjUkSY
plEYBwXcZJbP3rIYtG915FvodIdCK0Chva+OQvW0q/LUfVJCvDLKvIoSWOiI
IoJRvycm5P2EGXH8qtTBIv5sjdUp75Hx7cweyrDI0jbxhV1vVPsmbb4au12g
ndG8E2pX0HJj0cGsR8WNih+S+XVGkurIayAIRTBeMuq+b9umyQq3re2zb3nf
Whib6+zbNEjmYxgOKH1Gx+49i9Wdd/GN1QGdQf+IO/gT7en21fb00fMb2lPU
VLxP5tMh7Omy20lajrfU9m4nqw0advLJzewkDBZibqz3WE4TLUDLbucv0oH/
Tjq429Nqg4Y9/fFm9lRlhrvynuqEaXd72tygYU+f3cye5uc5yF7v47DzJh5R
Cx8mdrdrpkHDrj1ewa61Cjatypq1OD/MorxNLVPeXTQFBOEnNA7lpIjJWzTW
HcXnpcTmzuKyFpNL071pObPmEMX5DtcxjbofIwS0Vf00+vRNwNrM+L3M+MuK
9Z77r0vvssb8dbHFPuc/ry1rBVu79P4/A+HbvXykAgA=

-->

</rfc>

