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


<!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 I-D.mohan-asdf-sdf-protocol-mapping SYSTEM "https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.mohan-asdf-sdf-protocol-mapping.xml">
<!ENTITY RFC9114 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9114.xml">
<!ENTITY RFC7159 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7159.xml">
<!ENTITY RFC8949 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8949.xml">
<!ENTITY RFC3986 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml">
<!ENTITY RFC6570 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6570.xml">
<!ENTITY RFC9457 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9457.xml">
<!ENTITY RFC4648 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml">
<!ENTITY RFC8610 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8610.xml">
<!ENTITY RFC8126 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8126.xml">
<!ENTITY RFC8615 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8615.xml">
]>


<rfc ipr="trust200902" docName="draft-ietf-asdf-nipc-13" 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="September" day="20"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 61?>

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



    </abstract>



  </front>

  <middle>


<?line 65?>

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

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

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

<figure title="Gateway for non-IP Devices" anchor="gw"><artset><artwork  type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="688" viewBox="0 0 688 144" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
<path d="M 8,48 L 8,96" fill="none" stroke="black"/>
<path d="M 120,48 L 120,96" fill="none" stroke="black"/>
<path d="M 240,48 L 240,96" fill="none" stroke="black"/>
<path d="M 320,48 L 320,96" fill="none" stroke="black"/>
<path d="M 440,48 L 440,96" fill="none" stroke="black"/>
<path d="M 512,48 L 512,96" fill="none" stroke="black"/>
<path d="M 8,48 L 120,48" fill="none" stroke="black"/>
<path d="M 240,48 L 320,48" fill="none" stroke="black"/>
<path d="M 440,48 L 512,48" fill="none" stroke="black"/>
<path d="M 128,64 L 232,64" fill="none" stroke="black"/>
<path d="M 328,64 L 432,64" fill="none" stroke="black"/>
<path d="M 8,96 L 120,96" fill="none" stroke="black"/>
<path d="M 240,96 L 320,96" fill="none" stroke="black"/>
<path d="M 440,96 L 512,96" fill="none" stroke="black"/>
<polygon class="arrowhead" points="440,64 428,58.4 428,69.6" fill="black" transform="rotate(0,432,64)"/>
<polygon class="arrowhead" points="336,64 324,58.4 324,69.6" fill="black" transform="rotate(180,328,64)"/>
<polygon class="arrowhead" points="240,64 228,58.4 228,69.6" fill="black" transform="rotate(0,232,64)"/>
<polygon class="arrowhead" points="136,64 124,58.4 124,69.6" fill="black" transform="rotate(180,128,64)"/>
<g class="text">
<text x="64" y="68">Application</text>
<text x="280" y="68">Gateway</text>
<text x="476" y="68">Non-IP</text>
<text x="180" y="84">IP-based</text>
<text x="380" y="84">Non-IP</text>
<text x="476" y="84">Device</text>
<text x="184" y="100">Operation</text>
<text x="384" y="100">Operation</text>
</g>
</svg>
</artwork><artwork  type="ascii-art"><![CDATA[
                                                               
    +-------------+              +---------+              +--------+
    | Application |<------------>| Gateway |<------------>| Non-IP |                     
    |             |   IP-based   |         |    Non-IP    | Device |
    +-------------+   Operation  +---------+   Operation  +--------+                 

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

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

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

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

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

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

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

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

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

<figure title="Basic Architecture" anchor="arch"><artset><artwork  type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="288" width="560" viewBox="0 0 560 288" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
<path d="M 8,64 L 8,112" fill="none" stroke="black"/>
<path d="M 8,144 L 8,224" fill="none" stroke="black"/>
<path d="M 104,64 L 104,112" fill="none" stroke="black"/>
<path d="M 104,144 L 104,224" fill="none" stroke="black"/>
<path d="M 208,32 L 208,72" fill="none" stroke="black"/>
<path d="M 208,104 L 208,152" fill="none" stroke="black"/>
<path d="M 208,200 L 208,256" fill="none" stroke="black"/>
<path d="M 232,64 L 232,112" fill="none" stroke="black"/>
<path d="M 232,144 L 232,208" fill="none" stroke="black"/>
<path d="M 312,64 L 312,112" fill="none" stroke="black"/>
<path d="M 336,144 L 336,208" fill="none" stroke="black"/>
<path d="M 368,144 L 368,176" fill="none" stroke="black"/>
<path d="M 432,144 L 432,176" fill="none" stroke="black"/>
<path d="M 464,144 L 464,176" fill="none" stroke="black"/>
<path d="M 536,144 L 536,176" fill="none" stroke="black"/>
<path d="M 552,32 L 552,256" fill="none" stroke="black"/>
<path d="M 208,32 L 552,32" fill="none" stroke="black"/>
<path d="M 8,64 L 104,64" fill="none" stroke="black"/>
<path d="M 232,64 L 312,64" fill="none" stroke="black"/>
<path d="M 104,80 L 224,80" fill="none" stroke="black"/>
<path d="M 112,96 L 232,96" fill="none" stroke="black"/>
<path d="M 8,112 L 104,112" fill="none" stroke="black"/>
<path d="M 232,112 L 312,112" fill="none" stroke="black"/>
<path d="M 8,144 L 104,144" fill="none" stroke="black"/>
<path d="M 232,144 L 336,144" fill="none" stroke="black"/>
<path d="M 368,144 L 432,144" fill="none" stroke="black"/>
<path d="M 464,144 L 536,144" fill="none" stroke="black"/>
<path d="M 104,160 L 136,160" fill="none" stroke="black"/>
<path d="M 176,160 L 224,160" fill="none" stroke="black"/>
<path d="M 336,160 L 360,160" fill="none" stroke="black"/>
<path d="M 432,160 L 456,160" fill="none" stroke="black"/>
<path d="M 368,176 L 432,176" fill="none" stroke="black"/>
<path d="M 464,176 L 536,176" fill="none" stroke="black"/>
<path d="M 112,192 L 128,192" fill="none" stroke="black"/>
<path d="M 192,192 L 232,192" fill="none" stroke="black"/>
<path d="M 232,208 L 336,208" fill="none" stroke="black"/>
<path d="M 8,224 L 104,224" fill="none" stroke="black"/>
<path d="M 208,256 L 552,256" fill="none" stroke="black"/>
<polygon class="arrowhead" points="464,160 452,154.4 452,165.6" fill="black" transform="rotate(0,456,160)"/>
<polygon class="arrowhead" points="368,160 356,154.4 356,165.6" fill="black" transform="rotate(0,360,160)"/>
<polygon class="arrowhead" points="232,160 220,154.4 220,165.6" fill="black" transform="rotate(0,224,160)"/>
<polygon class="arrowhead" points="232,80 220,74.4 220,85.6" fill="black" transform="rotate(0,224,80)"/>
<polygon class="arrowhead" points="120,192 108,186.4 108,197.6" fill="black" transform="rotate(180,112,192)"/>
<polygon class="arrowhead" points="120,96 108,90.4 108,101.6" fill="black" transform="rotate(180,112,96)"/>
<g class="text">
<text x="160" y="68">Request</text>
<text x="60" y="84">onboarding</text>
<text x="268" y="84">SCIM</text>
<text x="56" y="100">app</text>
<text x="268" y="100">Server</text>
<text x="140" y="116">Ctrl</text>
<text x="184" y="116">Endpt</text>
<text x="56" y="164">Control</text>
<text x="156" y="164">REST</text>
<text x="284" y="164">NIPC</text>
<text x="396" y="164">AP</text>
<text x="500" y="164">Device</text>
<text x="56" y="180">&amp;</text>
<text x="208" y="180">|</text>
<text x="288" y="180">Gateway</text>
<text x="56" y="196">Telemetry</text>
<text x="160" y="196">pub/sub</text>
<text x="60" y="212">Apps</text>
<text x="336" y="244">Network</text>
<text x="412" y="244">Deployment</text>
</g>
</svg>
</artwork><artwork  type="ascii-art"><![CDATA[
                         +------------------------------------------+
                         |                                          |
+-----------+   Request  |  +---------+                             |
| onboarding+-------------->|  SCIM   |                             |
|    app    |<--------------+ Server  |                             |
+-----------+  Ctrl Endpt|  +---------+                             |
                         |                                          |
+-----------+            |  +------------+   +-------+   +--------+ |
|  Control  +----REST------>|    NIPC    +-->|  AP   +-->| Device | |
|     &     |            |  |   Gateway  |   +-------+   +--------+ |
| Telemetry |<--pub/sub-----+            |                          |
|    Apps   |            |  +------------+                          |
+-----------+            |                                          |
                         |            Network Deployment            |
                         +------------------------------------------+

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>NIPC registrations 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 as defined in <xref target="I-D.mohan-asdf-sdf-protocol-mapping"/>. 
The SDF affordances supported by the device, as well as its protocol-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-registrations"><name>Data application registrations</name>

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

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

<t>NIPC operations are protocol-neutral operations on SDF affordances, more 
specifically properties, actions &amp; events. NIPC operations can happen against
affordances that were registered in an SDF model. If connection management is
required to execute a NIPC operation, it is assumed that the gateway 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 will 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
may support explicit connection management as well. Explicit connection
management can be used by an app that wants to perform multiple NIPC operations
in a single connection. Explicit connection management can be performed by 
calling the /devices/{id}/connections API. After establishing an
explicit connection to a device, an application calls a NIPC Operation, the
Gateway will leverage the existing connection and will also not tear the
connection down after the operation completes. The app will have to explicitly
close the connection.</t>

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

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

<t>Extensions must leverage the /extensions path element. In order to assure
inter-operability, extensions must be IANA registered <xref target="iana-api-ext"/>.</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>paths:</t>

<t><list style="symbols">
  <t>/registrations/models</t>
  <t>/registrations/data-apps</t>
</list></t>

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

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

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

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

<t><list style="symbols">
  <t>properties</t>
  <t>events</t>
  <t>actions</t>
  <t>extensions</t>
</list></t>

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

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

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

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

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

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

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

<t>NIPC operations require 2 key parameters:
1) A device ID identifying the device the operation should be executed on
2) an SDF 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="sdf-name"><name>SDF Name</name>

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

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

<t>For example:</t>

<texttable title="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#/<br />sdfObject/thermostat/sdfProperty/temperature</c>
</texttable>

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

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

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

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

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

<t>Failure response:</t>

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

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

{
  "type": "https://www.iana.org/assignments/nipc-problem-types#inval\
\id-id",
  "status": 400,
  "title": "Invalid Device ID",
  "detail": "Device ID 12345678-1234-5678-1234-56789abcdef4 does not\
\ exist or is not a device"
}
]]></artwork></figure>

<t>where-</t>

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

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

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

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

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

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

<t>Method: <spanx style="verb">POST /registrations/models</spanx></t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

<t>Method: <spanx style="verb">GET /registrations/models</spanx></t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

<t>Method: <spanx style="verb">GET /registrations/models{?sdfName}</spanx></t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>Method: <spanx style="verb">DELETE /registrations/models{?sdfName}</spanx></t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

<t>Method: <spanx style="verb">PUT /registrations/models{?sdfName}</spanx></t>

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

<t>Query Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

<t>Method: <spanx style="verb">POST /registrations/data-apps{?dataAppId}</spanx></t>

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

<t>Query Parameters:</t>

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

<t>Request Body:</t>

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

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

<t><list style="symbols">
  <t>mqttClient: a boolean that denotes that the data application
is an MQTT client that will receive streaming data over MQTT</t>
  <t>mqttBroker: an object that contains the MQTT broker information
where the broker will publish the streaming data.
  <list style="symbols">
      <t>URI: the URI of the MQTT broker</t>
      <t>username: the username to authenticate with the MQTT broker</t>
      <t>password: the password to authenticate with the MQTT broker</t>
      <t>brokerCACert: the base64-encoded CA certificate of the MQTT broker (optional)</t>
      <t>customTopic: By default, the topic will be composed of <spanx style="verb">data-app/&lt;dataAppId&gt;/&lt;namespace&gt;/&lt;json_pointer_to_sdf_event&gt;</spanx>.
You can configure a custom topic to publish the streaming data to (optional)</t>
    </list></t>
  <t>webhook: an object that contains a webhook URL along with any 
 credentials that are required to authenticate the webhook. 
 The webhook URL is the endpoint where the streaming data will be sent.
  <list style="symbols">
      <t>URI: the webhook URL</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 base64-encoded 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 base64-encoded 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[
=============== NOTE: '\' line wrapping per RFC 8792 ================

{
  "events": [
    {
      "event": "https://example.com/heartrate#/sdfObject/healthsenso\
r/sdfEvent/fallDetected"
    }
  ],
  "mqttClient": true
}
]]></artwork></figure>

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

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

{
  "events": [
    {
      "event": "https://example.com/heartrate#/sdfObject/healthsenso\
r/sdfEvent/fallDetected"
    }
  ],
  "mqttBroker": {
    "URI": "mqtt.example.com:1883",
    "username": "user",
    "password": "password",
    "customTopic": "custom/topic"
  }
}
]]></artwork></figure>

<t>Response:</t>

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

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

<t>Method: <spanx style="verb">PUT /registrations/data-apps{?dataAppId}</spanx></t>

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

<t>Query Parameters:</t>

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

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

<t>Response:</t>

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

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

<t>Method: <spanx style="verb">GET /registrations/data-apps{?dataAppId}</spanx></t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>Method: <spanx style="verb">DELETE /registrations/data-apps{?dataAppId}</spanx></t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>The primary goal of the NIPC APIs is to  perform operations on SDF Affordances, such as properties, events &amp; actions.This allows a user of the NIPC API to get or update properties of devices, perform actions on devices, and consume events from devices.</t>

<t>The NIPC APIs consists of 3 main collections which reflect SDF Affordances as defined in <xref section="1.2" sectionFormat="of" target="I-D.ietf-asdf-sdf"/>:</t>

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

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Request Body:</t>

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

<t>or</t>

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

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

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

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

<t>Response:</t>

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

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

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

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

[
  {
    "status": 200
  },
  {
    "type": "https://www.iana.org/assignments/nipc-problem-types#inv\
alid-property",
    "status": 400,
    "title": "Invalid Property",
    "detail": "Property https://example.com/heartrate#/sdfObject/the\
rmostat/sdfProperty/temperature does not exist or is not writable"
  }
]
]]></artwork></figure>

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

<t><list style="symbols">
  <t>propertyName: The property to read. This can be a single property or multiple
properties. If multiple properties are provided, the request body MUST
contain an application/nipc+json payload with an array of properties to read.</t>
</list></t>

<t>Response:</t>

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

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

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

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

<t>where-</t>

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

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

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

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

<t>The event is the global name of an <spanx style="verb">sdfEvent</spanx>.</t>

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

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

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

<t>Response:</t>

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

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

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

HTTP/1.1 201 Created
Location: /devices/12345678-1234-5678-1234-56789abcdef4/events?insta\
nceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

</section>
<section anchor="get-status-of-one-or-more-events"><name>Get status of one or more events</name>

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

[
  {
    "instanceId": "87654321-4321-8765-4321-fedcba9876543",
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected"
  }
]
]]></artwork></figure>

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

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

<t>Response:</t>

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

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

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

HTTP/1.1 201 Created
Location: /groups/12345678-1234-5678-1234-56789abcdef4/events?instan\
ceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

[
  {
    "instanceId": "87654321-4321-8765-4321-fedcba9876543",
    "event": "https://example.com/heartrate#/sdfObject/healthsensor/\
sdfEvent/fallDetected"
  }
]
]]></artwork></figure>

<t>where-</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Request Body:</t>

<t>The request body is optional and may contain a value. The media type of the value can be defined by the underlying protocol, for example it could be octet-stream for binary data.</t>

<t>Response:</t>

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

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

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

HTTP/1.1 202 Accepted
Location: /devices/12345678-1234-5678-1234-56789abcdef4/actions?inst\
anceId=87654321-4321-8765-4321-fedcba9876543
]]></artwork></figure>

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

<t><list style="symbols">
  <t>Connection retry parameters</t>
  <t>A protocol map object. In the case of BLE, if no protocol map is included,
service discovery is performed to discover all supported properties when
connecting to a device. Optionally, service discovery may be limited to
properties defined in the "ble" protocol extension. The services to be 
discovered can be added in an array. Property 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,
  "sdfProtocolMap": {
    "ble": {
      "services": [
        {
          "serviceID": "12345678-1234-5678-1234-56789abcdef4"
        }
      ],
      "cached": false,
      "cacheIdlePurge": 3600,
      "autoUpdate": true,
      "bonding": "default"
    }
  }
}
]]></artwork></figure>

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

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

<t>Response:</t>

<t>Success responses include a protocol mapping with an array of 
discovered properties, as defined in the specific protocol.
For example, for BLE, this is an array of supported services, which in turn
contains an array of 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",
  "sdfProtocolMap": {
    "ble": [
      {
        "serviceID": "12345678-1234-5678-1234-56789abcdef4",
        "characteristics": [
          {
            "characteristicID": 
              "12345678-1234-5678-1234-56789abcdef4",
            "flags": [
              "read",
              "write"
            ],
            "descriptors": [
              {
                "descriptorID": 
                  "12345678-1234-5678-1234-56789abcdef4"
              }
            ]
          }
        ]
      }
    ]
  }
}
]]></artwork></figure>

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

<t><list style="symbols">
  <t>A protocol map object. In the case of BLE, if no protocol map is included,
service discovery is performed to discover all supported properties when
connecting to a device. Optionally, service discovery may be limited to
properties defined in the "ble" protocol extension. The services to be 
discovered can be added in an array. Property 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[
{
  "sdfProtocolMap": {
    "ble": {
      "services": [
        {
          "serviceID": "12345678-1234-5678-1234-56789abcdef4"
        }
      ],
      "cached": false,
      "cacheIdlePurge": 3600,
      "autoUpdate": true
    }
  }
}
]]></artwork></figure>

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

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

<t>Response:</t>

<t>Success responses include a protocol mapping with an array of 
discovered properties, as defined in the specific protocol.
For example, for BLE, this is an array of supported services, which in turn
contains an array of 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",
  "sdfProtocolMap": {
    "ble": [
      {
        "serviceID": "12345678-1234-5678-1234-56789abcdef4",
        "characteristics": [
          {
            "characteristicID": 
              "12345678-1234-5678-1234-56789abcdef4",
            "flags": [
              "read",
              "write"
            ],
            "descriptors": [
              {
                "descriptorID": 
                  "12345678-1234-5678-1234-56789abcdef4"
              }
            ]
          }
        ]
      }
    ]
  }
}
]]></artwork></figure>

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

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

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

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

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

<t>/extensions</t>

<t>The extension APIs allow for extensibility of the APIs. Extensions must be IANA registered.
Extension APIs can leverage the basic NIPC defined APIs and combine them in 
compound statements in order to streamline application operation against
devices, make operations more expediant and convenient in one API call. an example of this is the bulk API extension.
They can also introduce new functionality that is specific to a use case or protocol, such as the BLE transmit API.
the OpenAPI model <xref target="NIPCextensions"/> below, we have defined a few example extensions.</t>

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

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

<t>The error types in the NIPC APIs use URI-based error type identifiers 
as defined in <xref target="iana-problem-details"/>. The error types 
can be generic or specific to the API category. The error types are 
organized into the following categories:</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

<figure><sourcecode type="CDDL"><![CDATA[
start = DataBatch

DataBatch = [* DataSubscription]

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

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

BleSubscription = {
  serviceID: text,
  characteristicID: text
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

{ ... }

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

[
  {
    "sdfName": "https://example.com/thermometer#/sdfThing/thermom\
eter"
  }
]
]]></artwork></figure>
  <vspace blankLines='1'/>
Request Body: JSON object with the SDF model, from <xref target="thermometer-sdf"/></t>
  <t>Read a property from the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

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

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

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

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

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

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

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

</section>
<section anchor="enabling-an-event"><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[
============== NOTE: '\' line wrapping per RFC 8792 ==============

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

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

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

{
  "events": [
    "https://example.com/thermometer#/sdfThing/thermometer/sdfEve\
nt/isPresent"
  ],
  "mqttClient": true
}
]]></artwork></figure>
  <vspace blankLines='1'/>
Request Body: JSON object with the SDF model, from <xref target="thermometer-sdf"/></t>
  <t>Register the data app with the event  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
============== NOTE: '\' line wrapping per RFC 8792 ==============

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<section anchor="iana-media-types"><name>Media Type Registration</name>

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

<t>Type name: application</t>

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

<t>Required parameters: none</t>

<t>Optional parameters: none</t>

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

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

<t>Interoperability considerations: none</t>

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

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

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

<t>Additional information:</t>

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

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

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

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

<t>Author:</t>

<t>Change controller: IETF</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

</section>
</section>


  </middle>

  <back>


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

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

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


    </references>

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

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


    </references>

</references>


<?line 2237?>

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

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

<figure anchor="openAPI"><artwork><![CDATA[
<CODE BEGINS>
file "openapi.yml"
=============== NOTE: '\\' line wrapping per RFC 8792 ===============

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

paths:
### NIPC Property APIs
  /devices/{id}/properties:
    put:
      tags:
        - NIPC property APIs
      summary: Update a value of one or more properties on a device
      description: |-
        Write a value to a property or multiple properties to a
        device. If underlying protocol requires a connection to be
        set up, this API call will perform the necessary connection
        management. If a connection is already active for this
        device, the existing connection will be leveraged without
        modifying it.
      operationId: UpdateProperties
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be written to.
        required: false
        allowReserved: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/temperature"
      requestBody:
        description: |-
          The value to be written to the property or properties.
          If multiple properties are specified, the request body
          should be application/nipc+json.
        content:
          application/nipc+json:
            schema:
              $ref: '#/components/schemas/PropertyValueArray'
          "*/*":
            schema:
              description: |-
                Any other content type, such as 
                application/octet-stream, application/json that will 
                be written to the device.
        required: true
      responses:
        '204':
          description: |-
            Success, no content, used for a single property write
        '200':
          description: Success, used for multiple property writes
          content:
            application/nipc+json:
              schema:
                allOf: 
                  - $ref: '#/components/schemas/PropertyValueRespons\
\eArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

# responses

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

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

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

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

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

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

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

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

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

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

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

<figure anchor="protocolmapmodel"><artwork><![CDATA[
<CODE BEGINS>
file "ProtocolMap.yaml"
=============== NOTE: '\' line wrapping per RFC 8792 ================

openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) Protocol Mapping
  description: |-
    Non IP Device Control (NIPC) Protocol Mapping. When adding a
    new protocol mapping pls add a reference to the protocol map
    for all the schemas in this file.
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.10.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

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

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

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

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

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

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

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

openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) BLE Protocol Mapping
  description: |-
    Non IP Device Control (NIPC) BLE Protocol Mapping. 
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.10.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ProtocolMap-Zigbee-Event:
      allOf:  
        - $ref: '#/components/schemas/ProtocolMap-Zigbee-Propmap'
<CODE ENDS>
]]></artwork></figure>

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

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

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

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

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
2/schema
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API write binary blob extension
  description: |-
    Non IP Device Control (NIPC) API write binary blob extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.13.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-13"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing
      one or more basic APIs into a single API call.

paths:
### Extensions
  /extensions/{id}/properties/blob:
    put:
      tags:
        - NIPC API extensions
      summary: Write a binary blob to a property on a device
      description: |-
        Write a binary blob to a property on a device. Will chunk up
        the binary blob and perform multiple writes. If the 
        underlying protocol requires a connection to be set up, 
        this API call will perform the necessary connection 
        management. If a connection is already active for this 
        device, the existing connection will be leveraged without 
        modifying it. ID cannot be a group-id.
      operationId: writeBlob
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
tat/sdfProperty/firmware"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-Blob'
        required: true
      responses:
        '204':
          description: Success, no content
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureRespo\
nse' 

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

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

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

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

paths:
  ### Extensions
  /extensions/{id}/bulk:
    post:
      tags:
        - NIPC API extensions
      summary: Compound operations on a device
      description: Compound operations on a device
      operationId: Bulk
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Extension-Bulk"
            examples:
              bulkRequest:
                $ref: "#/components/examples/bulkRequest"
              firmwareUpgradeRequest:
                $ref: "#/components/examples/firmwareUpgradeRequest"
        required: true
      responses:
        "202":
          description: Accepted
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/bulk/status?instanceId=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the bulk status response
        "401":
          description: Unauthorized
        "405":
          description: Invalid request
        "500":
          description: Server-side failure
          content:
            application/json:
              schema:
                $ref: "../NIPC.yaml#/components/schemas/FailureRespo\
nse"
      callbacks:
        bulkEvent:
          "{$request.body#/callback.url}":
            post:
              description: Callback for bulk response
              operationId: bulkCallback
              requestBody:
                content:
                  application/json:
                    schema:
                      allOf:
                        - $ref: "../NIPC.yaml#/components/schemas/Id"
                        - $ref: "#/components/schemas/Extension-Bulk\
Response"
              responses:
                "200":
                  description: OK
                "400":
                  description: Bad request
                "401":
                  description: Unauthorized
                "405":
                  description: Invalid request
                "500":
                  description: Server-side failure
    get:
      tags:
        - NIPC API extensions
      summary: Get Bulk response
      description: Get Bulk response
      operationId: getBulkResponse
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
        - name: instanceId
          in: query
          description: Instance ID of the bulk operation
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        "200":
          description: OK
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "../NIPC.yaml#/components/schemas/Id"
                  - $ref: "#/components/schemas/Extension-BulkRespon\
se"
              examples:
                bulkResponse:
                  $ref: "#/components/examples/bulkResponse"
                firmwareUpgradeResponse:
                  $ref: "#/components/examples/firmwareUpgradeRespon\
se"
                errorBulkResponse:
                  $ref: "#/components/examples/errorBulkResponse"

  /extensions/{id}/bulk/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Bulk status
      description: Get Bulk status
      operationId: getBulkStatus
      parameters:
        - name: id
          in: path
          description: The ID of the device. Group ID is not allowed.
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
        - name: instanceId
          in: query
          description: Instance ID of the bulk operation
          required: true
          schema:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        "200":
          description: OK
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "./Extension-Async.yaml#/components/schema\
s/Extension-StatusResponse"
        "303":
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/bulk?instanceId=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the bulk response
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "./Extension-Async.yaml#/components/schema\
s/Extension-StatusResponse"
              examples:
                successExample:
                  summary: Success
                  value:
                    status: COMPLETED

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

    ## Extension that defines an operation in a bulk API
    Extension-BulkOperation:
      required:
        - method
        - path
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
                - POST
                - PUT
                - GET
            path:
              type: string
              enum:
                - /devices/{id}/properties?propertyName={propertyNam\
e}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?prope\
rtyName={propertyName}
                - /extensions/{id}/events/conditional?eventName={eve\
ntName}
                - /extensions/{id}/properties/file?propertyName={pro\
pertyName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4\
/properties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%\
2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              type: object
              oneOf:
                - $ref: "../NIPC.yaml#/components/schemas/Value"
                - $ref: "./Extension-ReadConditional.yaml#/component\
s/schemas/Extension-ConditionalRead"

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

    ## Return for an operation
    Extension-OperationResponse:
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
                - POST
                - PUT
                - GET
            path:
              type: string
              enum:
                - /devices/{id}/properties?propertyName={propertyNam\
e}
                - /devices/{id}/actions/?actionName={actionName}
                - /extensions/{id}/properties/read/conditional?prope\
rtyName={propertyName}
                - /extensions/{id}/events/conditional?eventName={eve\
ntName}
              example: /devices/12345678-1234-5678-1234-56789abcdef4\
/properties?propertyName=https%3A%2F%2Fexample.com%2Fthermometer%23%\
2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              anyOf:
                - $ref: "../NIPC.yaml#/components/schemas/Value"
                - $ref: "../NIPC.yaml#/components/schemas/SuccessRes\
ponse"
                - $ref: "../NIPC.yaml#/components/schemas/FailureRes\
ponse"

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

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

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

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
\2/schema
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API write file extension
  description: |-
    Non IP Device Control (NIPC) API write file extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.13.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-13"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing
      one or more basic APIs into a single API call.

paths:
### Extensions
  /extensions/{id}/properties/file:
    put:
      tags:
        - NIPC API extensions
      summary: Write a file to a property on a device
      description: |-
        Write a file to a property on a device. Will chunk up the 
        file and perform multiple writes. If the underlying protocol
        requires a connection to be set up, this API call will 
        perform the necessary connection management. If a connection
        is already active for this device, the existing connection 
        will be leveraged without modifying it. ID cannot be a
        group-id.
      operationId: writeFile
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/firmware"
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/Extension-File'
                - $ref: './Extension-Async.yaml#/components/schemas/\
\Extension-Callback'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
\cdef4/properties/file/status?propertyName=https%3A%2F%2Fexample.com\
\%2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2Ffirmware&i\
\nstanceId=12345678-1234-5678-1234-56789abcdef4
              description: |-
                URL to get the file write status
            Retry-After:
              schema:
                type: integer
              description: |-
                Time in seconds to wait before retrying
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureRespo\
\nse'
      callbacks:
        callbackEvent:
          "{$request.body#/callback.url}":
            post:
              requestBody:
                content:
                  application/json:
                    schema:
                      anyOf:
                        - allOf:
                          - $ref: '../NIPC.yaml#/components/schemas/\
\Id'
                          - $ref: '../NIPC.yaml#/components/schemas/\
\PropertyValue'
                        - $ref: '../NIPC.yaml#/components/schemas/Fa\
\ilureResponse'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          property: https://example.com/heartrate#/s\
\dfObject/thermostat/sdfProperty/firmware
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          status: 400
                          type: https://www.iana.org/assignments/nip\
\c-problem-types#invalid-id
                          title: Invalid ID
                          detail: "Invalid request"
                          property: https://example.com/heartrate#/s\
\dfObject/thermostat/sdfProperty/firmware
              responses:
                '200':
                  description: Success
    get:
      tags:
        - NIPC API extensions
      summary: Get the status of a file write operation
      description: |-
        Get the status of a file write operation. This will return
        the status of the file write operation, including any errors
        that may have occurred.
      operationId: getFileWriteStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/firmware"
      - name: instanceId
        in: query
        description: |-
          The Instance ID for the file write operation.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureRespo\
\nse'
  /extensions/{id}/properties/file/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get the status of a file write operation
      description: |-
        Get the status of a file write operation. This will return
        the status of the file write operation, including any errors
        that may have occurred.
      operationId: getFileWriteStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be written to.
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermos\
\tat/sdfProperty/firmware"
      - name: instanceId
        in: query
        description: |-
          The Instance ID for the file write operation.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success, returns the status of the file write\
\ operation.
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
\tension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
\cdef4/properties/file?propertyName=https%3A%2F%2Fexample.com%2Fhear\
\trate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2Ffirmware&instance\
\Id=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the file write response
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
\tension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

components:
  schemas:
# Extensions
## A File Extension
    Extension-File:
      required:
        - fileURL
      type: object
      properties:
        fileURL:
          type: string
          example: "https://domain.com/firmware.dat"
          description: |-
            URL to the firmware file. 
            The HTTP method is assumed to be a GET.
        chunkSize:
          type: integer
        sha256Checksum:
          type: string
          description: firmware checksum
        headers:
          type: object
          additionalProperties:
            type: string
          example:
            x-api-key: fjelk-3dl33f-2wdsd
<CODE ENDS>
]]></artwork></figure>

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

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

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

paths:
### Extensions
  /extensions/{id}/properties/read/conditional:
    post:
      tags:
        - NIPC API extensions
      summary: Conditional read of a property
      description: Conditional read of a property
      operationId: conditionalRead
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be read conditionally.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-ConditionalRead'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/properties/read/conditional/status?propertyName=https%3A%2F%2F\
example.com%2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2F\
temperature&instanceId=12345678-1234-5678-1234-56789abcdef4
              description: |-
                URL to get the conditional read status
            Retry-After:
              schema:
                type: integer
              description: |-
                Time in seconds to wait before retrying
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureRespo\
nse'
      callbacks:
        callbackEvent:
          "{$request.body#/callback.url}":
            post:
              requestBody:
                content:
                  application/json:
                    schema:
                      anyOf:
                        - allOf:
                          - $ref: '../NIPC.yaml#/components/schemas/\
Id'
                          - $ref: '../NIPC.yaml#/components/schemas/\
PropertyValue'
                        - $ref: '../NIPC.yaml#/components/schemas/Fa\
ilureResponse'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          property: https://example.com/heartrate#/s\
dfObject/thermostat/sdfProperty/temperature
                          value: dGVzdA==
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          status: 400
                          type: https://www.iana.org/assignments/nip\
c-problem-types#invalid-id
                          title: Invalid ID
                          detail: "Invalid request"
                          property: https://example.com/heartrate#/s\
dfObject/thermostat/sdfProperty/temperature
                          value: dGVzdA==
                          
              responses:
                '200':
                  description: Success
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional read response of a property
      description: Conditional read response of a property
      operationId: getConditionalRead
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be read conditionally.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - name: instanceId
        in: query
        description: |-
          Instance ID of the conditional read operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Value'
            application/octet-stream:
              schema:
                type: string
                format: binary
              description: Binary data of the property value
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureR\
esponse'
  /extensions/{id}/properties/read/conditional/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional read status of a property
      description: Conditional read status of a property
      operationId: getConditionalReadStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: query
        description: |-
          The SDF property name that needs to be read conditionally.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - name: instanceId
        in: query
        description: Instance ID of the conditional read operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/properties/read/conditional?propertyName=https%3A%2F%2Fexample\
.com%2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfProperty%2Ftempera\
ture&instanceId=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the conditional read response
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

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

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

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

# yaml-language-server: $schema=https://json-schema.org/draft/2020-1\
2/schema
openapi: 3.0.3
info:
  title: Non IP Device Control (NIPC) API event conditional extension
  description: |-
    Non IP Device Control (NIPC) API event conditional extension
  termsOfService: http://swagger.io/terms/
  contact:
    email: bbrinckm@cisco.com
  license:
    name: TBD
    url: TBD
  version: 0.13.0
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/
servers:
  - url: "{gw_host}/nipc/draft-13"
    variables:
      gw_host:
        default: localhost
        description: Gateway Host
tags:
  - name:  NIPC API extensions
    description: |-
      APIs that simplify application interaction by implementing
      one or more basic APIs into a single API call.

paths:
### Extensions
  /extensions/{id}/events/conditional:
    post:
      tags:
        - NIPC API extensions
      summary: Enable an event until a condition is met
      description: Enable an event until a condition is met
      operationId: conditionalEvent
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: eventName
        in: query
        description: |-
          The SDF event name that needs to be enabled.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfEvent/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-ConditionalEvent'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/events/conditional/status?eventName=https%3A%2F%2Fexample.com%\
2Fheartrate%23%2FsdfObject%2Fthermostat%2FsdfEvent%2Ftemperature&ins\
tanceId=12345678-1234-5678-1234-56789abcdef4
              description: |-
                URL to get the conditional event status
            Retry-After:
              schema:
                type: integer
              description: |-
                Time in seconds to wait before retrying
        'default':
          description: Error response
          content:
            application/json:
              schema:
                $ref: '../NIPC.yaml#/components/schemas/FailureRespo\
nse'
      callbacks:
        callbackEvent:
          "{$request.body#/callback.url}":
            post:
              requestBody:
                content:
                  application/json:
                    schema:
                      anyOf:
                        - allOf:
                          - $ref: '../NIPC.yaml#/components/schemas/\
Id'
                          - $ref: '../NIPC.yaml#/components/schemas/\
PropertyValue'
                        - $ref: '../NIPC.yaml#/components/schemas/Fa\
ilureResponse'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          event: https://example.com/heartrate#/sdfO\
bject/thermostat/sdfEvent/temperature
                          value: dGVzdA==
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          status: 400
                          type: https://www.iana.org/assignments/nip\
c-problem-types#invalid-id
                          title: Invalid ID
                          detail: "Invalid request"
                          event: https://example.com/heartrate#/sdfO\
bject/thermostat/sdfEvent/temperature
                          value: dGVzdA==
                          
              responses:
                '200':
                  description: Success
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional event response
      description: Conditional event response
      operationId: getConditionalEvent
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: eventName
        in: query
        description: |-
          The name of the SDF event that is enabled.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfEvent/temperature"
      - name: instanceId
        in: query
        description: |-
          Instance ID of the conditional event operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Value'
            application/octet-stream:
              schema:
                type: string
                format: binary
              description: Binary data of the event value
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureR\
esponse'
  /extensions/{id}/events/conditional/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional event status
      description: Conditional event status
      operationId: getConditionalEventStatus
      parameters:
      - name: id
        in: path
        description: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: eventName
        in: query
        description: |-
          The name of the SDF event that is enabled.
        required: true
        allowReserved: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfEvent/temperature"
      - name: instanceId
        in: query
        description: Instance ID of the conditional event operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
                example: /extensions/12345678-1234-5678-1234-56789ab\
cdef4/events/conditional?eventName=https%3A%2F%2Fexample.com%2Fheart\
rate%23%2FsdfObject%2Fthermostat%2FsdfEvent%2Ftemperature&instanceId\
=12345678-1234-5678-1234-56789abcdef4
              description: URL to get the conditional event response
          content:
            application/json:
              schema:
                $ref: './Extension-Async.yaml#/components/schemas/Ex\
tension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

components:
  schemas:
# Extensions
    Extension-ConditionalEvent:
      allOf:
        - $ref: './Extension-Async.yaml#/components/schemas/Extensio\
n-Callback'
        - $ref: '../NIPC.yaml#/components/schemas/Value'
        - type: object
          properties:
            timeout:
              description: |-
                Time in seconds to keep the event enabled.
                If the event condition is not met within this time,
                the event will be disabled and marked as failed.
              type: integer
              example: 5
<CODE ENDS>
]]></artwork></figure>

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

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

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

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

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

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

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

</section>


  </back>

<!-- ##markdown-source:
H4sIAAAAAAAAA+x9aXfbSHbod/wKRM6M7TRJbV7aetPTkSXZo8S2FEudPkk0
pw0SoIQYJDgAKFktK7/93aVWoACCEmXLbvLMtEWiUMutW3eru3S7Xa+IiyTa
8rfH/vZkksSDoIjTsf8muIwyf39cRNkwGET+MM38d+m4u3/oh9F5DL8M0nGR
pYn/6N3+4c5jL+j3s+h8y8dvXpgOxsEIeg2zYFh046gYdoM8HHbH8WTQXd/0
8ml/FOc5jHR8OYF2+3vHrzwYOjpNs8stPy9Cz4sn2ZZfZNO82Fhbe7G24X2M
Li/SLNziaY2joruL3XteXgTj8LcgScfQ1Tj1JvGW/z9FOuj4eZoVWTTM4a/L
Ef7xd88LpsVZmm15ftf3fPjE43zLf9nzX2bxePBxFIzpV57/yyArSg/S7HTL
34nzQeofXeZFNMrp50FcwMRfwnTzKBE/pVMAEf4aJafxdEQ/RqMgTrZ8gBZ1
+q8D7Kk3SOFpV0/nfc9/m55ZU3mfnsWF8WvNPHJYb1Rs+evP1/xfo7zwj4Mc
pu7vZvF5JKYVQncvnq5vPjFmfgRt/i3NI3vmvxxtm7POcA6jtGbSAEPoBTAl
NCGYBVEYja0nNPXDsziJJybwdoIRQCU8bZ5Dnzvs5dzhv064H5qNF+NvI0Dh
8wg22H/5Zu/p5ha9LdD8ZTKNijQtzvydNIv8o0k0iIcC6Tv+f0YZ4qT/tLdJ
LylUoU9X/CsWoLs62n9Nj0JA4C1/Y21jHb7+d3zaj6KNDWv43+nHumE3Nvz1
3trskXfS8TgawCIBbP4RIn+Qhbm/nSRxMB5E1lzWn8PX10FRdN/vHR13tw/3
rQlt+/jzcJr48MSf5lHoF6kfDAZRnmMfAWytOPE5PI7Hp35xBuRgOh7g3IME
pxBGw3gMb0JTfKgB83r7+NifZOkwTnhWRZCdInaeFcUk31pdvbi46PVlc9zC
VfWtm0V5Os1g3NVTnD58LbrBJF69zc4ANHq9nud1u10/6MNZCQZAP47P4twf
RaMUVpIPsrgPa4XjgBApzoLCD5IkvYCfNH3MEUoToI2AbX4Kf4hfg9MAjgK8
4cOco4vg0s+j7ByhBrQJJuePEOskPOVood+/xAGPdl9BgzBKev4xwBGo6HQU
jQtjVnKzjKn4CZHqWJFq98xS3Bs433Lwjh/k/kWUJPhv4O+8PHjf7Qe4/5Np
P4nzsy7QaB7W6BvZAFKYYIRrQvzo+QzNURyGsMneA6TOWRpOCT/g+wP/aADz
8Lw36UV3kl7AXPNoDIQZpzAopkEBf8LqQx82DB4OGLlhIhJMseiQMMyLxudx
lo4RMPwaIK0/gJnnfj4dnOFy+tM4CXGCQPiC0wibdvyzKEiKs0GQRR0f2MjH
SRIgGDxoMx3iRIAgn3b8JD2N8yIecN8AsUlcMJbDm346LICW9QEfo+ySVxOF
Pf/XGHDNS+JRjPPmRfanQMlgXFjUJUzkEhhT4QMwg35Ce5RPJxPgTnRigKvC
KQGOBfyUNiqKM+8ihr4RZ/CPBM+j2occlzPGvcbOZU+yi5yxNov+MYU3YXMT
nJBnTqvnH2bpKCbsij4Fown0D4tjCOp+cMlXV0RFr68RIN7VlaRr19eEpRqj
/OJyAjiZJEAQUjU6rBSO9Wg6RnSNYC0AKfGCB2uzzxQdtiwycABe3z8UiAkc
HzcONxbofBYAIk5x3yLAQZgJsPcUN9fqkqGJABZv8yDjiPs2pwazyaJBhGyy
AHiPIuA+/hDAhD3AMscs/iQKjeW6RyCi4JLzFFpm6fT0zDj/niSV1akg/IDw
yJayIcIBkAxo0zhP4Bl99z09VeysSOlXMSeFPLQ4fFCepUSSHM/r/+HHD4L8
/FQRzht+6P0fuubnB7vFDzMf/ECdfLbkz89/Mbv862dkYQSlygMhlX6un579
CL8plDIf0l+iN/q6y5D7XLPGA0lcy2t0PSitHafG2+BdbfkPTi+YH/+0IpeJ
hFZsLk8jX7n2GMv9s+A8AkoCOBINh7iniA3MgxWYNDJhT+qEInoITPACfwLS
bTyYJkGmMKijiGiA0hNzcOQ6xA2xL/qVR8m9R1dXlmxxff0YSBPg3TlgHhEn
PVlJHlG+8FGSADqoqV5mz0cS9R6wE+TURO2AQAGXBGYy9nMh9UjeiEQBxvXK
hx/aG2e/QonGpkoDVBV47CT9GBGpO4/GYZp1cyGr+TFSSaSYondaGSwgiYe4
38gH6DyDoDJNCqTWuCCgh1Hi2fQKF9JH8UQcfeY1Yi5irsDFIuKx0SRJL5ER
wGIIJB4IC/gvsKE8hjlHAWyYoJj4Rh7hsEDCLpFhpCWi0+GFB36IbA6QxMuj
AicEuwfEYZvJRw6yO6DkCHml5D5CKJykMXJegUU4IC1FHSlPvTAwxVRD2hAL
5eaqdRENzsYpst+IGI+nVj7tx8BLAOjTPLkExSgYX+KEmSrXTA+5CHKgyYTG
KM68LAjjVByBQSDoK2AkwV4QfgDKEDYTuSLsF4IAtNNcnwnFCz18qcwLYe9z
U7D3g3hkns1AnU55lngJ3jubihuTBHkhwbMEUgwJiQUOYsgDFlYBwoFCBJye
GBvB3tbZc0YIA8lY0HTPuh950ScQd/IYJJaO6t2UXaJPhESnBMPhlGZRYkk5
SNvb6rjGv8M6xJwkMLR0eRYguUJhm9AqGgPcinzLQ1V9+zyNQ+Z5yLsRevJ0
yQ5LQkHNW3VSvDz6OJ1TKTXDE6T+Gi1M6ZNGeAUjAlAQACTbD1JQU4AuE+LD
nofphLn/sLoXxk7gKHbfKDnbkEJACuhKmeHtL0ekYJ3HIYxVALLAdAwYKjYg
gDhF0aJQOw2TZkUq/j2QszRVi0ESk5iN+IgzvIjhBEuEJLCeGhjtEvXsNfOe
8EElNoAaBNIBHDgd91NAES349/wD/glXAngImyqOBs4FRy9hEp4YAAQscHiJ
PEZSbiECkUAfIOkawq+4MjJiAZJjf0E/nTLxE80Rz1F5G9irRMEWVFFeC56e
oB+TfsCnLgeVDbkOYXXAkh/pdIx8ANIgJ1FbLZIIB82A1UwTrNDndAyHjs4P
Mjj8RXatKDn1xLCtaq04bD/uhkA0hMruV0TJcXWXDgx9dXAWADVJ+LhkKW2f
BEMH+d0E1k0qJSJUfjlC2Tke4JqsoXKesSG4ElH2labvPxLIcUhU/DFBpfCB
CCC7mqR5kLjAzhqpr6V2Qc5DFt/HlXMHzZMusjdCpHSGytAjwYupeCyPCTZJ
NXoqKR/2EvEIdSlUe7kp/CiVeZAxpoUnaLs4uaz/8zc0BLGGI6miZj7/9P7V
zvNnT56ALiYOIbYEneyf9ru7PbKy5oN41OWVdgntkDWhTVbSubxkFJDog5t9
CsrLxEv7/wuYIjXMWCmSuWqpl01sQnaNqm8Wp5lBVaENyHU0vhrWHFXMDWUP
Ji6gxCGhxdNanhgcbd87BaZAwpYvFB3cRYN6EDNC4RWQDhBUkoM4ylDxwW00
tQx5zGJ8QwqJcivRekyod5rCmYkl9n+6BMZzmaRBCKe2D++gbCsIEeK/xV33
C3wRNX/cz3HI4i9aAYTB5AIFFTmiR+eWdn6SRXi2wgittTmfxBDXkQuhQc6h
Z6tz9fqcrcA0fn6o78WtZrmbeuaQqAC9Z5pBvdSqhZVePht7W1oEqH/+0c7+
25kTw17gA+ecvv3F7uYH/wgIPXDxmb2UVrRTZIm/Nw4nxVwrqn/U+GLzXKxe
LDjhwx8cf8MXgsuOuMnhB6TKKej6fED5Lfxh+1D9LfVjCV3/z9VFfObvkkPT
l4a5HCsSjns0mfZX82nfucJ6uNBDOOW5Yy4VuNwIum0/bXf6naA8u6TxkFGu
XS9znWnD3hBkwFKExeElaJEDfxt+Ae2cJGe0NFxdYRtgNPkZChFT2/rdYekL
MaNqiZZE9dH2m9ePO6ApWaoZ/Hz4WEgKksI/2n3Miog9RqVrT3ZNb5udBmRV
NzRllK2777SdLULElTYwP/CUyiC4LOi5ZzEABdjdFE3JLllWy4a9CidBDi/H
j4m/KZUhCIENxnjXQBpBmI4CuigJSM7wJNuJ2LiQE9zgKAGYeBg4mpGUOOqh
rfgTqwIVq6JXFnMu4vxMsPAZZhF5ryNVFbECFI6lVqok1p63bQ6ibCY4koC5
JDcoAyldQl5saBO3N1udKE1MghaxQ19eFKkHgyBgDZmpfOGBZEaPzcrXcYTy
C1okLlly+Bhd4s0B8P0V1LtWOvyv/+6A/n6/9x+/7L/f28W/j/62/eaN+oNb
ePDl4Jc34jn+pd/cOXj7du/dLr8Mv/qln95u/9cKHRpv5eDweP/g3fabFV69
IVrSKWDxQskQKCiZF03wzsudQ2/9iRAnN9bXX8Ap5y8/rj9H2fICJD8+oek4
uRRfyZgHCBQFGSF4koAQS3cjfJWEdGLso30SoWfRE4LmwTnqUtGFV7F2aPMK
mhZB0mGrSse8T5AGlPF01AekR/sZki3PkGXV5UEej2I0IQaDLEUCoQwR/p5x
00GQw+agC4S0WO8igxmLSy0Wmfk0CXEShK9Q6rn68gav1PQsUFXQJgVb7rXE
7Y55aHKyTuT+Bs5qfArK+vpjf19eZeNbSjfF28VA2EINXZVsSfDqFl8c8o90
L9GPPK1YC9VGUeiod9rDAzyKgjFBBYWpx0IlNdRRWoi0QhSosIF+B6fJmoJQ
G5TELW8141BL9eqOeBLAaYYBPdU9QLbnbdSvu6RO80qlXCGWqi7XxA54cvO7
42gKBDgxdoMxnJUcpeGAWA44Tve1Q7/8soVtqbZdKzuDgQfiaozwcYoUkSV/
A/qeCXfz8rdjH1dTuyMfGvg/KHUOsb8i3OjbDyEk1wkvqiFvYqlhRcr4wfGm
fxWH16XWf60M57hLMYWrz4wK+gKlQfZRA3fxLhPeKC4bZSWj/TbjUZv5UPu9
cymSfTYulHDD2q2XfmYj0CzIOudjim5A1AFbpfAmyFRECJwD+aJrogNxNQwI
uGE/Na5jgNsOQeOOwo77EtaTlkFAQ2TVDURNUIAYtNHyY49uza3WE96tGA1G
Kd3357CaKZDeQFxZwa+CZavOcxAkc5wDi0F47xUiHcxN5xPLhYK5jtIcPW/f
MGDLxTTZJjomdUO7IbxH4EObgMdkjpxfBsBt9PGmDqU05P8aMfHjp0hVc/+h
1mcf9kCKDLLCk/fMGpbcfQclUiLGeQpcAkXeILvU97wW8SVzJjqgeAGZUoio
IWQ0RUXxIE0LlEYn7FxXlm1NxxAPtPWAvEGsyxxqUsaDICfTJ19dmDc/MfEQ
uqXfThLAKbwgN8w1g3SakI0+BbYiGL5lVMKbB3INQVYpAOLBCtLxaUK2PpAS
lW1FSZSWuYxugGbYyWhVCAcilvLafHAWjQLafjo18HOUwKpDcclSBCwMwd7w
zgQFsMb+tIj4Uk/coAiWIcUGhB0j6PvoVKgG2ASEI4RqZv1IxjFixpW7C4F7
9g6TDYmMTl4WJYG6cpWYJSSIXmlsYZKMK+w3GHttjdl0oF09mDP35AwVglZs
2pZCAWB6oM+1DRwWzPVD97Tg34KEeSSACEYlAY3k/ZMc2isslxZS5SpCBJ1s
k5yEKYGdKYaajUdSiUQSJS4ICQOAJWWNygDYhUHjPEPa0PfRKS4nsAigwPAR
OokqYaGrXhXjoUlYwc0kpQI9tVJXpQhE/ModInHOlDW7JOf4dXKOtZMwI/Ug
F+p8GyEIcWMX3RRNzbiEItsW+vkGXysaZXWJBCyc842oFDCFRsJGA+tY4jmS
18naVY74GTtUSlLvKSZBMjs86qJ9snL4pSBuSKYwBHeoLtF89HywXfrkLomr
REuwyv2rB+SLnU7ya0F1TFqeRVWktIFTwp0O3xR56ioZqbjJ6SVv/7Ng7RVJ
gQB3hhrmWLpReiZyEtVAfzsBoShzMH1/f6iYD9Iq5f+HLMOkN9GnaEAiR2ka
it8SNws1o1V2lhHudZFcat4oSH0BqjEq4xdjTdn0XMjxCrH1UAGFKLvnKem1
jtC7vTlN4EoFukg9UmfRaZCU2fMgmbI1C9YwEueFxV88GAwlGldJRIMy/uvu
ozEuGFEww/s48QUwOgpIzzcvdngokpxhJJag7QXStKjLSHcYCcTOIuldoifS
k92x2i5IVSpcjaTIKNxXVx3uq2JSO04EoQgH+5B43qs0K7tlSMdGN5r1yQlR
oBd7RhjIJe/CJDLRlZeEPGNWXLh7BlESvQKNjn08tibmBpaeTucJfXumE2SJ
uk/r1tgU9hCBGX8RnMYbwbAQMNaCMkpEIHhNkog8n7ZtGwHyVe0k0rQuOQG0
zlTaeUY7IZ+QizobFpDiMVUIxoXlyzGaJkUMU6toI8TPhe+ZHsY5tl8dW4uk
MAEPaZz0h18VKLqKWvCqcerJrOFvEwAVwWC88FyAMSS1Tklu8nHAXO7ygd53
5CWvTYyyPDSUj465oeOQW7JakRZEvKgjoxWhgmvv5b7nymrPvZF2RMSVFwZE
cpCggczGJ0kJ97RsfPVAC8qSHwEVph9DIguBWrkpu+HO23Zv4TWh6LvHk/3k
Cze3MtcxMQKZLQKZxFire2FOMg+zdtICxhOfkw8QXv3DeBEzw0i6mSSXbO4P
tKXLR6lEeF5Lji4hwD3TNQROPp2iJVYNy+qU358mH9lm5hlwJInT2v5VQwMh
o5u4Z7AFWGR3QMCJUnZpLPau6JgKjDSy7W+/2zaZ8NVVDEcFYzO60FqIZYJW
S3LsO8ixYAtC3OB20tGxiYrLrsWpTIeevmwhh70tz+v6R1aYAktd4pRulR8i
w0d1FZUlOMrqb6WNeOIeVPAYgDuM8DJLg3AQ5PCD2Ts8MTgMv7ElvXhNR80/
I8/T3wlqh5LZ8BFR3hH6TGjBTql6fI0Bg8lblL8dHx8KBfjF+voTFPi3E1CX
eT341DsDOSESgRe/vN8HLk8DENb929HBO6k/rz/F+wHl8cBa73l0yc0Nk6gW
EywJVkl+HcHZccCJFHlsiynIaAK7yb+VPJfQt1T4GglPTfY2Iu+/Eep1dihL
lGVplvc8vRrsj1YEhDsOCEP8FYOurqIg/MP/5ul4xdeqqSFiegLB6f0uYRha
C6JPg2hSSD/OOg2Vdq/jexfkuo0NjWlk0TCBzc8lgSwEQxQyrSfswdpQTXFK
7lWARsSL4FtDeYFhiZa5HXYyFY53ZFzR/dIue1L/suYmbh1kvz0DS6snNhLC
X+Nj9tQdo5sLifN4L+c/EvdRL54A8j2m9fNh9wStlXJfFOPc6by//Y/jY/jn
16h/lqYf+a88HXyMCj5YQPvEoXpNPkQJMB0kiHmXfYoS9q/nxdABUucsLt2g
oTGB1VkmqWRmiZn3Bf5LxF04UrwP8psvrwq11cgHrM4uUUmkyCMUqIS/5dvt
/6K7NrzmDsNYuO15NJhlXoEG3Ik+DdgPmhRxfsIFi/ZMHKKeTzwbSYaH0yKK
8sv7N4z6ozQvRJAT2mVjpG1iz1coZm/FuPZA0xhKKeLe1cOAT3Gzj/6PMG2Y
NM2Zt3PzxY/PkBTBBMjNyWighG90hSxZ9ABV6Ij2SBoXPHNLejqtyFBC8YCC
CLH56gooOAp4CTrYnYs4S3GLiBwe74zCEI3gQ6Nzf3bv5+s0gJKO2Is1K43R
0ZddljEIBfIkESzC8FEjlHE+UtxurO7+lJsv4f+qRXa2NEjN35mXdJW8ajRz
2j6wKTnf1bfkx4a1Dd/RUoPxnhZwmKPhWpFsdz+OUdJEbPyw2tO/EKA/2PYt
IsS6CbAmgIsn9QI0zCBLPTc3RV41mjeNQmM/iwybl9i53LPttizjKrZDR/z1
3rFiSqm4hVdnnLz7kOF46mJeGsXJOG/PTFy0TxSauidFrXzPBiFPjYiYMTRO
pIgAW9FromIfhHP47OnzNZTSjk0cIkJgi6S6F3Z9FYSEYKghK3ivF5j2Q0Nq
JHGOfEUydWmJfMq7gjO2gv38hv2sbPkrtOErHfxdrht+/h86iytw4lbgr7/T
Y92/0UD/yGoYisjUm+uhNp+s9pO036YdRjG3aYcmGNQBJe2pfYc5YKumRvdk
2SFQeNfGxWD0ic4FnyVxPSgcHjT24lmsHDG8MlRs/L1tO7XvCCzNQqPADyXi
I2x7yt1KW8Rt0Qhx2m33BEwhtHZQtlW2EVd/lz2ZorNpywGtIbus2EFR50PI
8slMhUTh8D42bzksHwePfByMiFz0eCB9uK8kPHbDIaIdZ0A0FLs2/SFAKZyP
wwEPQuRYYVKaR4hI7q75EjK37ihLmmxxxgowztxTJsex6fXGfiHMiDigRKMl
fhMCH/wlZH76UWEyTVM4RZSs+8oWLZTHI7p2MwQycQ+X0EUC6C7nMZBKMTtE
L37esemdV3NtUGFjo2Dic4BEQtaDknF71h3U/DfLQsCv3qt5xmWDcbWMG6S8
kSo3SZYOYt0bnVmX7xIptR0rHffKV2hCzjA0IOsCx3E/cXgArIc0S89WhAQC
9tNQBuxpKdSyIFRG94ZRMTiTgRHVIZEBsx1z7MOevpf+Rb2as1/ecGnE3SCn
Pi08k+fVtjz7+7sqnEgyPxkbZNnD8jO6wu5Luy8BFn2ZxDbroAb3RvmlfTLo
Ea3ngXS13t/18A69eveeGUPrHBSahAUVItbzpEVCUjjrxpRulW1PLhlSMZ3G
IcD5s78tr7qFr8z76B/k3YIpfSw/F8mGnC45XtkJ5gfjv/ZfjR90/I7DkrfP
Mf0XZ0zf1zc2nzx99vzHLv7Rtf96EfQHQDqewIyQnTIg4AfJS3et8B8N3GmV
QSBD3Q+lpc4Am+21J+hpTC11YAv6W6rDgXYh8ybW0FKMjSaPBSFj+ducCKPD
Yin3HpArLSClVig6PosKZGERfMG6JtU2FcUyjqQYJ8nhOzg31dNl3+JVrplJ
Q8wi0ytQnGXvFEQx0AnhSL8jZVI4ZQvWOU2EuhiPB8k0lGcS9c58wvc7x/ZJ
ooPBHP3QuC8TBkSApbgLk+pAnOlZCd+lIdtaWEv3ShzaPAQ3PADlWIObYT+h
v+EHJ1Gfpw1/uYQI4KMZktXowepf+tnqXwHsB+RItIoQQ1tAUKBdSfa7igoB
whbjfPmYIOMGvt1wTlxsUNqPpOT5XoYQ+hjjat1iiagwfC78WEodSj0svxwP
zrJ0TFHi7CutHBJYgZsmyoClbq5MwzpzKzL9SIFZBo2xrS/WiTeCfnrOkoyt
2gJyXV0Fk9i4zlB5UqTy7ymrPgKYvf47AgOnmjeZt87GjYa82yqfOjLoFyyg
iSuX6l1jFsHejXmNOPg099DyhjmrxE0Puy6UjEY0OTj5ghGKK3LhCiEnFhfC
fJHE8s6sQFKmJCIxLvJusQ2Gmigcq08jkkQ9cc+ZjsU0FedUAsT+kPIhJEk/
GHwkC1YQhhmGhFzYQqDxlhG3Yt6SGtq3Ft9U10ybPNMCIFGINlHBSNmCqvtr
XJnJa3dhj2UFnK76DAxGMoc57jpixxDqxqb5ctM8YhaEkCr8FANjJgX5dWqb
f+C/SQVhZ8s/B86IABCEuOxAOphzqicaDdNkYdodCuUfBnEyzQydkhBLWAv5
yFdmCr8++fQJ6e3TT586wtseXxOrxwWI64onT59fXyMlA+wagdwDJyah3R8F
wjnsg2n1nnBDsnx/8LQNu2S1kXMUxrcP2OQD6GJRInkPmU0MaY/Qhi4TqD8Z
sXQ2HQXjLmr4hP4fQpqg6IoHNTv3hHl1n14v25GvrmiAM3iWsF8W8JcSeNEW
uWcaZcrw35LewT/ZH7Q17235D09OHvoJ+Spl0t0Mdh9A7f/4/MWGX3rLY7MM
LgEtMmaeNjS99dLsdDXI8/iU0xSQHtoVm8BXIw/i8XmQnHgncdiNQ7bmMC5A
h0/W1ugH4hU4wD42BhlFCbj8AoMVG6gH7YS3MI3I9RHG55tv8kjkEFwps61Y
dhMJz5LJpAxmZFV0h9NFvbwrQOSr/S0rCspNT+MQvydgIYWa8lkRnRN8uPd+
FkfDThnz8ulohP6mkpKWRhEA5B5Kr+L1POwlU1c5TemfnA4G04zkHwzjcZmE
OOxPpMSzPRQoNIQFV9vVr8Zd1LMc1sKyHx87dzDfKjvUWa50vmd6izZexUkj
RINX7TxL6JndTQXf/eC6l/tg3LB1KkFZ3tXVkbD5P++t4wD1/o7vXfPzvLdR
cZaGW/4H0sedRrMPHmh9OCoxvC3VU26lJzQcMd2LRrMg87yXoNqzJUjMRZm8
YU106Soot6C9KhPikIeCZR1TyBMOrsRPvEsWQVyC2UqVh4gmC6eksCu4vNfU
0KKWFSr5P55PFE6oGCaRqxGNtVTMKQQ5e+GK5197f1d0BHcYbbAAdRyyTE2s
uZAYW+cIa9GZrp6npBeo7MhDX6STLppkEwVHC4wyvW3JK1ncgVKCEGOvDQRC
Ca0V/kAveakb06xT9uX+StvUadeXgVZmb8bPNXsOMivAwLXtpxUou/nJHe+z
m0zU7vLVz2Iy1+79rqJuzW7/B11NH2rrmk9rFb1vLWad9uG3bZnkyYHyMxNZ
gyA1URjPTWLYDodCfB1Ed/fe7B3vzQtU7vOew7X5tC7oqF5XjhbMw3WuQt4G
E1xf9FT9MgmDejQ4/GXug8Ud3k8cqOH0ysTf8lTdkm/fGYpNJy4Mm/IOfyUM
mxHSMr8g20K29upkazNMRY7HZqdIXGqJvkFJ63EubdDWBmkmrHbq1jEahyJb
B7VVUFI5X6wGnsMXTx0Dy+B9XO47tpweDNH6mSVYO3NleR4FZOrly5476oaU
7DaZEp2Ls8h0yTRCeXTOXWEAnOHCM/pHUeyQ9WzLjgli3wz0cBPWNWkZ53u5
apCKbt/P0o9osufeX9K3+t5Fa2E8sf2GZAwsG99Z0zFeQhF/GJ9OxQvYuxGY
ckZOcB1/kEWkKAcJ29ypAzgnrIFKZ+EixQlfsCtfabY6iYtsYC2dQpWneV90
03olsi/U5f9sTlPMhF0JG+fCTUxH5TkGFy87hi/pfJWjPEPzU24RVz/jn9uT
yX5Y4T9aEXSQitbMR/W/Jd0g5H1XZcpVtiIdpQM/EYZE4SCqY50rE5NxH5KE
+X7FQpBm4lZImmnpNpqOsHLIch5IXpJ5JAMMnUYPBJ4S7FBaRA3zw+lUTu5s
owZ5r5E3q28fWrRUM+Oo+pOZB9HwEKWkncrzWDznqCN51M7KE+gxX+oiLm7J
kyvhY4wjWk2BDI+VyCG/kY6rs40aGZSqPUyCPOfCLkRKxbd5euAvO9s7UVZs
KeekZ0+60rF4Z9sf4OXfUKR6ryzGfyQvAR6LPgfTvEhHx0iatvyXlIMmmCaC
DTDFkv4UZO8nF/yh/0Get9W/qOPw19W/qDtK+Bslj9+Ip0TZb0X6GwgEvxGu
//VDT/j8/Fc6JUomaSr69fGEHMSysoP41FyPQUrrcCgwCOAb6+JgfMn4YFJu
lWvHDKm0NssgqQKfji0i+0bKS4pxazQtLUZCOceolTJqGj2KRyKwgSoa1R4X
Gf3AfjbYs0Yv0aXYCXXfdGy8JraGbxMAQIGdV7d0AEUvcaYDq+W0pV8kT52/
zY3GdmfVnZesq3HvFf9x7v6NNp+75O0/LnG5Be6/7nOBGCAiB+4YB8TUF4UF
VncmHpR1K80JZ94ezXN5JG+PmHErz9wr6chIv99UeTvxMnxArhurQ1B4dqOC
PCtXqPtr5RusWfYK1Q+LHEofiEjYjFlyVlX/CBWMjq4bQCiM5G4NqyJbf6cA
ZxkFhuKxV+CA4rj4qGcMurX+44+b0slZygrYEP+Wv0sJAH9Xf4tnBlfGx/x1
lXgiTuu6fq8Z/E17LdZwbVkl9qkoDubdGU6TjnQlMW6V+9JRbhAkUtM10UNG
u0qbUaP8XrUctRLflfnoKwjv/hGKe0LHq5yL4ky7klYnx/Gr742r7tuD27B7
N4HaYf1uBWo2gVeXchNj3Vwgt0zc88HEvRNedSdME3cT8NyG7lbwU9bu7xWE
ZszuMZmGYrqopyzilTAkTttak+IDbYLbZo4VaU4xc38ILfnP0ue+ZyZvDEgh
Kw8rHa1gScLOqTu04hyakoJQUGbK9Q7EHMwo6J7hvE8rNeMJN31K1KoD3XJh
zxLhEuWVV8KYpEFvvbdRc1cu8IPGtzKsbJl2TLfdlK7tsLIcA0d4+iID0nDq
qd51bpMWXdfkO/FIPnSkPFGjGLlaWgxT3TgqY6K25sB93S8j/O0MOyq2Qfg3
5LytKnGN8KclkBnTZHHZ6F2YPwOXXZxyb6m0HdoTgJ3XrRf4iWWODiOKlTXi
QazUQY/iXtTzDUfWji8FG04WHA553o/LfoPa/m8lrN7fVdKdhZaNpmXM+FDy
+1exFsoRWpfYFK7Q5n2C/bZX9iHRx+JJvQOJ3BOze0kBKYZSem2bxM4K0eDg
cJFQzbJ+69xk8hcMrFH2MUV+aDx9hWBkIzNnJbMeQrsB7JRSf0QeSL3aDXaY
MUKMdcYr6+i3uDJxH33j2PuiDyt66FI57VqZdgQf0fVkMEJEZY0Kqa84N98Q
CGE0MsO5STlG0MhEJSpnUAJyDzvE6r4Ifuj0dcnJLWT0SZyraAK+oqvmh8EN
ij2r+BQeUMzlR2UohBdwzwKozCygTrGZUUClqNjhTAJd8pFnioHuqp6hjwcD
ClbgDVCZPaQ5F3RqyqVF6ZD4uFj+Viqbw4eOxcWt5BHA0pHXCfdTjy2/5KjE
eazFpZwqjUnu3qJ0Wj8eIz+n+Rg46bGWLl9dodRbK9IxlOIGVIHTQqUq6Whh
Jc5VTTIK4wEoqCIr2EjlVpNTFTjHWeMJPTCCX7vAsjz3KyUCU5vCGcHKOoeV
vkhj+9XP0lPfeWv9aynHmOlEZkoUOvLN8yoSXFwV3UTTisjHnpfmlLasUoJ8
0pFR0eklH3HCdyMmkgtOy8I7naqgV7br8HZxEIhIg8IGTSWjEgBwWM65JrZL
5chwzoLSc86YCYV066n4TiyXc9JTwpZZFlyKFNZyFxRYdMVA6ZGnAzKYzVFf
tCqHAwDswD7vUynzhLUxuMT6pbFB2QnowoZ0WyArEzO3w9xRNrvA1tYIMpUJ
D8QdeFhA2udF3h6MEoSVqRE4gguTknTMHCiCktDaJ5gAhIsa4TLYvqNY31PJ
+J48e/IjMT5p1SAMoplSIWR5/PVKtqxg/AVZo9D+JCxAKsZnHvNToeKOTry6
yCNpCmICC72Hr//z93D7p5/IANS5qxmcTUdxGENv5eEjHP6lGN7hHjidjHAm
Tg+Tmr2xbFBsFUGcYVYpAziw3GRE6clm8D9bz/UUYovABxlgQ8EQoseNtTUO
NQy4HrSgrJxsLxcnAA42lXD2hf+/OFdsca95G93q+cZA0OiZi6Nqn4WdoUhl
77BITpkeOUhQSeXfWHviv0ulTCJrn0g7UrND0uJPjIqSAOiXUPmW8RgnHgZZ
dNWB6JQGFGEZrsCMw9I7OjJDidbznK0Tb1ZcoYzgqIRvIOFHjbnhnDV4cjlO
Wa1Pl3EQhQHfyQlUQlp1HEocgcoXOpmCGUhFyCjDf/k8cmljcVZ0LOIhlvc0
EspfXYk+rq89uzph+VXpRAIctV4SJJNoK0nwXxwOJNC1kATJDPQFZMGyKHh8
ZkuBqPtYOSscwiJOUQZU2vYdlHJcSGNkuq4T2ujGtKXcNktmo0WUbyTugBlY
A7eWbSy5xnPINTR/7UwnO2kr7jRJOl+cPi8lGnWjFoROWptZBKY9pb1U7rNV
WUMhEL0gtGqZBPWysAgxtdUYRThGUftfntqWbcMtbE9z5cJepBmKMm8uxgpF
Ydne4qxQSKPaGKEEqARelGynsJwP0uD7QYb0Y3IXI0GSeLPMeVz5n8iSy+NJ
SNHOidS15eZ+PBQR8+X6Ch7Vdk4uzRoQPd/IMNHBd3EyjobY4cs3ex22Xs03
ncIEGLzjBeE5ntScg9X5EdfmkZshtAR6pIX2pjs8tc/mSKbLHara0p3ZmpHM
5UelgbCcu/bWY+83eRknZnOsPPLYmsovWdb0ykT3d2V9H3Lr8z3loWf33lG6
hphekUfJ0L1LqhCDMQpO6cNKm9jllQ++Vxor970PrWLV6BLF/FV7bsT5IRAm
9AP50CFUsXwXF80ub+P9aLzdBl7l5TIMTrxmKIjlAkeooAQlzDfqRjL2Mrg0
JvF3VEsKn+p4460Y4SaANBwEWShK/RgdaafQH0y+v/rgA92mSEdgpKXyKlXg
4Aej+Qcr0w2b+02fUEPfZZ8k67gxupde8PjKJy8fMLwBYsGTErWPXdyo4ndu
qQ68jquf6V+n9Zh7zXUxE84UKY3cC1MS1Ay2jKOl2K3BPaTdkvPhSgFVZNCR
933YRdDP0wRTnlCqTeMB8x2vlu8YUvx7ikvMXVk91v0dYJgq/fjM1B3onUnN
BdWQBZ5KErL2q7kzYRkXs7reWzcX4cnZb2kMaXW8GYN+puWceLCg/fCnH58/
e/pkc2O9S//Bb/zXMAoH/eAFP5ZHHDe2DDrLBxS3Tx40NwxlnI1ZfAIZ01k0
+Ch3zZDXDJ70VRT8Xbfc6PDccZ5VuWqX2w73PM9pZTN63Wl1CVa1Vz56YqIz
maRGR5GpYy334lHax52ODO2zjAwqeQ6/fCFL3ETh47Zn1bIfopikD5mYiEx6
ax4O8y3NkL48vqCXnMTioWWykbnbG4xDVaypmoVeczqnxkFaYdIdIBLnxMPc
xGgyxrNvBR6ZSEYcfRgnaFUG0d30rDbN9F/aIKFXg1p7K9oodf1beQZnIGXV
egbXZEhw2gvQ20KZCwQ2CFSpsxgYay4lWDSJgrp9kKqQ8LLqypWr8APaaskI
HK98lXPpFrjc+lxFDONknuYZbSd5VTtuIXq1O3lLIeweCWECP+aWwcYn3lIG
u7EMNvPwSsmsenxvIpg1HuY6yWwpj90DeYzXLvF6BtKQVNaMMbcRymZh0cKQ
KFjKXncpe51G57CnMyUw3rqlHGZd4Rge7S3ucOojJqTDulGN8nY3NiW/Ye82
Nza237B3yxsb7Tbs1dzYUCFcnReYodVsUBQQvfqZ/3CaFCtd3tZKUUu89CT4
xUBtnMCAiuPkcdlTAJNtClpGdwyIDTpFrXG/bvg9icnxjbsQiGQEgggrdlwV
2WnjqeCoqFeQAuUouhxwzfX29NW97XWgkhZnZv2IwMq6jVUdLAGXV5vVs+sN
4cYQUULgVnJ2Q55iEgk5T/FXFLr1mm5s+hS4Tlz8xAvu2vZZAmmjwG20Z6jL
osr01HrSaD1Sx7lBtt1RI2pR5e6PdgvhVsxgtkj7eO4MZ9Ilb2Xn4O0hagS7
rqRlAnrU2MXWrX2o8nAjC/E4pCwCogQlpf5l6TMqLzbqnfY6/sr+u98O3x+8
fr93dLSCQqMx0cdfReWSGfgrxZRzs4Qz8+9tP0kL4eskinqHXAC5sax3x6dM
7XRach3vxNEbUiCg9VKeaZAJLkUFUpFmXtdXb67yTYPMVXD8kYwJfflm7zHN
M8ba8PF4QCIdcQRXCKhys5RFm+UEa6qP7wM2YWVjLC6Q+2fpBbL4jgwwHcWn
Z4Uql/wxiko1x0HoGXfMSgCMVBi9CqxM5gwRNRqoQqzKwy/KWgksVHFEAjT4
QqnyQSx9CJDeGwubUYc8l2n9Nfpk0YjopSlWGQUP8IoXWRxGEYrYW79FBKgq
ji1Gl2KeMXJPFJ0Q0UexWF5eErMUMMgPREbQErbkNfsoiDU/841q483ClzG3
CpF29TUHFXbElxjlkzNKDKgLNNHzbasElvA4F1ggagfDIASUeIgO3VZzLIrD
uddCVsgwXwpugCwdSaKZlnHMopIoO2svHsPBDU0XHNWi6zsbEOn5B6rGRMcx
oChFmsSjuKAhZWyQ7N8IM8U1rqAftF6WqqPBAqPoXya3ob7kWFGonGFD4X8p
fUB7OlpSLVi07U8pDI+jjIJBluYmguUdeXpUekSVGW8AqhzJT2oLe34pSiUt
KSBSZ9C8XcHJ8lK1OSdiCnpsb/mbHfn98q1QbbcP8/pkMDh0mYHq6ZQVXzmO
2BKR9ZMrysL0xGOEq6rDYjjpKbJLuepQLkWgdh3TtcQvo7csEq5U8XiYBezq
xOwWC7BBr0qdD0jqZQGaTKRZEMap4CrYe0Z6tj6MpAsKN+IVBNYKe7DrIEyz
S4m0NEHkW2LpPSqIpxZvJSMhvSOJP0bWqTLDho00BKpcnhdYJ5jkcQuJRT4+
3o8LUSxP9qSqs3n6DJQDpWg0IBhlNLwbHOyIXLay2PvbYKIz5/Qp/kKl8JFn
WSX3MRP8mC32d1FqbOVopt6+Fn/9vSOHw+MaoUlrCMc4sn/eD5PocJqd4vw2
n8mQEXgaTIuUU9AYC+TFYGnT8Sn5NLOjnU4e5MrVg+CfZBVxtrwripVbu2IQ
JC3pCoKJe6twiBmGuNPSEC7HeigyamvYceYrkHOCBgk1X1fZhMHxrLLyIvvB
2o6CJvMbdGyYEihRQqwCq4zK1AtILwxBpso+OL0DnWaZq0zPS2+bOiIgvvmU
5O0RjMECVv5YMM8BzlgVNEQBSOg4OEQ/GlJAB3RHejamK0OpUPqWyhhwmDGn
J5NGsMFZMD5lsijB0aEeTeSRWUuIokbFRZp91JFiGoxK7MH3zZFAIRvjJglU
o/x3CgVl55fplGKVAXCZLA4m2vgjEoF01kVRjA/HScf9NMhUzTktvSgt7oit
DEo5UWKG7yBflagPgzhZgRhBhfdXkixYhdHZ1kOyD9f/K+G0El70Nogie9D7
NBt7Oi2g8RpsH2pxGZr8BuVXfNcrXiiExDTjVajA+qsrmJ0cnSI5mAoYohgH
aYtceHTQFMn6rP/6K09roOZlUEXK4KmeDowO+NkwCU7t9lbfeohdvYzyU+5J
rxMG0WWFjDVKaoY06EgSm2pGOZc5IA5bE/UWTEUyEM0+bsA8OvrlEvgtFmUz
qUpjGrAE0HnHp3doI0sj0wO0YJcaw6+qeLb+/L3Uo4G4jn6vKliwYmJAdVXt
V1Z68dqeped6In/lX/7ewFVdVqKBqWfVlLmK9f1ORXfzfZEB38Q5ixpsSwKC
uK/Og0ENsI8SQfg6V68qPZ8GSmOSjAaNWHQlWLw48QAamShSyNqvsJxplZdT
/W2zSHPHn44TZCyK8GtAlitpSx1MRDDfTg1fqtnfnZo9lsKU7rVSYeO71Uoa
NY/pxGUGqKJQ1ZZ+xxrGPVUwbP1iUqNfzK1S3HeNYinwL0LgX0q+vvVZSr7W
Z3GSL1P1pew702VVgIMvsh13Qs64oQYZuL7LuWTSNi6fa/7BvzN51dk5K56f
YjILpz2umnU8mrNunYaK406+Ad2+ki8zeopWYsAb3ToaUMLZWUknkiyVzG78
46P8sRfnq4G+AUeVSHDaXMkqI6FfGX5zoJQE57Au9vqVhbWpa5XJVeQWUj3P
qzTN49uxZGlLliZmeUtjDp6dGUytyX13Nm+7LWu7B3xNJGBhlb0fJ3FxKWqX
Y0oK8TOXpgS9wEcnnS3PR/3jsCS7b/nvogv3DST1E/JQfF/I4jbuIFKjMbw4
Tsfd/UPt1YNDoAKvrAlYqcb6rvxnubLUFFNUo0eWyvQK+gqoA5SE2/elawz5
nGDmAXIxGl5SeCP73sjbZyK2hj9KDxaMnrgVA4cs867sC3LRCgquO1sYnN7S
PzlyVP8T5qUepaC9qcTUXZVAWgyDSgKiFnoC/Xd82o8iMnXJZAXSMabj96eF
mpIn52jvL971kKZseG3l6PNV3RlphvGsRC1qc9EnAdAVtNlRINTPnszxb+n9
liLOKGLWNACk8NQbsJyLKEl6ehNkH9LLR3UQyITFyJg++9tFAWBFRyT/M2AB
JVT+rOmKpAl1n8/eD13j80Plj9mfzzCLvh7is8z9+NkoNUWrhr3suhAGZ/HZ
/513uLkLRgNXL9gFgFTCr74Lo5HdD3SBVzbwHLcF4C3p6jYnIysTBLq9EWbQ
sUkaeLRO8ykx7YLiAJaO/9WDYBLr7zDYqnky2TdMfDddzdjL2yB4kq5zOv49
PYJM9L+//W7byNnT8/bsfnGuihjRTamiPMpKwROgahCjvkgJP6LCqy7qZdYT
YL9z8rM2vUQUwZK56D1VdGIUfLRzXlHE0qcJesiLZP7Ap86jccxRRBTZJKMe
ehQjp+U0aS6hdU2Tj/Y2kA8ep4MmU2s8LrI0nA54y4fT8YAtzbFMVhYbFnqy
SU9zaSXXxMcuiYo0Tub85voh+OvBJBrjVDjd/tUVQtvAhmvYONjtDtANdt6U
GxH4Q5iZXKB+o1dCGbt2GdnpsumY0vxp0OqJDuNsdBGoNJd5x1OpzAlqxnYo
zyLz/sLM+ch5k2hIzzVmUUZtWSmTzE6BHTEgRByP9EDOSpiUIwolzcVgYsuH
XXuUWx5a7HlZ81AujXph5oB4JX0CZIosc/6emgEF4CgNVdwgON6orJj0W0Pl
9VSYpJ4YXbYgkp2CCARH/VdnEzyPWH1H5AxrMfrm2qZ/BLT5gLbb1LtFtIa3
IIijJqnnmo5bYEIVLnJoEIimgY71gO4GUT00DGExywA7/waohHtKPCHCn87E
L9fiIFEzrmsgTLS6zA0e+l/e73fZpKybivJCwxjt9165ng3m8lVpeznFLlpK
/fJwnsBAEp85DZVJc+TdEHr0n6bZZbUDPMdwfk+Dcfw7DS7eUnVv5bvs24aa
wGsea8t/maVBmFxKWk1Bzth1LtVxStw5BUEpi38P2L+bVJlY5BI2QMBp1eQy
hFiP8ijL32a5HtoV1GSSgC/tdJJIgvgjVA5XSRd8zB2YFXmqb0fqqf+IYwxX
RWjwYzW+zb1r5lCSJDQdE7OwWKlzJlYLQaZVf+VtK90KUC5kZgUkDjLykhQ4
6/PZNwwzM1tD8x2BT4bw+Lm9mAiC4jyNnc1RyBNo1AVMmj1lmb/asAlmqkg4
euGOH6IRbpCe4kkgiEKbzxLbTTlZj4y6yjRL2o2M9WyQCMK4pbI/aHEakmDk
u0akIRVudBVedeG9rgg+CK0hDxRdw5h5Tp4tmuWxJH6TDECRIgVWrYXarOeA
I+MiSfToijDQrpHUsbxYo0CSiBmtbdywWD1kPO4iBW2Crx4y5uR7jZ+6ISUN
IaDizIN+nbL0WVMkjhRqamy3JyrjHFJmM281ZHPjhiGJ1ql9lBHVNV2Iglhi
HxsbG+3VeNaQhKozelBdEMLOatxqyCbkqwxZylWKhQYqOSHrhpTkHzTCLsxb
gVgZks0hd5kGScg62thTrDAg55DjtGvY+0pdvEtNYyATG1ykIIc3HFJ32S3i
UYQGEd1FyX2+3OCGQwrX3K4gVXYXOKT03XU0uP0qy51WVjlj1LZDCktpV3lc
6JE/m0ZWwyWjbuS2QyqeJoZOs65t1TdYmTkDTAtstyO+WR2UJlMamE09tXj0
WVr7WuJRm7WKIeVyZb1xWm8ypVKeeqFieFWUHBcrGsEqm4bU/Foq9GpIIirW
rOVwSvcvNymt8tiwERjEXQ0pVfRuBmJ8PwCFq9LFK6nF1zUptS8ZguqHZKtA
9XwaQwp3m+az4h5S6WCo4SlPapZ1d/CnFaGUAdEGDpjFOFDlkjjOheKoxWd9
y4Dq3+GU4jtXj1TW3n3MTzwMBiI32UQ00Gl9Y9mgQ9mncAN14Xrjoc577YlO
rAY9HBu75cy7yjwoc2FxZogxpT/vX/qjCDDBEzp0Xf1dUYpWRsWOolFK1iKE
UCrCsoxyesJQvfPy4D3a59+/2vnxxZMXsozizu7uG+Bg8rbF834VZqeAH4k3
nq2vXV/7xq0MX2pfSL0FB/V2YVAB4om4pRLpvTGDv1mFEpaKTqAFpb/I8wA9
vQT40G9MaK1GemOZ1r1uCEopR0tUNSlpQGkGI5wILrisL5YQoNICbFVCEgTo
NJqYxYVtX1Njotwv2gw9ASdmurJo6CDNGPk4UTS+ebSz/9ZIL6Dvr/GbJyuF
4BLyPB3EUn8M/I9jvG9TPgJspqFKTso0QZskbXnB5G0w2A5DtBJxRcQ8jyXK
pWo9nvTcpQsWjnEXvfKtl0IjI9uI9q+bpEl6ShWU0GFQgoWsqGc4CZkcmzdo
cJbiajn5kN4YA21k6hPCWWlr7Ud0HyVxQo5GKCGHVGVfdKVh7KcGR3JVCUE1
JsIx4czhfAOD774MCuEMJ+CLyEe11PCLB6iSFf5Puqnn6bd+8v/nXyoT+LtX
PRo/0e30z7ToLUZHvNtWuLjlDwErio7///xokvJ8RCgXvyeQbsvHG40O/WZu
v/7d3A0PyGluT+MRNAGBwZzclv/S/sFfXeVW22YhAWpm/aLa6RDvI6LT1LT8
I7dmBm4P/9+V37gtnOBDPi1b/nv1t/fY88oTZvAqjwkNjbJrAz9BuFQWw32M
HCD9mQ7Wlj8GOt8R71ZWV/+60hBg49M0ET1GQY5rhy6xRwcIuEMpvODUaXhf
yjDGL4G8PBS/mT+hDUkNo6Eouqciip8KAzDCQWEQhsk1swwks+L+ke6rjNwF
2o3AvK1QZuE68u2FEXDHgvk39R/Gwek4JQEUlDlhSsa5mFna8PCsbPlnD9c2
1tbXt+G/22s7689evXqys7a2vrb2/PnG+qsn6y/XNl9srD3/8aEqcqb9aJ4/
HYbRi2dh98cfnw27T4LBWjdYD592w+HzF8Pnz6LngxcDmdlNHU54cf35xvMn
Pz7ZfLHZUW47FvoY/vTwVKMBJX9Z33q6s7W2Jv+3bnrqIGpBo+7GU8OjnRK/
obgkRKQDjleMWHgXGqg9Pry1IHjdo3W/Q4vZ7db+ZPPJs821zefy380XT57C
v8/uGjtMvLeBZDl2BU+iZ09eDJ90n/Sjp931dfjPjz8+DbvDaDj8cf3FIBy8
GNY7dnEfgyeD9eGzaKOxjwYoI1xfbwOnfWc4yzuBekewKhPTGyOVIrXVIBHX
oncqHlYij+F9w6cq17RBpLkEvm0CRPIK+P2Z8bvBMfCNDeORqE653gA7oVhr
n5UK4jyYm2OMKc7Eyq9j+SuwC5N5PZ2ST9R0TCmvlGuK6WakSjwJvyi2qWJ1
w1Wqdq21KhV+cREpTaKcCEcUHQ9YjePKxewO7UljsLz1oeCcAYm5JYctGg3U
6C1fVCYWpF2PoovTsCIhdUv/ERpOMAhkkE6UywPtEuqEj6m398IKilqqNq3b
rrQevaPDtG+fM4975ExDthZL4/MkzVrxW1YZxTwcUllDasYOAVvuOovU4m8g
J2yRc0ByBn/y4Fd+r9dDzKMWOn8f3ivTb6JcNJVRreudGrpcccMhJoesy/Ja
NNVvOqFu8Jn0ItUeoXIX6E8rZtP/t6ODd5a/EyGE3NEOI97VlTE03mddX3sC
DRBL9dWqymiHB+RuscDyIm+VH1F7U1FZUgEwUQj0JwL4nza3/7TxCv5ngB2+
Gav/08Ym/CCBD39yN1aLV0a9RPjGk/wNU8vfBvMWjWyzykI2YduJIAeiWpYq
Dmks1WSXzhKVbhT1Ca9+leXaDdxKx18Is6yw7TkxawYFarHN93yn/kCo6Mma
GuShMuY7vQZWnpY4LHur5FExnVDIo6lK2OYSdi5h7kk5qYRl7tY8HiegriVg
T27A9O8vz1eW659V1cCfxGl94TiujCjq0M51Um8qLAjc4rTldizJrSo08lqs
Oo2iYx3+PvpHUexQoUxbSbn9Cb6XyzLOLf65ICkHu7KRX12D4HFSffEJXmL/
EvvvAfZ3ZSkocmutFunVaHoHWHqTao2ihpNk5UIWJ0l7Llm8IhHwY2Lc8Kcu
5+rCWfNEvInGp8XZlr9WwRddHAkf3LpKJc9Vpg5vma1d7R7ttSvfuSJJ90f7
sopCDQSyz7XkxWtF9lG+kdqNv/JaXMWTq6fzgX8UDaYZxn8AsuVxqCS6qwe5
eIKeLsYTvh6h7D2mm7RPoqgKixF14AN1o3ohnAYwlA0TBAl38zevVRiKCJ0Q
L3hBOIrHzGHQsU2MhffZGoKPMOOjzvliCKRCPROpy3tsjTuDVyN8yMJln27G
RdWKPuWaRXd6vp6XfgpUz+cTRcrx9D9G6LyQ8a3twP8YXWIxdQsU4so2S9H3
C33o2Yd9E3Oaj7A0BT7RsvJ6T4rKFKgp+4oo9kunbDRd+kRQEcCXBGe0rUeZ
R8jWpWgGM1ZPeAz3YKyNHhEVGN8ax0rvjTK/rOMBDbU5cbNHV1uz35S1oIso
ATpfZDT0Pt14T9JchTQOpxnd9Wd8S85ACdEZAFVtDpjAWC2yZHKYl42kJSOr
KByd+6fTmJ2UhWsC6RWAV/42DH6KDjTvKNdxLldSXHqPsP/H6E8pwG3KN4gE
pKpZru+IwZSACBGH3aI5fkO4k6xvPJMOKG+p/Ak5tr83+716QFETVB2FCER+
LRYVpoPpiKuvsajH0VYrTvqxYtZX8VAHUg4npZz5pcQ85kCDIMvQCcLT+bdU
7UJojEIrOajgGGMqGmPMBTMJ9Qv9yCBt7zmbe2jk9drCsFXQzqT3iePRHo4s
SvMYW46FH50PKLyAgzOAIvPOo4OHcHAT/rEVEJahB9ulKGJ5ZAwiwg6urupI
47XCRRmaJ6FLrkywPiJRIrCx3D8v/FB5CEnfPMHTLbToWLtqN8VEG5VzOSVn
F/Kkkmvd8rxXWXBKm6/DWmqmhWGkYrPiMftcxZR4revvoncJ05wgidF5H0u8
a5sAMz7qxofmb4NTvO+mEwgEXA7Q9V/FZsif9ehtMMAwn/wMq6hFjOeImUaj
Q0AeAPyffSx4kGBoKjkI0X3JuAgGbNGQNMdeA24NhSdP8dBs+W/23+4f7+36
vxztUYKMIot1LSzR5ji1EofrA1ZOfmVjAVMcGHOHgq8llU2ibMvf3zt+5Tlj
aYlKBJO4C79i3C7SQvLrIbVS1LYhSZBY7oWkXhzcB89XFKroflekv5lqTCG1
0ptMh1Opa7Oc9lv7OGIBHusHsip3zdAc+IaxoDB3YaERofTS8GPlI0T0pEYy
thfDPaIL4UtHTlugPSA38V6p2ZWA5cgnaewAhxlZC5jx+Vxanvp5rvgjfOEt
LY0yQZAJzZ87Bqk2CmnOXmpeQO9YI0qbs+FQfGz9ol7KoGP75x30fFRZ/BH5
HpI3X4DBPKeJLiMmX3CECDuno43bq0QKSuMSDeFLSj2pz8KCHzD1IB6t5qYt
+hMdHXGT6fSTtF+BDpcisyekpyMqldGbDbO60XQoohBd6STZ/sz3Y+ZPOKPP
lWuzKXCChLPIckskNcNpAsDjSKu2s2Ely5qEeazORSZHczqfpbFAlYJd2GyU
o3oViU3fdMfPeG0vHVjNm/FKP86pIEH/NUqSLju6AslRFP1C/VxH1DPT0Kcp
8oXVn0r1SsP8uxpmRVP2wMrPqfydn15fE0XETo6mw2H8Cc8uc6YdxZkwYM0U
MPxdKTOaq7dJmYvAtKFSlAkDhEcFU2SKlf2yRaH/+fujB5OgOMu7nJIneYxg
R85WgpNi1DEHBoOa3NNNSJ6WThMYxQwknqKYSwxebF451HketsziGzNlORgK
1itGC9Yl9J7/8v7NFi5VGgUuLi56OJFemp2uBqTZUHoKWoaaHSkVj6kOomGv
9d/+cnQsZEKKqsSdh76VxaFlxw9WHiu5moQygHJJqmCMESApDVxEoG8jdKxA
8iMhQz/pbaAcDZj64snT56RKzXNG6KDJk+GAtCdBTSfAfNZGLJj5mTtA+b0p
GLiO1GI+CxA48IzeAAsf1AU/3zzS2VaVOb7nNjMrB0fPHwm9qBnNjJ1eQMT0
oubaGG09f3z14qdlR2TPH369qBnVBWzPH5298BnhmEYAnDEj8v2bFZl6RzAy
gsbnDydf+IxIjDejWtWMhFvkrEDahRGHmpD4+ePfFzujasT8/OHxi5+RTW3m
j55fIB7NiLefP8z+ruZmB+bPH4t/V/NyRF3PH7V/V5MrxfnPH9v/BaBmzW2e
JAB3NbfatAHzJw24qykuNM3AHc61PjPB/EkJ7nB+i0pjsNiJaoG7jznCBkFe
yn5wg5QHC59aNUnC/FkR7nBWdh6F+bMnVKfGAdEV5ZxyBYo7G2RDKMOLfJQc
yYOOon2656kYc3SpEzOxb8/zQLP1EX542yzzV4ZG0oBjy7wwJoWM7pDOI6lN
5PISmmal0niSvyzlK8S8xuT7lGayaOD/eX/ZOdjd81/uvd5/d/RXj2zUKylf
mvQuR8mK91ONo8w8njI/4bIug1HSTYLx6TQ4ZdKL907/zPmAf5JYgJeiXf6N
ECHMgmGxurG2sdZdP/FONlb5mSfmuOVv9tZ6mx7eqW15PodLbYHIMPb3D6VE
I6yJ/iO0xDymtJK+qjtI95ufu2SRIxww7jRhn97vHR1jDQRTLEuCS9pe6TEM
8KbXT1WxetoIOzmn8psQWZOlawO6Z9Db5sWR7NlKxSyyEeqq5pzCn15WQVsv
k2lUpGlx5r9JL/y9cZSdXlp5oAlTL32uB4AJrpNLMfwkSS8ppa4Pw4/yg6Eo
vbZFRxT2Jr8ITk+jrBenq9QCI8bFBecWh5Dg9eeW3+9nMLmPo38dIONEzyF4
CtCLKKU/NuSL+uOXXFZymiXyC6wipx1Z663Dznq4+mwcJLvpANOL27tGhjWy
0RKWeKIniUpIIYFcDjC7RRwVQ8andMA41cWfOIU2EphVjzGSRulyRytXpxe/
oYPVNdEg8d76JjsznQdZjEpFviV8p0Rj+dWXVY/KrnV6s2VlB2FsQrcurwhO
xRwYSGZGcM5O5lU6EOjrixzmeOfOGY0pm0mR+qcRJ/cVtFBIzvrGpife3x+W
s1KoVMwZu1KYBdVEYhU2hMdycTIPiU5gCzg3wZQOOpsy5xMur1JnlrzBEoXX
F+oFnI1SdJdFmIqczuLYk8AXR2++5Yq37UXfYrlG3vlW65WuZoH2B1D+UaWu
9Rzbd8/vSNwwCpFUeres6637V6ZyOHLMs3KV+cf05fI8uk/Zogoq0nZuYb9d
MkVjMZ+8yVQdQXmW+NOtO0uYwmOEznFbuowluVxRpMmYkIoyZRtZyI2kzAqr
XOv31YUr91iK5Moq166iEEBgkApVW74RUQNLwEYPEdUF1qSfTkSBM4mPjLkS
qdj9EYvH4K1wBelNtKepWKNh8I2wGiBynkfKAae0CpmhGjUSdqPSdcn5GElG
FsqSAXoCaRgPae1xIemVYq/7ody7QzsCzTf9uzyJCIzMcag6j2HPEO3cBPqY
bf52SSH/NWXcgd9FERyiR8xA+SO2JjT802k3SILReOkLLyV09cEKfurDbkJb
/nRqzNSXEgAGkc/2Ni4tWWLeOxmCKRf/jynot+7VG7jsEyjQhK1QmPxS6IBj
0QZZzBONkgXm0E5d4KAylOp3gtv7iPjvjWGlgOJ0XD6LgCBjvRRyWz6g8Bfh
t5yDVAlyghUxh3eDiFjTTJXHEbd+XN61HZjUgbfgIW5GNAGocmH8wBFzUQYU
25RbYUdkYmNvFixSanSgC0Y63Tb1WMJH3ISx8w2zgWtj8PPPWTQE5eDBKpUu
GJP6xi3zVQnd/0SwUAWch8bbK/+y+i8rbYaohzl/tseXIru+WBhhjE7HX3nB
XGw6KKKiy3noOn7ZWdPIrlXppbrHMnZRtnBSA6UQ6mU+3Fh78tBcddOKRcGv
DpYPFuvtaMdA5fE0sS4LzKHW6odSfav+qi5C1J9Z2d2BTa3wqW67iTwcDJ2V
pLrt8U1UGoOzXkY9KaTXQYFzJcp9mmelwmQx12KbFiQqsMmiaQ/ZiwRE+5uL
OwY2CU8sJloUBSglHwcZai/9WN22En5Egg+9GUvxhyZgij/yNFjyz+uoWAo/
ixZ+Di2pnNyCg3DWIm8i0VAdYONXoKuj3CYQNZC6ufAD5DDNWwk/Li41m3Xc
S76wHz6c+50SLwlC2FwAHgGlIso4hZn6ddTuagWqDmlnprzjeGNegcfRhSRX
7J8hU92UJZ5vmLXCopX5Yc80S9m2B/YyFnYHw/bn5MQl85bBhst+x8ReVXrs
Vny2TRfIcVks5GSx6bDEn1qaxEqsVnXSj+ZmtaYWUrUqtmS1qhMOt5iX1arX
ZZHCmZYGBjZnQeHHC+CzMmtxSP6HtEHxTE7zNdmpiFVvz0sZMyu2AuGbcxdM
dRFmAvgxKc5IdRjnaaaDm4cwo13Yc8p+2Mgp1+fhlFwIrMT6VXh9kzYsG0lZ
TeZAjwxErYdYI9z4o5AoiyvPNGRdJFJFu++HP12pvwGm4fWKgSzfLL/weLJY
D+2GPGBX3Frchgm06sO3OIB5hcCfG3AAQflVF9+XsuXiAALSf3QWoE91Wx4g
3zCqZtewBbrGAwrRgjV8DRDMbblzmOq+B8pXepe+z7JJ1VPB1yA/6uQtzDvm
sDbZr2syaFiazD4tygiopvov21XonN+1TeU+YvnND7qlrO7LU68XLfZBHXtx
6odxQk7RDmDYt0Z3YUepAdwiCcRXNpo0HW1Cck4HLo/3d2UrXyWO+gU097Js
dRPVfSmf3Uo+Y5iSkXrBMppF16SMRmu8OIsHZg7EG+i4S3V+PjDcV3W+I4BT
hsX3oN1XqahbuQ8BxN+Hcs9zXbhuPyebaNeJw4KremjLJ6r8QXXRik+Y/MFk
Wy35hMkf1Otz8YnW+vv9YRDCafVec4iltr/U9v270e7npIVz6vlW76Tn506q
AN1qirBAdV9RAXEGKHEm/XgfcX3xOn++VPrbCYxUZzeL4W9zKkszwE3XUjUD
qFt9O/rCvrMSERYtrQPlOA6D4B3KkI2xbNXeltn47tIcMJc5YJt6kl48iyPs
349vHKPYPOq/QMqKJKcCob4hCwDjxypVHm70+J/hLG+6U7VxZm/Qx+Uec57G
GZzRzXY26tkOF7LAEIJAnVNREbqyfYs0WgQ25WiCzR34Igi67rRXADrsfyfO
CPjCLCG9gWlVhOu5WVdjD43uCCWmkPekgESMRLMUYiUdCuqfZlTqXTwEeqsJ
DLWqk/S3TVRc8gJ/YYK/Q+mv4xUDrNjxLWn8bST5Mpp+NUmeMbx6Vf+Nkzbj
U5HcjbDlltK7K1TaIIaiYHFbyldu3vM3hUqXY/JbAfkOECN8FYjBJT3Wx2qS
AjAvZRkPK5k7h5JjmJ8y8kpRv3yA8mruog4mLk4cOY2EeK1nIAWADigVCZJe
RbHFy85E55HIq8EfmmW9JM6Vg3bKqkSVCjvpsIMSL4YW1xIgN/Z+KZPC/HLo
XEGbwfjyYFg9l80REXrvqtEU6s3eqpGCiaIo6MvbYNLDbDBmxyB+mdEWsl1X
5CB5A2rhwzKWtxKC70WUSuXnWwaptAYsBjfnTYCFP78TxsDkfkbyhxnUXqR/
GAQDLIKiQSTCJmzbSx0PaNeJ/8pJjlUvlbwic5Bj1YnFNOrJMc9Yz3RJjr8i
OZ6fduKpQGvGknYuaaf43IR2tnBxmEE+d5GK2QKwjB5s8Goov9JAqHZpiku5
8Zv1P13Akf6mD1r5Qz/NstXNOHVobTOuS9DwFlmyxowj6Hh/mpeEFWmFuziL
ZNaxR/lj1UWcr3JCQZEyuqOyEyoJZyQEIH2w/Fib+4JzgFVASQ4F1HgoRUbE
0VMj1NMIWM6SQPyRCYTjnSXPr1yE0024VZgHOixVVucsfS0Nae6sgAadUoXj
g7GvbuNm0CbnO5K64HWVzs/R4UD9HBNdaroykEvDj0UtZD7Co9JUbiLgw9QW
kiML5kKV+lzi+sysUV/55Lo9cfjj8McRI9Yd91kHHiClihbd1wN5Q1p2szxP
M48fsnn07TAKT+haNFQ2tYWc0NyBU3KHifNm1TvUaWYMB8nyQXDdPDVnRRE9
SAt6YBS95NLOsm45XjyWyRB+6nzPmh0W5mTkN3VbAP50lpPbwpfMzeMmbzfj
RFUS930eWnxlljVy5pmV6WjH+qTNOKSONxbDLjl1NOzet3aKS8f0nh7ipczx
BbWFP5Lw0Nq2N5MYsfFtHund8cZiiBEvpyy5L5gkqTlzaXHdajG6/LclAiyP
5q2X5oxJtxVuTIbfxYoGi9e5KdH+9mQy48hWX2CvLfRmwuhDqnk7iNCRW1jm
sJk7IalUFHatkZtOqRhyv2ySazyn2s1M1hIwEjX3I0NfWfgZ/iZvFp3IKfbo
DyQEVFb83RKZxSkiVjt07W1JVWa93kRjgN81kxnu/CsTGVaPlhRmSWH+cBSm
2sGiVY6bkp1Zr9eRHWPDZog4PMKS9vyxbhv/MAeb+ljIzcNNj3D53VBU0lzs
MYZRlmd4eYa/wzPs6UbYm2i35T3wXwZ55KdkWMq9Bw/8bU5LEYcdbXWvhOjR
hODEGAIl4ahxSBSeMU6mloWuVKsPP3FoLnO+wK6mKwReT/c0GuNBj0L/l1/2
d51rszNxzHs0GHYTM7ZcBpo3gWliB6O3BNak1HMDyO6uIhoNYgeXNa3Uivlt
uU52QptnlTsHbw/f7B3v7bZEjyMVn6oDFBV27L/77fD9wev3e0dHiCC6b95s
qmZEvVFBkKbF66at135u9tmwdBUhfllELoiEr//z93Cbii+rSYt4XF2Dib7u
ajdBq9KJnESJGLWrlfKwZXsa6SFPcsz+IzgtVfST5p1XJ0dJSbYs0JrOJyWX
k9bVXXgmOicY/dW0w2b+vZY7HJ2X+EXNDjfhL3Q6gF660XiQYinyfzs6eOdT
ufookyXo8ApYZEYq348qLJk3bQIGytcnTmTasK8CiLfmA0xcebEBOoviCcot
lUEl53BjhmAOyEev5I+qv84JHhFJWoUN7vpplDmAA082N1xL2bR6vXwr8mZt
Hzq676dpEgVjVzcl2RTL5vimKC3+ln3CyWtPScS7b/9RFDtJDI/akhTjxZdZ
+jHK5nzx16h/lqYf538rTwcfIzXNeaiBA+otklrNzOOEjp7GNmhQtsM8Xftp
VHmzih7lkRj2NxnJfrPmbfxUCTJv1y/v90u/THMsJG/d45IYFuT5RZqZBMQ5
K/xAp5V6Yw05StQZwRX1+rQkJK9bP/7446bVVs6tLO+36RzfXbc5g1jSjeYq
X7a75MnvbO8AXMqTtMvl7b31JUfa2fYHCMch6kFR27kMpnmRjo7TSTyYAxzW
JLgL/+1/HB8DJ4SOkB9Opv0kzs/MelWlpfNrq/SGaGNitCAK86Lzhf1azau1
r+Pnpngnhiace/LERjlnSp/aqeEnCMMY4Rskhw4iNse8Ku986gaTuPsxutzy
h/8bJR+7m2GyuTnsblyEuW20IK8tiYdNIDGflTaRafQNttF+sQFad7GRPPgf
cytJqNDeOJYpkTJkxEq0Mt1HGrbYNlKBlPzL+zfsYkgjCvEZhpyNGMKx6G4U
8lKqMnb4kQslr71aFa1m++2V0/AV39LSWq29IT/vSTCo4VVfGN0U0GboMdaL
wtD3rnklzSey2nO3LNu28HQiD9aH87zBeCFu9WUPrRFdb3dxphfntL+Uum63
jTfKJHKkzUwNqUTqXhVS7tzvbc/KXTJrB6pIYfUl8xAf0cGtWH3FxKuwivPD
LMqdj+i1g2kxmdJlhasBNTGi1txtQJ5zHSb5EdpHeI5bnFPcaXX6DAbniSQr
gWvVen4VG6bVgTjSNRNst8IZa/RlXOr+7kytHhNGVxR7+zM4C7JgUEQZZi8d
NPUJndUaC9T6anADP6axpQFCs9BENGsFyJmgbA9MWH39wvWnLTihuwbbi1rl
tmVrKT3GlJ9/DFSTPMM+unMwjdlWexdduCHbuDHTuBnLuAHDcNL9JvrXSPsa
6V4bRGxAwvYI2IR97TEP/wLsq+mvnsDNIm5fhv/NAy2UzBuO6zwgg65qt6CB
iNUSsG8cZyS1Kp+YOehV6Yq1hmK5jqSTZtlKqvOC/iaZ71ZRvXMkHHDRtzqS
46YcszCgZvdvv/Pz7Tp2hJWg7b7k/lukYuGbXyFE7p1/IAAv8uRLpx00Eqjo
AlyCoxhXrV5cp2HPJHOzXUMWkO6iwiSdqNdEsGesYjZ5qiVOiyBN86IoQMro
TSLn9qxbvNthZ5Xmf1OEycmavkGi5D3Qnm+CL7FfW9n75ZbOLTe4xd1YWzN+
trDtb8fHhzKZE17IsF8DObE9XVszHdRUyiXLua3kSjbnGqlZZYXNHg6/vN+X
pteI5okvmaseT0tVFbrK7HdxcdGLg3HQS7PT1SDP49PxiJAY/Qm7wgOvix3m
D2Kke+dBEofdklPkrfsD7O5Os2QBnUafkDiDHgGg6Spn1e44LbrRp2gwtZ1F
bzpKjhLssEvW364o1NJ1BswtZIR43J3m5SvYm/Q6yaBXJkMEEpw4ev8uuGvs
totFBhYCivKkL7K4uINJY7fR4mZNEVjoaSTRo1rU9NZdE1bfTbcLRWYGs2Sf
XXiioFLOTLfgYcZpd1CtvLTQIXT/3SIeRWaBpYWO00/HGP6/6HNVt5a7HEZI
JV2VvvlOR4vHgsmIUdOsaws1ix/29/i0H30Z1BBDyUVG45C8GWmVyRSP8KK5
aj9Lg3AQ5IUaFGMzFj3KMM5GF0EWdbM0SfrB4OOdDcAxJG4UDPqwaVv9JBjr
8Rcohz6ZQw5Vg8VFMte9+T7vknBX9vdrXb3/Nh0FYyUTSGESh/N0e4wjmmf0
kiupmkQrfcQP0yi3ihNx33Bs0cFc5g21E7a2W9cIC/OdRqCUooCv3KaVyJgb
ygv2SP+xXJ6tMo/7RaSE7Lm8NUs6UVvnSWc46Yw52rpIg9f3HH7fFSCIS/ZS
oyBcDLRKPucLhlVplq3hVbEdzLGI0qh41SfhKB3q65GyruhoI3znnG3FpDUj
pazyRb/x9jQubUFI3AQ5mMFfdg529/y9d7tHf/X+jz7e1Zb/ADZivH24f422
DWmOwRTNEyR+ngjrFKWEKE4x0GVFRTMqTpGl5zH6egY5hkwWqsDx7iuP80Ka
aaSR0p0F5xHupH51mpPLFbxVLkxHdT59Lxr1oxBblmfQo3TMlXlhICiHQ7CV
ghfgyQIZebleahENzsZpkp5eojMt1SQGOI+mY/Jb5UkYWau9IEnhLfo5GF8a
Jjlgj8wocQFY5qyhM0/muvdwDTRbfleC0LUsE9wBcAw0B9B455F3wDvqa7Bj
LyC4AX7ElDhPdBwjO0PJIs16imfYQ1l9eRJvGJVe7r3efwfINAQhw18p2w9X
vJ/sj//u4HgPcPfkoZ/EsO0XmRgDKIH//tWO/+PzFxt+6aWfPA8RNJjEW/5m
b6236SFk8USwzOC/AwDvH0oevJOOCxCu/EeIQI/1ct4KfHbHhMzVR8//ldKR
h5S4jGXEcXRR3aVJkmOrcsbC8o5SB3Q2koR9Dfk4cy0t2GoEL6ZTBbF3lB8M
RfZpdnMDYTG/CE5BROvF6Sq1WPU4DjWQd+/QGYg3fr8P4szg4+hfB6ihoFMc
PE2gJ2XR45jm45csTE2zRH4BdSYneK311td6a170qUAv9WQ3HRBxsmBKR3d/
7/iVH2bBEKUc6knKtihXF6CooAd8HBVDknHDdLBKrbv4UzdA2xnKuqsNQauV
vX1g/0YwFcDi2hKqqI5pwjYqo8xru601X1fc/yyruzn6yzd7zhouytJ+4hlN
7TIu7RaM3HWaFHXrNmZ+75dtJVxv6P2/SX1sGODEq7S2xnBC9qVUEfMKLNWj
BYPS9+8AmGqydwdLYwgnKINKjHTlRulbgCTOdXSXOKkGcENxbNwxVy5svwUA
OtyvFgk+2X2d5Gtcf5J4c10Rgfjgv9kTgs8suUet/z7IPjCXhcg/rn4odcpS
HrGTaLjgzck0BE8mbUSoDiT9y9KvqjLO/q6Dudh8f85z3XfZ1ZrClKzTKMsK
lq/h6ws81JR3aAgJaXJ/Meawv+v2AGmsDI+f2rQ38nPzkG6u61ieV1PUOX72
h/4FpzOn901VEZ2KVFUlMhSOH3KZ7CpEU05oKu8bQBXsR9ARxa6D2KcuoXrO
vavGcfPUOfFNpd6BWOt+mESH0+y04pdhB13SsqJPkxjmATsbp2HHLBfFiddz
57yqBmdrizafra35D+Q8/XX/LJ3ajYNpkXIayHn3Bd9ku7kupxkP5Zzz6WSS
ZgX8VPiPxPiP5wBtXZg8FkimSzAyxTA96BgFos3Cz5SVR1gynEM3RyqJHsuP
K64U+Omq8R2PxkAAHT//7zQvLtLsY3lnZXD1x6haDqbrp2mf+G6FeErmq+in
LEdaQx0NucWVnEPu6QLo5y3D8Wvmr63MrqctlmbcgnRLPk5zrtpJc+fLvXEz
qlqa9Z2DfscY78SLBzV7sGNNq2kryq5lxqNhEpzmxndJj9Jszt2puK994U2i
hczeGocjYNfHGyvrB3JRad7Q+rz5DtJVGcI9DP86Tot4qOds7MidY96uGqsG
53SDJnzTU1a41hKLzDe/FAY103llNnDCo2JkcYFDu1B9EflYCFmBw1O1lA/l
QdVgqdZ9WGcMMYwMd7nouswpVbbCv9fSuJvqF1XZvkGcaZDnbyHJN5DUrzEf
The1S6Jf7ofxkC4QCpoHZapDvOFsQU6smZmq7K5wpuSnOyc+lF2FZ4Bewfc0
KNqKtY6mhNPKrek3A6x2GysOOr81Is+DHWuLwtZ5Bl1vYTgDtKgxm7ERrq3l
zDDwrdzG6sX9LMTwVdPV0vZVtX3VQb2W3YsXmjS7yr1MEzljj8H5KBq/c6eC
njRECwdGh6RXatG0RukGaat57A85pwahu1qIy9+6Jk9yPl8CrDs8Vj1URYNG
fY2bWDDVEJtTL5N9LQSoGqZubnlXUJXSaD1Yy3d0zky/BXCf/rSIXJC9PNZS
QkvYGv0tBmXL0KU5LaRr69dawV9QwH6tzlO+S/1S5E+86PQGMiZee4Nr313e
/azrJFEHueQH1SPPv7tQdm4J1k1ZdUdu+3YdTlGPVZTFj5PYLGScZ9aDmoO3
mBXZQ9VL/7eCWi3PNXUkdiA1brlnurvWXtbPFpoZicnjkiQ0dLBDOY6c+HP/
6gH+qn+4Zs/AYYrXJhWnvFzcEPiBP4wu5MLN/oTTmSfH6tHhViOTaczvx+Mg
uwQ1L+3rd5uk9z3ZqPsS3lnstfcDH7vrJsH4dBqccnAN8HH/nxn+P0kBFsso
dPk3ll1Rbl3dWNtY666feBtiu26jT8wC0A30itld3g/tYvPLahe8xzRKlzta
uTq9+O0szYtrCnwR761vcu7D8yCL0fCmCLBobFo4xW1mkg6CBJ8Zj4x1vA6K
6CK49P+GLWRdG1nixXVCvUoX6jqRnJXJyzhH79p4eGmFV1NOduHX3L/UDrha
UUeHaAzlwJvcfpDHA+4SXkzhhKODNBw+nA4sKYGTPAmKM9TB0LHenOCqnu7q
VRxer2qOtYoIx2CaVQ3QsW6jms+vhMWBhcc0TSkcwGrKkSx1t7Bz9dXzf8W8
G4Oz6fijbxTsQDJndhCMQyQ1yChUGj4+e3kP7+GJLMqXDT9w5Z+rPN8Dw0Ik
7t7zqICxO74xepyrreHMIHJwHAjexvgcfTePXamXR8EYKB3iAs3MGg8dRzi2
lHzizyPh1A2/GxiNgOlwyDwGE+E6jD5kopIE3QNgpJBcUNKpccEL7ATwlRzM
cRK76KOAsUhUI4Uqo3Rj5U5gFU0ikCIbkJJbpWaSPE6GjRQLJSH2ug8lcjyY
gqyUJLb9Nc4Cf5dhUsgSTR+HmlJJ1do6d39RJpcsEdgqOl2tElXvnnB8ZmcK
oX6ZyKBrSC7wETcBTip8Wxw4blM5plw4RgYn3qbS/SKqT9qCy42KUD6ZWeeq
A+gpF6PfFByp/u2bV5aap6KUdLHsrSKRr/eqNKOYTjyMY/IbjIAG+yG3N5MQ
7xnSje/bO9B8TaFoSut7Ct2jfq1dxRziJ3n8e4MdoCLc27J0f5p8NEPb5pWk
4fXvWZIm8NxaeK70spSX74+8/G2Iy74/W2BGNBNSsgGmG4jJO0gxQbo0CcMM
wbjdK5YMhrSjVvxyCmAOEWwxQtg9rVh51+LGyixxA3ZoxbWOit8zot57nm8d
97YHkx2tGm+ulN6U8tcvk9MsCKOb9e/uRA/VVohaAdayUisGbYMMNbET6DhL
W7xJeaPaCj6NzuIKqUxKMDNLM6EYgX2VM1v8rCuX/XQDv49SGrQ3KNyfRgWr
tsj4RP6Mioy48mRtvR6iv4yDKah7GQg3ofnK0/pXZI4NcXD0W0/X1urfOiK2
1M3jELRUlh/vVoxdmV+MleiKPAHTsJjiI4C4kgl05eqfBRB6fSAfMIh4sQd8
93rFntkkrR4qm7aLl0mJpy11yPv4scg7NpRvlto5KVsjxNvBvRn6oo+6DKT8
6bbepP2wTK8cvbQgsCeezH1Q7s9BheQHqNHaimsV1sYd/Hv1xSdtXnwZVE+R
0cP67B6cx9fo4unsLuqOs+qlfKydvdQd71mVwZslJCzt/dJxEmyxs6aRdUxg
Hi+JBVpNlgKRk+MoECiOVQJFYx1zmRXFAIit/t7v5buFkgbOZh1/hziyUN42
M7PzTSnqPLSUT9GJV6WldYKrFF3tRLHmp4X06ibfDgH2hqM4+3Gt0ue8Wi9v
s6RKD1Q026lsrppZ2BZEULnLRnJqNXER0yOzwZKULknpd0dKDbq3nV+OB3VE
FYiE0dROtaWJx8rm2maTghT5B3hJ8k0pt3et1d71lccXRwIL7A4+mfM90V5d
PUODmIsrJUeTc8y2V6O2MS/xdw7eHr7ZO97brb25wdYlWyiaRwVzoFb19zfK
RuqoOzkvYDVYQUvvSmV3xehxTmc8bTx1u5XNkcCgvdB0IAe1cQGOJV5GuCcy
u5CxI16d0pChbxf3TGdJr5i8CJCD5pNoEA/jKETfgBPPbAMAiOTrGGE+GkVh
HBRRcllOGqCuBlSbMqLXhNvUta/E03gS7RQ0+V4gFDFQwVhPHGPhA6YbIAY5
UFLtQdPdIkgxZ2lo/GBIK21rqNZhHvc9x2bXwe/w4OjY9fMvrl9f79m/4oIW
MIdVFs4qfkQ/m54NP10Z3wDNrmd2xPc6+erP/Ad3ov92dtDg1IT+MXA6xzIF
I8/uxHPNr13nHAhm9Uk/cXfwJ5Cp4iZTxWvfKvBOvNrpae4tIdiGB594tZtF
d45/2tz+08Yr+J/h0wHf2IGDZPw/bWz+6cTbeCVrwJafvjL8O/BZNKKDZ9t8
gXo4yv40ZIRx5JFjmLbVfCkJbVWZc3IkzFW7o3e43Cky+yqdN17A91cU8Xor
ncyyCKAAFJbTnTmEeZemPXdpFTeDmzMyZBZTU8TU0mBpue9plTIbWd0CKx3U
SgxLKruksq2p7DdOFLMai9KMytkLoH6zOtDp24EluU1x7TvTl2+qM6+sFzmu
u5XyIyz+9FC+JtqUtB83MZRy3pb73M6HPIQ6cOxuhzyEISfezZFHr6lMob7d
NbmlBN5iP3z9n7+H2z/95IZBmXgLILQ3dAg4YA7JZjrXBjAnngs0Xw4w+BkF
n95HkwgNfE9Lj0AwyS6P45EKKHMZ7Munj58uj58Gopt2t0LX7+jI1sFBGp/s
moR/oCM7D4LU3jGpU8he4cuzOBeoWQSft6QSKuFYj8qozecsKKhx3K53RCOz
N7ScO1nhajoRtYd0W1eYhQEVCrQ4PvEQXubvVqCFASl5jeYY/o9FkW6DDYoq
tSm+2QIxlD5MW1PTi8QM3fgiyK0X0Lt5EIl6ErBX6TT3TzxtJK0U/1rS3z84
GjR7ACt280o086fcbjHq17dIZahs9cHx9r3SU6ITr8lk0hYSJ97Mg0aOsPBn
WgRHCIkSdjYA4u1/VHQSUS3S1khmosetKFLVzr5A4BhoIs/VTOjghH55/2bL
yeZlL71+XE4eTYFpRxiYBiJ1mc6cBRtPn+2cRYOPcIK3fJG7TQDrxZr7+4lX
3+K7Ob7DeBznZ/ft/H51pslJzi2vrpmQcRzoeYwM3wM2Ueg9AO6m+DTDfbGJ
/S5C5/sWQe7kv1/b6HBv+O8MI0PpyH7HrHY2Rjz5bo6Em6d97TNxf3nagg/J
vcaNeTiUiRkzkhpwsirKVTBnPoNXWLqyOZ/BXAkNFpXP4GSxqcFKoLlVTrBK
X8vkBvcnucE3kt1grmRgiHAMpsUkAyMEvm0WsOZOSum/7DRe9GqbxF+OfF+q
kzZ5vxzpvtT7k1l5vxrSfalOGtJ+zcr2pfqoT/vVlO1LvT476xeSeE+yyGXW
rz981q+Tr5n2qybKozmXqy2uPKx/e45ABoCD4S0qIhlulGpsoz5Z2DeUJeNE
C8QG25EZM9qJxtAL/KCwT8nGjIFKNMY+a9XGP8fQy+IimRxRGaXgJuJGLNnl
VeXkPdrJutvDohoY0rw57oTIs+aGFjmMncgj1M6IglwEcSELR5LVztzzbztf
3QkmrBN9OTJ9yJ8Wn+3jq+bjcHuPyk93VsIOk9zNAjeAeD+s0ssbdiVPK7mv
1vfavs9XAfSqEcLABvtTH6PHn9mRerLdzHg9/jRE7fEnDm9UMsr8SJLqvmoy
WTgAqczF61h4zXh8w9wUIV8C0KuyZ8KXh0/97bz5ae8ugCzO8BhAf4GYE650
a8oOixHY0CCTs5SKEtgf6QuwUkrlUp8458vgQUNiHRBg1h66ttKVM5Wa3T7v
AbJdkSQrHUpdkllwOZ6+jmG27aYHUjroJKRkccSP6sJ+vSQKqA46wI4HyRTr
/yLpZl/A3OgEpP1RcOmfBaD9pYPBNMsitzIGcEPxlRToGQkbllrZUisra2UN
+SvmBY+ZzIINFm7cv5eIstB8z9Lm+C1Lz7NMhwtOWrMk3kvivSTeS+K9QOK9
1oJ4y3DtpoMPG+Fa/x1R63mSpiCKONPRaIX34ebaZgMcvqGcRG5TYvvrdTxr
CLBb2BDFGSH7x6KzIRmH7UsJBgtGNWtzb5f5CNOgJ1HVKx4/DVaCW9kH2idO
qpa8QCZemyvpVaxX68pHI5yDpfzULgOE9Ci+CQcK01EQj23f4zCwzAlNFmWB
uIy0wmURp9PzrWbIVf52fHwoPGvoVjOHHY5CwW4DDEfT9FT7OlfWVLZ6l1yf
Z8PAWo6a9EB0oBo6SF9NZooglE5OhzU5KmbshtX2UzeYxN2PEWD+8H+j5GN3
M0w2N4fdjYswD2d56RgOVxTuNa+vjisRyndahoTAY8Lr1r47jT0uPXiWHjx3
6cFT9rcU3jy3LVpSIiekR1tVfys1S1q8Yam9AzuN0lLn/Xo6b5mAmSkAa8BC
4APxDw/6AvRih+pb1nuNaM/7U0SulAvsD+zkUVHMyoSphb/HiVfV1uZX1U48
A1X+vMDUtbMdPipi2NLt48uXKRRdLb0++LNgr4/FOX3cic/H0uVj9lX/HJy2
YcTmJFTys3QPQfeQb9475EuiDH4q5PVeOZlUlB0VpDu/ntT4avmecGepMy11
ptvpTAu6LnQULakIv+U7+3uFLze9LmxWxb5s2YrZIpFDtjJnkw6KqOgCmKOg
kpb4RrqjqqxN5b+bVJWXXCAcDYsSgdSJIz5hIOFdOdIIpvzDF94UqbKAuqvl
1HlsfAt2u6nwJNN5Zi5m1vDiDFa2dHxZMrQvzdD+eDzsi5beupmHwR/Hl2Wm
xbSFW8uJdytTqThOAPUFm0pn2UXvp3fL0rnF5dyCr9beeMhp1tT/mltCvUm8
ratwmNnjvIVFVGqzJgx3mNrhxXg0HVGyw5rrgLN0miD2Y/eV9x8JSdd/2sG+
/PW1x6U2TRcBigjZ+dh0NrY5V0Or6EfFRRSNafa5eY2g5rp+q7muz+PYQmm2
5vVsIVv/H8S1hQG0UN+W5i6Xzi1L55aFO7dUawItxKdlb4ybgKWqGKensJiE
c6/wOKgUgtbpUnTnfLfOz4Vo0VLHreq4KoHirRRc3hu3dhvRDs6GwhdTaQkX
7r1TC83yD+/VUqVI0pmlTeZPLBc2h3om836WnFhAO/kqbix8qJZ+LEs/lqUf
y9KP5c59L4jczPZIAPp54rViqw1jLT1YvnEPlvuHLPipkNR767vCvL3EAWtv
+JytG671ltrOnWk7pOMISGjNh5QegMO3o+t8GWcUhs73dZO39Ebhz915ozDW
LF1RnBa5O/RAcSicM1iS1XYWQ1o6mizZ0t2xpT8gJ1r6lMjPPbZXtixRRFrT
iXcrQ6U4MSfeXTqROHWRbwTbrP1depFYRsxaN5LFeYPc2DFlTjcSWfKyCcPb
2bk/RtHEEEkrfFR+9k3B1bqaRBEE5Bwq/wB9UxUJnF+nSpNUB7J4RBjnNB6V
1QC0+4h/5sIsVp5ESweVGU4fylPVkBpbOXtIU+z37OSxzF+ydPH41l08YCvG
+SguFuLYcSw645JBrSoNqVcC0OwukzQIzZd7pMyIOea5oKGiqk904oVYjggJ
5fahfwFCUWSoflShOwlygHkUSQHf0km3CeJyBrWKqFMVdSiji1FHa1UQt3BU
K7nWKCI3VUW+jieE3Jsb+T3MYbO7X9ak211Uu0654dpOOQ0XctplkTASb+nU
jrW8MM3Ngl4grRB/n0EMXD1Ox1l0GudwIEHakd13gKn1ozAUY5jRTX5lUD+W
NGJfVAsL04hPn8Am81WePo8pExT/VzqVZbk4JSSRKCrK5dcU5WLaglIQLWpJ
XL4OcZlViaql7lG+SbR7kAgH+JavHoovb4NJudcTT/drNFOy8o2o3L3Lif7l
KZ71mUH+MhUpcUvqhyEXCyV+VofDLB21on5V0nWn5I8UFJ5cW/rXmB5hSf6+
hGw1B43Cs3biLZhGzXV7egdXpVXyfQvz03dDOeuMhdjtsaUWNgaVzYNZOAJy
QROzXmag9A1AT3toHIhyUubB5UDVN22Zkplemed+irVo88l4Wrr97lYb4Y+l
KLIHUmMtOHQLCPDIqEchnpUjweoMdmp+m2uGD9kDNhoAt1CRYbLjvGbAffHC
XIM+NcYUCvoct2D9yyJy9bp9uhdsn6ZvX52/eLv9cvtvg7MXL/Pdj6cR+nO5
TJK+sMHTZeYoDaOELKgVZpdTtYSXb/Z872rLf2BUae/m4fC6yXZptO1B2x6e
whXvCqa/ghwqnwSDaGXLv6L1mK1XaqpJmE3gpWs08a4I6vHO6NHqixrB8FRn
vm64KwHTFXUpZPwIP59FQVKc/eZ+iVoYFAtn8Dd6AdmqNRHV3IhVLvWEc9O3
Tr8hPlRaVMc71q/4x/hK2fy9kvbR8oeWPGg/DJK8YiFfQVWssQEKK6IBsqjK
c16VJESOaUMbfr36AF9nQ+z+Lq5o/ce1F5VVULPBWYC2vSjD8tADbr2xvb5b
dae89pq+X9u9r4yiIAf4oZ3wN0kLWoD+rX7NlxThjwf+jfW5wW98uy4fDro5
az4ZxnbNeUCMHatuFFKAaTGZFrtBEbhh2ALOjZDGhfCxXjkNiuoc5DCt9qP+
QOy4/IvLezLvIaGDMYrCOCiAOBn+JbO3YN941Tf243veg72F7IHn+lv+pXao
DO/X0RimM6CYNDRaiFuy/TELE9hKvVrHj1ZYFfwNGfYMlie6R0Zs87pm0meS
vTJVa6J4szCgZu8rO7pWRT/3XkLLNruie1sBCSqCnsaDWaDb1g1vCLnqw3sF
uvX/P1KDLjcxrzQNaBCweCgCJ754SJOYQED6ImkDp0SFYIi2oRSsjsQGq5El
ycEKaujHA3thScBgJS5EwV0DP7CO4R2YJqQGJtCYFNA9O/FFwJIPNKRJXIh6
QLUpBEG1De9gNSc1WGHXF5EYrG6wW49GRrCakRqsxZXFwOZafGYKgXAMBqtT
AFo0PAPOmKiAw2hbYe2TKGUWBxSlFmP2QNADFTR+kphSBhpRKwb3O4oxhgPw
NHgJN3ZxNnThjVw028lpb+og+9s5Py8vFRi6hJITyOfJELWgPAlZvktvzyMc
EA91ACXtbS4YWctVi2VsrdoKst7NVonUITalWi4A/5P1/W/dAgA=

-->

</rfc>

