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


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

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


<rfc ipr="trust200902" docName="draft-ietf-asdf-nipc-06" 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="May" day="15"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 60?>

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



    </abstract>



  </front>

  <middle>


<?line 68?>

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

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

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

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

]]></artwork></figure>

<t>There have been efforts to define Gateway functions for devices that support
a particular protocol, such as a BLE GATT REST API for BLE Gateways
(<xref target="Gatt-REST-API"/>), however they have been limited to a single protocol or
a particular use case. In absence of an open standard describing how
applications on an IP network communicate with non-IP devices, bespoke and
vendor-specific implementations have proliferated. This results in parallel
infrastructure of both gateways and non-IP networks being deployed on a case
by case basis, each connecting separately into the IP network, with a distinct
set of APIs. At the same time, wireless access points supporting both IP-based 
wireless connectivity as well as non-IP based wireless technologies are
deployed ubiquitiously. Many of these wireless access points are equipped with
radios that can transmit and receive different frame types, such as <xref target="BLE53"/>
and <xref target="Zigbee22"/>. This specification aims to define a Gateway API for these 
Non-IP protocols that can be leveraged by this wireless infrastructure in order
to connect Non-IP devices into IP networks. The specification aims to be
extensible, in order to support existing and future non-IP protocols.</t>

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

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

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

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

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

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

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

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

]]></artwork></figure>

<t><xref target="arch"/> shows us applications, the NIPC application layer gateway (ALG),
an access point (AP), and a device (D). The applications, application layer
gateway and access point are deployed on an IP-Network. The AP supports a
Non-IP interface, which it uses to communicate with the device.
The Application is deployed in a different administrative domain than the
network elements (ALG &amp; AP).
The role of the application layer gateway is to provide a gateway function
to applications wishing to communicate with non-IP devices in the network
domain served by the gateway.
Applications implementing Non-IP Control can leverage RESTful interfaces
to communicate with Non-IP devices in the network domain and subscribe to
events levering a CBOR-based pub/sub interface.</t>

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

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

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

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

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

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

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

]]></artwork></figure>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

]]></artwork></figure>

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

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

<t>where-</t>

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

<t>Example protocol mapping:</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>paths:</t>

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

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

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

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

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

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

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

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

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

<t>Failure response:</t>

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

<figure title="Example failure response" anchor="failure"><artwork><![CDATA[
{
  "status": 400,
  "nipcStatus": 1000,
  "detail": "Generic error message"
}
]]></artwork></figure>

<t>where-</t>

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

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

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

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

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

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

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

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

<t>Request Body:</t>

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

<t>Response:</t>

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

<figure title="Example register sdf model response" anchor="exregresp"><artwork><![CDATA[
{
  "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>
  <t>"id" is the id of the sdf model</t>
</list></t>

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

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

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

<t>Response:</t>

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

<figure title="Example get all sdf models response" anchor="exgetallresp"><artwork><![CDATA[
[
  {
    "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>
  <t>"id" is the id of the sdf model</t>
</list></t>

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

<figure title="Example delete sdf model response" anchor="exdelresp"><artwork><![CDATA[
{
  "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>
  <t>"id" is the id of the sdf model</t>
</list></t>

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

<figure title="Example update sdf model response" anchor="exupresp"><artwork><![CDATA[
{
  "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>
  <t>"id" is the id of the sdf model</t>
</list></t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

<t><list style="symbols">
  <t>mqttClient: an empty object that denotes that the data application
is an MQTT client that will receive streaming data over MQTT</t>
  <t>mqttBroker: an object that contains the MQTT broker information
where the broker will publish the streaming data.
  <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/{data-app-id}</spanx></t>

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>The event is a global name reference to an <spanx style="verb">sdfEvent</spanx>.</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/<data-app-id>/<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 /{id}/event/{event}</spanx></t>

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>where-</t>

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

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

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

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

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

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

<t>Response:</t>

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

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

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

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

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

<t>Response:</t>

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

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Description: Broadcast a payload to a device.</t>

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

<t>where-</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

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

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

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

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

<t>/extension</t>

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

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

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

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

<t><list style="symbols">
  <t>1000-1099 (Generic): Broadly applicable errors, including 
authorization, invalid identifiers, and generic failures.</t>
  <t>1100-1199 (Property APIs): Errors related to property APIs
(read/write).</t>
  <t>1200-1299 (Event APIs): Errors related to event APIs
(enable/disable).</t>
  <t>1300-1399 (BLE-Specific): Errors specific to BLE operations,
including connection management and service discovery.</t>
  <t>1400-1499 (Zigbee-Specific): Errors specific to Zigbee operations.</t>
  <t>1500-1599 (Broadcast APIs): Errors related to broadcasting data.</t>
  <t>1600-1699 (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>1000</c>
      <c>Generic catch-all error code for any API</c>
      <c>Generic</c>
      <c>1001</c>
      <c>Application not authorized to access the device</c>
      <c>Generic</c>
      <c>1002</c>
      <c>Invalid device ID or gateway doesn't recognize the ID</c>
      <c>Generic</c>
      <c>1003</c>
      <c>Invalid SDF URL or SDF affordance not found</c>
      <c>Generic</c>
      <c>1004</c>
      <c>Operation was not executed since the previous operation failed</c>
      <c>Generic</c>
      <c>1005</c>
      <c>SDF model already registered</c>
      <c>Generic</c>
      <c>1006</c>
      <c>SDF model in use</c>
      <c>Generic</c>
      <c>1100</c>
      <c>Property not readable</c>
      <c>Property APIs</c>
      <c>1101</c>
      <c>Property not writable</c>
      <c>Property APIs</c>
      <c>1200</c>
      <c>Event already enabled</c>
      <c>Event APIs</c>
      <c>1201</c>
      <c>Event not enabled</c>
      <c>Event APIs</c>
      <c>1202</c>
      <c>Event not registered for any data application</c>
      <c>Event APIs</c>
      <c>1300</c>
      <c>Device already connected</c>
      <c>BLE-Specific</c>
      <c>1301</c>
      <c>No connection found for device</c>
      <c>BLE-Specific</c>
      <c>1302</c>
      <c>BLE connection timeout</c>
      <c>BLE-Specific</c>
      <c>1303</c>
      <c>BLE bonding failed</c>
      <c>BLE-Specific</c>
      <c>1304</c>
      <c>BLE connection failed</c>
      <c>BLE-Specific</c>
      <c>1305</c>
      <c>BLE service discovery failed</c>
      <c>BLE-Specific</c>
      <c>1306</c>
      <c>Invalid BLE service or characteristic ID</c>
      <c>BLE-Specific</c>
      <c>1400</c>
      <c>Zigbee connection timeout</c>
      <c>Zigbee-Specific</c>
      <c>1401</c>
      <c>Invalid Zigbee endpoint or cluster ID</c>
      <c>Zigbee-Specific</c>
      <c>1500</c>
      <c>Invalid broadcast data</c>
      <c>Broadcast APIs</c>
      <c>1600</c>
      <c>Firmware rollback</c>
      <c>Extension APIs</c>
      <c>1601</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
x-request-id: 1f1c5a37-e21c-4edc-aeb0-65b9d747fe07

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

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

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

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

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

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

{
  "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/23456789-1234-5678-1234-56789abcdef4
Content-Type: application/json
Accept: application/json
Host: localhost

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

</section>
</section>


  </middle>

  <back>


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

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


    </references>

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

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


    </references>


<?line 2364?>

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

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

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

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

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

  /{id}/property:
    put:
      tags:
        - NIPC property APIs
      summary: Update a value of one or more properties on a device
      description: |-
        Write a value to a property or multiple properties to a device. If underlying protocol requires a connection to be set up, this API call will perform the necessary connection management. If a connection is already active for this device, the existing connection will be leveraged without modifying it. 
      operationId: UpdateProperties
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PropertyValueArray'
        required: true
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/Id'
                  - $ref: '#/components/schemas/PropertyValueResponseArray'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request       
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureResponse' 

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

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

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


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

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


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

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

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

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

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

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

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

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

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

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

## Event
    Event:
      required:
        - event
      type: object
      properties:
        event:
          type: string
          description: percent-encoded JSON pointer to the SDF event object
          example: https://example.com/heartrate#/sdfObject/healthsensor/sdfEvent/fallDetected
            
## A Connection
    Connection:
      type: object
      properties:
        retries:
          type: integer
          format: int32
          example: 3
        retryMultipleAPs:
          type: boolean
          example: true
        
## A broadcast
    Broadcast:
      allOf:
        - $ref: '#/components/schemas/Id'
        - $ref: './protocolmaps/ProtocolMap.yaml#/components/schemas/ProtocolMap-Broadcast'
      required:
        - cycle
      type: object
      properties:
        cycle:
          type: string
          example: single
          enum:
            - single
            - repeat
        # broadcast time in ms
        broadcastTime:
          type: integer
          example: 3000
        # interval between broadcasts in ms
        broadcastInterval:
          type: integer
          example: 500
        payload:
          type: string
          format: byte
          example: AgEaAgoMFv9MABAHch9BsDkgeA==
          
 ## DataApp
    DataApp:
      oneOf:
        - $ref: '#/components/schemas/DataAppMqttClient'
        - $ref: '#/components/schemas/DataAppMqttBroker'
        - $ref: '#/components/schemas/DataAppWebhook'
        - $ref: '#/components/schemas/DataAppWebsocket'
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'


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

    DataAppMqttBroker:
      type: object
      properties: 
        mqttBroker:
          type: object
          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

## Error 500 application Failure response
    FailureResponse:
      type: object
      properties:
        status:
          type: integer
          format: int32
          example: 400
          description: HTTP status code
        detail:
          type: string
          example: Bad request
          description: Human-readable error message
        nipcStatus:
          type: integer
          format: int32
          description: NIPC error code
          enum: 
            - 1000 # Generic catch-all error code for any API
            - 1001 # Application not authorized to access the device
            - 1002 # Invalid device ID or gateway doesn't recognize the ID
            - 1003 # Invalid SDF URL or SDF affordance not found
            - 1004 # Operation was not executed since the previous operation failed
            - 1005 # SDF model already registered
            - 1006 # SDF model in use

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

paths:
### Extensions
  /{id}/extension/bulk:
    post:
      tags:
        - NIPC API extensions
      summary: Compound operations on a device
      description: Compound operations on a device
      operationId: Bulk
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-Bulk'
            examples:
              bulkRequest:
                $ref: '#/components/examples/bulkRequest'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
            Location:
              schema:
                type: string
              description: URL to get the bulk status response
              example: /12345678-1234-5678-1234-56789abcdef4/extension/bulk/status?requestId=12345678-1234-5678-1234-56789abcdef4
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
      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: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: 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:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          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'
                
  /{id}/extension/bulk/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Bulk status
      description: Get Bulk status
      operationId: getBulkStatus
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: 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:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          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 bulk response
              example: /12345678-1234-5678-1234-56789abcdef4/extension/bulk?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: Success
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    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:
                - /{id}/property/{property}
                - /{id}/action/{action}
                - /{id}/extension/property/{property}/read/conditional
              example: /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              type: object
              oneOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value'
                - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-ConditionalRead'


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

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

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

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

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

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

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

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

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

paths:
### Extensions
  /{id}/extension/firmware:
    put:
      tags:
        - NIPC API extensions
      summary: Upgrade the firmware of a device
      description: |-
        Update the firmware of a device. Will perform all operations required to upgrade the firmware. Id cannot be a group-id.
      operationId: upgradeFirmware
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: './Extension-File.yaml#/components/schemas/Extension-File'
                - $ref: '#/components/schemas/Extension-Firmware'
                - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-Callback'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            X-Request-ID:
              schema:
                type: integer
              description: Unique Request ID
            Location:
              schema:
                type: string
              description: Location of the resource
              example: /12345678-1234-5678-1234-56789abcdef4/extension/firmware/status?requestId=12345678-1234-5678-1234-56789abcdef4
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
      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: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: 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:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
            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'
  /{id}/extension/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: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: 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:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          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"
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API read conditional extension
  description: |-
    Non IP Device Control (NIPC) API read conditional extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.5.1
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-05"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing one or more basic APIs into a single API call.

paths:
### Extensions
  /{id}/extension/property/{property}/read/conditional:
    post:
      tags:
        - NIPC API extensions
      summary: Conditional read of a property
      description: Conditional read of a property
      operationId: conditionalRead
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-ConditionalRead'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
            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
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
      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'
                        - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
                    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: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - 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:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyValue'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
  /{id}/extension/property/{property}/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: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - 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:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $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: '../NIPC.yaml#/components/schemas/Id'
                  - $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>
<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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
4pW694z4F84QaJLPv8y5jRncN0xO37niMBn7iFWmidxzYm1PfZtfZZ5BiQ+a
lHg7nU31x76VWB7jSNji+LDLhfKPDzFsSrqm9AmbShCS36qJm9p7zgdWUmh9
Szle3rMq7MRJAbeU+CeOCu8teFdV5muYa1fp1XnrxrX6VyeJaqzD0vHrKzMD
37Bg71XIqD7c+kZXIUWhGEpPhYzuMDnktUGpMFBFLULUrL4sly5n5fOhwy6K
fVRZ6Bw+xiPVpUblpEb/KMsDcpDtkRdkNMb4Ht5LNLAoTrMybhklDopzXjC8
RHnbppqrFJtCASlyFC/y7EOc71nJMyqFXZ5FQd/UQ48+tKM+qNSpjuiR76lz
FcfG0UTuDQ3EKjoY9sDLifEPEktWP/IrsGfzVEsN9Rc5gE2NVqtUVR3CGIxI
viKHz8L5r3kg8B8H+wdxXjKUg33RxwOFgayFXxu9+EE5Eh9JIP1JUWajs2yc
9BkGP0DGynlIzSjD40A+JrChdsQlxxM1L12oPiFhGJqYNqwMzRfK5DF5DkMV
ls5HMybBwcERDk1ClMt4Zp5QH5LRawZlqKMyJXUgXVDQaoUiLIjylYy/oyuZ
GqlUBenxCTpCNqsqQUo8at/omdUM3b/GMXllT52PBRy6l1CS3KSZq2FLVi2H
zn9Npx63dX2pOWBsymLzR03LfavVZpC83mf2o+UuuIG5xCWXQXZ3vOhy6Lde
dqe9vfBVZdIIGlehZIEG+uR/U+c6G5Ce31rNxMd0WroxAI3rMC4pjGlN57b9
jRzXRpBhet6N36eFH7GAyutKKi2YBeamZd7SM+hX8CxpyFz4fmGJBa1J4QTq
x17xVdfqcm/r2bMdmae4pgQefoj/Vs+VGMPn+t/ynSVp8DX/uUFyhj5pWSNG
W9sayUncODbP8cA6X1pXx6zWMVFPBZX0w6FSkO1lVZqoMlpb9dCa6TqbGqot
2C+shIpTqnNQ1CZtndRJ/bs2ME67fG+dPC2OasvF14bmuqNvNjSzv68+lfl8
BXOi23HTzYcP/yoE9VWw3XRtiPM662bDnfbZfY/os7MzsJ9xnoywYBRVDZeD
M0XOubJr/AlL6p/HSoWglEOnHOo6xt/qGEU8RKQIdkxbVT4KrYeoApe6HIBb
HLZrhZyynwGPhxPOiaYLQXaEvI4zieVFEfSxk3m7Z3sO/J4KOgjAq9iY28mA
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
6ik/+VuLiPTZ8X3bYmoo09xqzAsZ46fJydnl+4oxIE1rOrd2OQKobPSvcxCg
Sz1Yl7S2+OGazVoJSIpquY8xuVKWCpEK80u8QaIuk+myI/tinHUxSYcoLjQ7
N2islgtXhpSsq7CYLb2ylb87WzlVKpKBWstm+T5Ni1bzYTL2GfJ1+qkxyLs2
E+6plfAHNRJWOvwydPiVMrtSZmlICyizzLBX6mx7JKTEhUo2r53VOKGQU9Xa
ZoBzqZl3dCDqDwJsohJzcfetDjC/WqBSLVXDG6A0dSm9oCrmiRJw5Nfihz8U
j4Kk2ECrQ7ZG60TKvUJrDiNp6liBG2AfhB9hVhgG2dUXGBFoXagn4dMNDXle
++WOswtXAsY8/f4FDFIhbospIqYtHGy6pFlI0NwPKePUEpJZOPXwiJboAF05
hWjqtkWGGntezAMyf1khwQnSak11URbXHlDcUd9V7TlSdEvzTItNmvdc8Bas
4vbMptX2pnn6CkK4CLj7aKrvEql3WPTp1iWcanzPVNKZtk2+dvGnhTgcytJb
V4W6Iw63HF7llFa6tUPx/mwfnI+PJTnzXHGk26D07ipz3a7Q1jfGjF7kWRj1
w2L28MuealFlPQYUcJzwagh/uWcpi/AWrJ1QYxN6KHdmjF0T+dFX/as+PVpD
vjmU5eP0CM4SKmG/o2671S+OMe0dSAlePpbvJHIQ1v75Ubh/nr15+fH5m/0X
+z/3L56/KA4/nMcN8eE9s1wuyesXtyimMj+t4rrKC5m5JIUQppEp08pufcKb
3kZ6AvR8XV1gr7CKsYFgJI7jECO0OlUMKzAl/IG7b4SFSou4T/dSqVH2bJrO
J6kLRy9IK6xeXF7GoG7QKYVuyxiTy1fhDDRr0/WUEqGUZmIuxI4KVfubrizm
a6mdm6apQI26Rom2AJ1dmlL53a/AQGTZGj7G7CXDBNkYPcMCHvIxXytXXmbi
MryCjS8Qiye18thv40t/aCXBibgrDoTkUwgkOlzyFBqmXDFdtadzLsSuuZx+
r/K3zqTxXGBOIZ+wekmfS14LofIJKDYeqz1QNDwQP2bDIXpMWC15vZyi6wJT
AE5qh74FLFitiLOaASDg5madJ60PZRVWNJrUYU7g1seqlIHvks2PBPRfyXkv
jumYXxWCkFxVpg0oyIHqyl1HjF6j7aoRTUfIaVZfAXUEHTjla/QicgpN0b+I
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
/LQ27ynY2k3w/wDZZrPqFsUCAA==

-->

</rfc>

