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


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

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


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

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

    <date year="2025" month="May" day="13"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 60?>

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



    </abstract>



  </front>

  <middle>


<?line 68?>

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

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

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

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

]]></artwork></figure>

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

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

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

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

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

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

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

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

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

]]></artwork></figure>

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

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

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

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

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

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

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

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

]]></artwork></figure>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

]]></artwork></figure>

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

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

<t>where-</t>

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

<t>Example protocol mapping:</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>paths:</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>NIPC operations happen against SDF affordances and are referenced with an
sdfReference, which can either be the full path including the namespace, or
and abbreviated reference.</t>

<t>The opererations 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>#/sdfObject/thermostat/sdfProperty/temperature</c>
</texttable>

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

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

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

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

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

<t>Failure response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

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

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

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

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>where-</t>

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

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

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

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

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

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

<t>Response:</t>

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

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

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

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

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

<t>Response:</t>

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

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

<t>where-</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

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

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

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

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

<t>/extension</t>

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

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

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

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

<t><list style="symbols">
  <t>1000-1099 (Generic): Broadly applicable errors, including 
authorization, invalid identifiers, and generic failures.</t>
  <t>1100-1199 (Property APIs): Errors related to property APIs
(read/write).</t>
  <t>1200-1299 (Event APIs): Errors related to event APIs
(enable/disable).</t>
  <t>1300-1399 (BLE-Specific): Errors specific to BLE operations,
including connection management and service discovery.</t>
  <t>1400-1499 (Zigbee-Specific): Errors specific to Zigbee operations.</t>
  <t>1500-1599 (Broadcast APIs): Errors related to broadcasting data.</t>
  <t>1600-1699 (Extension APIs): Errors related to extension APIs.</t>
</list></t>

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

<texttable title="Error Codes" anchor="errorcodes">
      <ttcol align='left'>Error Code</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Category</ttcol>
      <c>1000</c>
      <c>Generic catch-all error code for any API</c>
      <c>Generic</c>
      <c>1001</c>
      <c>Application not authorized to access the device</c>
      <c>Generic</c>
      <c>1002</c>
      <c>Invalid device ID or gateway doesn't recognize the ID</c>
      <c>Generic</c>
      <c>1003</c>
      <c>Invalid SDF URL or SDF affordance not found</c>
      <c>Generic</c>
      <c>1004</c>
      <c>Operation was not executed since the previous operation failed</c>
      <c>Generic</c>
      <c>1005</c>
      <c>SDF model already registered</c>
      <c>Generic</c>
      <c>1100</c>
      <c>Property not readable</c>
      <c>Property APIs</c>
      <c>1101</c>
      <c>Property not writable</c>
      <c>Property APIs</c>
      <c>1200</c>
      <c>Event already enabled</c>
      <c>Event APIs</c>
      <c>1201</c>
      <c>Event not enabled</c>
      <c>Event APIs</c>
      <c>1202</c>
      <c>Event not registered for any data application</c>
      <c>Event APIs</c>
      <c>1300</c>
      <c>Device already connected</c>
      <c>BLE-Specific</c>
      <c>1301</c>
      <c>No connection found for device</c>
      <c>BLE-Specific</c>
      <c>1302</c>
      <c>BLE connection timeout</c>
      <c>BLE-Specific</c>
      <c>1303</c>
      <c>BLE bonding failed</c>
      <c>BLE-Specific</c>
      <c>1304</c>
      <c>BLE connection failed</c>
      <c>BLE-Specific</c>
      <c>1305</c>
      <c>BLE service discovery failed</c>
      <c>BLE-Specific</c>
      <c>1306</c>
      <c>Invalid BLE service or characteristic ID</c>
      <c>BLE-Specific</c>
      <c>1400</c>
      <c>Zigbee connection timeout</c>
      <c>Zigbee-Specific</c>
      <c>1401</c>
      <c>Invalid Zigbee endpoint or cluster ID</c>
      <c>Zigbee-Specific</c>
      <c>1500</c>
      <c>Invalid broadcast data</c>
      <c>Broadcast APIs</c>
      <c>1600</c>
      <c>Firmware rollback</c>
      <c>Extension APIs</c>
      <c>1601</c>
      <c>Firmware update failed</c>
      <c>Extension APIs</c>
</texttable>

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

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

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

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

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

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

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

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

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

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

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

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

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

BleSubscription = {
  serviceID: text,
  characteristicID: text
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

</section>
</section>


  </middle>

  <back>


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

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


    </references>

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

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


    </references>


<?line 2361?>

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

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

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

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

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

# responses

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## Extension that defines an operation in a bulk API
    Extension-BulkOperation:
      required:
        - method
        - path
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
               - POST
               - PUT
               - GET
            path:
              type: string
              enum:
                - /{id}/property/{property}
                - /{id}/action/{action}
                - /{id}/extension/property/{property}/read/conditional
              example: /12345678-1234-5678-1234-56789abcdef4/property/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              type: object
              oneOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value'
                - $ref: './Extension-ReadConditional.yaml#/components/schemas/Extension-ConditionalRead'


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

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

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

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

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

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

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

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

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

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

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

    ExtensionErrorCodes:
      type: object
      properties:
        errorCode:
          type: integer
          format: int32
          enum:
            - 1600 # Firmware rollback
            - 1601 # Firmware update failed





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

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

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

paths:
### Extensions
  /{id}/extension/property/{property}/read/conditional:
    post:
      tags:
        - NIPC API extensions
      summary: Conditional read of a property
      description: Conditional read of a property
      operationId: conditionalRead
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Extension-ConditionalRead'
        required: true
      responses:
        '202':
          description: Accepted
          headers:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
            Location:
              schema:
                type: string
              description: URL to get the conditional read status
              example: /12345678-1234-5678-1234-56789abcdef4/extension/property/temperature/read/conditional/status?requestId=12345678-1234-5678-1234-56789abcdef4
            Retry-After:
              schema:
                type: integer
              description: Time in seconds to wait before retrying
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
      callbacks:
        callbackEvent:
          "{$request.body#/callback.url}":
            post:
              requestBody:
                content:
                  application/json:
                    schema:
                      anyOf:
                        - allOf:
                          - $ref: '../NIPC.yaml#/components/schemas/Id'
                          - $ref: '../NIPC.yaml#/components/schemas/PropertyValue'
                        - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'
                        - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
                    examples:
                      successExample:
                        summary: Success
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          property: https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature
                          value: dGVzdA==
                      failedResponse:
                        summary: Failed
                        value:
                          id: 12345678-1234-5678-1234-56789abcdef4
                          errorCode: 1000
                          reason: "Invalid request"
                          property: https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature
                          value: dGVzdA==
                          
              responses:
                '200':
                  description: Success
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional read response of a property
      description: Conditional read response of a property
      operationId: getConditionalRead
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - name: requestId
        in: query
        description: Request ID of the conditional read operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          headers:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyValue'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '405':
          description: Invalid request
        '500':
          description: Server-side failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '../NIPC.yaml#/components/schemas/FailureResponse' 
                  - $ref: '../NIPC.yaml#/components/schemas/PropertyErrorCodes'
  /{id}/extension/property/{property}/read/conditional/status:
    get:
      tags:
        - NIPC API extensions
      summary: Get Conditional read status of a property
      description: Conditional read status of a property
      operationId: getConditionalReadStatus
      parameters:
      - name: id
        in: path
        description: device id that need to be filtered, group id is not allowed
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: property
        in: path
        description: property that needs to be filtered
        required: true
        schema:
          type: string
          example: "#/sdfObject/thermostat/sdfProperty/temperature"
      - name: requestId
        in: query
        description: Request ID of the conditional read operation
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: OK
          headers:
            X-Request-ID:
              schema:
                type: string
              description: Unique Request ID
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '#/components/schemas/Extension-StatusResponse'
        '303':
          description: See Other
          headers:
            Location:
              schema:
                type: string
              description: URL to get the conditional read response
              example: /12345678-1234-5678-1234-56789abcdef4/extension/property/temperature/read/conditional?requestId=12345678-1234-5678-1234-56789abcdef4
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '../NIPC.yaml#/components/schemas/Id'
                  - $ref: '#/components/schemas/Extension-StatusResponse'
              examples:
                successExample:
                  summary: Completed
                  value:
                    id: 12345678-1234-5678-1234-56789abcdef4
                    status: COMPLETED

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

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

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

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

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

</section>


  </back>

<!-- ##markdown-source:
H4sIAGyOI2gAA+29aXfbSJIo+h2/Iq98e1x+JZLavOl11YwsyW7N9aKxVF13
Zk4fF0iAEtokwAZAyWpZ89tvLLkCCS4iZcs2eWa6LAAZmRkZGVtGRLZaraBM
ykG8K/ZSsTcaDZJeWCZZKl6HV3EujtIyzvthLxb9LBdvs7R1dCyi+CKBJ70s
LfNsIH56e3S8/ygIu908vtgV+FcQZb00HALUKA/7ZSuJy34rLKJ+K01GvdbG
46AYd4dJUUBPp1cj+O7o8PRlAF3HZ1l+tSuKMgqCZJTvijIfF+XWxsbzja3g
Y3x1meXRLg8rjcvWAYIPgqIM0+hDOMhSAJVmwSjZFf9dZr11UWR5mcf9Av51
NcR//C0IwnF5nuW7gWiJQMAvSYtd8aItXuRJ2vs4DFN6yuN/EeZl5UWWn+2K
/aToZeLkqijjYUGPe0kJA38Bwy3igXyUjQFF+DQenCXjIT2Mh2Ey2BWALQL6
bz2E1O5l8LZlhvO+Ld5k585Q3mfnSWk9bRhHAfONy12x+XRD/B4XpTgNCxi6
OMiTi1gOKwJwzx9vbu9YIz+Bb/49K2J35L+d7NmjznEMw6xh0IBDgAKUEtkY
zMM4ilPnDQ39+DwZJCMbefvhELASnU0eQ5cBtgsG+G8jhkOjCRJ8NgQSvohh
gcWL14ePt3eptSTzF4NxXGZZeS72szwWJ6O4l/Ql0a+Lv8Y50qR43N6mRppU
6NeS/5UTMKBOjl7RqwgIeFdsbWxtwp//lZx143hry+n+n/SwqdutLbHZ3pje
836WpnEPJgloEydI/GEeFWJvMEjCtBc7Y9l8Cn++Csuy9f7w5LS1d3zkDGhP
4OP+eCDgjRgXcSTKTIS9XlwUCCOEpZU7voDXSXomynNgB+O0h2MPBziEKO4n
KbSET/GlQcyrvdNTMcqzfjLgUZVhfobUeV6Wo2K307m8vGx31ee4hB39VyuP
i2ycQ7+dMxw+/Fm2wlHSWWRlABtBq9USYRf2SdgD3nF6nhRiGA8zUfCiwDwV
SkKLIQ6IISYOQ4RxxZfhVSECmONFEiF2slGcU4tChGch7IsSOJLFN4EVhYW4
jAcD/G8o9l+8e9/qhoj4YDTuDpLivAXcsejlSTeu9Id7OxxiL7gybXEKyI5i
/jQy3wLYPA7iT2WcFkl3EPOHhU1zIhwUmVw3HAWMH/glcPMhzBk7UAsM1BAA
QcBjWFrAlBkQPIX1Gmbp4IrpRk5TgSragnE9TKIIlj94gHw7z6IxAYa/H4iT
HqArCF5nl61Rdgn4LWDIWY446pXjsIR/CqBuAUsJL3tM9tCVIshEAqTZB3F6
keRZOozTkpvBsEQPUFuIYtw7R3x3x8mAlglYYngW46fr4jwOB+V5D5C2LkDA
fBwNEInrAXwz7uNAgFWfrYtBdpYUZdJj2OdZMUpKpn9oKbI+oFt0gVLj/Ipn
E0dt8XsCVBgMkmGC4+ZJdsfA46BfmNQVDOQKMFcKWOwQ1grRWoxHI5BbtJcs
hIqMtleSB5cJwAZSF/iPAe5Us/Y4nRSXB4ErSHpN4HFYijz+xxhawroPcECB
Pay2OM6zYYKYEfGncDgC+DA5xqCBg1O+vib+enODCAmurxXHu7khiitivU7l
1QgIbwCUEmW6d0lA4xRpMoa5AKZkgwDmZm0+OWzs09AAND86ljsHdAFcOFxY
kAB5CBtljOsGpA8bHFYCdg8srgOSsYkIlq25kzRm2PbQYDR53ItRgJaA72EM
ckn0AU0IAaYpKX+gyVjNewjKC04Z9lp5nmfjMyBCxTVEoPdYbSiIP9hs6kv1
IeIBiAw4V1oM4B39LQIzVN6w9LSyG3ly+KI6SkUktF//B3+amd7yR+1/btm/
n90vfp764mcC8tnRST//2Qb562cUa4Sf2gupqX5uHh69AnrgR/iXJiZhtaN/
SWj05wHj7HPDHN8p7l+do+9FZe44NLkA17viwdkly+hf1tQ0UQTIZeVhFGs3
AdO3OA8vYuAhQB1xv4+riXTA/F2jyZARQtJ7EwlD0kAAkgA03qQ3HoS5pp11
zT5D1KhYqqOMJJ0BYdFTKQyDn66vHX3j5uYRMCWguAugOWJLZrCKMaLOIVC7
AA5o+F3ujkex8zYIEpTgxOeANYHmCmIkFYXUhJRMRHYA/QbVbQ/fW7u+xoOq
4robF6PsY0xM7iJOoyxvKVkqEuSPyCsldJoZTGCQ9HG9UQLQTgblZTwokU/j
hIATxoPA5VQ4kS6qLFqpQCkjxyLHCvIrJukfjwbZFYoAmAyhJOhe0X9BABUJ
jDkOYcEkr8QWRYzdAvO6QlGRVdjNOk88FBEKOCCSoIhLHBCsHrCFPWYcBejz
QJJDlJJK7khFcZQlKHMlFWGHNBW9pQLdoGerrpYiJCfKn+uvy7h3nmYoeKVS
o2c+7iYgRQDp42JwBcZSmF7hgJkfNwwP5QfKntGI+ijPgzyMkkxugV4oOStQ
JOFesnxASh8WE+UhrBeiACzWwuwJLQUDbFSVgrD2FcUrGdp7M9S7U+0lnkLw
tqJNmUGCpjDAvQT6SyRg3UkvszQBh6qA4MBIAhlPIo1w79rxBROERWRedVGO
umvrlesauq21xJ+IiM4Ih/0xjaKmGgbBnt6uyT9hHnJMChlGzTwPkV0NQGoR
WcUp4K0sdgM03/cusiRiaYdSG7GndpcCWFEHGlq5ukYmgFmjHam3Pg7nTKn1
8Aa5vyELW++kHl5Cj4AURMAwI6UFTBfgy0T4sOZRNmK536+vhbUS2IsLG3Vm
F1OISIldpS28+e2EjC4wSKCvEogFhmPhUIsBicQxKhWlXmkYNBtXyT9DNUrb
EOoNElKwkR5xhJcJ7GBFkITWM4uifUqeO2deE96oJAbQtkE+gB1naTcDEjEq
f1u840c4E6BDWFS5NXAs2HuFknDHACJggv0rlDGKc0vlh1T5EFlXH57izMix
BUSO8MJuNmbmJz9HOo9z+qc9S1RpwTzlueDuCbsJWQa864rxEHtiqg5Z5xtm
EVApER+gNCxIydaTJMZBI8BVKxy0AsxxCpuO9g8KOHyiQGtOTpAYtymvBKnQ
DA677SatCJiGNONFTYlM66v0LiVdmGn6PARuMuDtkme0fAoN6yjvRjBvsnaR
oIqrIWrNSQ/n5HRV8IgtlZWYstDWv/hJEscxcfFHhJVSABNAcTXKinDgQzvb
ysLo65KdR6y4p7V9B58PWijeiJCyKcZCmxQv5uKJ2ib4SWbIU+v3sJZIR2hF
ocHLn8LDKOuN2QTtjstA8na5c4m1h/wXOofYtlFc0Qif//X+5f7TJzs7YIXJ
TYhfgjX2v45aB23yvBa9ZNjimbaI7FA0oZ9W8bnC9lqQTiHJHX0cYLaMgqz7
d6AUZVsm2oQs9Jdm2iQmFGg0evMkyy2uCt+AXkf9627tXuXYUPdg5gLmGzJa
3K3VgcHWFsEZCAVStoQ0cXAVLe5BwgiVVyA6IFDFDpI4R5MHl9G2MtQ2S7CF
UhLVUqJHmUjvLIM9kyjq/3QFgudqkIUR7NoutEHdVjIipH9Huh6V2BBtflzP
NGL1F+1/6Sq5REVF9RjQvqWVH+Ux7q0oRg9uwTsxYo8VKw1qDG1lR0y25Fzz
xf/7eTIIv4VV+aZmK6Hh8555BYFoNAddEJ+tBf3sDhNsPnGyf/SmeUifa2af
azW2Wp/FCbB2kNuTQVQmsl/mA3GYRqNy9ok0o2ri2wmjcEA46/qz+Zv/+bOF
i315hiM+/9put9Fgg/+0P7d/ZbsXtyF+CI8E7Ef5zwNsaaFT/Et97J/5byWE
7VHVRnGqWfTnP7fbo3G3U4y7OIo/V0E24ILewBYuPKOo4uIW6Jz6m3FR30pe
ckA2DDnYZgUx2061nAdhDvJBug9egEnYE3vwBExtUoPRbXB9jd+A1CjOUSMY
F47AW2dVCgmg7gRXHPKnvdevHq2D2ePYWfD4+JEU+4pd/3TwiK0Kt48a6ECB
ptY2UGSJjtmLinLrrXGXxUigypUlwkDr/1JkgtF6ngBSQHaN0SPsU0yNoteu
iQUU16r/hISV1v/DCGRaggcKpN5H2TCkk5CQlIZAyZCYPQUF4Q02DaCJu4Ed
GCv1oRnbWtiwXl9zDgZVneUyKc6lPJ7i41AHN8rukDNATVeZmFr9bAd7difa
AYI9SZwrroIKjTYM1JmK8VQH022DysAUapE6zBlJmQXQCSKWOiNpbx+rSI5i
emY76jRGVQSdC1esBHyMr9D9DyJ8DU2otXX+r3j7jv79/vA/fjt6f3iA/z75
y97r1/of/EUAf7z77bV8j/8yLfffvXlz+PaAG8NTUXn0Zu8/12jLBGvvjk+P
3r3de73Gc7e0RNoDrClodQB1nsI5AxIv9o+DzR2pGW5tbj6HPc5/PNt8imri
JShxvD/p7Ib/JL8ckE8c5kTegwHoo3TAwQdWyCVSga5GxJ7DTQib7y7QLIov
g5rjwnhK0EsISgs7SNbtQwHlC0nHwy6QPLrCkGkFllqqTwCKZJigNzDs5Rmy
B3PcdGgdVxDm8HNQ6yOabHCZw4jlyRlrv7yXpGYIelSkTFZzApOhHapHgVq/
8Q64KqyjOa/bW6YgR0MhtnBU6RnY3ZuPxJE6qcZW2szE88JQujUts5PcQtB0
Vx750UM6XOjGgbGRpZWi+XPcPmvj9h3GYUpYQRXpkbQuLcuSJqIcCiXaXmCq
wV5yhiAtAK08s4GCxrVR0PUR8CiEvQwdBho8YLYdbDXPu2IZ80yV/iCnqk/I
5AoEavFbaTwG9juwVoMpnO0VbayE+nwTxlZt7FBbZtzQ2mVg0YE83yJ6HCM/
ZCXewn5g4x3QdHLwkme27m5X21CjEBn4f7DPHA2+psQYtUcqvU16iv6Ql6/y
YU2t+NnTUlwn0Q39Yb77tdad50DE1qM+MxGYU5BZdKYWHkVCi/JqNh0L3Uh8
xDLDeOj7wwulhdn6LC7VbPOlx+zJmYZZC74DojpEW4sDDg+kq/Q4ybNiouYC
eBkd/7yTh71AjVvuW+uYBQRvHyzpOFr3H6sGyuMHNIlSewKHk+wgASuz+jqg
c3Dn6xEvYIKOoIxO8AuYzRj4cCiPouCplN4aeAE6ZYFjYI0Iz7MiZIqFHWhi
bykW6MYxGARHlmNaTWaSz2HdZnXoD4R2hD609QPmeRTo0gPRY/Y6AVSKkfg9
Zk7Ib5HFFuKhMVkftkGhDPMyUCfHBpcMfh2VU+LMRQYiA7XfML8yJ7cOJyY3
JcaXBCG5SIjDIWYMe0VdIctKVExHHEhXVXPtWJQArPGQ4k+cQxr6pEoHYUEu
TT6SsE90EhIodO6+NxgATeGRt+WG6WXjAfneM5AxUvo7ziI8UaBgD5SbEiEB
zCBLzwbkwwOFUftMtHLpuMHoZGeK/4tmhXgg/qkOwnvn8TCk5addA4/jAcw6
kocnZciaEawNr0xYgpzsjnGvobCRJyNSfigdAnHHBPo+PpNWAn4CmhJiNbce
ss+LBHPtSEKSnrvA5BoiX1KQx4NQn6QqwpLaRLvStfQ0JjVRHKbBrD5q2s8+
CPbIAzVCTZ81V7VjWgCWHpht7eCmYCXdvPQPC/5bkmKP/A/RqLWhoTpWUl0H
pROjQkZdTaGgjW1zkygjtDPD0KMJSENRNFKNpgJkKb2j1gGCsFhcYGke5pg5
S2N5LFf5XFGZMdPMxg7U2SryMISJIM2IkJiUNemqLqKuugT1BWmb2RfSPJ+u
1ghe4gMMLLRNXRtwEOw5RCQs4VRO1L7VUrK6zceVSmWUNgY7AZzNhbtBnfWa
CDsSShwBqfh1oDk9aeHwqoWuxOoOVpq1pWpCDwxPH3AJjEpwIwHVsjOzOK5G
5F0/UB/AkxtCkrUZxmxH8QogNLIX8IS2NxizBxz6QUqoUBBGSFmc1BarNrYn
acPsjwlc24VkFg3BUbrLGg0zTmo0H2jmavMP2ou48usyHBHP+M/RVol0hFV1
9yHR1bBZ4UkY32hFQYZnaYahfrVhBp69qfBAMqUaECKnTLETFjA81wjYgyTU
eYFlyb5ErYitWbKa6RgkjKKcghqUVnXFdCMPJIPeeYi8Lc4pSpH8XYPY/hq2
JdvehDaGxg4E96MwAJqhE2xJumlETjhEZC1Q1DpRtE7JsWUaX1rhC4laN3ys
uJBQh1492HaljMpQNqGKxBuPMHqXHtGxMIvpyhlHS1i7I3BVbPrXr6IrY5CN
It4i5Kqp+1txxHbF+mgpROq2jtaelRQvy2q7tmHe8KRRad9TDhXilLIBaiV1
8jIatLaC4yEw2UiqwYE1b22k9y36CcUazHxNkLhc4+msyS8BicFnsad32mc8
liHkYFqGY69I50rVDrKsGceHbv2v+6+pv88woq7uCEZwSv8rtd7PFO3F/yb9
AVbQIMtSyHBEn1W8/SyAeEV9sD6rZYXPrVWVQWoEgkyxS9R8WxRUwSjHbZZW
9HWpBKg1NW4t1a+UxTAvJDojFBCqWr0FACNQQ7wG9jvSumvbW05PqYxhJE+m
acOyq9Xe5widmwSBopgqzF21WdZAJ3hHH6/timtousaR2BwELp/BU/hMbSL9
kD/OUezG1kN4zEKQAmzgxRqK6t44J0c9KDUYMIJuIczrobbrpiUGdmET9kLa
b8ZpgmNc68KkO6Ae2O+yLjJgVDPgiz7YbrH1En2ODa8UWoAtOBMQTDzuI8QC
s/mjAxzI5tb2zuMnT5+18B8t91/Pw24PtJ0da5AEwJUPc8CxwNwE1X/xf/F/
b4IbiwvGnyp80CIH5odDix86RILkraMg0BOAi2XpDtKNJl2NFW0iMCEZYG8P
MFGMjmUGbF5Xgyw4BGbAcs/yVFKkleOyKkADo/S1bFTcSOPNNonzuK7cuzpS
RfNa50CaQEfaoQpnO0yUi+RfpIek5nCh2Zyj1z5VySaBbRwQD8BEBKmjxrnH
dyKO+tqGR5tPJ0ag5W3rSPGnuEeem8owtNuCnAKR8Vfok6shatuAZONikBZz
CfsQDzguU6ONmbEUylw4NmwNLWRS55iGmgxmpbY2e6PUoUSZBXREgNkUdEBw
EQ7GfD4IcxhKm5Qdi9Cz9DBSv9qx1KtaIAZ8nOKEkZHmGK4k/wCbAjgJnp3Y
cS/cFfkkoSf2TboTpGERyNgAjKVtkccq+NYMpK3A8VGINBUzGYmtPG8y76jj
yTuSg9r3EgglhbqbJAhQd23IN/GTWZeyMyR5ceCoRVwqVOjMiudTiGfCSko/
4Lb4HbMlLLgCd62jsDtHHwQbI5/HaAxYMJ2YOttlhvTL5IvYtFqE/VKi2Lgb
0a/Uy5AHUlz4nnvsAvogusZMFO2kqakx4JlX7bvA+k6yO8rP4uMaNDuZL4Rp
6QS7DseDMkEOXXXrEmuUwfmmG2/fot638e3BAALkciqJsIMnCx3ePR0beXqP
ySVkbGrmwTQS+FBkeb/WK74ogV0XasnfGSJApUhRQD2YFcOZOZ7ZHmEaSZuM
XLVZSZyMIFlfEWH4KEFRQaGDIhgaeZyJ0/LMgGP2BngC6VKXYos2LyIS1YZB
VeVy+dbkb0mS0XdEJnUmF5jMiDFlN+H8MTfDEjKOg4HPyggkzVB1XTMm+dsr
zS8mbwLFL43X9fqBccHeoAKq34QUhF46qkQPuY6S+G68O08tcB26SdkWFZC4
kNk4jWSiBA1eUw8dYXM+vCWGEDA066IzSu84631CRJylhDCiWbbmZHhyDwMw
Um3cqZNu9ruzjTwefHR4nIr7pthlDEmXvQZur9ilfuLMVG5kCrNEx8LR3ts9
e7EZT/LUFcbKSTLG8DBoZL3q0JE6wiN1pPSTWhV/p9JdJgkrBVqOOOsHJkqH
0jbA9miJEyeNlt17kqZ3qy/JwQT6I3onOlGs/62d14GMk5OiFBYNeniRZ2HU
Cwt4YEOHN5Yg5Ra7KpfLTtf5FxTt5m/HIVgw2esYWamKJk4ar/K7cwQMdKbC
b/5yenosj0ueb27uoEt2b5BBlzQffBuAcYTR5cTkfnt/BGtKHVDU1L+fvHur
Tls2H2NoiY575TOSC9gB9LlFXUYbchz6WsFdlwoMdqitA/ewHVRRSeKU5UTx
65hhJCPOZb4Ox5xTDsgQjwHcXOs4z7McSNDMhjxzKmmMpgZiKgmJVMSaJTs6
fy/AmoRxfurFo1Kl6ZAS7fGM07Kg/w01b/zOgprH/QEZ1JKll1KaS5U8kLaN
iV2g7HT/oMAu/pkG1rZIor49YqlQTnzNyVEpRhaTiYDxU+InGTf0fAdW+hEN
incWiIAB2FS50iXjBL0HtLne/MfpKfzn97h7nmUf+V9F1vsYl0zFIdj3PNxX
FLY94HMdGhwRp6bhpBLYhOc6fCTB4SV04pVcSM/sC6QLIFcOqVN/CRXBZc7v
BFBMfoWefvZOFzqj5c3ef1IIFMYeRlEiEyMC6sw56YIPGIihNNtOlUHutMSS
QNuCJD1uxwCHRbv1t/eveaMOs6KUCeR4Qp4g35BCao0qJaxZ/nf0fqJyI4Ph
AiyzIcMt0Z8Iw4ZB05h59bafP3uC2xwGQIHk1gdaf8dkk8rZKlBGB83ddmA5
o3cD7XyRBRzkCyrdgJ931oLghWI6fAhOG/DDxxS1IZy7JKonm4+BfaCfGJop
ji0P+DE/TK/AAPMgLmSJDBkhhod5yh3luDt3xfQhXmziKPWOee+eMrpHpY4u
SO5nwtzPouOehREkHX5qzgUdjker5D03QsmIgFlAObA7DKj6VIGxJmJbYSAI
86uaBwNVCmSv6CogRZP2rSetwj7ndSK+Aor4sooMYPwXKa9dzdzYa4Pv+kle
lGaX2NFhoMTOR1iwamgvrDG/KIBaUVz4QHMUhjLhq1Ef2j2ByKBzGO0sSO0I
YI6SY7rkTDlzUNBiron/YBlGj5SaQyOU0WGVQ1HtQLppywIYeJZhsUAZgzCg
41eQxBcJkH9mPF38fp2jPlUwTNB02lr1F6FzTXu8AD3Vs8BJB/C3CaqRUq0e
UxBYR7RWVA0ZHCoqUx5Zm8MiW+w6R+bnjgatqNEYnrBBq9EDkt9YWqxz6F0/
1D1+B4KElKTA8UMqwutmEWUgn5cW03fU5FrnQT8ue+cq06vW46tD2SF6JaL+
exVk2W7Y8tXFVlbUFkU2G1FF4ad7assfHej0SCWzVK6jY7NK/0RXOWoIrRjQ
KdfYJGn5l0lUVsliQzSfB6q0wtFBgLFD9Zij3OpaldaxOVdY413tQOnWirE5
oSIUTuOGs6oUsfE4QSFkn43xIdKtzsfcs7EFzsfwSCuJHNDqWAtHTH/P4tIX
fKTFiIAHykd/4KQzGuSO63IB3fZHkTI8LbS5ocuSjSb0pUnUw6BzvTfQwrFD
V5zTS73QFKlFKQk5bCwu6aOiACJWqLgeUWDy+9YFqx1kK0hx4ESWGOtASwpO
AjOsUO87zxZzfe+14BxSyvLYjo+WGzqwN7RKTUG2ICVyl/cLhnUIqX+qOA46
GoetXIwoqwWLZGA3VH4vIeTmFqc4lbvO3UbcybHlDpeGM2BeurrZP4/lhgw8
GeHZZ1uENeigIsaXdJzs2zgLHCqb7WOFFKutwxOBfz3o6BPJDmII9fKw7Fjn
j50yHtLyY1UD3kQo0kGiT9hFPgmpdAncRg8oNlAmTAs8DXO80jIHFt/L8L4K
QGUEF1dp7zzPUqqJwekkOsCLTBGsQWK8X9ITbQGSoozMMGVNqxRZNn0TU2Ao
7GYXrOOw/0M7edZBzwlHieWK0/WglBEWaMcZIpjTotYlxY2N5LIPkawDKO3A
qmxHCg4qWWuTTlPn6EAiEtYu5Tli5+MiQKNXbG1sSF8tx4JVDDgaHGYXsZiU
J14ytkwNLCnZ+mSDkiuKIKPTypLsFyW7XAaNJZV6chaTdhrIY4sslaPUYlUr
F0d9Kv4yGHTD3kcyJi9DHddD/7Y0RKulldtnH3xwTQo+hNTKnQbPfCvQPhZJ
BHodNZq0u7u+xJbf2zFQuIKCBHxO4Uh//N+WTBBuHR38IdglpVP4rFxui9nX
MXSIVXBATmAkNTq/dCfG2x7yigQSyUQKsDRIDe/+T5s2Yz9MBmPi4nZraajz
DreoSYPY+fQJ2enjT5/WZf6RbMZuiJT9Ufw5u6/CAlYbZjKI+FzAfKC5MYUN
AuvIkdO7H9SNDXp9Di3xxIUsjpeVqaC1fGhcyWFtrjpWg8IzCOA+dLe2KzY3
NjYwwGCNx43BBK/YQSyHNcQg6bN4zYkKUPArMQHVbqvRNKZjXHwLcTI5PqIM
QukDv+IKC/TVOhfRKLyoIcTd3FAPchZMW+fjYZi28FiYj1ft+WD2m89twLmy
HAxXOXiijCpWddz4yobI6sAJC42qsbJ8ese8rBq16sSrisAOrG4w66QP2Tqj
8cefzzODtg1uLFnxHz7X5R+Wc3O9tk5g155IZ/nT9iZ24E+VeqCD63l88Fy6
X4I3cXmeRbviD7LfPI6VPwIwEnTE0K6GU8wyUfQWMd97AeYfewmcZjAJ8iuz
83BdJy9K9qm0XKJJ1jjIRtMze2/2obNP/fuTlUrcij4vio6XstUcJ+LK2qq4
OBjEAwjDvqobVlODRnXj3pWDUpaCsRMlDsps1EIv2wBhnZ7LWAk9QlWjuRJv
j5CTSEM1Zoe19uxkpqI35nFh0QTK4RlIAmAUFSC2XV9NY5hj1f4bJmeC3BZb
OwzA+ltt/UCdgJH7lvCshpn7vIT+Td2wgJ1rHvGNfyVTh2onrOOx8ZkIwgSD
3V0iFpR9TKd3cd4DZaaljmFQpWPbxOUEpzaOOJIddVrmmTOym8DPb9gPgzpa
E8oPDl8fnh7OhXUG+B0g/uuwYBisb/9GvEz3nQH/xtH7TVL5t/k2MEP7dknp
+1YWxiMfocr8jftNqJNT0uZXkmdQ24Mmtd1OM1P9sZcjlscrErY4OmhzAfuj
Awxnkk4iffKlEnfkt2ripiae84GVrFnfT4739bQKO3FSsy21/YmjtHsL0VXV
9xrmJivx6hy0c63+1UqiGt+wtPr6yszANCzYuxUyqg+3vs1VqE8oBtJnIKMu
TG53bVAqPFNRixA1Oy/LpYdXeV/oEIpiElV2OId18Uh1CVA5qeE/ynKfXFW7
5I8YjjDuhvcSDSyK06yMJ4wSB8W5KBj2ofxeUw1UihmhQBE5ihd59jHOd62k
FpVaLs+IoG/qoUsf2tEYVIJUR9rI99S5ii/jKB/35gRiFS0MR+DlxLgEiSWr
H/kVWLA5X2ZCRx3yL3LFmtqpVgmpOoQRmI18dQ2fUfNf80DgP/b39uO8ZCj7
e6KH3vu+rFFfG734Sbn0HkkgvXFRZsPTbJT0GAY/QMbK+UHNKMNjOvbJ21Bb
4pLjfJqXLlSfkCgMTawZVmzmi17ymHx4oQoX5yMTk3jg4AiHJiHKZTw1T6gP
yeg1gzLUUZmSOiguKJi0QhEWRPlKxsXRVUmNVKqC5/hkGyGbVZUgJR61l/LU
aoaOWOMivLKnzg56h+4llCQ36d9q2JJVy6HzX9Opx21dX2oO5Jqy2PxR03Lf
arUZJK/3qf1ouQtuYC5xyWXw2x0vuhz6rZfdaW8vfFWVNIKm4hsmgQbq5H9T
5zpLj57fWsvEx3Q02emDxnUQlxRetKZzzv5GLmgjyDBt7sbvxsKPWEDldR2V
FswCczNh3tIX6FfwLGnIXPh+YYkFrUmtBOrHXvFV2+pyd/PZs22ZP7imBB5+
iP9Wz5UYw+f63/KdJWnwNf/ZITlDn0xYI0bbpDWSk7hxLJ6jvnXSs64OPK0D
m64K9uiFA6Ug28uqNFFlsE7UQ2tm62xqqDZfv7ASKk6o/kBRm7R1Zib179rA
OB3yvXVitDiqLcfeJDTX3XuzoZndfPWpzOcomBPdjntuPnz4VyGor4LtnpuE
OK+TbjbcaWfd94g+O2sC+xnlyRALOVE1bzk4U3ycK67Gn7DU/VmsVAhKBXTK
lK5jXKyOHcRjQ4osx3RS5aPQeogqPKnT9N2irW0rFJT9DHism3CuMl3UsS3k
NZlJLC9woI+djNhd23Pg91SQ9x+vSGNuJwO9ZMUBObi2hm5yUWcA3ZCfGpDi
4klR1b1YOWozdONJTIMeJgGdkvhW75POjqd2K6bnw7l4XdcV73IFpl2p56NK
fVhbThG5ru1lgnHlEWvBhKOzo2VUF62zhQZTSMqJRg19/jWqk6XT1LT2wUN3
G/Abx2kVxZRMYYUvW+np4qekHbeFFVy1LpQewxV+oz6P+pGuQlEJaDFzcKpN
Hx1oXczySl1fT/RD6fhga4Q6SFiH75kbMM8GWReYBnkCvHWNgnrUgfKK7TQf
ZatR2OAVE6QsXhVraPM7J7gY6CHQRdDY3+ArKqNqTxjnjo7Fof6Mw5Hv0HNG
pMiz6u1mE4jGKf2wZAVyMUcnHcUUWHA41ww+Vj/nsriWkDCcuHeTVOpkdktp
Ym53wfhmXaQgIlhJYbeQNGF9VC1RQbWedPKmylEfgNbDEVsGFtV6RHlxxUmG
KnY6KbRkYcd/UstAxjVKAucqKFU7iS6FkFFqUmf4nSobhFzboOZPpTRsFZDY
uVb/qqkGBKVQYHTdLpmvZ+L+PcqARwfgT620il1FrAwQwHNBBgwQr7tUaQzc
pHtVxsr8xiaYR5WklK3zZIeT2ihQtel8hLvRHfuPS5JorrorayNTsWZ2o66c
GnTKwGnyCDl69dd/Rnu//OI7jbnMfacxDZOtnsV4T0zMmpnpqa/MunFxgUIv
BXoOW2rM6nO5ZrpAyaR1MyF4xJlUFDkWJVDJm/hBbFJA2+IYb72y6rFeX0sY
NzeBe2lPtak6j8Cy4bUNQxbJrPsFYZjtQsc7d7xhqJIJdjTpMDCMvj9ax7rH
vigl31zvgNQN3qdTOn17X8icBYNW8Lj2TdXR4dC7VyhYRXMy644wy865JbXX
GD+fmYd5Hl7JGu6WJcUqgbn9UpVFsysmpta2VnRCRiQ1pquhFTYMcHd7mOd1
R95dbgXqwLMdyM23fnfjOB8PkygBWPVBxDiIF3oQ6Gv0xgUMcTzewIAGjDve
vWqU8lK51moZ51jGCfEdnkVclOXi0kiPunfHa57KQ4hqO58M+IbN/9W0imZu
W9cufCqFYrakUCyZ3f4HlTWwGgSuwsE5dqG+TzjSAQ0uJ0YhN29A0mr/3vH+
xUXx7uDcIcuvsH9xAPd881YdoTN4KuYq1LdMpwXVy1mOz4KyzILl+SyweMxU
lwW6mxhVFFNpe56coECY1h/KZfiHSlTEhHarFkQDmfpKXXBlrQurdh2voCw8
Vf1cJH2ZB1gtwh/Q/byDK7vgv1PUex3bUjBR/UME+OL14TrXGZhvOKWDuFQE
YXSBm63g/Dt+xfewqEWRWWv0qk1ne74TmrojOimcnuy4I3gf8En7ujsicgzK
K5HpSm4TssQhSMrHLUeDy8kv2AfHjRw3bG2gRwfqLpd+iOmugc6VdqGrdFM9
vLKIB33/KumC/VYvOKQ/ZpNWf4ig0lchgj+88qA0Yb0kEcgLbz81R/1JcQwM
CsMG/lgnUmFMyU2mRas+9fuzdSD3a+fPGi3wbxQQHyh2Js4/lNkH6OMDjfTX
wLSfZarVkToCrWn8qo77Xn0xqSCnddEf0x1P1NAA/40F6EsuKI/nIURVgIyo
F+aRvJDFAvSHntfPtoDvPPiDHOgqcBG5oTysUdTzh/X5HyYTn/dO6IbU2YWM
KWrE2Sjr9Rg84NvjwtTPsbYGOv2B66qih6lPnvg9u/RR55r+U/NRMaDC3FBB
vKVyS/ocKqSPr+oI2F1rD2j5WGP3eGSgDhRkar46zsHmYbfIBphtjTGbOuZG
ColgBiFxt1rp3UTy1JU5Rp5Pm4td2vBqcPMun5yWDrW7MHG+qshxHH0dm+rA
r1t5oiGm7wYJa57twD6p+fDZsB+klvhlN8T3sh8k8ryZUhUK+QI7Qnb5lbYE
BlbxgGSFC5+LYeJGeMVVKJR2aF9h9CV3xFl1GKu9cZu9AWikrprSgG1a+TL7
A8tnJl9zexjC1n4PVSe1aa9M3yO2M85cajl1t8yJXK+TzmygZhedyjny7qs5
ne1NgcxzboEvEfzs3xBeRxjipUIPU7bFJFfY5K1Rd43ZOWHkFvuKu6QWPDeD
v6s5NE5FhVmXCizm3apE5ASLeLfciJxgQe+WCcgJJgTkHJuKULKAqO/MVV6N
cM3/rQnpGpBFZTMfr/YYOolPvSRybb0HsnOH4viyFpNCV6CyCk3LpMQJ3rLA
qrljbuugq0h5YO3KOS/rMnKWDk+bKdJAocRlHPy0kpJwBxqD7GcRXsl7ugO7
JS+bJ+jjjnLqtz0UkGPXqlnPSosOC1Ou9V6wu6kXaizADauBwoHlXJ0cJewE
13J7q7acYmyWu35dFJnL4fQlgha7lDfwWHezyE7c23/s21X8rqbaXS5VluWF
NDt/8nEf60aFnJLaTaVbel+5W0xefMilAuV1AtAJedyBzaSZ+znWdaDSm3HE
+oq8ho0vaKAadolFu9KMpzdcXUcfDVgHX1j9lFNfzZUPFkba4p2uxbfu6VAW
Px8kw4RvfCZYFnwr6hnnyJcR6mnpkoMcCC7hK65NsFRfsebDob5wUiosbRO4
qycsv+2O6c4NinoH0s2zwpbXBdEkjovvyi0yUze9h5e5InfXS9gWHvZdvZsJ
ub2RehpPzmmjy3eRUvjgeHtd/X31Rmp+e8f4oszHsYc9YtdVxmiGU+WJqh+5
JMz5ZA17yhWh14hXXbLSOgGMspgu96ZFoZQrRGrLM1znoicLWh5LJTNJ+3nI
5yfMV7GQNUDV2m5ICV2CTgGI5+RhlGRSG+UrkvF41mxGUp7wtiygmzVE1hof
2JobV2yQimhpgKhTyam3qay4nryTEUcFpwfJx9jZVb6bUa1ixXhhWO1KI4eI
ZWkDXo9LWXJcQdJlrgOzB3waBN0cW70i7E5oUMU61C6LrFwTqS6INEaZbZjZ
X9zm6kd13ePftNWGezWOqhdb8uOjaBAfj/MzHN/2Ey4USW/DcZlxEqQ1O55M
lqJqSOoXH90ZE86XLYq4H+U1HaW6JPoKKWdJLG6kd6zilvJKYPt2V3nmYTBc
tdw0D1Wcl8+Bk1xolHNKksKaMFcUQOe4UdlQUXDU3cd4NTK1oD3DbKBboBBM
9a1YxbpJBqKryIzuUZcdnCVFW1nloptx4bKNaNn0/jgHzYaS+FlY9nCQuhI8
3j+CwRp4BxRAlWoEQqDwjRYw+qFiF/qUHMeoL9oitYjz64gLKgRw3U6bXFRt
TWKgcXmZ5R9NyKdBnL7wCNvbPYmf4P+7V+pc+BHf0iuJTgG/ysYUwwqoylXZ
ZPmNGJK+g0jvJ2d0iywVMcd+srSbgVLq1s93TIETzpfVSqfWKoSHW6mi/5q8
LF7kXhBaE/W1DB/n+hYurU6qjr493aZirauYZZAVdwH6OE8DU+jBakb3yqpr
ZatNhK9JoO7ozeQVTdZl2DA61TulCfG+tzSvgjlGy2wtzaSci7vd624Liw9S
KRT9tmcB4Hf9QXjmfu/ANl0cmGlU3zIkM0/oxFTBteao+BdynRPFXurVB5YU
L9ckQ5S8sK5RXuS64cpVw65EEtWLjW99L3HlfmNatkpX9AL9OZWP5dXM8Zrz
9G8ViBaZeuBe19Z8zV7v21yvjL8bd0iB7416yk/+NkFE+uz4nm0xeWz5qca8
kDF+mpycXb6nGAPStKZza5cjgMpG/zoHAbrUg3V56gQ/XLNZKwFJUS33MSZX
ylIhUmF+idc51GUyXUJkX1izLsbpAMWFZucGjdUy38qQknUVFrOlV7byd2cr
p0pFMlBr2Szfp2kx0XwYj3yGfJ1+agzyrs2Ee2ol/KBGwkqHX4YOv1JmV8os
DWkBZZYZ9kqdnRwJKXGhks1rZzVOKORUtbYZ4Fxq5h0diPqDAJuoxFyofasD
zK8WqFRL1fAGKE1dSi+oinmiBBz5tfjhT8WjICk6fNc9tUbrRMq9QmsOQ2nq
WIEbYB+EFzArDINs64uHCLQu1JPw6YaGPK/9csfZhSsBY55+/wIGqRC3xRQR
MykcbLqkWUjQ3A8p49QSklk49fCICdEBunIK0dRtiww19ryYB2T+skKCE6TV
muqiLK49oLijvkPac6ToluaZFps077ngLVjF7ZnNRNub5ukrCOEi4O6jqb5L
pN5h0adbl3Cq8T1TSWfaNvnaxZ8W4nAoS29dFeqOONxyeJVTWunWDsX7s31w
Pj6W5MxzxZFug9K7q8x1u0Jb3xgzepFnYdQLi9nDL7uqRZX1GFDAccKrAfzl
nqUswluwdkKNTeih3Jkxdk3kR1/1rnr0aA355kCWj9MjOE2ohP22urdWvzjC
tHcgJXj5WL6TyEFYe2eH4d5Z9ublxfM3ey/2/tI7f/6iOPh4FjfEh3fNcrkk
r1/copjK/LSK6yqvRuaSFEKYRqZMK7v1CW96G+kJ0PN1dVu8wirGBoKROIpD
jNBqVTGswJTwB+6+IRYqLeIe3UulRtm1aTofpy4cvSATYXXj8jIGdYNOKXRb
xphcvgpnoFmbrqeUCKU0E3M1dVSo2t902TNfEO3c+UwFatQ1SrQF6OzSlMpv
fwUGIsvW8DFmNxkkyMboGRbwkI/5UrnyMhOX4RVsfIFYPK6Vx34bX/pDKwlO
xF1xICSfQiDR4ZKn0DDliumqPZ1zIXbNNfG7lb91Jo3nKnEK+YTVS3pc8loI
lU9AsfFY7YGi4YH4MRsO0WPCasnr5RRdF5gCcFw79C1gwWpFnNUMAAE3N+s8
aX0oq7Ci0aQOcwK3PlalDHybbH4koP9KzrpxTMf8qhCE5KoybUBBDlRX7jpi
9BptV41oOkJOs/oKqCPowClfoxeRU2iK3nk8DOXpW1tVzXeOPZ1zSCYF+4YA
WPxAt5A3W7cNshUMlT6lAYSFvLAMJdFnsVeWsAiYyis+gw79D/hfIU7xru/P
xuejeG3T73Pwc8v6/Wz9r/2P6b/PMKKu6QiGcIr/K+8I+mxdkER4gNVt+eKW
cUSfxT95zWcBxOThg4WAANUKr9MAWZ+60AAQhqjBe1w0WA0lx/YiCnCssgWK
VpMBIqnNILi39fpWsBFgR0yg97cK3Cato723e1YdIrlrKzzj+kE4SszfMLaO
/ksmj6s/7eSdPh2wWkxSyWH8RotAGoGdrWN1DAAugHCz3KDTvG0Hh26vlIWj
+RvJKM3M9Hkwjw9z4bJhVxZzH9IFiz6GaF8IwPdNDLCNHVGveaCqIh/ojKRh
+NEtPkY5zJ9GeDu7rMcPYhdmSDf8YV+pSalsIwGM8iTtUSoBDPNKpSfBytKd
Vjy9/jjtcbQOoBjjiqhw0btRnCIorl9/fY1IsJbwBhYf1mgdOIc4Dy9ijZ9Q
9IHglNIZ2Oh2V9q9YosiFUDpoNKwZsrrmGFxTmwnyYeXoS4rWawHsLjMVbvj
wUcbTTo7wg7fso14LihFXQa+PssqRaqLE+ngPQQ9Y0vsgQIxoiN91jYCo24A
ZLm2fJmYYbtYGAFLbZ3HvY+VNHUny4SrbDW8VFMjKCwfrCQxXTvMHn+gR0BZ
t/pKBhlA5WlRm3FVswro1MgdGMWaISfB6+lBfv7u/QT3CV5nI4upzdD79sa2
OAFm/I6W21bvpPYXLAnjeHZnxiqvyJgXL6pr0H3GoblYF8D14mZsWHphngN1
/gVICdeUGH+Mj87lkxu5kegz7LJQQSrmhhpJIqTKchkuzQBLHbum7pCQH9kA
81heX8KKtTW/yvUdeHvE883NDXVZhw1EGRa2Eli7Ogc/0HegBu41OqCNboJl
2NrceP5c/PSKx/lImsyDK8VGqYwM9luoU1DcCxy8NwadKU/+GXLeZZKCBQP2
nDTCkpjCZGDPKhxIJR61T+x8EzvfxM51rCDOAoZAi4R4GoQcwmiMPErMx85/
QmcHH6g8kgC3EOAWAjRFK73QYlPTkkBxNaeOLGGjwG0juG0Eh8rMiVxiA9Be
dFRmLSZHYA227GTUMAX5N9Q3vlQD0WTfO9j3DvYt9Z/J3Usd2oxAgnmMYB7T
FLQR2IgVbSfqS2MZyBME8oTQ6oh0P2qdT6RYMvqBRcAc1+vEgZVEbST7SAPm
zbqPvOizsPw6jdquUXvFPhP7lU8l/uwotrPrwNM+R40U95QehNxVeIFV77xF
pfU0BmR5PCLp6vfeQSPoTQ16z9JySO2Qm1FeKcpxDVZ0QiNwCXlLQz6S+9jc
LYRVPfjWM0rQTB9iREkvO0uhO+oDvvHAl5C3a5Dx6h6UHQC3cv8QzqRPet5M
6NjRoN9pto+Z9Qgm/hT3xqRDJEo2jHKYUjYuLCEhHQimLwn5sYZsXbkk62RY
6rCH8KYMetMiD833cLwIO+xOMuXci4N8oDfrnyJo5JKLgd6yRi3vq5LIUBVa
m0EbZuxFyJY1av6UVm8K2BlBb1U+ZUQ7hV1xC9bKcE4ATZC3LXwc8D5RCNGx
PU2DtqWJF7TBx9vMlh28MXDMcmvOD3rL/tSpQZMMY/R/NKJ6Kuht+1OdQyj3
14TfDKB37E8djEyGPgPox/annrjwph5mAP1Ef6r4nt0FSgHnEAqZ6Gygdyzi
k5J/xpVU3/ugS9CG+NSoZRf6smkc+WBMt06qIc8C+rE1agXauKZpBzb8PgtX
e6kh5IkF+qUyZXPQe7shGCaTfp9FxU1RB20Q8tK1kqdQ32TQ2vBgZUidnGiF
h5xMp1wfAE8UE+ywai6gicPWktGhjBcdbZ5jvt6+c6IrAdNRQz/syaKbI/mB
KRWcqA/WqY47rou5zNN6aapgBxKI80Eb+0awXM1XW009AIXMEbVfVobJyKbL
RANpOPpvcZVXmpLnDTofxsOMPCSIn0waVDRcvjxc+tD2X7x7L02pZ893nquL
+PYPDl4D51ZnCUHwu3S1hPxKtniCxpewzhw4I+ZSqa500HQAnUoEj2TEnCz1
jQez9lWGMFFUAnGkQ9DPQkzvkMjDZBFpsVkFk1WJ96YuqLYjTXGoLjakDpXn
hygivOTrYfH4h86F2JGCjAKIaTiyL6l1s8usgTJcTMgKJJ5YCKmrJ3tZro+N
5DxO9o/ekProlIiTla0CdRyLUyiKrJcoEyIUH1MM/5PupCBgzwQYlINIW+O0
SMp9FY7ehL29KELHCE0uL4pEEVym5xOoXD06Viip5o+Eymc6moysslsmqWaU
DbIzzDg8xPM3hRZKUTvHQahy27xAvfMMZ8vV8MzCWGRToisf6+QhzapKnd2Y
DlMUTajeiCRUl/r60h6wOMn1AU4DjRT6dgT9MbGNEdci53MHbPsCjRQbv0h8
eNZLfwTmk1/Ef/9/td7+FtT3wS90cP2vNMNdpj00jTXh7Yo+kEC5Lv5/EY8y
7lwednI7SWG7At3y6/TMXmvz3EZ9AJyzcIfxE3wC6qQ9uF3xwn0gOh3+as++
QYA+c57o70wZphNiyfRp9SF/zecdbvf/VXvG38J2PeatsSve638Hj4KgOmBG
r46CMdioRrfwG8RLbTIMY+hB6b/SLtoVKbD0ddm2Nrvm5loNhoXPsoGEGIcF
zh1AIkQPChig0jVw6NS9UCqH9SRU52Pymf0Ij8l0NwaLEjxyRximhRgZ0tCL
osENywfkqfJwrZBH44Uqv6hDmG13vHZ7NvHqIIpBEJYsqgl+lIRnaUbKHxgm
0lWKYwkwllwGfeDmWdsV5w83wFLa3IP/3dvY33zy8uXO/sYGWJNPn25tvtzZ
fLGx/Xxr4+mzh+uyWWxio54+7kfx8ydR69mzJ/3WTtjbaIWb0eNW1H/6vP/0
Sfy097wnY6PW9OaEhptPt57uPNvZfr69rgNQHPKxorHgrSED7HR/c/fx/u7G
hvq/TTsBAEkLPmptPbYCqv4WyHIRUht6x0VGYlacpZnl9g+tloSvezRvvGo9
W2zuO9s7T8Ake6r+u/185zH898ldU4dN9y6SnGC9cCd+svO8v9Pa6caPW5ub
8D/Pnj2OWv2433+2+bwX9Z73m/NFGEZvp7fZfxJvTYQxAcuI11d7IFbfWumw
XqTeEa6qzPTWRKVZbT0N3Dfp/Vpqhyxcfd/oqS41XRQZKYGtbYQoWQHPn1jP
LYmBLbasV6iM4bMJuJN2sAnLqBHOg7klRkqZ5E4hTdTu9Dk5By7Zx68ZhfeM
U/w+1rEWdiSNvttJhviwXw+DsDuUamJMKJ1gfRlrs6FarJL1aQoPh39wWD2H
cKsAnyvl5af0+x7ptJXYI+oNLOddIfjkSbL2auS3sRqUGSl+Ql8Gpnn3spG8
dz7hYxs0AB8RtPfSo4cGqXHXuul5AbUxtZU4iNQxNKkZvdxHBSEtW6xGWMuD
5WR/xsBH+oyPqd0P9Mu/gGDfpdPqwXlWUGQYH5tdi3a7jeRCX4FJ39lsb8rD
TnrWk72Xtd418E8tWaWghdGqm/3N3uNw+2kr3trstXbiqNcK4+5G68nj7vPo
6c7TfrzxlLszsdNR/33cbyqrW067lMkwVoVT+qcTICv+/eTdWycEh5ZXrc86
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
lcPx7ch6T+SM8Hqyq+JeX3I7Y+zMnFUrLH3AXJNrpWBM0QNMm1CoKzmdBA4s
pmPu6cX6RLrEhyzRtXcsr0W1bvnEW9gH2KCIY8X5PSJU994oQ71S1CNDFpGk
PjHaKF78pNnIzBrE6beVIaGX6YcSLyt2PB3LX40da5KcdNBUZ8bGMLhzbqxK
qc/IiKuft8W2kFXMsZShrJa1bt1nTK+vYAqwcleqZCFfMKyvA6cKfMAutEVX
N+Nql96vi/4YbKba83qRp3UwEAd4+KW9laouOnnD7FJt7miaJcI+3Q9u7ihc
CYavLRjC9Mq3xSdvT7OA9V2pW7Y7ihphC5GGperStq/C4aBJDVMftWQBvteJ
XzDZvtbvSzLdDyY+xe5Z0urCP1cW0jchks2enyyTl0YhnnjLObypc4pzmVvP
12oIQ5wyzUDdu+ZZe0vIzwZEvPx68pdHaEa2kr9fW/6uhOVKWK6Epfn0Pqzm
9yEsZ0hOuL28tG520FEzU6Sjp8kESXVAo19ZivNKqhVvv0vevmK6d4bmL8d0
6dG06MHbs0YMBbQiFDAqMHYsgCl80tN+XFRMCBWWfnkeqzLleNdKUnQ4To1a
IwvT9yMoe2MozRHrNCfpi/ACsB/S9QpyHRi05u0yHEFDbmbcMPwV115x7a/N
TlYa+Uo43B+NPKgcVLm38N35YVW9zGNqqmbxjcINIGYvHJmKcVq/GONqXY5S
9sFdVjuzPFgyujDKYpY4kl3rjjUM+4KMtvjPbKwC/C7NRYpKFEwJ8/tdX4W4
ElVf8yjKzxsm72sOsqrzg6XtYxUZ9EMFR3zDsXeVqDtPs+VTxErym9+9k/ze
oliVX6N8xqj0OxfPtZKWi0pnz/UL90Y8I0ZVSc4Z5fN7db32Sjx/+ydVK3k6
6zKs5KkfzSt5Su3ukzzl1Lj3Fs+nvDhbCHToOsIZZan/9kNHZMqLDkGw6QSe
qVLR00a5SFHMmaLI61wqs6CLQ+Vtjj4ZpSTqSWUIt+HDMKSflxHODWN5g6he
MdgvvrkA9e/jPigPaW+V+PM1uNlsZeunchc8gsHUVkthLmhpZykD4W/oHODo
ags+ngKjP3E6W+3UqQOq1k7gn6eCguysidpWG/zeb3C/XtG55n02Y9r9VA6g
7lpKxcnBS75JecrW97RYTLfg+8qB4mYwfXnyc5i/3ECllYSAEEnV0v8A70/P
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
ani0Gs+XQOs+99WMVfnBREuTP3FwajA2H1Y1rKUg1ap7dqe1HX2nW5xg0YTW
6ingpKKyPsRenRpNac5qs8si2Brg04r6dftqivbTRttH8r9uo61WPav9UszP
Z7QN6wNvPCF2j0jvftRNyriHWfKL+obn5x6CnVuH97NVA8jvlG8iKYJYp1j8
eTnNUvp54rzwb7vlTMjtqdn8WQhpjfLWNhI5nNc6TZ8aWT0xIkBukUmGQy2c
5f7YDlubJqr/70DMs1sCvDkpLJf0TozCRO00LSjM+voBPjUPbjh8tJ/hIVYt
crOQ5zUiFP34Ui2pDU8GOQaqrzYhX/dMrkrRTdIQrJnuIOuatpNMkkP1UesF
tFncHJk2lFuYJdNB3hPjZPNLGidcgo16aTGgteuzyw/nWVHedOgTbrfxmIuP
XYR5gulPelfJj23XrjzEHWS9cIDvrFfWPF7JbL+/4BfqmhZ1c4lvKwQ1EPoU
lULHKea7wFjnpH/lpHpS1V0ZZd69MuHQuH0wMB0YzhCPrrthkfQYGDTJYBNx
7WAaCExmAJsFL09B4w1TIuyhda6T6KajR9tRMqBzrf5100GKY0RNuwbRM3Pr
eprfiYxDh5BpuKormJWO9Qg8uLeOn+eC1Ra/Y9p873ycfhTjEXESuyFerw2N
kHXqCli86Yo2Bh5UwvAVFzSJB6GTEkUxBkVcQlcya18tBKfvq64QLDSKiyI0
oQcIYRim4RktNXXvQMdwGJnPhqRxEcsI+qSQk6VoCFgFdJnBYK2mqnbAAGMd
oIOI4mmycYlMGIiPYvexywjjLDAZkK6uoAsrWokOidDJNHixD2EJmaeSX7V7
fdTesJzGtdt8nFWWoQNJxFsD4zgkToFpU2biOo8JP0k49ZViIyyfV8PtPvUL
T+7+7E/N31Gip2NB07FGQlHBwtIma8o7wqb4gDvCXKn+dS69dOXy6u7LRa/y
qYej2JGe7Q4y7+bgTjun7TbtjY9BtV1dwmR+t7+EaSriq3mCi5GBWkYnLL/R
SWxpGXw7hCVvDy3tVQh3s08+y9NyZubDPAPRNJvtBgFSFwogqWazq2YmuVZJ
dzz4aOeezmuTQPPl2CQ0kIXNkBqUleWxsjyWZnkgdUkrw0LPLcyMfWRJWLzB
2nlTDIvZmjiKL27Olc57zy5Ld3mnq7XIedSi5ZHupB5Wl7a+zhSgjtXyVirq
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
9cnCAgA=

-->

</rfc>

