<?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 RFC9457 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9457.xml">
<!ENTITY RFC8610 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8610.xml">
<!ENTITY RFC8126 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8126.xml">
]>


<rfc ipr="trust200902" docName="draft-ietf-asdf-nipc-07" 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="June" day="17"/>

    
    
    <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 /devices/{id}/manage/connection action API. When after establishing an
explicit connection to a device, an application calls a NIPC Operation, the
Gateway will leverage the exissting connection and will also not tear the
connection down after the operation completes. The app will have to explicitly
close the connection.</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>paths:</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>For example:</t>

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

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

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

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

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

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

<t>Failure response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

<t><list style="symbols">
  <t>"sdfName" is the reference to the top-level sdfThing or sdfObject 
 in the SDF model</t>
</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/{dataAppId}</spanx></t>

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

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

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

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

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

<t>Method: <spanx style="verb">PUT /devices/{id}/properties/{propertyName}</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>propertyName: the property to write to</t>
</list></t>

<t>Request Body:</t>

<t>the binary data to write to the property (using <spanx style="verb">application/octet-stream</spanx>)</t>

<t>Response:</t>

<t>HTTP status code 204 No Content is returned for successful writes.</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 /devices/{id}/properties/{propertyName}</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>propertyName: the property to read from</t>
</list></t>

<t>Response:</t>

<t>The response will be the binary data read from the property.</t>

<t>If the Accept header is set to <spanx style="verb">application/octet-stream</spanx>, the response body
will contain the raw binary data.</t>

<t>Example of a read property response if the Accept header is set to
<spanx style="verb">application/json</spanx>:</t>

<figure title="Example read property response" anchor="exreresp"><artwork><![CDATA[
{
  "value": "dGVzdA=="
}
]]></artwork></figure>

<t>where-</t>

<t><list style="symbols">
  <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 /devices/{id}/properties</spanx></t>

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

<t>Method: <spanx style="verb">GET /devices/{id}/events/{instanceId}</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>instanceId: the instance ID of the event to query</t>
</list></t>

<t>Response:</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

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

<t>Response:</t>

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Query Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

</section>
</section>
<section anchor="nipc-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 /devices/{id}/manage/connection</spanx></t>

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

<t>where-</t>

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

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

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

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

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

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

<t>Response:</t>

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

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

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Request Body:</t>

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

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

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

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

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

<t>Response:</t>

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

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

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

<t>where-</t>

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

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

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

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

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

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

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

<t>Parameters:</t>

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

<t>Response:</t>

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

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

<t>where-</t>

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

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

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

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

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

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

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

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

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

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

<t>Protocol mappings need to be IANA registered.</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 use URI-based error type identifiers 
as defined in <xref target="RFC9457"/> Problem Details for HTTP APIs. The error codes 
can be generic or specific to the API category. The error codes are 
organized into the following categories:</t>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

BleSubscription = {
  serviceID: text,
  characteristicID: text
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

{
  "sdfName": "https://example.com/thermometer#/sdfThing/thermometer"
}
]]></artwork></figure>
  <vspace blankLines='1'/>
Request Body: JSON object with the SDF model, from <xref target="thermometer-sdf"/></t>
  <t>Read a property from the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
GET /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Fdevice_name
Accept: application/octet-stream
Host: localhost
    
HTTP/1.1 200 OK
content-type: application/octet-stream
    
... (binary data)
]]></artwork></figure>
  </t>
  <t>Write to a property on the BLE device  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
PUT /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Fdevice_name
Content-Type: application/octet-stream
Host: localhost
    
... (binary data)
    
HTTP/1.1 204 No Content
]]></artwork></figure>
  </t>
</list></t>

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

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

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

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

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

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

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

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

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

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

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

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

<t><list style="numbers">
  <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 anchor="well-known-uris"><name>Well-known URIs</name>

</section>
<section anchor="problem-details-for-http-apis"><name>Problem Details for HTTP APIs</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;
&RFC9457;
&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 2128?>

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

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

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

paths:
### NIPC Property APIs
  /devices/{id}/properties/{propertyName}:
    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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: path
        description: the property to write to
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Value'
          application/octet-stream:
            schema:
              type: string
              format: binary
        required: true
      responses:
        '204':
          description: Success, no content
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

    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: The ID of the device. Group ID is not allowed.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: propertyName
        in: path
        description: the property to read from
        required: true
        schema:
          type: string
          example: "https://example.com/heartrate#/sdfObject/thermostat/sdfProperty/temperature"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Value'
            application/octet-stream:
              schema:
                type: string
                format: binary
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

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

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

  /devices/{id}/events:
    get:
      tags:
        - NIPC event APIs
      summary: Get status of events on a device
      description: |-
        Get status of an event or multiple events on a specific device
      operationId: GetEvents
      parameters:
      - name: id
        in: path
        description: The ID of the device.
        required: true
        schema:
          type: string
          format: uuid
          example: 12345678-1234-5678-1234-56789abcdef4
      - name: instanceId
        in: query
        description: Instance ID of the events that need to be filtered
        required: false
        schema:
          type: array
          items:
            type: string
            format: uuid
            example: 12345678-1234-5678-1234-56789abcdef4
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventStatusResponseArray'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/FailureResponse'

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

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


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

    get:
      tags:
        - NIPC registration APIs
      summary: Get all registered SDF model names
      description: |-
        Get all registered SDF model names.
      operationId: getSdfRefs
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  allOf:
                    - $ref: '#/components/schemas/SdfReference'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'


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

    get:
      tags:
        - NIPC registration APIs
      summary: get a registered sdfObject
      description: |-
        Get an sdfObject, including Properties, Events and actions
      operationId: getSdfObject
      parameters:
        - name: sdfName
          in: path
          description: sdfObject name
          required: true
          schema:
            type: string
            example: "https://example.com/heartrate#/sdfObject/healthsensor"
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SdfModel'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

  /registration/data-app/{dataAppId}:
    post:
      tags:
        - NIPC registration APIs
      summary: Register a dataApp
      description: |-
        Register a dataApp that is able to receive device data. 
      operationId: registerDataApp
      parameters:
        - name: dataAppId
          in: 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
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/DataApp'
        default:
          description: Error response
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/FailureResponse'

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

# responses

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

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

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

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

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

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

</section>
<section anchor="protocol-mapping-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.3
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.3
externalDocs:
  description: NIPC IETF draft
  url: https://datatracker.ietf.org/doc/draft-ietf-asdf-nipc/

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## Extension that defines an operation in a bulk API
    Extension-BulkOperation:
      required:
        - method
        - path
      allOf:
        - type: object
          properties:
            method:
              type: string
              enum:
               - POST
               - PUT
               - GET
            path:
              type: string
              enum:
                - /devices/{id}/properties/{propertyName}
                - /devices/{id}/actions/{actionName}
                - /extensions/{id}/properties/{propertyName}/read/conditional
              example: /devices/12345678-1234-5678-1234-56789abcdef4/properties/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:
                - /devices/{id}/properties/{propertyName}
                - /devices/{id}/actions/{actionName}
                - /extensions/{id}/properties/{propertyName}/read/conditional
              example: /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              anyOf:
                - $ref: '../NIPC.yaml#/components/schemas/Value'
                - $ref: '../NIPC.yaml#/components/schemas/SuccessResponse'
                - $ref: '../NIPC.yaml#/components/schemas/FailureResponse'

  examples:
    bulkRequest:
      summary: Bulk request example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            data:
              value: dGVzdA==
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/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: /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              value: dGVzdA==
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              status: 200
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature/read/conditional
            response:
              value: dGVzdA==
    errorBulkResponse:
      summary: Error Bulk response example
      value:
        operations:
          - method: GET
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-property-not-readable
              status: 400
              title: Property not readable
              detail: Property https://example.com/thermometer#/sdfThing/thermometer/sdfProperty/temperature is not readable
          - method: PUT
            path: /devices/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-extension-operation-not-executed
              status: 400
              title: Operation not executed
              detail: Operation was not executed since the previous operation failed
          - method: POST
            path: /extensions/12345678-1234-5678-1234-56789abcdef4/properties/https%3A%2F%2Fexample.com%2Fthermometer%23%2FsdfThing%2Fthermometer%2FsdfProperty%2Ftemperature/read/conditional
            response:
              type: https://www.iana.org/assignments/http-problem-types#nipc-extension-operation-not-executed
              status: 400
              title: Operation not executed
              detail: Operation was not executed since the previous operation failed
<CODE ENDS>
]]></artwork></figure>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

</section>


  </back>

<!-- ##markdown-source:
H4sIACPMUWgAA+29aVfcWJIw/F2/Qg+eHttv5cLipczbVTMYsIt5bMMYquvM
zOnjUqaUoHamlC0poSjM/PYnlrtKV0olJDa2k9NdBkl3ixs3buzR7Xa9Ii7G
0ba/k/g70+k4HgZFnCb+m+AyyvyDpIiyUTCM/FGa+e/SpHtw5IfReQxPhmlS
ZOnYf/Tu4Gj3sRcMBll0vu3jX16YDpNgAr2GWTAqunFUjLpBHo66STwddtef
e/lsMInzHEY6uZzCdwf7J688GDo6TbPLbT8vQs+Lp9m2X2SzvNhcX3+xvul9
jC4v0izc5mklUdHdw+49Ly+CJPwQjNMEukpSbxpv+/9TpMOOn6dZkUWjHH67
nOAvf/e8YFacpdm253d9z4efOMm3/Zc9/2UWJ8OPkyChpzz/l0FWlF6k2em2
vxvnw9Q/vsyLaJLT42FcwMRfwnTzaCwepTMAET6NxqfxbEIPo0kQj7d9gBZ1
+u9D7Kk3TOFtV0/nfc9/m55ZU3mfnsWF8bRmHjmsNyq2/Y3n6/5vUV74J0EO
U/f3svg8EtMKobsXTze2nhgzP4Zv/iPNI3vmvx7vmLPOcA6TtGbSAEPoBTAl
NCGYBVEYJdYbmvrRWTyOpybwdoMJQCU8bZ7DgDvs5dzhv0+5H5qNF+OzCaDw
eQQb7L98s/90a5taCzR/OZ5FRZoWZ/5umkX+8TQaxiOB9B3/b1GGOOk/7W1R
I4Uq9NMV/4oF6K6OD17TqxAQeNvfXN/cgD//Oz4dRNHmpjX8n/SwbtjNTX+j
tz5/5N00SaIhLBLA5h8j8gdZmPs743EcJMPImsvGc/jzdVAU3ff7xyfdnaMD
a0I7Pj4ezcY+vPFneRT6ReoHw2GU59hHAFsrTnwOr+Pk1C/OgBzMkiHOPRjj
FMJoFCfQEj7Flxowr3dOTvxplo7iMc+qCLJTxM6zopjm2/3+xcVFbyA/xy3s
q7+6WZSnswzG7Z/i9OHPohtM4/5tdgag4XW7XT8YwDkJhkA7Ts7i3J9Ek9TP
eVNgnRIkgUEQx0QQY4sgwryii+Ay9z1Y43kcInTSaZRRi9wPTgM4FwVQJINu
AikKcv8iGo/x38DffXn4vjsIEPDedDYYx/lZF6hjPsziQVQaD892MMFRcGd6
/gkAO4z401B/C91mkRf9UURJHg/GEX+YmzjnB+M8FfuGs4D5A70Eaj6BNeMA
coMBGzxACHgMWwuQ0hOCp7BfkzQZXzLeiGXKrvKez7CexGEI2+89QLqdpeGM
Ooa/H/jHQwCX571JL7rT9ALgm8OU0wxhNCxmQQG/+oDdPmwlvBwy2sNQEiFj
0SGt3ouS8zhLk0mUFNwMpuUPAbS5n8+GZwjvwSwe0zYBSQxOI/y0459Fwbg4
GwLQOj5cMB+nYwRix4NvZiOcCJDq044/Tk/jvIiH3PdZmk/jgvEfWvrpCMDt
DwBTo+ySVxOFPf+3GLDQG8eTGOfNixzMgMbBuLCoS5jIJUCu8GGzA9grBGs+
m07h3qKzZADUT+l4xZl3EUPfgOo+/jLGk6r3HpeT4PZg57IntSfwOCj8LPrn
DFrCvo9xQp45rZ5/lKWTGCHjR38Ekyn0D4tjCOp+cMlXV0Rfr68RIN7VlaR4
19eEcXmk9qm4nALijQFTwlSNLhBoliBORrAWgJRo4MHajMMnpo1jahyA5gdH
4uQAL4AbhxsLN0AWwEGZ4b4B6sMBh52A0wOba3XJ0EQAi9Y8SBJx3+bUYDZZ
NIzwAi0A3pMI7iV/BGDCHmCZAvPHCo3luifAvOCS4awVZ1k6OwUklFTD99QZ
q0wF4QeHTX4pP0Q4AJIB5UryMbyjv31PT5UPLD0tnUZeHL4oz1IiCZ3X/8Uf
RUxv+EPtf+iaPz/YX/ww98UP1Mkniyf99Fezy58/4bVG8Km8EJzqp/rp0SvA
B36Efylk8o129Jvojf7cY5h9qlnjoaT+5TW6XpTWjlMTG3C17T84veA7+qc1
uUy8AsS28jTytWuP8ds/C84joCGAHdFohLuJeMD0XYFJoxH2pM4mIobAAQ9u
AuB44+FsHGQKdzqKfAbIUfGtjnck8QzYFz0Vl6H36OrK4jeurx8DUQKMOwec
I7KkJysJI/IcPnIXQAE1vcvs+Uhy3oOLBG9wonNAmoBzhWsk8XPBCck7EckB
jOuVjz18b5z6Cg0qX9eDKJ+mHyMicudREqZZV96lfoz0EWml6J1WBgsYxyPc
b7wB6CQD8zIbF0incUFACaOxZ1MqXMgAWRbFVOAtI+Yi5gr3V0S3fzQdp5d4
BcBiCCTe4JL+hQsoj2HOUQAbJmgltsgjHBaI1yVeFWmJ3HR44YEf4gUHSOLl
UYETgt0DsrDDhCMHfh5QcoK3pLx3BKM4TWO8cwUW4YC0FHWkPNVgaLKuBiMk
Fsqfq6+LaHiWpHjxCqZGrXw2iOEWAaDP8vElCEtBcokTZnpcMz28P/DumU5p
jOLMy4IwTsURGAaCsgJGEuwFyQegjGAz8T6E/UIQgMSa6zOhbkEPG5VvQdj7
EuMVT8yzGajTKc8SL8F7V+Km9CSBUxjjWQL+JfRh34kvMzgBC6sA4UBIgjue
rjSCvS3H54wQBpI52UUx64HJV3ZU7ybXEv1BSHRKMBzNaBYV1tDzdtRxjf+E
dYg5SWBoNvMsQHI1hluL0CpKAG5Fvu2h+L5znsYh33Z4ayP05OmSHZbYgZpW
Nq+R+kCsUY5URx+ncyrZeniD1F+jhcl30givYEQACgJgkhLTAqIL0GVCfNjz
MJ3yvT+q7oWxEziK3TfyzDakEJACupJbePvrMQldIJDAWAUgC0zHgKG6BgQQ
Z8hUFGqnYdIsXMV/BnKWpiA0HMfEYCM+4gwvYjjBEiEJrKcGRruYPHvNvCd8
UOkaQNkG6QAOnCaDFFBEs/w9/5Af4UoAD2FTxdHAueDoJUzCEwOAgAWOLvGO
kZRbMD/EygdIukbwFFdGii1AcuwvGKQzJn7ic8TzKKNfzVUiSwviKa8FT08w
iEky4FOXzyY4EmN1wDzfJA0BSwn5AKRBTky2WiQRDpoB7lpugRX6nCVw6Oj8
4AWHT2TXipJTTwzbhHeCWGjuDocdxN0QiIYQ4/0KE5lUd+kwIV6YcfosAGoy
5uOSpbR9EgwdvO+msG6SdhGh8ssJcs3xENdkDZXzjA2WlYiyr6R//5FAjiOi
4o8JKoUPRACvq2maB2MX2FlW9jW/Lsh5yIx7Ujl38Pm4i9cbIVI6R1joEePF
VDyWxwQ/STV6Kv4e9hLxCKUoFHj5U3gYpsMZi6CDWeEJ2i5OLpH2gP9C5RDL
NpIq6svn/7x/tfv82ZMnIIWJQ4hfgjT2fw66ez3SvObDeNLllXYJ7fBqQj2t
pHO5qbUgnkKgO+o4QGyZeungH4ApUraMlQiZqy/1sumakF2j0JvFaWZQVfgG
+DoaXw1rjirmhrwHExcQ35DQ4mktTwyOtu+dwqVAzJYvRBzcRYN60GWEzCsg
HSCoJAdxlKHIg9toShnymMXYQjKJcitRo0yod5rCmYkl9v9xCRfP5TgNQji1
A2iDvK0gRIj/1u16UGBDlPlxP5OQ2V+U/4Wq5AIZFTmiR+eWdn6aRXi2wgg1
uDmfxJA1Vsw0yDn0pBzRLMnZ4ov754fmLtwSVumbiqyEgs97phXURa04aHfx
ydjQT/Y0Qebzj3cP3tZP6VNF7LOlxm73k38MpB3u7eYuSgvZLbKxv5+E06L9
QupB1fi2YRZWF9a+/qD/5l9/MGCxK2w4/qefe70eCmzwT+9T72eWe/EY4ofw
yIfzKH7dw5YGOP1/rc79E/8tL2FzVpVZnCgS/emvvd50NujnswHO4q/lLmtg
QW/gCOeOWZRhcQNwzv1puanvBC3ZIxmGFGxtu2h3Ug3lQZDB/SDUBy9BJBz6
O/AERG1ig1FtcHWF38CtkZ8hRzDLrQuvw6wUIkBVCS4p5KOdN68fd0DsseQs
eHz0WFz7klw/2nvMUoU9RqVrT3ZNrc1OkSRaYi8yyt13Wl0WIYJKVZYfeIr/
F1cmCK1nMQAF7q4ZaoRdjKlm9HqVawGvazl+TJeV4v+DEO60GA0KxN6H6SQg
S0hATIMn75CINQU5wQ0ODYCJh4ETGEn2oR7a6rJhvr6iHPTKPMtFnJ+J+3iO
jkMabqTcIVaAnK4UMRX72fN2zEGUAgRHEjCXVAUZGiUYSJuK1lR782WD0sQk
aBE7tI2kSD0YBAFLg9Ftb5pVBEXRI7McdRIhK4LKhUtmAj5Gl6j+hyt8DUWo
tQ7/6787pN/f7//nrwfv9/fw9+Nfdt68Ub/wFx78cfjrG/Eef9Mtdw/fvt1/
t8eN4alfevR257/W6Mh4a4dHJweH73berPHaDS6RzgBzCoodQJ4nt2xA/svd
I2/jieAMNzc2XsAZ5z9+3HiObOIFMHF8Psl2w3+SXg7QJwoyQu/xGPhRMnCw
wQqpROKjqhGhZ1ETgubhOYpF0YVXUVxoTQlqCYFpYQVJxzQKSF1IMpsMAOVR
FYZEyzPYUmUByONJjNrAYJilSB60uWnfMFcQ5PBzYOtDWqx3kcGMheWMuV8+
S4IzBD4qlCKrtsCkKIeqWSDXr7UDNgtrcc4d88jkpGjI/U2cVXIKcvfGY/9A
WqqxlRIz0V4YCLWmIXaSWgiabguTHz0k48Ig8rSMLKQURZ+j3mkPj+8kChKC
CrJIj4V0aUiWtBCpUChQ9gJRDc6SNQUhASjmmQUUFK41g65MwNMAzjIM6Knu
AbI9b7N+3SXJmFcq+QexVGUhEzvgyc3vJtEMyO/Y2A3GcJZXlLASKPsmzK3c
2MK2VKuhlcrAwANh3yJ8nCE9ZCbegL5nwh3AdLz3ilfWsY+rKaiRiwz8H+Qz
i4OvMDGa7RFMbx2foj7k7St9WGErfnC09K/i8Jr+0N/9XBnOYRAx+ahPjATa
CtKGZ+qiKRJaFJfteCxUI7GJpcV86Pv9c8mFmfwsblW79dJj1uTMg6zRv9VF
eYomFwcUHlBX8nGCZkWEzTnQMjL/HApjL2Djpv3WMLPAxTsCSToKO26zqic1
foCTeGs3UDhBDmKQMsuvPbKDW19PeQNjVASlZMHPYTUzoMOBMEXBU3F7q85z
4ClznANzRGjPCpEo5qajiXmk+ELXikHPOzAU03IxTTqHjknqUB8I7Qh8KOt7
TPPI0WUIV48+69ShZIz83yKmhPwWSWzuP9Qi68MeMJRBVnjScqxhyd13kDkl
ypyncGUg9xtkl9pya1FiUlOif4kXkIqEKBxCRpNX5BXStEDGdMqOdGU21/RF
8UAaD8j/xDLS0CdlPAhyUmmyScK06MR0oZDdfWc8BpxCk7ehhhmmszHp3lO4
Y8TtbymL0KJAzh54bwqAeLCCNDkdkw4PGEalM1HMpaUGI8vOHP0XrQrhQPRT
GsKHZ9EkoO2nUwOPozGsOhTGkyJgzgj2hncmKOCeHMzwrOFlIywj4v6QPATC
jhH0fXQqpAT8BDglhGpmPGSdF13MFZOEQD17g0k1RLokL4vGgbKkSsQS3ESv
NLTQNMaVqzhIvLY6ajrPrh7MmXtyhgo/K6pqS7QAKD3Qx9qCTc5Mun7pnhb8
WxBjj/QPwai4oYk0K8mhvcLyUSGhrsJQ0ME2qUmYEtiZYKjZeMShSBwpe1MB
sCTfURkAuzBInGdwHtrMnCaRMMuVPpdYpsU0fbA9aVtFGoZ9Ypd6RohMUpq0
WRe/yrp41Q3p6dXnQjyfz9b4vMV76Fhoirpmx563YyGRb1xORSP3LbeS2W02
V0qWUcgYrASwDheeBmnr1R52dCmxB6Sk156i9MSFw6suqhLLJ1hy1garCSNw
f8rA5aNXgu0JKLedicVR2SPv6oH8AJ5cE5CMwzBjOYp3AHsjeQEttMPxjDXg
MA5iQgmD0EPKoKTmtWpCu4kbZn2MZ8sudGfRFCymu6jgMMOkgvOeIq4m/aCz
iDvfEe6IaOM/Q1klVB5W5dOHSFeBZokmoX+j4QUZnCYpuvpVpuk5zqaEA90p
ZYcQsWTynTA6Q7uGxxokX9oLDEn2FXJFLM2S1ExmkCAMM3JqkFzVJeONMEh6
w7MAaVuUkZci6bvGkfk1HEuWvQls3BsrEOyPAg9whizYAnWTkJRwCMiKo6hh
UTSs5NgyiS4M94VY7hs+llTIl0avIRy7QnhlSJlQeuLNpui9S4/ILMzXdMnG
0fWN0+HZLDb99rM/ED7ImhHvEnDl0t2t2GO7JH10JSBVW4trTwvyl2W2Xckw
b3nRyLTvSIUKUUrRALmSKnppDlpJwdEEiGwo2GDPWLcS0kcG/gT+Gqx8zafr
co2Xsya+BCB6n/wdddI+oVmGgINhGZa8IpQrZTnIkGYsHbrxX/u3uT+fYEYD
NRDM4IT+K7jeT+Ttxb8T/wA7qIFlMGQ4o0/S375NR7yjrr4+yW2Fz41dFU5q
1AWJYhfI+XbJqYJBjscsKfHrggmQe6rVWnJccRfDuhDp9KWAvcrdu0XH2KlG
Xt33IXHdleMtlidZxiAUlmk6sKxqNc859s5NPE9iTLnPbXlY1oAnOKSP17b9
K2i6xp7Y7AQunsFT+EweIvWQP87w2o2Mh/CYL0FysIEXa3hVD2cZKeqBqUGH
EVQLYVwPte3olujYhU1YC2m+mSUxznFtAIvuA3tgvksHSICRzYAvRiC7RcZL
1DnWvJJgAbJgLcBn5LEfIRSYzB/s4UQ2NreePH32/Mcu/tK1f3sRDIbA7Twx
Jkkd2PfDAv0Y3Vx75d/4X/zvtXdtUMHojxIdNNCB6eHEoIcWkiB6Ky8I1ATg
Zhm8g1CjCVVjiZvwtEsGyNtjDBQjs8yYxeuykwW7wIz53jM0leRpZamscuDA
KHwtnebXQngzReIsqjL3No9U4rw67EjjKU87ZOFMhYlUkfyr0JBUFC60mjPU
2icy2MQzhQOiARiIIHjUKHPoTvyDkZLhUeZTgREoeZs8UvRHNCTNTWkaSm1B
SoFQ6yuU5WqC3DYAWasYhMRcwDlEA8dForkxPZdcigtHmqyhhEzsHONQncAs
2dZ6bZQ0ShSpRyYCjKYgA8F5MJ6xfRDWMBEyKSsWYWShYaRxlWJpWJZAdPdR
ggtGQpqhu5L4A2QKoCRoOzH9Xngo0knCSKybtBdI06IuI91hJGSLLJLOt3oi
Pdkdm0KEqJgKT2ypeRNxR31H3JGY1K4TQSgo1D4knoe8a028iRvNBhSdIdCL
HUcN5JKuQqeGP58EPCNWXLg77vm/YbSE0a+Pp9Zi2C3TB/WNns8zFAaMPi2f
OlNlhvjL6IvQNFoEo0KAWKsbUa80TJEGkl/4jm12AX4QVWPai7ZpaXIOaPOq
fOcZ3wlyR/FZbK5BsZPpQpAUlrPrZDYuYqTQZbUukUbhnK+HcY7tV8fWuj2Y
gIdUTgYR9gWS9tHC0OeWfROI6qyJrWSoKiLCuOK5QGVowTolnZSPU8jl1h9q
ZEDmSGJC1akV3ZrZr9mcYRIK2YxUtmlBFI16Mr4iBHFhhMSGXDlHcG+keSaK
yysDyjkcoyXSxjJJHk2aRKiqBIQy62XTr+Zv6Uaj7whdqsTO0xESM4pywvVj
jIZx2ViKBraZUZe0Qjl0Rajkby8V3Wg+DJJuau3r1QOtir1GRlS9CcgZvbBY
iiFSH3nz237vvDTPVuzGRc8vdYkbmc6SUARM0OQV9pApm+PijesIO4ZmA1RK
qZNnvI8JidOEAEY4y1KdcFMeoiNGooQ8afFm/TvLyrPxR4vWSf9v8mFG13Qx
qmePikOqJ9ZKxYEmd0tUMBzsvNsxN5vhJKyvMFcOltECiAYj81f71u3jO24f
cQsK7oq/k2EvTZeW7FrMOB152luHwjdABun6x1Y4Lav5BE5vl1+Sogn4SNRS
AN1Svysltif85cSVCpsGI7zM0iAcBjk8MHuHN8aFyi22ZUyXGbbzr3jF678t
xWDOaK98ZQVLGlvhvFL/zp4wMJh0w/nl5ORImE1ebGw8QdXszjiFIWk9+NYD
IQm9zInI/fr+APaUBiDvqf84PnwnrS4bT9HFRPm/sq3kHE4AfW5gl+aKLMW+
YnQ7gpHBAZWUYBvdgSUVKE7RTuTHjpFGwvNcxO2w7znFgkzQHGDHXEdZlmaA
gno1pKGTwWO0NLiu4oBQxV8z7o7+P3KQKmGefwyjaSHDdYiZdmjIaVtQD4cc
OH5n9JpFozEJ1oKkF+JWF6y5J2Qc7cNAUeruSYF8/ANNrGegRPV4RIKxbHzN
QVIJehiTqIB+VP4j4T/04gns9GOaFJ8suALGIFtlkqeMYtQi0OF6+58nJ/DP
b9HgLE0/8m95OvwYFYzFAcj5PN3X5L49ZvsOTY6QU+FwXHJwQvsOmybYzYQs
X/G50NC+RLwAdGXXOvmXLz25tB3PB4zJLlHjz1rqXEW2vN35L3KFQh/EMIxF
gIRHg1kWL/iAO9GYZsqrwtmdtlggaM+nmx6Po4fTotP66/s3fFAnaV6IQHK0
lMdIN8QltUYZE9YMPTxqQZG5EU5xHqbbEG6XqFeEacOkac68e1svfnyGxxwm
QA7lxgeKj8egk5KNFTCjj2JvzzOU0tueUsKIRA7iBaVwwM/7a573UhIdNobT
AfzwMUFuCNcukOrZxlMgH6gvhmaSYgtDP8aJqR0YYzzEuUiVITzF0Kgn1VKW
2nPbnz/F8w2cpTox721ro20ytXhBUkMT5H7w+7ZNjHpSbqjaPmhRPNolp/0I
b0bsmC8oq+8+d1R+KrsxFmJKY3ARZpcVTQayFEheUWVAjCadW0d4hWnvtTy/
PPL8MpINoB8YMa8DRdxYe4PvRnGWF/qUmF5iwMQuhliwaygvrDG9yAFb8bpw
dc3eGFKUL3t/KDUFAoPsMUppkJiewOwtx3jJEXPaYNBlqom/8B1GjySbQzMU
XmIl46hSJF33RCIMtGkYJFD4IozJDAs38XkM6J9qjRe/77D3p3SK8eqsrmW9
ESrZlOYLwFO2CTYZ4m/iXCNutapvgWeYag3vGhI4pHemMF1ro5F57Vqm8zOL
g5bYqAVQOKBlLwJBbwwu1jJ+V427R4dwkRCT5Fn6SIl4gzSkSOSzwiD6Fptc
GdwbRcXwTEZ8VUZ8vS8GRO1EOHovnS17NUe+vNlSitokD2d9VZEb6o488gd7
KkxS3lky5tGSWYWeYiAVNgRWdOwUe6yDtdzb5Jd2ySBDtJ4HMsXCwZ6HPkRV
36PMGFqm2DEpV1ChXT1P8taSsFkuI+RWY7u1ylCx2SzGS8i0kbEx6UZ2MttG
dgs7GZq24tDqWpq3cMb0dxvVvs+mLQYEPJC6+j0rrFEDd1a9F1B9fxBKwdMA
m+3CLMhoTF/qgD10PldnAyUc04XFsmKqjSaPLQpNyOBgcWof6Q0QMkPFeYk8
HefX8ZntIFlBXAeWh4mWDtRNwcFgmhSqc+c4YrYOvuKkQ0xZFpl+0uJAe+aB
ViEq4tKcjQV/pp04yC4O5zefsm72xD5MdDb4Lj8ydN1CGgZwCj02K98xl5Ce
k3DfHLGAwWyxV7qbl2Qrdp2GW1iM9Zkw/IXleeCFwG8uhkKZEB/0lS2yj+BD
Tjwo+oblsV9EEwI05jPgY4OXONzhDefGdSdK7gEPzgPyChSh0j7awSx9tIh+
xffCsa/UoRR788tkeJalCWXD4EAS5dpFwgdmH9H6LqGDNjoSlxcJXlJ+lsGx
LOzGOrVQMEjPmathjYdS63SAswmmsaF8U5mgpNjlKVUZApgDojoCHWf6rjLN
R4bpSamsSgeQ3IIK5tOEmtQyGghAwt4lvEYcfJZ7KOZivj6hnWUvsJLIRpPD
uCK+GIWtS3iVyYnFBcubLEJyLhEkbYo9EuPiXS62QUFJBp2cRsSPesJgkSZi
luoiVezEwYjSvozHg2D4kcTHi0B59NDvBk9otDSi+kyTB2ejYPOjYudU90yp
PKVVEUig9lGBSSm4q1tsaLqlClq4OXNaClLRG0iMZA8ttx2xaQh4Y998uW8e
3R+EkyrSHsMGpwW5umuFVuC/SQWtZ7UWhxUKdShCXXYgndg43x6NhpkCMbcY
ZS0ZBfF4RrRcwINwS4jrfOorM4WnT/74A+nv0z/+6IhopJg0urR6XIDQxT15
+hykYSA6gGATYIXg0IwJAyaB8FP53VT9TPlDUv/87mkFERsUKnMUmo/f8ZPf
QSqLxvImIoncYAAJbUhTRv3JeM6z2SRIumgwpRPwe0gTFF3xoGbnntBvHFDz
siLn6ooGOIN3aBMiWehVCbwox+9rJXdQgb/yJiEHEunCYeaXjIMk6KXZaT/I
8/iUU6n08YOugF6XVMJs3I+T82Ach904JPeJNd5G6PLJ+jo9IEqPQxzwl5pd
5QYMEfxAvWjHioVpxFkBKIEOeVfz35L9WrP8KyQcSt4VZfBYfknoQkQQ8tW+
lHl+raxXe8/tBCAkc1LGcdE5AYd7H2RxNOqUMSafTSboOi+JYGkUAT3uodQU
rUBBIqQQy6kJ82sM2clnSIkmXfocDmZmb8WSRZBC3pgHtR1ga1zfPctvNyw7
M7N5la+cslux5VDse6bne428LZT7hvHMHSCwyAp6ZnczcWP+7tIp/25onTuV
WFPv6upYWDGe9zZwAHcs2wMV/cDzg+dCL+a9jYqzNNz2fyfB2qHx+t0D6U25
dG2rfvI2C0U1Hl9PL0EuZ/WN1QwWQQp/prAdFV0qbjkpfhC1YsaQhGe1svea
DFlkqkKe/gcQXPuzvQMe3qRTc5lSyzOOnK3+rogB7hM6XAHscNgySVCIoaDu
pg5dPTN5yrUwL+BRpNMuqkLH2NnJmXBsUdOUCbVLwRFCzU/ph/QscmPzkS9q
sffQR17qxNSslANK7tf2AH8HU3ft0GkFNF9uh9yHs2Z/+ldiPtfunUosnGvY
pyOtlfJpoaLf7SUuUqogyEAaZUO4+LrS0oU8NEuK9pkmFbNaAgUNID/K1K8l
4fDclINVXcgU1wF9b//N/sn+YnDnHr8F0DefV+L2bn9SryunFGbrOqIh79SX
JaG/ciRE3QX664JnlLv7inHlftzsd4aKs6kLE0U4zJfExOb4vcUZ1hYstFfH
QpsxeXI8VgxFwgYl+gZBrMfZ/kEiG6aZ0Ksp86CMchLfSglFJxC0PjAiW6vn
xVJRn5T7jq04doOFfmYx0M6sfWVWugK5ZoZaGov7V/jbznR6EFaogsFfV/el
BUlQPW9Ls7A0BFSmWj3B0hcq8MdCnSLcUnQQfGVK0o9VYorvV+StNBO6cqms
IisdKaBkGD37vfFMVa5UsaTJP4tilzR72xQPN5miYxIfEpoYCNFpETXMEifF
QTvoFyPVhHMFRXKqIU8aMYuXWfoxyraN6B8Zgy+MaDA2jTCgD013FcrVqlyR
xHsaXDrgsRuUXWKCaEAXVQW8nagzEFAyxhFfgSSZJeo6kH+R5lonmTVybVV7
mIL4xjV+2IjPfy3SA/+xu7MbZQX3srvjD9ESMhLJ/Cuz9x9JDehj0clwlhfp
5CSdxkPugx8gxWSdQz3I0I7J9g2z165/wY5Q9VsXyE/oljN1l8klb8Mwi0hb
E0i/erYp6QgNC0Y4NdGj2MYT/YTGEPeCIk4aO0pLkpb0nLxtSxhh9CheCcdB
qilVi6XSu5BN/9iz3lXRpYCjUnufGM1Qb60UmgCgwM5iXMJ70Uuc6Th5OW1B
psXU+a/52GO3rm41e7rN2Wz+qG67b7Tb3CXv94n5aLkbrvtc4pYL78A73nQx
9Rtvu9Xe3Pgyl6gvGptT5AsNGMX/ocFVOCM9vzH/iI/JzNsfAbe1FxXkf7Wm
gvP+TsppfZFhfOG1g+cEdgE/4gsqq3KftGFGN9cN6xY6OTdzZ9yGTIXvF5T4
otUxqID9OCq+6hlDbm/8+OOWCLRckxcefoi/y+fyGsPn6nfxzrhp8DX/2ad7
hj5p2CMGW9MeiUVcW8LMAdXyweRCo9m4I+3Dhp1oIL1hhsFYMsfmtkouVEqj
jTxoRSZtw4IqwfSzMqD+MSVpyCsLNgywgu+uTItjRt8bRqvbg9lQyjWBuKqa
awNi1s9VF7KY+L8QqC2l2mKwcO+AV90BU6nWBDSnaq0N3JR+7dsDnRlKguNM
s5hMdZTqXExOZ2bndLTRH1gH4DSSbAOZkq0crh10FlYOlWjMI3d7jLWVCgfF
e8isnCqHgZ3Rtmf4x7JeAR1rYw7kpiomW76oIRpHoroFfWyFC2+bmgK3ZoL0
8Vg/jimc8H4T6RjE5Hqqdx2o26LrmuBdj5gVR/yuGsUI3GsxjCNaD0Zo6nRO
NGB1TKrDMHdYf36QoA3XjkoHmMlueqVkRzIPinHgJJKrxGfaQ1mYN3NGHBU6
LrziaJ8NMOgsW5aLbuBSllESMRW7pzgOnrrdgN9YSqowoggTw6fbiN33H8W9
qOcb/mcdX/IunP44HPGsH6sUHSWfH70GKxX3wZ7ivwwt1NVVo95JOU0bM1Se
08qnUZcHPR2nAyAaJP07kz55ZUuy1oI9qTcjy1mY3UsiSCHO0gHTpHeWxzXg
g6cyxLGOwZVxRybm0AodFR9K42kFIxcYtGYk0bOsvGaxh+YplKok+XGmSytG
R2efsChXC52qm3IZVMsXfVjBADrS1gp7F7eJLn2DTt8qg0NIfcW52ULghPFR
OX8HJcJSEa0ygH8M3A47tem+KBEm3heXHHkpHcrjXN0srMePK2HZuEexZ9XJ
komlqGKGcOTrWQCVkffqQGvHByN+cpdD9brk88q0A93NPEO2DYbkf8wboMJO
pSIS5FPKa0EB7XxiLMeLFCSSost34u+Cbwwu/EGc4F0sY1FJePbM5CXGvd9X
HALzkXVDkX9Hx+IYrPhJaI23sHBS81gzSo5oKnmVYUnJ2S9U1JIz5ysPQIDF
UQCQz57IpmuUbGNNuo+Rt7Gq9VqoaN2OZoziXBVpI/9/gLWqOoMfqWwqcqoC
sznzvsxMZzjKMc/4G6X+CDj5R1l+sdIU6LPUv5KuvE7rGnWZyz5VljsR1aqj
Yxy8YVxlCvlTI/hIm91UpzAEpzDBUIqSbp10vsaeGN/anTyah5OPLYbU4ZX5
BBhAeU4skzm5VCqZiMfPLadKIq4yOgCTTsigXPwg0qjZ84+wqpmRb/fqSvRx
fe3ZRZnKTaUJBdPCV/abhKmb7Tf2qLeb7FOfYcMpdw0ONl9MKKOAamp12mPZ
FR8xaZMOs0R1KIPlXHplkh/P8j11kLNeRYMUGOHfqq+4cU5elbDZ+iQmNNv+
Wvj6b3+GOz/95DK4YvZsl/+Ua0Jla6ugZELFOrgsSvmXArr1Bfkjisj5OL4A
7jOxU/ccJzxqSfScVM7ImZQaJeIMSe6G6F+xELKRP8iy4FKk8DdkRWZ6dPFT
mRXPTJiZGKdebjCJydSYKoNLuOjOXV5iKoxjEV1kMTe0ROoFHfjq+9eduxn/
bDaJwxj6Kg8e4eAvxeAOl7bZdILzcLoo1MDS0kaWnbub3PJWAGeAN/iEOMBd
S6+MHRG6eOepUhSMhwgrp4vUADUH7Itd7PW0remCd93okrTRPblk4vaflDvC
aOBV73sOZgxUAedQOUbYtA8vmJu5u67OFd38Qeg8WZmFTu3P1aViBTS3xlnX
coNn+6oYh7K2s4U6YqFUhcvUTFCmoOUoJijazlueYgLT5rTRSwhQkR+kqV6y
3PhgWb9LveDvMmATQ/mNLBgCs8r0x5Xkg3OKnRvZ+3gHRcqt8ufIlHM8ZLkM
gUcViseXZskDK615RzL0jg+xw5dv9jusclhsOoUFuMT3gvAcT2zOcYj8iivR
yE0R0iu96inhp8m8o/bbHMl0KIL3HpvQO/aMSPvHGbK4KLn2RWLfIqnIFrPB
7eQXrGjjRpautTLRgz1ZzWYUYNivpwLG7d5l2K2aXpFH45F7l1TJAmMUnNLv
7TII/w5t7bFy3/vdSe4L7YpLBJ9U7eZTbcOP8yMgUOgP8HuHUIUhJQ6ZuuuU
We+vyub2c/+vCijwO94CH8glJso+FOkHGOEDzfNnT7dus9DyPK3bqm72Mo/9
TnUrKSGpUeiQsY6XqTGA/8aAwYIT6qPJg3AKQBEOgywUBWmMjn5X6/rBvLX7
D34nHbn0R0RaKOwxEnd+Nz7/3UpGwBpc01POTORMziDWMelUXeuAas9ynTfI
OBio1weaK5M9Jq7bpOL8ajF6vI7+Ff3rVOFwr7ku10FkplQyfkH1jRpt20B/
dTUalB6/0fnApM5UpC+QJhvsIhjk6RiDztEXU/nSiDvCa3FHGFzie9LN5a7g
6g1/1yjKMD+CWtVwECdc1h4qsaKGArDCleIs+hu9DXN0Tw67rbez1VEU2/3j
82dPn2xtbnTpP/gX/zaKwuEgeMGv5RHEzSgv03JhQ5DLg+Ber0ziYWbeRYJ/
Fg0/Sggb/JBB67+IuLTn5sscrhLOsyRX7fKU4J4XOU2s4Kk7TS6GhRuoSYiG
MoZfe/GrYyfh/igd4K5Ghga0vPEqtwA3vpDZvKPwcdszZKnCkdXQyC8m0nPg
vtlKXw6fHzfQ9YjXLtJlNInRLTDiNSe4UKdgdL9Qg1I5Lhr3czf+iFXV9Cm8
ww/rwkfNfarKpnKeygOYvlb3h4Hamrc1CPiXQj6NKEoCl0lM52LifOQztTm6
BOVcNFwQC51anhJm1it57LsFsJY4uVGMdS1Q1DL9j2+kVdXTQCRudVlK5cpd
ueLWxE471TOI+iXcqD0EQkFjrLiUtcwkDpR7DDWd8lyoRI+1R6mmyRc5PW7+
2C02V7hmzpB3O6a5OkgLrrlKwlf88zL5Z7GxK/b5rtnnuQdNMtWuo7Y4T914
2Oo4pxUr/QVZ6bkIQmzNgtgxj7+ehyZtSfIiSEIH9x4z1afReT1TzYv/vljr
m2LmzfntpaDlis1eFptNJyKfy2wbZ2PFcqs6LDqQoIV1tD5aQgYKGEW4bmcL
LTlpe7exhdpO2t4tbaHaR9ursYVSBUCdR1Uk2m9U9QuI9q/4F6fcUunytkoo
9k5TA/JHgdoksdsVn7aTs1LAFmYzFORGlVqR/pOWG3i9AdUz8hxaJezI2cBO
bqPSsWZmqvzASimMGewtwYOnm9Wza5vCUzOiVKet5J+GDKzERXDWn5sIQ3oy
N7YmSIy6O3motPxGQcj4niEkyzTSW+tNo6pMnZMGrnJXjWjxlUs8My34STHa
fFHj8cKJm2SC17Xdw7dHKJXtuVhFASn62HU3WjB3cYkqf2oSUkoBUflJVCam
TMnlxUa9017HXzt49+Ho/eHr9/vHx1TF25jo4y/CQS4aO3irq7AcOOgZfhjN
UYNWsB23N9Jxy1vN8Ozp+HlqX2+q4rpxV4pypUYhSzGIXSrVN0pQNl9WlcKX
lRPo6rH9EXM5URvl5zJKbqXLgtD7UkFmUS2es6yL2mswCDnpwDWUpJX6zVyy
IAqZiRW1q7maHVUkinPjsmFlAr3hPJjKm8hwuEMdAqfB0fXxDIj0/EOVxrzj
GFBUihrHk7igIakvo38jGhLXyBXc1bJUtnYOEBX9y1wm1JccKwpV1GgoqqhJ
79qeDuhTCxbfDmYUKUbRsIDCWZqbTFtOuInzQraMElepIlNDYIDp9ldb2PNL
zu1piW2TnJYm3ApOlmepTSoRU9BfeNvf6si/L98KgWDnCF8U2SxyUE8cukwx
9XTK4oIcR2wJU0pR8ItiyOk1wlVl+zecBlUebUoEhgwCArXrmK51txq9ZZFw
6YqTURawyxXTV6z6A70qISgg9oM5GaI9WRDGqfDfxN4zkk70YSQOWoTRrCGw
1th/WscJml1KpKUJIp8glt6jGkxq8VZ+DKrOM44/RtapMoNblduyruyCVZYr
9V8tJBZpzng/LkR9JtmTqgnk6TPQc6EgEIxKXeU7wUF6ZwTy6kQuA8rervLJ
yIOsMs2Y2WbMLw72kEdo5e2mWl+L3/7ekcPhWY1QBwDSeB7Zjw/CcXQ0y05x
flvPON08vQ1mRcopUYzV8WLSBL2Byb2avf10LhtX5hiE/TSrMC/lLVH1dq0t
MaiR5msEtcSNVQjEt4Ww8mgIl8MMFA2VlJddR+PMVyDnVAUSar6u5waD40Fl
tlT2g7XEBEHmFnRmmAwMcrwEE1VCGOvZySQBVLdZ8yDVu4OzJ9BRlnmp9Lxw
26a0bep8nAGHQwm9+LIc4iRV2Sws1iiYWOxVsBPYA0VTdIHQTyS50FHJMEdV
lZjYI867QVRQAqBDHZroIvPdEwGNios0+6gDpTTgVHQztjdHAoY7wW0RyEXZ
zRTSyc4v0xlFfgGoMllxRnzjT4jvQaCP4tNZJis+4ThpMkiDTFU10syK4tKP
WbpTzKfiKnwHtZIV0hR6GbTIYhSDylVfify3al1yHSpidWSJZQuLFa+it0GU
cYLeQTz2dNI3oxlsH3LpGepFhuUmvquJFwqeMBX1bFUQ9tUVzE6OTukD+Nwb
nFfOFKOrj5YiUp/0bz/ztIZqXgYdpLSI6u3Q6IDfjcbBqf291bceYk8vo/yW
e9LrhEEkBfMfGGuU9AupzrEkL9VMZC5xLw5bk/F5d4i8L/RtcYO7oqMbl2Bv
3Uj2nVT5+EYDUj+0baWh6AUq9Uofw1OK2V6znv691KOBpo5+ryp7vmbu9+J3
LP9c21PyXG/kU37y94Yr0iXgD02Jqaa2Sqz12w5Fh4gOUuhknfIdSRgQpxWe
G6ccOygd9C9jPVJp3zREGmOH54q3okNxZYvzjMlXRPpAwTi/wnJ41buZKrea
VT47/iwZ47WhyLoGZ7kQqxSoRL6128nUK5n5m5OZE8kq6V7t6+SbFTEaxYjZ
1CXQV/Gnqga9Y3HhnkoL36mwsOLll8HLr5jaFVNLU7oFU8sEe8XWNntyCljI
3E0V240zEmoue1vf8ULsZhsfyXX/8P8y8dTJHiuukmIyS6csrlpKPJqznpKG
isNY2oBxX9BnrhIz3mhbn4sYzi5LQo+8Nklrxg8f5Y+9OO+jLCNao8wjbtNc
8SMTIUAZvkEgdQTnsDp2lpWVVqlrlR5U1BxVPS8qFS1iel9dW6tra64uBo/F
nIuryftw/v11q+vrHtxdIi0Ly9qDeBwXl6LYLSaoEI+50Bnw9P5FcAnn2EfZ
4aiS4/lddOG2A1I/IQ/FVjtmlXH7kMok0DDhtN+yPQljKHnrcvDbpb+V75+j
ZDjZJ0HWAFae8jb7vvSLIYcOzGdALhyjS/LqRfBoGzARUStzuI9+K0cVzQSQ
8J1KJmK5AgDA9XWHF600BxIqCkxS4vDshEylXOY9QiF05/vv+HQQRaSLkqkO
ZAZV9nWRPXtyKHsf0dRC0qwCNOk5krS6A1JP4lnpWdQmogcAoCVInJNAiIg9
mfrdks0tYZlRITKS3MPme6qFKI3c08CWfUiHT9VBIHPL4sXyyd8pCtgEDMzy
P/nvo3/Cf32f8ux+0iREHv+6n0/eD13j5wfjv+Yv838+wYwGeiCYwgn+VxS3
+WRU9iE4wO52XUZ2nNEn/0/e8zYdMXq4+sKOANQSrvM6Mj61e4OO0J4C73HT
YDckad0JyRpXJgtkWhFazMQkEDxap3oUTACYaj1kJsqdm6h1sPNux8izI05t
iWZcPQimsf4b5tZXf4lwQPmn6XFGruImkZQXAX7T8aOYzhTNwHQxMwaGDs4B
cdNMg1O/7Xn79qjkOqboG9lEFTFTSgueH/r4ppOByEg+oaqALoJoZrXnhKtj
bGO6fygaKFOhe8qNbhJ8tJNrURzGH1NMhSySysPVByuMORaC4jWkE3gPEWCa
AZdJfi8wzUvpUwc7S8WYeHmjWTJklXKMuWQPOBf94TRKsCtOwn51hUAwtvAa
Nh/2qAOUwz8LziMFn8AfAcLJUp2eCW57p+3aUKROy2YJZf/US+6gJHRGZCfO
JheBymqYdzyVeHowG380waRceUwbg5nyjxMm0ZCea8yijJGy4h9phwLbV1qw
Mh4JdJxLcVyOpZNkF8NcLY9g7Z9ruURxFqmal3Jp1AvfD4Zno8qNZc7fUzOg
OAElagotv6NFZcUkqBqyq6cCBPXEyCCClASLmsP9+ZvzEzwnWJFFJAtrMfrW
+pZ/DMT4kLbbFKCFn7q3JIijSKjnmiYtMKEKFzk08D6zQHu5Q3fDqB4aBl+Y
ZYCdvwAq4Z4S4Y/w0Zl4ci0OEn2GQ+ZSk6rLrGA6qV/fH3RZ88ufYu50UXhm
FKOa3QtKBSWwnsGLJ0+fw+kGog9X6cTfi+B4jpk9I/WFrrhhTsATOEm8M2e2
UhS30BYdUerlstoBnmw40adBEv8ZidIw2ErV9SyViQFG9TWPte2/zNIgHF9K
qkrBvdh1LmVsyig8A+4pi/8M2G2YhJg4OQeiF5pA4QxrchmCp0dmlJlvsyYN
7RPKMOOATW06byTtwSOUAfsk8j3mDsyyM9XWkXrrP+LgqL4Ik32sxrcv7Zo5
lBgITdnELKxbzzkT6wtBuPUNWtq2kjq/oA2g24F4REbnXTytrX4++YbKpc3n
uwKpDIbyU3umUfKOt/6ceL14OuwKrOoCYs2f/IFAQUP7l8kSVOQXmzxEddsw
PcWDQQCGbz5J5De56NLwWIVllo3bDY/lVpBUwuClmjHIL4yIrfFdw+pxFdJ0
FcJ1oTE8j4YzRCxz3ENFAjHaFsdQn+WxpJPTDICSznKDYAphWk9EDY/LJV6l
K6LbugZLWF62UWhHhMLVfjxv2XrcOOki2W0Ct1XqvPnjeeNKWkMwxjUEgzoZ
65OmXAjp5o/t74ka1Y+LxK31uM0fzxuXqKPaWxk8WtOPKLok9rbxY+N7NWh1
XELkOd2ofgid533cftwm1KyMW0p5ilx+JUVl47iGJqULK1AQV+plc9w9ploS
0I5v7HlWbrD6cZO0a+gLS/28S01lIpMnXK6gorcZV/fbLeJJhAoX3U/JGb78
wW3GFe63XUHh7H5wXOmf6/hgSest91xZ75yhFxpXKGC7yglDD//J1N0aXhp1
wy80rroexfhp1rWNAcataE4DWR77O7qHqyPTjFyjs0apFsE+STVjSwRrvWox
rly4LCVNKx/PqL6kXrKYg6o3jcsWH8F6546rmYABMuXDIC/UwESHzPnLMWV1
KL/0RXm9J/I7x+2gxpV6gm4GksMgAKmv0s8rqUqo+6T0fUlNNGdc1k9Uz7Ex
rvDPaT5O7nGVNMj8t7SwKB6bNH8nHGEEl2kW40AVu7NZ4kkVIpOmDRREj2YU
O9k/VgmIDzDT8igYivxdU/GBzlAcyw86lO0Jt1KXCTVe6tTbnujE+qCHY2O3
nERYaSNl7ikUz9hOS5oPKlPqCWneXRtWFEsldSgMPokmKamtED6piMcySr0J
xebuy8P3QiT+8cWTF7LE3+7e3hu49qSBx/N+E/qvgF+JFs821kGINgxBbCW/
kNISDurtwaACwFNhFRP5xTELjVkkERaKDqM400mU5wE6hgngoZuZkJWNPM0y
r3zdEJQ+jZY4kSUTnUWfqPAsJjGgGges3UKiBMg0mZrlb22/VGOi3C+6cnoC
TnxJy6KWwzRj1OOM19jyePfgrRFIrk3h+Jc3DS7HKVZYQKteng5jKbUG/scE
TXzK6YDVRVSoTqlIaJOkTjGYvg2GO2GI2iquo5fnsUS4VK3Hk16+ZOvh6GHR
KxvaFBoZiR20O940Haen6Ku8j/6FEizk3HqGk5BZvnmDhmcprpZzteiNMdCG
9DiYR4eKwolkeIOILFwSJ+RohBJySFUYFWj3WNww0E8NjuSqJIP6mMjGlFOg
szEI274MCuE7J+CLyIdmYfrD05/85P/P/1cZ7e9e9Rz8RHbuf6MVbjPuoZVc
Id62PwIUKDr+/+9H05QHz0FGBhzidgLDtn20lXTombnX+rkJeg8oZ25P4xF8
AkyDOblt/6X9wO/3+asds2wBfWY9Ud/pQO5jIsn0afkhf81Xtz38f1ee8bdw
XI/4aGz779Xv3mPPK0+YwaucLTQ0yl4R/AbhUlkM9zFxgPTf6BRtw/2YwN/c
trK6+uZKhoCNT9Ox6DEKclw7dIk9OkDAHUq2BadOw/uSezGeBNJoKZ6Zj9B2
qYbRUBTdU4XLPwoDMML7YRiG42u+H5CmCosnJRSiencii49yUzBtJEoXXUer
vTCCi7Dgq5r6D+PgNEmJCQWZT+ivvVL+Kjw8a9v+2cP1zfWNjR3478767saz
V6+e7K6vb6yvP3++ufHqycbL9a0Xm+vPf3woclfJs4OuJM+fjsLoxbOw++OP
z0bdJ8FwvRtshE+74ej5i9HzZ9Hz4YuhzHmlDic03Hi++fzJj0+2Xmx1lMeP
hT6Grz281WhAOT02tp/ubq+vy/9tmE4+iFrwUXfzqeHtTkmxkDMS3NAhhylG
zMALGdUeH1otCV73aN1YxD293dqfbD15trW+9Vz+u/XiyVP499ldY4eJ9zaQ
LJ+w4En07MmL0ZPuk0H0tLuxAf/58cenYXcUjUY/brwYhsMXo3qfMO5j+GS4
MXoWbTb20QBlhOvrHbhW3xmO9E6g3hGsysT0xkilSG01gMS16N2K+5bI8Xbf
8Kl6a9og0rcEtjYBIu8KeP7MeG7cGNhi03iFzBg+a4CdEKm1r0wFcR4sfGMk
FINipeRB7k45L7A3mWkTT8nnapZQJiPlAGO6N6mCUsLvijWxWFGvTyVDtQil
QjMuIiU2lNPdiLrUAUtsXLiYnaml19WlNCxR4M6QeNqSQxiNBhLztu+zzU+Q
dj2KLqnDUoMUI/1HqDfBAJFhOhVpmmKOXkYB8DH19l4oS1Eg1ap52wXXozY6
OpuzAVmCJjWjl2ap8W1zezCn4w/oI0mfse+A/YF6+Qtc7NvkQjA+S3Ny12Nr
5ZXf6/UQXegrnSoNLdD0TBTg7haV0alz7sSTdDUcYcq7uiyVxbyaTppESujQ
r1aQpf8fx4fvLA8n2igJ6Q4jxNWV0S3aU66vPbE9VPBZWVVVAjFEXPfuWD7d
rbLEab+nPsHhL1s7f9l8Bf8zoAF/GVP8y+YWPJAwKb97ZRQ3hL94Lh8wRXnt
1pv1mJtRYLFdr/RL/0EkemQkJXxsgpDg/pusMm4Xw26GvBVFfB8hX38228Pf
Dbvy1lgZrI3zIZP8kztCwkaYBqKalmgduybkUTGbUmCaydTZgit7EjAdoxxA
QiFya2qLE1CqYVStLU5+V9T3/lNfsWhji5SOFDdd9cV41mKPVOU6QRdeNBGG
OXt5s320wc+ZB634iuVVNhRd6vDuyT+LYpdKSyIfei22bjmIdB9WYiFhVxYy
IRe4aiVPjS0GstykStzS7gxaNfyqqzvWEQKJlG+i5LQ42/bXneR/Q27kZymD
p6BJsHdlflUn9fbM0sIzWxIno461A/lvTENrMd7C6Af+cTScZeh9Dtufx6FK
7y0d3S3PQp8udOXzLaopB8occCHsXRgSgpkwhM/mm9fKDVv4H4sGXhBO4oQp
KfpziLHQGKPh8yh/bOY3MK51wba9ZoeyHkuXZ9A0wpd8RQ/IrENmNcodEgzJ
J1WkThUmNkq5/wdFnPD0P0Zod8vY5DD0P0aXWIrYAoWwN2QpujegIyq7fW6h
V/oEWSh8ozmOjZ5kOCiwSfYVUZSEzjxmerIIj3mAL7EfqCuKMo9QqUsuwWbM
i/Cq68FYmz06yzC+NY6V4RY5J4TIkD/U4vFWj1S181vKiqxFNAYCWGQ09AGZ
a6ZprkKDRrOMDFUZm3gYKCFasriSEWW7CfKYJHMOdyhjoqU0EOVbc/90FrMP
n7CrEXcGeOXvwOCnaPt9Rxk6c7mS4tJ7hP0/RjciAW7zHkckoHTklrcoYjAl
20DEYa9BdoIWttCNzWfSeloOJfGqwSL06LdoPO6yNe/X9we5bFvvkex53W7X
R1s+wkjGLoSGnfbEciZOyDkRzb24QcIlT1W+pb5VZAXxyuSqjtFrdJWlmczY
9r/eX3cP9/b9l/uvD94d/+yNYtjUNTiBSTCNe5eT8RrM5zKYjLtjODqz4JQ9
X6Js2/8XDuP6SRIvJHJdftZLs9N+mAWjor+5vrkOlLjPLzzR87a/1VvvbXlx
Mkq3PZ9VTdsgdyT+wZFU+woU9x/hDj2mOABfpWqje+lTl0gdoQ8CTDh0wP6+
3z8+wehz87SNg0tAU2WpJyiJQ8WaFQafHU2hzqiIdDPLJVhRfNK9ADuywueE
s7jUfamwaaXsegkYWaQpYNyb9ALYjyg7vaRuzNi9nCNgOAYbgw/HmPZkOk4v
KWoJDmk2yQ9HIpfVto+7ApuSXwSnp1HWi9M+fYGWNtLKDYttGgM2JQYqMhhg
pM3Hyb8P0V0JLyB4C5CLKIQaP0yowMDJS87CN8vG8g9YRU67sd57CluKC8+S
YLyXDjHq094wui0O9k9e+YQdnuhIohDy2XBWh+gBEEfFiPEoHTIudfFRN0CP
VXRe6XuMiTRKlztauzq9+IA39XWfPuF268/5YjwPspiKWW2LG1h8LP/0ZSKZ
8pXPr8xAeuHhjPyBVwSnYg4MIzMOk11BvUoHAnN9EVqKJFelKSdtJ1Y+wf0X
vjZCgDWiO0X7g/qSDKJ2h1WJg11PkAZIpjjWvhpmLQarOoeOySqtUvv832CJ
grkwaqs5app5Evri2C22XtHaWPXt1mvEA7dacEO9lXLXeo7tu+c2EjmMPGSV
3q1rsHX/0hvXhzPHt0yunKNMnsHzpkFxBofggUzVf1RCfztRhaE6u5IHhSqm
8EmcztSRlGeLf7p1Zws9ISbIk20L7Z+oO1LVAqpcKI5TrSDgt+2lHT6Wi+cM
IkrIPZuKnFCq7g0hpsQZ5qIxFwfyms4z7KqO4y+tOo7vrI7jH1DiPHTWJmcc
8vTpxqEkSOrqxNoanOdLIoP4Ympk95D7yqgah2oDYtgPRCo3/T05iyoeVj3/
NTkdwXORUoTITaRm5ssdCQ17IeEO8SYazXyfRTiu5Gk8Zg+7bX82M2bqy7sd
TWvzhdDSkk30b7l4ji0RyIi55oS+e2nLVOtpXwCM5VIU2vuGGht4jgmhwyxT
aUNEgjrOYilHFKKzObey/Gy+c60Ff/4FZJBt/+GDPsUyJyTs85d5/294kh/W
DGCq0NsMVAM4/JE4wmr25j1Rqel0/w831588NIeztl4k5+lgLs+hoaHnD5l3
qWvLTrZySOMrB/Bt6ExZdPmhug118GneCpEHSKbueciKHeB4bk71ha2NybVI
enUDsm91s6L6N6T6r6NiRfLvlOSTYwKi+ddC8110bn0unVuESC2LOFXuibY3
Rf1wDbdF7X3xdVPzOnZ/Cfy9SgbORLpU5dUsNrMcZj/TtXfsdEvWbfAd3QRz
+fxY1n5YkX05lS/B8EqCTASN0so9bAbPfaPSsKmHsLrKc8Si1guXZKkEgK+b
vC6dWZYk1EHplsM8u/u2stOu6KjJOa+I6GK88z+xGLt79UfWtY0WXdjXmy6S
8qkbT4FzmOT2ia5l974rHvum1PsgfLhwm2+c4gMQlWJ937S42Gy28G65on9N
dbph4nJeFiUrjnFTCF+oQPpkOmsvO4Bp3AptusD7gbNQc9woRocuYvD5pi4G
173AQGSPW369hFtBBiaHlLOJAB/fmC5+DuKvELvlAhnhyJKFKT8l+Re5bb6k
6gQejouzPEry1PDjGgGK7sGeUkxTI1nfWISsc07B0iWlnPtKpMnqS1U6F5yD
TGIQnZuK5zpwNQKNfxSSZHHlnQarm8wZBeTXjP3/eqm8X0vRjaXyIGGEORdv
SNT3hLX9NlS9VR/+iqQ38PoChN87Ude43XKFsoGRWb+G0Au3knu5/JXpT1I9
+6eVdqOetmGFE+06fhsKt0BPBp0LLUIna6nEItaYSA2RmI6q2RCPxDsSwell
nVFtRSrujFSIZNT3cfX3U7BfWEYn5H3oGxv11dKsGj5te6m0i/tcQP1aR7AM
1avZp5saOknOXWsi7+Opm0NzGtSNB5Lo6HUKuCuqI4jOKB4XqpisvX6qpDoX
ALdRRtbA6tugUXMJEace+fZUhUia6Cr/zDrBspA3h1a16uM7FBRdVJhhRcaa
JTOAkuejZXAJWc0i3aXGbKUb/KK6wY5YfXmx34Kq0EX8vj1N4bxl3pmWcEE6
366TFaE3FYJflNLfZ5XZSmO40hgKjeHdKAgXJG6LdLV0XeAXpRL3WFu20hXe
RA7vlHHyiwnm34QU7mTQ7k49uCS6VaMorJCyuRRpifpCRZLEkaQ8KfTwPh6/
pSgN85XWsB21oiIgWQy/m1NZ6RGXokdUDod2ygPb7iHSGvSv+JdF9IvlTAoG
oTuSSRMS+VV7I0hj2+9QzlwobnOHul6FbtYTdo3nLZcukLDCQ6rUI0tb7RI0
jbz/fbiJsuI24fqfM5revPLc98lm/X0ii2B35D7pSjSV/VmmcjQwk9M0w+YO
HCgV1f4G9aJzF9qOC2+4nSrc88J3VGMPLV0oDW2CRl2HOkG8nK9P2DFRckXz
/eVqEuqugW9SlVBGyC/BnDM6V90Mv2rqZv1UqB0zmn3NI7bkxF2Jxwx6J8qm
tCVu5c97/pYQ03JMxirg3zHK09HrS5gngPJSJl0tFWWnHKLAgigOvsq2V+qt
Ah2cAY9crcNaSf/WAYFgjNRUEV/RSBaI11ke7dnUM9G7ZP7UJWdqCauTtDoo
zHLIay2FcePo51ID3F2AfJBcupwVm10V9bZV/ZNVy17fKFJLIYj0x9tg2sN8
qXVxivKjrsjU+QZEO1dc/ny+9qvzAJ0T2bkkgMKv3wi5Z/I9J1eKwalyquho
ApQKC6hNy8mKxeRKiVSGwRATZWvoiUhM2zezjty368R/9eUoMc9Qz2xFib9o
qpIV2Sw/XpHNOXC7Cdls4fp0c8q5hwTMZnN1nuJaR6hykwaatUezX3GPX6Pr
+RJO+Vd9/Mo/9GgBfduCZxGVaYZZBPVqkcV8zDmYjvazvMS9SGXbxVkk83dj
yZI473M6flGGtKNz+0tWZyI4IbsOfHAOYAuoNIAAIHetiIk4gKrnekoB01+R
ie+UTDjarJgB24pNZuz3Ru57smFX6++1VJW5s+hbmdV0TUBlZ5tDgZxtJC1B
W5TOX9Xh9D85VYYQ1g0XbZB5+49LU7gJfy9rDy7A4zs3B+byFkH9lSUhdLvM
8I/DcUYMVne45x1vANL7aBRlWLXnvp7AG1Kum+UxnHvi8P5GZwyJ8qiFUMU4
8c5r4w3X3IGTUYeJ82blK8T93hDXfYf0r0RV1JZVTOaitsx0bJSXnYPLjha3
u0i4+hBsbgvWUqx+Af5StJA2nwBLyDEKidJxsuwhWsHL1yn+LIfPvKXnzG08
Zb7zy/WGJ/J7Ijat1VlzyQkrlRbhTB0tbkdOeBllrnTpRIV79xO74T0jFquT
+JWdxOXwq1TXz2Q22x5G4lOXdhKZfV0dw2/mGJau/2/2CNqMN1Yi7MLs+lf4
2850qjw8l6nL8UXnc05otQE7/KEjnKiVLEsqCz0vfuZODikJxJ41ctMRVQBY
4JBqB0VZ0pFnLO3ymkwt/QB/bXZrJ4KK3fk+uO7KYr9ZGrM82b1cfbwtKZnX
/OaEhXv+smSFtQormrKiKd8JTal24PHKlibV35TQzGt+c0LDPa8Izfdimf5u
jjL1sRS71U0PbbltGBUwzXxJBxd6X53a1amtWcbXeWo9/RH2Jr7b9h74L4M8
8lPSEOXegwf+DqcYicOONktVQjFpQnBWDFaR0NM4HgrFGB1TS9NWqoeKP3Fo
LnOx8D47ppkW0D2NEjzTUej/+uvBnnMxdhqVRY8BA2tqJguQmQOa4DK1swu0
hM601HMDjO6oyBqNYEcVNi3TivBuuUj2PVxkibuHb4/e7J/s79USHRVmrKNQ
FS4cvPtw9P7w9fv942NEB90Zby3VcaSOqaxa02r1p60Xe2722bBWlQDgsohc
IAhf/+3PcOenn8xJi7BqXX2S/tzT7qBWvTg5iRKtaVdx7mHL70VVaZpkwl4Z
OC3ZDc87r06OMspsW6A1XTpKjhyta+TxTHT6OPqtaYfNNK4tdzg6L10HNTts
ISz0MoRm3SgZpuj++x/Hh+/8aRonqFcFLoZyQO29kimryg4BCi2WmG2Xj/6B
igLfXgwMcaVhC2xfmMArL2ORx00MemPq7hs/fLJKbsa7pTDj1vAQwcBVYOAe
n0aZAxrwZmvTtZQtq9fLtyJ92c6Ro/tBmo6jIHF1U2Iqsdqib7LA4nfZJxys
9oRCtH37z6LYHcdWgrvWDV9m6ccoW7Dhb9HgLE0/Lt4qT4cfIzXNRQ67A+ot
co21SAnomdugQdkO83TJkUmlZaV1eSAG/U0GslvWtMafKrnl3fr1/UHpySyP
spI1lViqIM8v0swkGM5Z4Q90WqnJ2pBgRh0RXFFvQEtCWrr9448/blnfyrmV
mfU2nWPbDeulXNKN5iob213y5Hd3dgEu5Una5YL33/ry+tnd8YcIxxEKMVHb
uQxneZFOTtJpPFwAHNYkuAv/7X+enMC1Bx3h5TedDcZxfga/1i2dm/WphfjG
xGhBExZF5wu7WU3T2ub4c1O8E0MTzj15YqOcMx9T7dTwJwjDGOEbjI8cNGyB
eVXa/NENpnH3Y3S57Y/+EY0/drfC8dbWqLt5Eea2sgFDgxQeNoHEfFfaRCbR
N9hGu2EDtO5iI3nw73MriafQPjGW5o9yncSKszJ9qhq22JbzgCX+9f0bdqCl
EQWvDEPORwzh3XM3wnXV7Uau8q2OvHFIXzV7by+bxq64R5cWam0MefRPg2HN
RfWZcU1BbI7EYjUUKrp3zStpPo7VnrtlvraF0xE5Zz9cpAUjhbCyyx5aY7ne
7uJML86pSyl13W4bb5Qt5lirjBrSxdQ1LSW9bt1uZ15+mnk7UEUKqy+ZCvqY
Dm5FXysmXoVVnB9lUe58Rc0OZ8V0RgYG1we+ivd9G0zdHwAn5zpJ8keIHeE5
7m9Oaa2qc2cYOI+jolU18y/rOCsdiPNcM8EWy5uzQF8GFx/s3UCWt3+GZ0EW
DIsow/yyw1t0WI8P+GNqU+oW1gI18KcV/OZCcJkwXC4UdyyVSuk15mX9phFL
3gr2+VzgWpivY3cd/hteDDe+Fm52KdzgSnBS9iYi10jgGonbXPxrwL3l4N1S
jmE9IZtHxD7D3bas87ksSNURq1pC9dUiiSRM5cOxAGkqGT5riJPr9DnJky1u
Ou3kS8sK4aJjdaTFTSEaN75m02+/4bfGc7ntFklY+p5XCI57wx8IkIsyBNJb
BqV8I5yoWm+xVrCtE5Hn0rL5Xhm3xbjKBehEtyaSPGcJcyhRLR1aBhW6BVpK
hNyZZ3m7HUZWCfvXQ4Ocl89XRX+8B9q7TNw87DtWdjy5pV/JDQyum+vrxmML
yX45OTmS6bPQeMIeBuQt9nR93fQEU0mvLC+yks/WgmukzyorbPY1+PX9gVST
RjRPbGSuOpmVyld0lZbu4uKiFwdJ0Euz036Q5/FpMiHcxQ+6wtWtix3mD5J4
OuzGyXkwjsNuyfVwCT3Cee3OsvGyuo3+KEA0AAB1lVdoN0kLeB4NZ7Zb5q3G
wWmT0rYrSuB0ndFmSxojTrqzvGw4vXG/kooSYHDy6GR7J51fZHGxzM6JPVAQ
rxaAXkLnhCx31fHyccS4lrrwTsGmnHxv6QMlaXdYTt239EH0CN0inkTprLir
kQZpgrHoXSw+cndAM9ZztwOJ27+rklXf8XiKmotx06xrsw93MfCf8ekg+lxI
IgaTC42SkPz6aKXjGR7q5V9hgywNwmGQF2pYDDlY/jijOJtcBFnUzdLxeBAM
P97hEBwe4UbHYACbtz0YB4mewRLZvycLsH9qsLgYL2RaPuCdEv66/kGtc/Mv
s0mQqOtX8nA4nKe/x8iYRUZXo7bi1f0wjTgLKtXoQzdqmRXVTj/bbvITLB94
GoGch8yzcg5WjFhuCAbYI/3Hcuy1KlEeFJFiYBdyWizJG219CJ1xj3PmaPP5
Db7NC3g3V4BguDvXA7OunmcjFCtCbzOEKnqNOdlele/wjbegcWlLAn4T5GAG
f9093Nv399/tHf/s/S/9eFfb/gPYiGTn6OAa5d2jcpZnT0TRieI+FB8WVJJB
U+2ILD2P0VcvyDFSrZDBDsD7e5zE0UzmjCf0LDiPcCd101lOLjPQyp2N2qtN
R92jJMmVeWHcHfuus+TKC/Bk/Yq8XIW0iIZnSTpOTy/RGZIq/QKcJ7OE/A55
EkYOaS8Yp9CKHgfJpaGdAdrNVBwXgJXGGjrzZB56D9dAs+W2EoSuZZngDoDS
oXBI451H3iHvqK/Bjr0AdwH4EVNaP9FxjLQWL7406ylaZw9l9eVJvGFUern/
+uAdINMIbkB/raxKWvMQs4JpvO1v9dZ7Wx6CBFGZbyL/HUDm4EgS+t00KeDS
9h/hzj/W83ir0o27ojAX6qPn/0bZvUPK1QRAiy6qoJ2Oc/yinASxvA2MzOMx
ozifPy6GAnuD8MBkpcBKTfLDkUjmzK5FwHzkF8EpXPi9OO3TF32Po/YCaQ2F
zuCy9AcDuByHHyf/PkTeFx2R4O0YelJqGY79PHnJV/MsG8s/gFHOCU7rvacA
eeReMsDKvXRIxMQCJR21g/2TV36YBSNkOakjySoho1YA/4sex3FUjIhlCtNh
n77u4qNugAI+8kn9hgi/ypY+sJ8RSAWsuE7DuSzTbSogjcIjC+qmapSPFXcr
S1tqDv3yzX47JSl8aBdIabdWvAhn46Juyca87/OKraTlDX3/N8kh7brnb50j
OEHL+s5doFl5BZr0jl4tE5q+v3R46oneFTzNEZxwfCnltioY1at7DkU1z7sC
ojGAE4ZBJTi3Yky55yDEaU7u7lSr7t3gSwxbasU2ec8h53AgWuLpFZ3XMfaG
0oe4t+sKh8dn/M2+4OvmsXVq7bdi7aCTpbB3rn4ok8aK7bISK7jAzQkWBP9B
QpKQaEgokTVhVfmcgz0H/bd5nAUP4sCli2qKfrHOkCxGWDYX1+far8m03xBs
0OSXYczhYM/toNBYLR5/arOgyJ+bBwpzFcjyvOqy2Mifg5F/wTngqb0pwaKr
iyq5RLq25CEX0K5CNOWElVJfDxLqIIKOKCIaWFxlzuk5964aHcxT52QoVllB
Y60H4Tg6mmWnFf8BO5aPlhX9MY2xzHGUxWnYMWtJcQWl3DmvqpLW2qKtZ+vr
/gM5T3/DP0tn9sfBrEg559+i+4ItWdesi3DGsgS9n8+m0zQr4FHhPxLjP14A
tHXB13BE2ZBEGiKmBx2jcrRZGZoytQgFi3Po5hgY0WP5dcXqjz9dNb7jVQIE
0PH4H7O8uEizj+WdlTG7H6NqZY6un6YDui8rxFNemop+ymKm9fKQXIcro4Pc
0yXQz1sGedfMX+gua962WJphOeiWfHEWXLWT5i6WwuFmVLU06zsH/a41Xs0O
2B81bUTZAcp4NRoHp7nxt6RGabbg3lScrD7zFtFC5m+Mw1et66P5x3qA7h5R
83bWp0R3EK7KEO5h+GmSFvFIz9nYkTvHuz01Vg3O6Q+a8E1PWeFaSywyW34u
DGqm8kq8d8KjogVxgUP7DS2BOy4LydZkj+o0DYYYf5czrcuhUb0J+HktYbqp
SFBlxxs4kAYW/BbMdwMd/BLzYQ3pHnFruR/GI7JqFDQPykiGeMNpY5xYMzcl
1V3hTMkLdEF8KDuizgG9gu9pULTlRB2fEk4rL54PBljtb6y42PzWiLwIdqwv
C1sXGXSDyBZiGmvmh07NvK30XlCjgHqQ49u72Dh8jTfWNzZ8nr2QiXyn0w98
tyW+k4oT5bUmW8xX1cHpqFHUsdqvra7OUCjeSl3H/SxFY1fT1UppV1Ha1QG9
llMRDZpE0ooNrYmos5PgYieQ29wpjyo138Jn0cGklr5oWqP0fLTlU3aBXFD4
0V0txb9vQxNpOZ/PAdZdHqsequKDRlGTP7FgqiG2GFRVX0sBqoapm2e4K6hK
nrwerGUzYFO+XhdgL080q9TeECa6Ww7CVjo+cQYC3SS3pPm0VvgR9G9QK6yV
jbWfi/i5pLZJdeK1JmLbRnr3s67jxh3Ekl9UDzw/dyDswky8m6zqjtxa+TqU
oh6rGIs/TkqzlHGeWS/cx245C7JHqpd/bgW02vvWlBLZGdcwp8/N4dzoEiCO
SJPkUPFnuUfCwyYKD2IN/wBsbi8K8Okkx1xiPNEPUwUi5P7VA3yqH1yzA+ko
RTNWxXczFxYbP/BH0YXcU7M/4eboybF6BH01Mikr/UGcBCDODMbpQLdtkkn2
VeTES2gj5JEHPv7bHQfJ6Sw45Sgf4Cv8f2Gc+Eky1FijoMvPmJdGPrq/ub65
DiKmQKDbCDfz1nUDIWd+l9+jqMMbTKN0uaO1q9OLD2dpXlz36RNut/6ccxOe
B1mMARnqPIqPTU2xsAmP02EwxnfGK2Mdr4Miuggu/V/wC1kjRpZNcZ0rr9KF
MsqSJzq5kOfoOh2PLq14asqOLpzWB5fau5oqpyfk8z5BS/ggyOMhdwZNUjiR
6PcOhwUnAosZw8nDwi0oCmK8hDm1vp5o/yoOr/uanPWv5PWCKQmv+4h4DK95
ZfQcADBK5PxG2BxY+EyzlsPB4spxNnVG7YX66vm/YXKN4dks+ejPpkSdzIZY
WxcaITlWefL47OU9dGcoOfdLyqrDGQJDWSc8F/KogKFEbg+5H5zkQw6F3UIj
jBHSDg3YwyRIgJjhjtPwVu/oZMMRrRTWcB4Jv/w4F4vtcAA8hi/hZI2mMsPI
GD0oYICQvHTSWYGEHXCQIgJwyBC9NzDoiQqMUFmRbqwcLaziQgQlJMjyUqzU
FpJHxFBFVwoKWbuMd8/BniopJHbwNc4Cn8t4LLycTO+PmppC1Uo0d29ElEs2
j9ECizfzelBPTCrQTSYX2IVgh2MGfy0PADoXLJyND3gwdFXlL1M60b7yb1RB
8cncAk4dQCe5GN1S3Ar1rW9eN2mReknSxbPXR/pa79VZDhPzG3SCxjVA7nsm
Jdw32Avft+HfbLtRFKC18Ub3qJu1KxdDhDyP/2xQDFSYYpsHHczGH83IwUU5
UGh+DzlQWtWtmc5KLys+c8VnLo/PRPQS3OS8ku7N7OQuEjhgy8xzPIeBbNfE
YnDwqK94my9fRtkmvnYohFhHxb0aUe09z7f2arUGkx31jZY3Yjs26xmHHeA6
pnYaGme1hDcpQ68tq9BgYS9lyXqDTORpVLAchNRe5HlwcDMGeLets9wGZQiM
fe783wTiHIQ/LeR68vDJ+kY9MH9NghmIMBnwAqHZ5Gl9E5mOQsxHt3raWO2T
7oNuHocR6d2A2bpvPJ/oCOkxZiwxeS3YhkpSyodX/yJA0BvAYYYhRMMeXHfX
D+15TdPqEbIpq2hM0ijhVA0yWcQVP5QtS9856UwjvNtBvRn2oo+6fJj80229
RWaeh9peWpC7usrjDuIjfyrFa+WPtW2H/7fa8Embhi+D6gkyetiY34Pz6Bpd
PJ3fRd1RVr2Uj7Szl7qjPa8kdDN3gjWdXzrOgc3r1XxkHRKYh4kDK2akqmhR
d4u1cniWVd2faenibjeWb0uE93GxC1eotg63g8f4zPWqb0gtl0En6xhEySLa
KUrNnxZcontIn1NAvbxN/5UeqoPUSVh9M0vYkigZd9lIx6xPXFTs2PxgRcP8
FQ37umiYQXDew2x20Y+Xgxrr6ZpuYufU0qf54db6VpPsEfmHWNP8PomMdyIr
3lRI/FbwwIKh47bK2WSxX1d+zqDawrrh+KRSqd1ozZeGWTq+pRmBqT+9rTci
KM1ffXH2WwJWCpNmer0FfcW0atDt9rRAVoD2jMuhHFRkNpQvWXkbiqCbINGz
w3jpgI8iXN8OSKsum+w2cPuepaHxwLhp21ZwrAMk9+0GojsQxBUf0/WPDo9P
HE9/dTx8vW8/xNXcdgLQbZ/5inmOEnNbsqod/uBfahu1d81ARwDALnVGaqmx
nEcrUmyMR+aTv2zt/GXzFfzPqGUJf+GVNEmJgfvL5hY8kEUay+9eGYVw8F00
Idy0dWhw5zgqezQk1nBkH2P4tZU3KLdoQ8XF29Ii/Tm2xqrncLRlTXuscD/L
klykdnKwbm7RRjHy7cysbmq2FBd1PT9Faow0pbDU97RCmXypbnGVxrVXxIr+
rOjPXdKfrEZOn1dF9vaEZl4HtfmbF+/KlVDYZjgdVjPFVQplJQueopn4psRW
ugmP5Di23Ufla8ATvYQyCfhqluC+ankD/fD13/4Md376yb3kMi0Ua15U2Pt8
y24mUYvBAX8mwR/vo2mE+pCnpVdwo2eXJ/FERYW4lIvlo8Rvv9OzVE9zWyHj
13v+6pYtBXC7Lte3e/4W2f5afbo6UuyTuTpYTZBl9vMOK2VpJLari9Dg7Mgo
p0+6+ZpORKUP/a2csgG2vgGYB30JMPNp3wBW3wCVNAw4Bv+m6cstd3+hWnIt
EEHJfqLkirMXiQn644sgtxqgO+IwErn1YXfSWW4oyio5Nr4/cvodb/scR3CO
sCP/7gV9wF9hcYb75wPuXNCtwg8rfa38wVf+4J8j7hARj+G1nLhDQuTbBhw2
d+KKNKQWqxDD24UYIrWVau6V18jXH2Ioqx/enxBDxLBViOHdhBgibGvdAl7F
2pXBZaNG+vnr+zeS/reze4lGC+GkYg1SYFQSEjAlmvaAXVjTeHnr+EPZry8S
si/Me4pp3T/+01jZaRaES+BC63vsmAUFV4zqilG9U0ZV4uEyWNJfBSoz2gr8
TkdtmVEuAFHbWnChkglErtAIeJQ0Fu/5mWMei3FnogdJkVY82ucJlaxxUXT6
rihNxUIcUKXLua0ZA+7Qoabi3PdtRGTKfiWuwwLSWTasd61tpZNUxEcRrltG
Ysp74OtkV0VHq+jI20dHut1h5M+yoiPnBGHeyuelRafNtKiupOYqJPNOQzLt
H3p0+9gmqrzMAfDEQ1XkjfZ82aLd9YSPZC49+7mMWJqcpsTKYppKpPlwOXVE
dXA0WcLB1S0FfLilHOMsyIUB5Fbc3Cpa6w6jtaqIsfTIrXsRovVFGacvwnuY
F1uFds+l2d9fxoslxA63uOJvdLXXagGWHGD7ZS+h/dUltLqEvupLqBru+HmC
havlQ5eY8WAVbWxi6NyI4xuqRb6eoOP7iU7WNtwuaHlXXjSOjxrCluPwRvXs
xOA3jnkOfHlFNdg2TZvBAtZLu5luWqWujloBSZqF8bD0MI/HwSD37Anex0IH
XAJbgTZLHRow+mzD/EwYUtt5/Rn+k+QCvKj91XV67pcZllZlLvPWZtjGHleW
1pWl9XO4BJa9n4Ut9raJZEvUgIQjq5JSJY9sixaWTDO0g8FX0szndGUrk67x
5V24tFEEyiFdnCIEBVmLugiU++P4VslT0Aiar866WhInKle/lbJM/txYqJg6
trpCtW5piMWf9xhr2t0ZGVUU2wHMXbXLPlUxHKI48fMI50yH6CKIUXMzSkkO
g6FNoH/tnoyiI4dpWD6qmIfXGs3Da/PNw/fagLtE02uTjXeRfiQJrUmlsHiH
rWzC9UIt/8wXbeV3c7Ny8U+DkMs/txJ1+UeSqG1nSCXQ5gyY4CJa7DprGK85
nl7+sODWlCqTfxQoX1VLZ1dHvVtI1ge6mT+GqOxvrDd+KmPe1komm7Wvbjvx
p0LybukZYR6e21tcKjy8ChlfnP1vbFpOg7q7EgVWooBLFFiiWafC5X5bWWG/
lLXHQaFulQXKnE06LKKiC2COgkoSsBvIQEbpLKrv1cTwv+QKYKj/kgikjhGR
ewPt7soHVISd//Dl/QZuoY5aslNA5Z4xTfoLXVANDedcTyvr++qSWl1S/tef
uvy7cBaooNSynQZa6fe+Go+ClcV/AYs/Nq0GIy1oNx+WmtU0rWuOP2hqbDoS
hiug/BGnJI+SkI+JjEcp0sq3jwSPh1cxuRHiFRXkwsGWaTj097jUsCmtrRVh
vd3vK/Pm9o/rP64r3amt5XCSkflL/YWb4XLjZDiehaTKNhfduGI41cWle23O
JNRRHY7/0Q2mcfdjBDi+JjH1xXpZkROEkmYc1ex2BbYlPLTP6ILYmFc8OJrA
e6yYyBpwLuCicvDuw9H7w9fv94+PS2+MU2mvtMSYyh5rKwksKI+1JYpLKDGg
c4guiNzQMJ7MJn4RT6Iaa9ZZOhvjtYfd12P60w725W+su1HdbSRS59hOfKrT
ni64GlrFICouoiih2eem1UnNdeNWc92Y5wukeHFDFmvlBCS55JX3z8r7Z+X9
szzvH05N1Ye9SPJJXCzFxedllgbhMADWhWbXKo5CtwlApL8cw19m6x5J8wP1
ETAPIuFCFPopsxw7RxgRkUWGroOyGI6xQQ5kTwxm6WB2CN5qdHl9V1QvTuWL
QwOxHAVMrSzulj9q2cEaifz+ZVho4gZOBG7eyFdmAb32/VK33sa07jrohl6V
crwt5aTLPH0kPNJ5TfQVP8ut5HoTgIjGz3mZ/8weZ0kWncY5HEc47LL7Dlxo
gwg4eh6DhywPJqURWIXI3BemkUxGTDikBlZ98FhMIXr+f6UzGUvFCTqJKFFE
lV8TUcUkBRkWWsyKpNzTpC3tRJZqzJHZg0Q4wDdym6E/3gbTRt8a+ZFiaj9n
Jrxvh8pZP3NIXqZk2FtSPBSGl0rwrA5HWTq5RxSP5BCeU1uS1+hksaJ4n4OJ
+rJkaSFHgnsXI1pSU30jxLJO446dnliSX6OG73ZYpWSsh8ZRKKcfHV4OVerh
tkp+bLKILZalZfONQ2Va+QgflhR9D3wpNrN2DUjvRGO3fFdW1tUp0tT8tky3
xQesFoDrQSnvZMd5zYAHosFCgz41xhTy9wIW38FlEbl63TndD3ZO07evzl+8
3Xm588vw7MXLfO/jaYS+jC5VoS/MWGS4n6RhNOYkCOVrjis5vnyz73tX2/4D
o55DNw9H1006RePbHnzbwxO45l3R9NfwdsqnwTBa2/av1IrMNmtG7tqa6iis
g7rucJeChrwzerb6E5/J6hRNA19Z+LimPAoqr+j1WRSMi7MPTV2obw2qhvP7
hZrixVuaZqWh4cBQ2zuvRJtwPyA2NX7tmtOJUVDmBDtwz0g1TweoNUQtILQe
BeM8mtMA5bsFPpfVbNb4Upzz9VRTwrkrpwbc8/wP6eOclcEHewiojR/XX8wB
jmo4PAtQ5RhlmF1+yO03dzb2mnyg+aday7Ld2+v6ma1NoiCH7UWl5wdJ9hbG
k7e6E1+SwhWu6I+XjCubG3eIK843NRiEpIhCh9rTIQPfbkWODJSbh2lIs2fF
dFbsBUXQbncXRQdqtAhKUANBk9dOg2LeIqx2N0UnalxDfnbnoxT+NKPV/C9u
RqSIME2iMA4KuMkMn71FMejA6Mg30GmFQktAof0vjkJu2lV5aj8pIV4ZZV5H
CSx0SGG+qN8TJuSDhBlx/KrUwTz+bI3VKR+Q8W3NHophkaWt4wvb3qjmTVp/
Nba7QFujeSvUrqDl+ryD6UbF9Yofkv5pjSTVkddAEIpgvGTYft92dJMlblvT
Z1/zvjUwNrfZt0mQzEYwHFD6jI7dBxarW+/iW6MDOoP+MXfwHe3pzs32dPPF
He0paio+JLPJAPZ00e0kLcc7arvayWqDmp18cjc7CYOFmOLqA9a4RAvQotv5
i+jAfy86WO1ptUHNnj6/mz2VCd5uvKcq79lqT+sb1Ozps7vZ0/wyB9nrQxy2
3sRjauHDxFa7phvU7NrWEnatUbBpVNasxflRFuVNapny7qIpIAjP0TiUkyIm
b9BYtxSfFxKbW4vLSkwuTfeu5UzHIYrzXa4mGrU/RghoowZpdP5VwFrP+IOY
8ecV6z37t2vv2mH+utpmn/Of1ha1gq1de/8P+0f/6BuiAgA=

-->

</rfc>

