Parcourir la source

Expanded documentation with context about the messages

Stan Janssen il y a 4 ans
Parent
commit
31438d38ef
6 fichiers modifiés avec 195 ajouts et 74 suppressions
  1. 2 0
      docs/client.rst
  2. 1 0
      docs/examples.rst
  3. 0 2
      docs/index.rst
  4. 3 0
      docs/openadr.rst
  5. 142 72
      docs/representations.rst
  6. 47 0
      docs/server.rst

+ 2 - 0
docs/client.rst

@@ -5,9 +5,11 @@ Client
 The page contains all information about aiohttp Client API.
 
 .. _client_events:
+
 Dealing with Events
 ===================
 
 .. _client_reports:
+
 Dealing with Reports
 ====================

+ 1 - 0
docs/examples.rst

@@ -1,5 +1,6 @@
 .. _examples:
 
+========
 Examples
 ========
 

+ 0 - 2
docs/index.rst

@@ -75,8 +75,6 @@ The source code for this project is hosted at GitHub.
 Table of Contents
 =================
 
-We have prepared some ready-to-run examples for you to get started with OpenADR:
-
 .. toctree::
    :name: mastertoc
    :maxdepth: 2

+ 3 - 0
docs/openadr.rst

@@ -15,6 +15,7 @@ In order to track what happens after, there is a Reports mechanism in place that
 
 
 .. _registration:
+
 Registration
 ============
 
@@ -23,12 +24,14 @@ Here is the registration page
 
 
 .. _openadr_events:
+
 Events
 ======
 
 This is the registration
 
 .. _openadr_reports:
+
 Reports
 =======
 

+ 142 - 72
docs/representations.rst

@@ -6,13 +6,38 @@ Payload Representations
 
 In PyOpenADR, the complex hierarchies of the OpenADR XML-payloads are represented as Python dictionaries. These have been simplified as much as possible, allowing for a more natural and more readable experience.
 
+This means that you don't have to instantiate objects and sub-objects and sub-sub-objects, but that you can define the entire object in a single, declarative statement. This kan keep a simple implementation very compact. The downside is that there is little help from your IDE and there is little discoverability for what contents can be provided in the messages. This page can be used as a reference for that information.
+
+To help you, all outgong messages are validated against the XML schema, and you will receive warnings if your messages don't comply to the schema.
+
 The following general principles have been applied to representing OpenADR objects in PyOpenADR:
 
 - All property names are represented in snake_case instead of CamelCase or mixedCase names. For example: ``requestID`` becomes ``request_id``.
 - For all properties, the ``oadr*`` and ``Ei*`` prefixes have been stripped away. For example: ``eiResponse`` becomes ``response`` and ``oadrResponse`` becomes ``response``.
 - OpenADR timestamps are converted to Python ``datetime.datetime`` objects.
 - OpenADR time intervals are converted to Python ``datetime.timedelta`` objects.
+- Properties that might have more than 1 copy in the XML representation are put in a list, even if there is just one. This list will be identified by the pluralized version of the originals property name. For example:
+
+.. code-block:: xml
+
+    <...>
+        <signal>1234</signal>
+        <signal>5678</signal>
+    <...>
+
+Will become:
+
+.. code-block:: python3
+
+    ...
+    "signals": [1234, 5678],
+    ...
+
+- The messages are usually used as a ``message_name, message_payload`` tuple. The message name is kept, for instance, ``oadrCanceledOpt``, and the payload is given as a dict.
+
+Below is an alphabetized overview of all messages with their XML and Python representations.
 
+.. _oadrCanceledOpt:
 
 oadrCanceledOpt
 ===============
@@ -46,6 +71,8 @@ pyOpenADR representation:
                   'response_description': 'OK'}}
 
 
+.. _oadrCanceledPartyRegistration:
+
 oadrCanceledPartyRegistration
 =============================
 
@@ -79,6 +106,8 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
+.. _oadrCanceledReport:
+
 oadrCanceledReport
 ==================
 
@@ -113,9 +142,6 @@ pyOpenADR representation:
                   'response_code': 200,
                   'response_description': 'OK'}}
 
-oadrCanceledReport
-==================
-
 OpenADR payload:
 
 .. code-block:: xml
@@ -150,6 +176,8 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
+.. _oadrCancelOpt:
+
 oadrCancelOpt
 =============
 
@@ -175,6 +203,8 @@ pyOpenADR representation:
     {'opt_id': 'b1ef7afecc', 'request_id': 'u07a26b1cc', 'ven_id': '123ABC'}
 
 
+.. _oadrCancelPartyRegistration:
+
 oadrCancelPartyRegistration
 ===========================
 
@@ -202,6 +232,8 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
+.. _oadrCancelReport:
+
 oadrCancelReport
 ================
 
@@ -231,6 +263,8 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
+.. _oadrCreatedEvent:
+
 oadrCreatedEvent
 ================
 
@@ -314,46 +348,6 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
-oadrCreatedReport
-=================
-
-OpenADR payload:
-
-.. code-block:: xml
-
-    <?xml version="1.0" encoding="utf-8"?>
-    <oadrPayload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://openadr.org/oadr-2.0b/2012/07" xsi:schemaLocation="http://openadr.org/oadr-2.0b/2012/07 oadr_20b.xsd">
-      <oadrSignedObject>
-        <oadrCreatedReport ei:schemaVersion="2.0b" xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110">
-          <ei:eiResponse>
-            <ei:responseCode>200</ei:responseCode>
-            <ei:responseDescription>OK</ei:responseDescription>
-            <requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">ie8ff94fbc</requestID>
-          </ei:eiResponse>
-          <oadrPendingReports>
-            <ei:reportRequestID>p8c56f9ed9</ei:reportRequestID>
-            <ei:reportRequestID>hab1cced95</ei:reportRequestID>
-          </oadrPendingReports>
-          <ei:venID>123ABC</ei:venID>
-        </oadrCreatedReport>
-      </oadrSignedObject>
-    </oadrPayload>
-
-pyOpenADR representation:
-
-.. code-block:: python3
-
-    {'pending_reports': [{'request_id': 'p8c56f9ed9'},
-                         {'request_id': 'hab1cced95'}],
-     'response': {'request_id': 'ie8ff94fbc',
-                  'response_code': 200,
-                  'response_description': 'OK'},
-     'ven_id': '123ABC'}
-
-
-oadrCreatedEvent
-================
-
 OpenADR payload:
 
 .. code-block:: xml
@@ -418,8 +412,10 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
-oadrCreatedPartyRegistration
-============================
+.. _oadrCreatedReport:
+
+oadrCreatedReport
+=================
 
 OpenADR payload:
 
@@ -428,26 +424,18 @@ OpenADR payload:
     <?xml version="1.0" encoding="utf-8"?>
     <oadrPayload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://openadr.org/oadr-2.0b/2012/07" xsi:schemaLocation="http://openadr.org/oadr-2.0b/2012/07 oadr_20b.xsd">
       <oadrSignedObject>
-        <oadrCreatedPartyRegistration ei:schemaVersion="2.0b" xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110">
+        <oadrCreatedReport ei:schemaVersion="2.0b" xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110">
           <ei:eiResponse>
             <ei:responseCode>200</ei:responseCode>
             <ei:responseDescription>OK</ei:responseDescription>
-            <requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">k6565d9280</requestID>
+            <requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">ie8ff94fbc</requestID>
           </ei:eiResponse>
-          <ei:registrationID>o852fdbac9</ei:registrationID>
+          <oadrPendingReports>
+            <ei:reportRequestID>p8c56f9ed9</ei:reportRequestID>
+            <ei:reportRequestID>hab1cced95</ei:reportRequestID>
+          </oadrPendingReports>
           <ei:venID>123ABC</ei:venID>
-          <ei:vtnID>VTN123</ei:vtnID>
-          <oadrProfiles>
-            <oadrProfile>
-              <oadrProfileName>2.0b</oadrProfileName>
-              <oadrTransports>
-                <oadrTransport>
-                  <oadrTransportName>simpleHttp</oadrTransportName>
-                </oadrTransport>
-              </oadrTransports>
-            </oadrProfile>
-          </oadrProfiles>
-        </oadrCreatedPartyRegistration>
+        </oadrCreatedReport>
       </oadrSignedObject>
     </oadrPayload>
 
@@ -455,18 +443,14 @@ pyOpenADR representation:
 
 .. code-block:: python3
 
-    {'profiles': [{'profile_name': '2.0b',
-                   'transports': [{'transport_name': 'simpleHttp'}]}],
-     'registration_id': 'o852fdbac9',
-     'response': {'request_id': 'k6565d9280',
+    {'pending_reports': [{'request_id': 'p8c56f9ed9'},
+                         {'request_id': 'hab1cced95'}],
+     'response': {'request_id': 'ie8ff94fbc',
                   'response_code': 200,
                   'response_description': 'OK'},
-     'ven_id': '123ABC',
-     'vtn_id': 'VTN123'}
+     'ven_id': '123ABC'}
 
 
-oadrCreatedReport
-=================
 
 OpenADR payload:
 
@@ -500,6 +484,62 @@ pyOpenADR representation:
                   'response_description': 'OK'}}
 
 
+.. _oadrCreatedPartyRegistration:
+
+oadrCreatedPartyRegistration
+============================
+
+This message is used by the VTN in two scenarios:
+
+1. The VEN has just sent an :ref:`oadrQueryRegistration` request, and the VTN makes its available profiles and transport mechanisms known to the VEN
+2. The VEN has just sent an :ref:`oadrCreatePartyRegistration` request, and the VTN responds by sending the registrationId to the VEN.
+
+OpenADR payload:
+
+.. code-block:: xml
+
+    <?xml version="1.0" encoding="utf-8"?>
+    <oadrPayload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://openadr.org/oadr-2.0b/2012/07" xsi:schemaLocation="http://openadr.org/oadr-2.0b/2012/07 oadr_20b.xsd">
+      <oadrSignedObject>
+        <oadrCreatedPartyRegistration ei:schemaVersion="2.0b" xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110">
+          <ei:eiResponse>
+            <ei:responseCode>200</ei:responseCode>
+            <ei:responseDescription>OK</ei:responseDescription>
+            <requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">k6565d9280</requestID>
+          </ei:eiResponse>
+          <ei:registrationID>o852fdbac9</ei:registrationID>
+          <ei:venID>123ABC</ei:venID>
+          <ei:vtnID>VTN123</ei:vtnID>
+          <oadrProfiles>
+            <oadrProfile>
+              <oadrProfileName>2.0b</oadrProfileName>
+              <oadrTransports>
+                <oadrTransport>
+                  <oadrTransportName>simpleHttp</oadrTransportName>
+                </oadrTransport>
+              </oadrTransports>
+            </oadrProfile>
+          </oadrProfiles>
+        </oadrCreatedPartyRegistration>
+      </oadrSignedObject>
+    </oadrPayload>
+
+pyOpenADR representation:
+
+.. code-block:: python3
+
+    {'profiles': [{'profile_name': '2.0b',
+                   'transports': [{'transport_name': 'simpleHttp'}]}],
+     'registration_id': 'o852fdbac9',
+     'response': {'request_id': 'k6565d9280',
+                  'response_code': 200,
+                  'response_description': 'OK'},
+     'ven_id': '123ABC',
+     'vtn_id': 'VTN123'}
+
+
+.. _oadrCreateOpt:
+
 oadrCreateOpt
 =============
 
@@ -543,6 +583,8 @@ pyOpenADR representation:
      'ven_id': 'VEN123'}
 
 
+.. _oadrCreatePartyRegistration:
+
 oadrCreatePartyRegistration
 ===========================
 
@@ -582,6 +624,8 @@ pyOpenADR representation:
      'xml_signature': False}
 
 
+.. _oadrCreateReport:
+
 oadrCreateReport
 ================
 
@@ -648,9 +692,15 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
+.. _oadrDistributeEvent:
+
 oadrDistributeEvent
 ===================
 
+This message is sent by the VTN when it delivers an Event to a VEN. This is the main communication of the Event, and it contains myriad options to precisely define the event.
+
+The VEN responds with either an :ref:`oadrCreatedEvent` message, indicating its 'opt' status ("Opt In" or "Opt Out").
+
 OpenADR payload:
 
 .. code-block:: xml
@@ -889,9 +939,15 @@ pyOpenADR representation:
      'vtn_id': 'VTN123'}
 
 
+.. _oadrPoll:
+
 oadrPoll
 ========
 
+This message is sent by the VEN to the VTN to poll for new messages. The VTN responds by sending an empty :ref:`oadrResponse`, a :ref:`oadrDistributeEvent` in case there is an Event for the VEN, a :ref:`oadrRequestReregistration` message in case the VTN want the VEN to register again.
+
+In case the VEN wants to hear only about new Events, it can send a :ref:`oadrRequestEvent` message to the VTN.
+
 OpenADR payload:
 
 .. code-block:: xml
@@ -911,9 +967,13 @@ pyOpenADR representation:
 
     {'ven_id': '123ABC'}
 
+.. _oadrQueryRegistration:
+
 oadrQueryRegistration
 =====================
 
+This message is used by the VEN to request information on the VTN's capabilities before registering. The VTN will respond with a :ref:`oadrCreatedPartyRegistration` message.
+
 OpenADR payload:
 
 .. code-block:: xml
@@ -933,6 +993,8 @@ pyOpenADR representation:
 
     {'request_id': 'i8cf15d21f'}
 
+.. _oadrRegisteredReport:
+
 oadrRegisteredReport
 ====================
 
@@ -1070,6 +1132,8 @@ pyOpenADR representation:
      'ven_id': 'VEN123'}
 
 
+.. _oadrRequestEvent:
+
 oadrRequestEvent
 ================
 
@@ -1096,9 +1160,13 @@ pyOpenADR representation:
     {'request_id': 'oa1c52db3f', 'ven_id': '123ABC'}
 
 
+.. _oadrRequestReregistration:
+
 oadrRequestReregistration
 =========================
 
+This message is sent by the VTN whenever it want the VEN to go through the registration procedure again. Usually sent in reply to a :ref:`oadrPoll` message.
+
 OpenADR payload:
 
 .. code-block:: xml
@@ -1119,9 +1187,13 @@ pyOpenADR representation:
     {'ven_id': '123ABC'}
 
 
+.. _oadrResponse:
+
 oadrResponse
 ============
 
+This is a generic message that the VTN sends to the VEN if there is no other message for the VEN. Usually sent in response to an :ref:`oadrPoll` or :ref:`oadrRequestEvent` message.
+
 OpenADR payload:
 
 .. code-block:: xml
@@ -1149,10 +1221,6 @@ pyOpenADR representation:
                   'response_description': 'OK'},
      'ven_id': '123ABC'}
 
-
-oadrResponse
-============
-
 OpenADR payload:
 
 .. code-block:: xml
@@ -1181,6 +1249,8 @@ pyOpenADR representation:
      'ven_id': '123ABC'}
 
 
+.. _oadrUpdatedReport:
+
 oadrUpdatedReport
 =================
 

+ 47 - 0
docs/server.rst

@@ -8,13 +8,60 @@ The page contains all information about pyOpenADR Server API.
 
 
 .. _server_registration:
+
 Registration
 ============
 
+If a client (VEN) wants to register for the first time, it will go through a Registration procedure.
+
+The client will send a :ref:`oadrQueryRegistration` message. The server will respond with a :ref:`oadrCreatedPartyRegistration` message containing a list of its capabilities, notable the implemented OpenADR protocol versions and the available Transport Mechanisms (HTTP and/or XMPP).
+
+The client will then usually send a :ref:`oadrCreatePartyRegistration` message, in which it registers to a specific OpenADR version and Transport Method. The server must then decide what it wants to do with this registration.
+
+In the case that the registration is accepted, the VTN will generate a RegistrationID for this VEN and respond with a :ref:`oadrCreatedPartyRegistration` message.
+
+In your application, when a VEN sends a :ref:`oadrCreatePartyRegistration` request, it will call your ``on_register_party`` handler. This handler must somehow look up what to do with this request, and respond with a ``registration_id``.
+
+Example implementation:
+
+.. code-block:: python3
+
+    from pyopenadr.utils import generate_id
+
+    async def on_create_party_registration(payload):
+        ven_id = payload['ven_id']
+        # Check whether or not this VEN is allowed to register
+        result = await database.query("""SELECT COUNT(*)
+                                           FROM vens
+                                          WHERE ven_id = ?""",
+                                      (payload['ven_id'],))
+        if result == 1:
+            # Generate an ID for this registration
+            registration_id = generate_id()
+
+            # Store the registration in a database (pseudo-code)
+            await database.query("""UPDATE vens
+                                       SET registration_id = ?
+                                     WHERE ven_id = ?""",
+                                 (registration_id, ven_id))
+
+            # Return the registration ID.
+            # This will be put into the correct form by the OpenADRServer.
+            return registration_id
+
 .. _server_events:
+
 Events
 ======
 
+The server (VTN) is expected to know when it needs to inform the clients (VENs) of certain events that they must respond to. This could be a predicted shortage or overage of available power in a certain electricity grid area, for example.
+
+The VTN must determine when VENs are relevant and which Events to send to them. The next time the VEN polls for new messages (using a :ref:`oadrPoll` or :ref:`oadrRequestEvent` message), it will send the Event in a :ref:`oadrDistributeEvent` message to the client. The client will then evaluate whether or not it indends to comply with the request, and respond with an :ref:`oadrCreatedEvent` message containing an optStatus of ``'optIn'`` or ``'optOut'``.
+
+In your application, the creation of Events is completely up to you. PyOpenADR will only call your ``on_poll`` handler with a ``ven_id``. This handler must be able to either retrieve the next event for this VEN out of some storage or queue, or make up the Event in real time.
+
+
 .. _server_reports:
+
 Reports
 =======