xeps/inbox/sensor-data.xml

1258 lines
57 KiB
XML

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY exi "<span class='ref'><link url='http://www.w3.org/TR/exi/'>EXI</link></span> <note>Efficient XML Interchange (EXI) Format &lt;<link url='http://www.w3.org/TR/exi/'>http://www.w3.org/TR/exi/</link>&gt;.</note>" >
<!ENTITY pipe "&#124;">
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Sensor Data Interchange over XMPP</title>
<abstract>This specification provides the common framework for sensor data interchange over XMPP networks.</abstract>
<legal>
<copyright>This XMPP Extension Protocol is copyright (c) 1999 - 2013 by the XMPP Standards Foundation (XSF).</copyright>
<permissions>Permission is hereby granted, free of charge, to any person obtaining a copy of this specification (the &quot;Specification&quot;), to make use of the Specification without restriction, including without limitation the rights to implement the Specification in a software program, deploy the Specification in a network service, and copy, modify, merge, publish, translate, distribute, sublicense, or sell copies of the Specification, and to permit persons to whom the Specification is furnished to do so, subject to the condition that the foregoing copyright notice and this permission notice shall be included in all copies or substantial portions of the Specification. Unless separate permission is granted, modified works that are redistributed shall not contain misleading information regarding the authors, title, number, or publisher of the Specification, and shall not claim endorsement of the modified works by the authors, any organization or project to which the authors belong, or the XMPP Standards Foundation.</permissions>
<warranty>## NOTE WELL: This Specification is provided on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. In no event shall the XMPP Standards Foundation or the authors of this Specification be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Specification or the implementation, deployment, or other use of the Specification. ##</warranty>
<liability>In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall the XMPP Standards Foundation or any author of this Specification be liable for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising out of the use or inability to use the Specification (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if the XMPP Standards Foundation or such author has been advised of the possibility of such damages.</liability>
<conformance>This XMPP Extension Protocol has been contributed in full conformance with the XSF's Intellectual Property Rights Policy (a copy of which may be found at &lt;<link url='http://www.xmpp.org/extensions/ipr-policy.shtml'>http://www.xmpp.org/extensions/ipr-policy.shtml</link>&gt; or obtained by writing to XSF, P.O. Box 1641, Denver, CO 80201 USA).</conformance>
</legal>
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
<spec>XEP-0001</spec>
<spec>Etc.</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
<author>
<firstname>Peter</firstname>
<surname>Waher</surname>
<email>peter.waher@clayster.com</email>
<jid>peter.waher@jabber.org</jid>
<uri>http://se.linkedin.com/pub/peter-waher/1a/71b/a29/</uri>
</author>
<revision>
<version>0.0.1</version>
<date>2013-03-07</date>
<initials>pwa</initials>
<remark>
<p>First draft.</p>
</remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>This XEP provides the underlying architecture, basic operations and data structures for sensor data communication over XMPP networks. It includes a hardware abstraction model, removing any
technical detail implemented in underlying technologies.</p>
<p>Note has to be taken, that these XEP's are designed for implementation in sensors, many of which have very limited amount of memory (both RAM and ROM) or resources (processing power).
Therefore, simplicity of utmost importance. Furthermore, sensor networks can become huge, easily with millions of devices in peer-to-peer networks.</p>
<p>Sensor networks contains many different architectures and use cases. For this reason, the sensor network standards have been divided into multiple XEPs according to the following table:</p>
<table caption='Sensor Network XEPs'>
<tr>
<th>XEP</th>
<th>Description</th>
</tr>
<tr>
<td>XEP-0000-Exi</td>
<td>Defines how to EXI can be used in XMPP to achieve efficient compression of data. Albeit not a sensor network specific XEP, this XEP should be considered
in all sensor network implementations where memory and packet size is an issue.</td>
</tr>
<tr>
<td>xep-0000-SN-BatteryPoweredSensors</td>
<td>Defines how to handle the peculiars related to battery powered devices, and other devices intermittantly available on the network.</td>
</tr>
<tr>
<td>xep-0000-SN-Concentrators</td>
<td>Defines how to handle architectures containing concentrators or servers handling multiple sensors.</td>
</tr>
<tr>
<td>xep-0000-SN-Control</td>
<td>Defines how to control actuators and other devices in sensor networks.</td>
</tr>
<tr>
<td>xep-0000-SN-Discovery</td>
<td>Defines the peculiars of sensor discovery in sensor networks. Apart from discovering sensors by JID, it also defines how to discover sensors based on location, etc.</td>
</tr>
<tr>
<td>xep-0000-SN-Events</td>
<td>Defines how sensors send events, how event subscription, hysteresis levels, etc., are configured.</td>
</tr>
<tr>
<td>xep-0000-SN-Interoperability</td>
<td>Defines guidelines for how to achieve interoperability in sensor networks, publishing interoperability interfaces for different types of devices.</td>
</tr>
<tr>
<td>xep-0000-SN-Multicast</td>
<td>Defines how sensor data can be multicast in efficient ways.</td>
</tr>
<tr>
<td>xep-0000-SN-Provisioning</td>
<td>Defines how provisioning, the management of access privileges, etc., can be efficiently and easilly implemented.</td>
</tr>
<tr>
<td>xep-0000-SN-PubSub</td>
<td>Defines how efficient publication of sensor data can be made in sensor networks.</td>
</tr>
<tr>
<td>xep-0000-SN-SensorData</td>
<td>This specification. Provides the underlying architecture, basic operations and data structures for sensor data communication over XMPP networks.
It includes a hardware abstraction model, removing any technical detail implemented in underlying technologies. This XEP is used by all other sensor network XEPs.</td>
</tr>
</table>
</section1>
<section1 topic='Glossary' anchor='glossary'>
<p>The following table lists common terms and corresponding descriptions.</p>
<table caption='Glossary'>
<tr>
<th>Term</th>
<th>Description</th>
</tr>
<tr>
<td>Actuator</td>
<td>Device containing at least one configurable property or output that can and should be controlled by some other entity or device.</td>
</tr>
<tr>
<td>Computed Value</td>
<td>A value that is computed instead of measured.</td>
</tr>
<tr>
<td>Concentrator</td>
<td>Device managing a set of devices which it publishes on the XMPP network.</td>
</tr>
<tr>
<td>Field</td>
<td>One item of sensor data. Contains information about: Node, Field Name, Value, Precision, Unit, Value Type, Status, Timepoint, Localization information, etc.</td>
</tr>
<tr>
<td>Field Name</td>
<td>Name of a field of sensor data. Examples: Energy, Volume, Flow, Power, etc.</td>
</tr>
<tr>
<td>Historical Value</td>
<td>A value stored in memory from a previous time point.</td>
</tr>
<tr>
<td>Identification Value</td>
<td>A value that can be used for identification. (Serial numbers, meter IDs, locations, names, etc.)</td>
</tr>
<tr>
<td>Localization information</td>
<td>Optional information for a field, allowing the sensor to control how the information should be presented to human viewers.</td>
</tr>
<tr>
<td>Meter</td>
<td>A device possible containing multiple sensors, used in metering applications. Examples: Electricity meter, Water Meter, Heat Meter, Cooling Meter, etc.</td>
</tr>
<tr>
<td>Momentary Value</td>
<td>A momentary value represents a value measured at the time of the readout.</td>
</tr>
<tr>
<td>Node</td>
<td>Graphs contain nodes and edges between nodes. In Sensor Networks, sensors, actuators, etc., are often depicted as nodes and links between sensors (frienships) are depicted as edges.
In abstract terms, it's easier to talk about a Node, than have to list different types of nodes possible.</td>
</tr>
<tr>
<td>Peak Value</td>
<td>A maximum or minimum value during a given period.</td>
</tr>
<tr>
<td>Precision</td>
<td>In physics, precision determins the number of digits of precision. In sensor networks however, this definition is not easilly applicable. Instead, precision
determines, for example, the number of decimals of precision, or power of precision. Example: 123.200 MWh contains 3 decimals of precision. All entities parsing and
delivering field information in sensor networks should always retain the number of decimals in a message.</td>
</tr>
<tr>
<td>Sensor</td>
<td>Device measuring at least one digital value (0 or 1) or analog value (value with precision and physical unit). Examples: Temperature sensor, pressure sensor, etc.</td>
</tr>
<tr>
<td>SN</td>
<td>Sensor Network. A network consisting, but not limited to sensors, where transport and use of sensor data is of primary concern. A sensor network may contain actuators, network applications, monitors, services, etc.</td>
</tr>
<tr>
<td>Status Value</td>
<td>A value displaying status information about something.</td>
</tr>
<tr>
<td>Timepoint</td>
<td>Timepoint of value, when the value was sampled or recorded.</td>
</tr>
<tr>
<td>Value Status</td>
<td>Status of field value. Contains important status information for Quality of Service purposes. Examples: Ok, Error, Warning, Time Shifted, Missing, Signed, etc.</td>
</tr>
<tr>
<td>Unit</td>
<td>Physical unit of value. Example: MWh, l/s, etc.</td>
</tr>
<tr>
<td>Value</td>
<td>A field value. Can be numeric, string, boolean, Date &amp; Time, Time Span or Enumeration.</td>
</tr>
<tr>
<td>Value Type</td>
<td>What type of value is represented by the field. Examples: Momentary Value, Status Value, Identification Value, Calculated Value, Peak Value, Historical Value, etc.</td>
</tr>
<tr>
<td>WSN</td>
<td>Wireless Sensor Network, a sensor network including wireless devices.</td>
</tr>
</table>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<p>
The most common use case in sensor network application, is meter readout. It's performed using a request and response mechanism, as is shown in the following diagram.
</p>
<p>
<img src='http://i.imgur.com/tTGDh4m.png'/>
</p>
<p>
The readout request is started by the client sending a <strong>req</strong> request to the device. Here, the client selects a sequence number <strong>seqnr</strong>.
It should be unique among requests made by the client. The device will use this sequence numbers in all messages sent back to the client.
</p>
<p>
The request also contains a set of <strong>readout types</strong> that very roughly determine what the client wants to read. What the client actually will return will be determined by
a lot of other factors, such as make and model of device, any provisioning rules provided, etc. This parameter just gives a hint on what kind of data is desired. It is implicit in the request
by the context what kind of data is requested. Examples of readout types are: Momentary values, peak values, historical values, computed values, status values, identification values, etc.
</p>
<p>
If reading historical values, the client can also specify an optional time range using the <strong>from</strong> and <strong>to</strong> parameter values, giving the device a hint on
how much data to return.
</p>
<p>
If the client wants the readout to be performed at a given point in time, the client can define this using the optional parameter <strong>when</strong>.
</p>
<p>
There's an optional parameter <strong>ids</strong> that the client can provide. If omitted, the request includes all sensors or devices managed by the current JID.
But, if the JID is controlled by a system, device or concentrator managing various devices, the <strong>ids</strong> parameter restricts the readout to specific individuals.
</p>
<p>
<strong>Note:</strong> The device is not required to follow the hints given by the client. These are suggestions the client can use to minimize its effort to perform the readout.
The client MUST make sure the response is filtered according to original requirements by the client after the readout response have been received.
</p>
<p>
If the device accepts the client request, it sends an <strong>accepted</strong> response back to the client. The client also has to determine if the readout is commenced directly,
or if it is to be queued for later processing. Note that the request can be queued for several reasons. The device can be busy, and queues it until it is ready to process the request.
It can also queue the request if the client has requested it to be executed at a given time. If the request is queued, the device informs the client of this using the <strong>queued</strong>
attribute. Note however, that the device will process the request when it can. There's no guarantee that the device will be able to process the request exactly when the client requests it.
</p>
<p>
If the request was queued, the device will send a message informing the client when the readout is begun. This is done using a <strong>started</strong> message, using the same
<strong>seqnr</strong> used in the original request.
</p>
<p>
During the readout, the device sends partial results back to the client using the same <strong>seqnr</strong> as used in the request, using a <strong>fields</strong> message.
These messages will contain a sequence of fields read out of the device. The client is required to filter this list according to original specifications, as the client is not required
to do this filtering for the client.
</p>
<p>
When readout is complete, the device will send a <strong>done</strong> message to the client with the same <strong>seqnr</strong> as in the original request. Since the sender
of messages in the device at the time of sending might not be aware of if there are more messages to send or not, the device can send this message separately as is shown in the
diagram. If the device however, knows the last message containings fields is the last, it can set a <strong>done</strong> attribute in the message, to skip this last message.
</p>
<p>
<strong>Note:</strong> There is no guarantee that the device will send a corresponding <strong>started</strong> and <strong>fields</strong> element, even through the request was
accepted. The device might loose power during the process and forget the request. The client should always be aware devices may not respond in time, and take appropriate action
accordingly (for instance, implementing a retry mechanism).
</p>
<p>
If a failure occurs while performing the readout, a <strong>failure</strong> message is sent, instead of a corresponding <strong>fields</strong> message, as is shown in the following diagram.
Apart from notifying the client that a failure to perform the readout, or part thereof, has occurred, it also provides a list of errors that the device encountered while trying. Note that
multiple <strong>fields</strong> and <strong>failure</strong> messages can be sent back to the client during the readout.
</p>
<p>
<img src='http://i.imgur.com/5WsyGcW.png'/>
</p>
<p>
The device can also reject a readout request. Reasons for rejecting a request may be missing privileges defined by provisioning rules, etc. It's not part of this XEP
to define such rules. A separate XEP (<link url='xep-0000-SN-Provisioning.html'>xep-0000-SN-Provisioning</link>) defines an architecture for how such provisioning can be easilly implemented.
</p>
<p>
A rejection response is shown in the following diagram.
</p>
<p>
<img src='http://i.imgur.com/dfNFwDo.png'/>
</p>
<section2 topic='Request Readout of momentary values'>
<p>
The client who wishes to receive momentary values from the sensor, initiates the request using the <strong>req</strong> request sent to the device.
</p>
<example caption='Readout request of momentary values from a device'>
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
type='get'
id='1'>
<req xmlns='urn:xmpp:sn' seqnr='1' momentary='true'/>
</iq>]]>
</example>
<p>
When the device has received and accepted the request, it responds as follows:
</p>
<example caption='Readout request accepted by device'>
<![CDATA[
<iq from='device@clayster.com'
to='master@clayster.com'
type='result'
id='1'>
<accepted xmlns='urn:xmpp:sn' seqnr='1'/>
</iq>]]>
</example>
<p>
When readout is complete, the response is sent as follows:
</p>
<example caption='Momentary readout response'>
<![CDATA[
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='1' done='true'>
<node nodeId='Device01'>
<timepoint value='2013-03-07T16:24:30'>
<numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/>
</timepoint>
</node>
</fields>
</iq>]]>
</example>
</section2>
<section2 topic='Readout failure'>
<p>
If instead a readout could not be performed, the communication sequence might look as follows:
</p>
<example caption='Momentary readout failure'>
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
type='get'
id='2'>
<req xmlns='urn:xmpp:sn' seqnr='2' momentary='true'/>
</iq>
<iq from='device@clayster.com'
to='master@clayster.com'
type='result'
id='2'>
<accepted xmlns='urn:xmpp:sn' seqnr='2'/>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<failure xmlns='urn:xmpp:sn' seqnr='2' done='true'>
<error nodeId='Device01' timepoint='2013-03-07T17:13:30'>Timeout.</error>
</fields>
</iq>]]>
</example>
</section2>
<section2 topic='Readout rejected'>
<p>
If for some reason, the device rejects the readout request, the communication sequence might look as follows:
</p>
<example caption='Momentary readout rejected'>
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
type='get'
id='3'>
<req xmlns='urn:xmpp:sn' seqnr='3' momentary='true'/>
</iq>
<iq from='device@clayster.com'
to='master@clayster.com'
type='result'
id='3'>
<rejected xmlns='urn:xmpp:sn' seqnr='3'/>
</iq>]]>
</example>
</section2>
<section2 topic='Readout All'>
<p>
The following example shows a communication sequence when a client reads out all available information from a sensor at a given point in time:
</p>
<example caption='Readout of device with multiple responses'>
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
type='get'
id='4'>
<req xmlns='urn:xmpp:sn' seqnr='4' all='true' when='2013-03-07T19:00:00'/>
</iq>
<iq from='device@clayster.com'
to='master@clayster.com'
type='result'
id='4'>
<accepted xmlns='urn:xmpp:sn' seqnr='4' queued='true'/>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<started xmlns='urn:xmpp:sn' seqnr='4'/>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='4'>
<node nodeId='Device01'>
<timepoint value='2013-03-07T19:00:00'>
<numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/>
<numeric name='Runtime' status='true' automaticReadout='true' value='12345' unit='h'/>
<string name='Device ID' identification='true' automaticReadout='true' value='Device01'/>
</timepoint>
</node>
</fields>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='4'>
<node nodeId='Device01'>
<timepoint value='2013-03-07T19:00:00'>
<numeric name='Temperature, Max' peak='true' automaticReadout='true' value='25.9' unit='°C'/>
<numeric name='Temperature, Min' peak='true' automaticReadout='true' value='18.7' unit='°C'/>
<numeric name='Temperature, Mean' computed='true' automaticReadout='true' value='22.5' unit='°C'/>
</timepoint>
</node>
</fields>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='4'>
<node nodeId='Device01'>
<timepoint value='2013-03-07T18:00:00'>
<numeric name='Temperature' historicalHour='true' automaticReadout='true' value='24.5' unit='°C'/>
</timepoint>
<timepoint value='2013-03-07T17:00:00'>
<numeric name='Temperature' historicalHour='true' automaticReadout='true' value='25.1' unit='°C'/>
</timepoint>
<timepoint value='2013-03-07T16:00:00'>
<numeric name='Temperature' historicalHour='true' automaticReadout='true' value='25.2' unit='°C'/>
</timepoint>
...
<timepoint value='2013-03-07T00:00:00'>
<numeric name='Temperature' historicalHour='true' historicalDay='true' automaticReadout='true' value='25.2' unit='°C'/>
</timepoint>
</node>
</fields>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<done xmlns='urn:xmpp:sn' seqnr='4'/>
</iq>]]>
</example>
</section2>
<section2 topic='Readout of multiple devices'>
<p>
The following example shows how a client reads a subset of multiple sensors behind a device with a single JID.
</p>
<example caption='Readout of multiple devices'>
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
type='get'
id='5'>
<req xmlns='urn:xmpp:sn' seqnr='5' momentary='true'>
<node nodeId='Device02'/>
<node nodeId='Device03'/>
</req>
</iq>
<iq from='device@clayster.com'
to='master@clayster.com'
type='result'
id='5'>
<accepted xmlns='urn:xmpp:sn' seqnr='5'/>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='5'>
<node nodeId='Device02'>
<timepoint value='2013-03-07T19:31:15'>
<numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/>
</timepoint>
</node>
</fields>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='5' done='true'>
<node nodeId='Device03'>
<timepoint value='2013-03-07T19:31:16'>
<numeric name='Temperature' momentary='true' automaticReadout='true' value='22.8' unit='°C'/>
</timepoint>
</node>
</fields>
</iq>]]>
</example>
</section2>
<section2 topic='Readout of specific fields'>
<p>
The <strong>req</strong> element can take <strong>field</strong> sub elements, with which the client can specify which fields it is interested in.
If not provided, the client is assumed to return all matching fields, regardless of field name. However, the <strong>field</strong> elements in the
request object can be used as a hint which fields should be returned.
</p>
<p>
<strong>Note:</strong> the device is not required to adhere to the field limits expressed by these <strong>field</strong> elements. They are considered
a hint the device can use to limit bandwidth.
</p>
<p>
The following example shows how a client can read specific fields in a device.
</p>
<example caption='Readout of multiple devices'>
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
type='get'
id='6'>
<req xmlns='urn:xmpp:sn' seqnr='6' momentary='true'>
<node nodeId='Device04'/>
<field name='Energy'/>
<field name='Power'/>
</req>
</iq>
<iq from='device@clayster.com'
to='master@clayster.com'
type='result'
id='6'>
<accepted xmlns='urn:xmpp:sn' seqnr='6'/>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='6' done='true'>
<node nodeId='Device04'>
<timepoint value='2013-03-07T22:03:15'>
<numeric name='Energy' momentary='true' automaticReadout='true' value='12345.67' unit='MWh'/>
<numeric name='Power' momentary='true' automaticReadout='true' value='239.4' unit='W'/>
</timepoint>
</node>
</fields>
</iq>]]>
</example>
</section2>
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>If an entity supports the protocol specified herein, it MUST advertise that fact by returning a feature of "urn:xmpp:sn" in response to &xep0030; information requests.</p>
<example caption="Service discovery information request">
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
id='disco1'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>]]>
</example>
<example caption="Service discovery information response">
<![CDATA[
<iq from='device@clayster.com'
to='master@clayster.com'
id='disco1'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='urn:xmpp:sn'/>
...
</query>
</iq>]]>
</example>
<p>In order for an application to determine whether an entity supports this protocol, where possible it SHOULD use the dynamic, presence-based profile of service discovery defined
in &xep0115;. However, if an application has not received entity capabilities information from an entity, it SHOULD use explicit service discovery instead.</p>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
<section2 topic='String lengths'>
<p>
As noticed, a concious effort has been made to not shorten element and attribute names. This is to make sure, XML is maintained readable. Packet size is not deemed to be
affected negatively by this for two reasons:
</p>
<ul>
<li>For sensors with limited memory, or where package size is important, &exi; is supposed to be used. EXI compresses strings as normalized index values, making the string appear only once in the packet. Therefore, shortening string length doesn't affect packet size much.</li>
<li>If limited memory or package size is not a consideration, readability and ease of implementation is preferred to short messages.</li>
</ul>
</section2>
<section2 topic='Enumerations vs. Strings'>
<p>
This protocol has avoided the use of enumerations for data types such as units, field names, etc, and instead use strings. The reasons for this are:
</p>
<ul>
<li>Enumerations would unneccesarily restrict the use of the protocol to field names and units listed in the protocol.</li>
<li>It would be very difficult to try to create a complete set of field names and units that would suit all applications.</li>
<li>Leaving these values as strings would let developers the liberty to use units as they desire.</li>
<li>If EXI is used for compression, the use of strings will only increase payload slightly, with only one copy of each distrinct value used.</li>
<li>If EXI is not used, this does not affect packet size.</li>
</ul>
<p>
However, some things need to be taken into account:
</p>
<ul>
<li>Since free strings are used, XML validation cannot be used to secure correct names are used.</li>
<li>xep-0000-SN-Interoperability lists recommendations on how field names and units should be used in order to achieve maximum interoperability in SN.</li>
<li>Consumers of sensor data need to include unit conversion algorithms.</li>
</ul>
</section2>
<section2 topic='Asynchronous feedback'>
<p>
Since some applications require real-time feedback (or as real-time as possible), and readout might in certain cases take a long time, the device has the option
to send multiple <strong>fields</strong> messages during readout. The client is responsible for collecting all such messages until either a <strong>done</strong> message
is sent, or a corresponding <strong>done</strong> attribute is available in one of the messages received. Only the device knows how many (if any) messages are sent in
response to a readout request.
</p>
</section2>
<section2 topic='Field Value Types'>
<p>
There are different types of values that can be reported from a device. The following table lists the various types:
</p>
<table caption='Field Value Types'>
<tr>
<th>Element</th>
<th>Description</th>
</tr>
<tr>
<td>numeric</td>
<td>
Represents a numerical value. Numerical values contain, apart from a numerical number, also an implicit precision (number of decimals) and an
optional unit. All parties in the communication chain should retain the number of decimals used, since this contain information that is important
in the interpretation of a value. For example, 10 °C is different from 10.0 °C, and very different from 10.00 °C. If a sensor delivers the value
10 °C you can assume it probably lies between 9.5 °C and 10.5 °C. But if a sensor delivers 10.00 °C, it is probably very exact (if calibrated correctly).
</td>
</tr>
<tr>
<td>string</td>
<td>Represents a string value. It contains an arbitrary string value.</td>
</tr>
<tr>
<td>boolean</td>
<td>Represents a boolean value that can be either true or false.</td>
</tr>
<tr>
<td>dateTime</td>
<td>Represents a date and optional time value. The value must be encoded using the xs:dateTime data type. This includes date, an optional time and optional time zone information.
If time zone is not available, it is supposed to be undefined.</td>
</tr>
<tr>
<td>timeSpan</td>
<td>Represents a time span value. This can be either a time of day value, if nonnegative and less than 24 hours, or a duration value.</td>
</tr>
<tr>
<td>enum</td>
<td>Represents an enumeration value. What differs this value from a string value, is that it apart from the enumeration value (which is a string value),
also contains a datatype, which consumers can use to interpret its value. This specification does not assume knowledge of any particular enumeration
data types.</td>
</tr>
</table>
</section2>
<section2 topic='Field Types'>
<p>
There are different types of fields, apart from types of values a field can have. These types are conceptual types, similar to categories. They are not exclusive,
and can be combined.
</p>
<p>
If requesting multiple field types in a request, the device must interpret this as a union of the corresponding field types and return at least all field values
that contain at least one of the requested field types. Example: If requesting momentary values and historical values, devices must return both its momentary values
and its historical values.
</p>
<p>
But, when a device reports a field having multiple field types, the client should interpret this as the intersection of the corresponding field types, i.e. the corresponding
field has all corresponding field types. Example: A field marked as both a status value and as a historical value is in fact a historical status value.
</p>
<p>
The following table lists the different field types specified in this document:
</p>
<table caption='Field Types'>
<tr>
<th>Field Type</th>
<th>Description</th>
</tr>
<tr>
<td>computed</td>
<td>A value that is computed instead of measured.</td>
</tr>
<tr>
<td>historical*</td>
<td>A value stored in memory from a previous time point. The suffix is used to determine period, as shown below.</td>
</tr>
<tr>
<td>historicalSecond</td>
<td>A value stored at a second shift (milliseconds = 0).</td>
</tr>
<tr>
<td>historicalMinute</td>
<td>A value stored at a minute shift (seconds=milliseconds=0). Are also second values.</td>
</tr>
<tr>
<td>historicalHour</td>
<td>A value stored at a hour shift (minutes=seconds=milliseconds=0). Are also minute and second values.</td>
</tr>
<tr>
<td>historicalDay</td>
<td>A value stored at a day shift (hours=minutes=seconds=milliseconds=0). Are also hour, minute and second values.</td>
</tr>
<tr>
<td>historicalWeek</td>
<td>A value stored at a week shift (Monday, hours=minutes=seconds=milliseconds=0). Are also day, hour, minute and second values.</td>
</tr>
<tr>
<td>historicalMonth</td>
<td>A value stored at a month shift (day=1, hours=minutes=seconds=milliseconds=0). Are also day, hour, minute and second values.</td>
</tr>
<tr>
<td>historicalQuarter</td>
<td>A value stored at a quarter year shift (Month=Jan, Apr, Jul, Oct, day=1, hours=minutes=seconds=milliseconds=0). Are also month, day, hour, minute and second values.</td>
</tr>
<tr>
<td>historicalYear</td>
<td>A value stored at a year shift (Month=Jan, day=1, hours=minutes=seconds=milliseconds=0). Are also quarter, month, day, hour, minute and second values.</td>
</tr>
<tr>
<td>historicalOther</td>
<td>If period if historical value is not important in the request or by the device.</td>
</tr>
<tr>
<td>identity</td>
<td>A value that can be used for identification. (Serial numbers, meter IDs, locations, names, etc.)</td>
</tr>
<tr>
<td>momentary</td>
<td>A momentary value represents a value measured at the time of the readout.</td>
</tr>
<tr>
<td>peak</td>
<td>A maximum or minimum value during a given period.</td>
</tr>
<tr>
<td>status</td>
<td>A value displaying status information about something.</td>
</tr>
</table>
<p>
There are two field type attributes that can be used in requests to simplify readout:
</p>
<table caption='Special Field Types available in readout requests'>
<tr>
<th>Field Type</th>
<th>Description</th>
</tr>
<tr>
<td>all</td>
<td>Reads all types of fields. It is the same as explicitly setting all field type attributes to true.</td>
</tr>
<tr>
<td>historical</td>
<td>If period of historical values is not important, this attribute can be set to include all types of historical values.</td>
</tr>
</table>
<p>
<strong>Note:</strong> The reason for including different time periods for historical values, is that these periods are common in metering
applications. However, the client is not restricted to these in any way. The client can always just ask for historical values, and do
filtering as necessary to read out the interval desired.
</p>
<p>
Also, clients are not required to include logic to parse and figure out what historical values are actually desired by the client. If too
complicated for the device to handle, it is free to report all historical values. However, the device should limit the historical values
to any interval requested, and should try to limit itself to the field types requested. Information in the request element are seen as hints
that the device can use to optimize any communication required by the operation.
</p>
</section2>
<section2 topic='Field Status Values'>
<p>
In metering applications where quality of service is important, a field must always be accompanied with a corresponding status flag. Devices should
set these accordingly. If no status flag is set on a field, the client can assume <strong>automaticReadout</strong> is true.
</p>
<p>
Note that status flags are not exclusive. Many of then can logically be combined. Some also imply an order of importance. This should be kept in mind
when trying to overwrite existing values with read values: An estimate should not overwrite a readout, a readout not a signed value, and a signed value
not an invoiced value, etc.
</p>
<p>
Available status flags, in order of importance:
</p>
<table>
<tr>
<th>Status Flag</th>
<th>Description</th>
</tr>
<tr>
<td>missing</td>
<td>Value is missing</td>
</tr>
<tr>
<td>automaticEstimate</td>
<td>An estimate of the value has been done automatically. Considered more reliable than a missing value (duh!).</td>
</tr>
<tr>
<td>manualEstimate</td>
<td>The value has manually been estimated. Considered more reliable than an automatic estimate.</td>
</tr>
<tr>
<td>manualReadout</td>
<td>Value has been manually read. Considered more reliable than a manual estimate.</td>
</tr>
<tr>
<td>automaticReadout</td>
<td>Value has been automatically read. Considered more reliable than a manually read value.</td>
</tr>
<tr>
<td>timeOffset</td>
<td>The time was offset more than alowed and corrected during the measurement period.</td>
</tr>
<tr>
<td>warning</td>
<td>A warning was logged during the measurement period.</td>
</tr>
<tr>
<td>error</td>
<td>An error was logged during the measurement period.</td>
</tr>
<tr>
<td>signed</td>
<td>The value has been signed by an operator. Considered more reliable than an automatically read value. Note that the signed status flag can be used to overwrite
existing values of higher importance. Example signed+invoiced can be considered more reliable than only invoiced, etc.</td>
</tr>
<tr>
<td>invoiced</td>
<td>The value has been invoiced by an operator. Considered more reliable than a signed value.</td>
</tr>
<tr>
<td>endOfSeries</td>
<td>The value has been marked as an end point in a series. This can be used for instance to mark the change of tenant in an apartment.</td>
</tr>
<tr>
<td>powerFailure</td>
<td>The device recorded a power failure during the measurement period.</td>
</tr>
<tr>
<td>invoiceConfirmed</td>
<td>The value has been invoiced by an operator and confirmed by the recipient. Considered more reliable than an invoiced value.</td>
</tr>
</table>
</section2>
<section2 topic='Subnodes and supernodes'>
<p>
This document does not go into detail on how devices are ordered behind a JID. Some of the examples have assumed a single device lies behind a JID, others
that multiple devices exist behind a JID. Also, no order or structure of devices have been assumed.
</p>
<p>
But it can be mentioned that it is assumed that if a client requests a readout of a supernode, it implies the readout of all its subnodes. Therefore, the
client cannot expect readout to be limited to the devices listed explicitly in a request, as nodes implicitly implied, as descendant nodes of the selected nodes,
can also be included.
</p>
<p>
More information about how multiple devices behind a JID can be handled, is described in the XEP <link url='xep-0000-SN-Concentrators'>xep-0000-SN-Concentrators</link>.
</p>
</section2>
</section1>
<section1 topic='Internationalization Considerations' anchor='i18n'>
<section2 topic='Time Zones'>
<p>
All time points and dateTime values use the XML data type xs:dateTime to specify values. These values invlude a date, an optional time and an optional time zone.
</p>
<p>
<strong>Note:</strong> If time zone is not available, it is supposed to be undefined.
</p>
<p>
If devices report time zone, this information should be propagated throughout the system. Otherwise, comparing timepoints from different time zones will be impossible.
</p>
</section2>
<section2 topic='Localized strings'>
<p>
This specification allows for localization of field names in meter data readout. This is performed by assigning each localizable string a <strong>String ID</strong>
which should be uniqe within a given <strong>Language Module</strong>. A <strong>Language Module</strong> can be any string, including URI's or namespace names.
The XEP <link url='xep-0000-SN-Interoperability'>xep-0000-SN-Interoperability</link> details how such localizations can be made in an interoperable way.
</p>
<p>
<strong>Note:</strong> Localization of strings are for human consumption only. Machines should use the unlocalized strings in program logic.
</p>
<p>
The following example shows how a device can report localized field information, that can be presented to end users without systems being preprogrammed
to recognize the device. Language modules can be aggregated by operators after installation, or installed as a pluggable module after the main installation,
if localization is desired.
</p>
<example caption='Localized field names'>
<![CDATA[
<iq from='master@clayster.com'
to='device@clayster.com'
type='get'
id='7'>
<req xmlns='urn:xmpp:sn' seqnr='7' all='true'/>
</iq>
<iq from='device@clayster.com'
to='master@clayster.com'
type='result'
id='7'>
<accepted xmlns='urn:xmpp:sn' seqnr='7'/>
</iq>
<message from='device@clayster.com'
to='master@clayster.com'>
<fields xmlns='urn:xmpp:sn' seqnr='7' done='true'>
<node nodeId='Device05'>
<timepoint value='2013-03-07T22:20:45'>
<numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C' module='Whatchamacallit' stringIds='1'/>
<numeric name='Temperature, Min' momentary='true' automaticReadout='true' value='23.4' unit='°C' module='Whatchamacallit' stringIds='1,2'/>
<numeric name='Temperature, Max' momentary='true' automaticReadout='true' value='23.4' unit='°C' module='Whatchamacallit' stringIds='1,3'/>
<numeric name='Temperature, Mean' momentary='true' automaticReadout='true' value='23.4' unit='°C' module='Whatchamacallit' stringIds='1,4'/>
</timepoint>
</node>
</fields>
</iq>]]>
</example>
<p>
The above example defines a language module called <strong>Watchamacallit</strong>. In this language module it defines four strings, with IDs 1-4. A system might store these as follows,
where the system replaces all <strong>%N%</strong> with a conceptual n:th parameter. (It's up to the system to define these strings, any syntax and how to handle input and output.). In
this example, we will assume <strong>%0%</strong> means any previous output, and <strong>%1%</strong> any seed value provided. (See below).
</p>
<table caption='Example string IDs'>
<tr>
<th>ID</th>
<th>String</th>
</tr>
<tr>
<td>1</td>
<td>Temperature</td>
</tr>
<tr>
<td>2</td>
<td>%0%, Min</td>
</tr>
<tr>
<td>3</td>
<td>%0%, Max</td>
</tr>
<tr>
<td>4</td>
<td>%0%, Mean</td>
</tr>
</table>
<p>
So, when the client reads the field name <strong>Temperature, Min</strong>, it knows its the composition of the string <strong>Temperature</strong>, and
the string <strong>%0%, Min</strong>, where it will replace <strong>%0%</strong> with the output of the previous step, in this case <strong>Temperature</strong>.
These strings can later be localized to different languages by operators of the system, and values presented when reading the device, can be done in a language
different from the one used by the sensor.
</p>
<p>
<strong>Note:</strong> The XEP <link url='xep-0000-SN-Interoperability'>xep-0000-SN-Interoperability</link> details how such localizations can be made in an interoperable way.
</p>
<p>
The <strong>stringIds</strong> attribute merits some further explanation. The value of this attribute must match the following regular expression:
</p>
<code>
^\d+([|]\w+([.]\w+)*([|][^,]*)?)?(,\d+([|]\w+([.]\w+)*([|][^,]*)?)?)*$
</code>
<p>
This basically means, it's of the format: ID_1[|[Module_1][|Seed_1]][...[ID_n[|[Module_n][|Seed_n]]]]
</p>
<p>
Where brackets [] mean the contents inside is optional, <strong>ID_i</strong> is an integer representing the string ID in a language module. <strong>Module_i</strong>
is optional and allows for specifying a module for <strong>ID_i</strong>, if different from the module defined in the <strong>module</strong> attribute. <strong>Seed_i</strong>
allows for seeding the generation of the localized string with a value. This might come in handy when generating strings like <strong>Input 5</strong>, where you don't want to
create localized strongs for every input there is.
</p>
<p>
Why such a complicated syntax? The reason is the following: Most localized strings, are simple numbers, without the need of specifying modules and seeds. This makes
it very efficient to stora as an attribute instead of having to create subelements for every localized field. It's an exception to the rule, to need multiple steps
or seeds in the generation of localized strings. Therefore, attributes is an efficient means to specify localization. However, in the general case, a single string ID
is not sufficient and multiple steps are required, some seeded.
</p>
<table caption='stringIds Examples'>
<tr>
<th>stringIds</th>
<th>New Parts</th>
<th>Result</th>
</tr>
<tr>
<td>1</td>
<td>1="Temperature"</td>
<td>Temperature</td>
</tr>
<tr>
<td>1,2</td>
<td>2="%0%, Max"</td>
<td>Temperature, Max</td>
</tr>
<tr>
<td>1,1|MathModule</td>
<td>1 in module "MathModule"="sum(%0%)"</td>
<td>sum(Temperature)</td>
</tr>
<tr>
<td>3||A1</td>
<td>3="Input %1%"</td>
<td>Input A1</td>
</tr>
<tr>
<td>4||A1,2</td>
<td>4="Entrance %1%"</td>
<td>Entrance A1, Max</td>
</tr>
<tr>
<td>4||A1,5||3</td>
<td>5="%0%, Floor %1%"</td>
<td>Entrance A1, Floor 3</td>
</tr>
</table>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>
This document has not touched upon security in sensor networks. There are mainly three concerns that implementors of sensor networks need to consider:
</p>
<ul>
<li>
Communication should be restricted to friends as long as possible. Approved frienships provide a mechanism of limiting sensor information to authorized and authenticated users.
However, there are cases where multicast messages may want to go outside of recognized friendships. More information about such use cases, see the
XEP <link url='xep-0000-SN-Multicast.html'>xep-0000-SN-Multicast</link>.
</li>
<li>
Sensors may have very limited user interfaces. Even though installation of sensor networks is beyond the scope of this document, a simple installation scheme may include a
single LED on the sensor that lights up for a time after receiving a friendship request. If a user presses a button on the device while the LED is lit, the friendship request
is acknowledged, and communication is authorized.
</li>
<li>
More advanced access rights, privileges, automatic friendship recognition, etc., may be managed by a third party. How to implement more advanced provisioning and detailed
access rights to sensor information is detailed in the XEP <link url='xep-0000-SN-Provisioning.html'>xep-0000-SN-Provisioning</link>.
</li>
</ul>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with &IANA;.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>REQUIRED.</p>
<!-- TODO -->
</section1>
<section1 topic='XML Schema' anchor='schema'>
<code>
<![CDATA[
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:xmpp:sn'
xmlns='urn:xmpp:sn'
elementFormDefault='qualified'>
<xs:element name='req'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element name='node'>
<xs:complexType>
<xs:attribute name='nodeId' type='xs:string' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='field'>
<xs:complexType>
<xs:attribute name='name' type='xs:string' use='required'/>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attribute name='seqnr' type='xs:int' use='required'/>
<xs:attributeGroup ref='fieldTypes'/>
<xs:attribute name='all' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historical' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='from' type='xs:dateTime' use='optional'/>
<xs:attribute name='to' type='xs:dateTime' use='optional'/>
<xs:attribute name='when' type='xs:dateTime' use='optional'/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name='fieldTypes'>
<xs:attribute name='momentary' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='peak' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='status' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='computed' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='identity' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalSecond' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalMinute' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalHour' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalDay' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalWeek' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalMonth' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalQuarter' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalYear' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='historicalOther' type='xs:boolean' use='optional' default='false'/>
</xs:attributeGroup>
<xs:element name='accepted'>
<xs:complexType>
<xs:attribute name='seqnr' type='xs:int' use='required'/>
<xs:attribute name='queued' type='xs:boolean' use='optional' default='false'/>
</xs:complexType>
</xs:element>
<xs:element name='started'>
<xs:complexType>
<xs:attribute name='seqnr' type='xs:int' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='fields'>
<xs:complexType>
<xs:sequence minOccurs='0' maxOccurs='unbounded'>
<xs:element name='node'>
<xs:complexType>
<xs:sequence minOccurs='0' maxOccurs='unbounded'>
<xs:element name='timepoint'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element name='numeric' type='numeric'/>
<xs:element name='string' type='string'/>
<xs:element name='boolean' type='boolean'/>
<xs:element name='dateTime' type='dateTime'/>
<xs:element name='timeSpan' type='timeSpan'/>
<xs:element name='enum' type='enum'/>
</xs:choice>
<xs:attribute name='value' type='xs:dateTime' use='required'/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name='nodeId' type='xs:string' use='required'/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name='seqnr' type='xs:int' use='required'/>
<xs:attribute name='done' type='xs:boolean' use='optional' default='false'/>
</xs:complexType>
</xs:element>
<xs:element name='failure'>
<xs:complexType>
<xs:sequence minOccurs='0' maxOccurs='unbounded'>
<xs:element name='error'>
<xs:complexType>
<xs:simpleContent>
<xs:extension base='xs:string'>
<xs:attribute name='nodeId' type='xs:string' use='required'/>
<xs:attribute name='timePoint' type='xs:string' use='required'/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name='seqnr' type='xs:int' use='required'/>
<xs:attribute name='done' type='xs:boolean' use='optional' default='false'/>
</xs:complexType>
</xs:element>
<xs:element name='rejected'>
<xs:complexType>
<xs:attribute name='seqnr' type='xs:int' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='done'>
<xs:complexType>
<xs:attribute name='seqnr' type='xs:int' use='required'/>
</xs:complexType>
</xs:element>
<xs:complexType name='field' abstract='true'>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attributeGroup ref='fieldTypes'/>
<xs:attributeGroup ref='fieldStatus'/>
<xs:attribute name="module" type="xs:string" use="optional"/>
<xs:attribute name="stringIds" type="StringIds" use="optional"/>
</xs:complexType>
<xs:simpleType name="StringIds">
<xs:restriction base="xs:string">
<xs:pattern value="^\d+([|]\w+([.]\w+)*([|][^,]*)?)?(,\d+([|]\w+([.]\w+)*([|][^,]*)?)?)*$"/>
</xs:restriction>
</xs:simpleType>
<xs:attributeGroup name='fieldStatus'>
<xs:attribute name='missing' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='automaticEstimate' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='manualEstimate' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='manualReadout' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='automaticReadout' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='timeOffset' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='warning' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='error' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='signed' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='invoiced' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='endOfSeries' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='powerFailure' type='xs:boolean' use='optional' default='false'/>
<xs:attribute name='invoiceConfirmed' type='xs:boolean' use='optional' default='false'/>
</xs:attributeGroup>
<xs:complexType name='numeric'>
<xs:complexContent>
<xs:extension base='field'>
<xs:attribute name="value" type="xs:double" use="required"/>
<xs:attribute name="unit" type="xs:string" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name='string'>
<xs:complexContent>
<xs:extension base='field'>
<xs:attribute name="value" type="xs:string" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name='boolean'>
<xs:complexContent>
<xs:extension base='field'>
<xs:attribute name="value" type="xs:boolean" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name='dateTime'>
<xs:complexContent>
<xs:extension base='field'>
<xs:attribute name="value" type="xs:dateTime" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name='timeSpan'>
<xs:complexContent>
<xs:extension base='field'>
<xs:attribute name="value" type="xs:duration" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name='enum'>
<xs:complexContent>
<xs:extension base='field'>
<xs:attribute name="value" type="xs:string" use="required"/>
<xs:attribute name="dataType" type="xs:string" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
]]>
</code>
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
<p>Thanks to Joachim Lindborg for all valuable feedback.</p>
</section1>
</xep>