OpenLEADR / openleadr-python

Python library for OpenADR
https://openleadr.org/docs
Apache License 2.0
133 stars 51 forks source link

Unable to register client VEN using example from site #120

Closed robogeek closed 1 year ago

robogeek commented 2 years ago

I'm still trying to get an example setup running and the current issue is that the VEN client is not registering with the VTN. Instead, this is printed:

Request error TimeoutError:
No RegistrationID received from the VTN, aborting.

This message comes from OADRClient.run after this line: await self.create_party_registration(ven_id=self.ven_id)

In the server, I am not sure of the correct value for http_host. The default value, 127.0.0.1, would seem to cause the VTN to only listen to connects from inside the Docker container. But, obviously, the VTN must be able to accept connections from VEN nodes anywhere. It seems from the aiohttp documentation that an empty string for http_host has the right effect, but the documentation is incomplete.

The debug output includes the XML of the registration attempt. I've checked this against the OpenADR spec and it seems to be correct.

<oadr:oadrPayload xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07">
<oadr:oadrSignedObject xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07" oadr:Id="oadrSignedObject">
    <oadr:oadrCreatePartyRegistration ei:schemaVersion="2.0b" xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110">
        <requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">f71010af-6234-431c-a695-1faca3075de1</requestID>
        <ei:venID>ven123_id</ei:venID>
        <oadr:oadrProfileName>2.0b</oadr:oadrProfileName>
        <oadr:oadrTransportName>simpleHttp</oadr:oadrTransportName>
        <oadr:oadrTransportAddress>None</oadr:oadrTransportAddress>
        <oadr:oadrReportOnly>false</oadr:oadrReportOnly>
        <oadr:oadrXmlSignature>false</oadr:oadrXmlSignature>
        <oadr:oadrVenName>ven123</oadr:oadrVenName>
        <oadr:oadrHttpPullModel>true</oadr:oadrHttpPullModel>
    </oadr:oadrCreatePartyRegistration>
</oadr:oadrSignedObject>
</oadr:oadrPayload>

I have created Docker containers, one for the VTN, and the other for the VEN, as follows:


version: '3'

services:
  vtn:
    build: ./vtn
    networks:
      - adrnet
    ports:
      - 8080

  ven:
    build: ./ven
    networks:
      - adrnet
    environment:
      - VEN_NAME=ven123
      - VTN_URL=http://vtn:8080/OpenADR2/Simple/2.0b
      - RESOURCE_NAME=resource
    depends_on:
      - vtn

networks:
  adrnet:

Inside the VEN container, the VTN container and its port are visible:

root@128ac64ff0ba:/# nmap vtn
Starting Nmap 7.80 ( https://nmap.org ) at 2022-05-31 00:45 UTC
Nmap scan report for vtn (172.21.0.2)
Host is up (0.000017s latency).
rDNS record for 172.21.0.2: test-leadr-vtn-1.test-leadr_adrnet
Not shown: 999 closed ports
PORT     STATE SERVICE
8080/tcp open  http-proxy
MAC Address: 02:42:AC:15:00:02 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds

The relevant portion of the client code is:

# Create the client object
client = OpenADRClient(ven_name=VEN_NAME, vtn_url=VTN_URL, ven_id=VEN_ID)
                       # vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b')

# Add the report capability to the client
client.add_report(callback=collect_report_value,
                  resource_id=RESOURCE_NAME,
                  measurement='voltage',
                  sampling_rate=timedelta(seconds=10))

# Add event handling capability to the client
client.add_handler('on_event', handle_event)

logger.debug("After add_handler on_event")

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.run(client.run())
loop.run_forever()

The relevant part of the server is:

# Create the server object
server = OpenADRServer(vtn_id='myvtn',
                       http_host='', # '0.0.0.0',
                       ven_lookup=ven_lookup)

logger.debug(f"vtn created server {server}")

# Add the handler for client (VEN) registrations
server.add_handler('on_create_party_registration', on_create_party_registration)

logger.debug(f"vtn add_handler on_create_party_registration")

# Add the handler for report registrations from the VEN
server.add_handler('on_register_report', on_register_report)

logger.debug(f"vtn add_handler on_register_report")

# Add a prepared event for a VEN that will be picked up when it polls for new messages.
server.add_event(ven_id='ven_id_123',
                 signal_name='simple',
                 signal_type='level',
                 intervals=[{'dtstart': datetime(2021, 1, 1, 12, 0, 0, tzinfo=timezone.utc),
                             'duration': timedelta(minutes=10),
                             'signal_payload': 1}],
                 callback=event_response_callback)

logger.debug(f"Configured server {server}")

loop = asyncio.new_event_loop()
logger.debug("after new loop")
asyncio.set_event_loop(loop)
logger.debug("after set event loop")
asyncio.run(server.run())
loop.run_forever()

The full output is the following:

test-leadr-vtn-1  | vtn at top
test-leadr-vtn-1  | vtn before OpenADRServer
test-leadr-vtn-1  | vtn created server <openleadr.server.OpenADRServer object at 0x7f215f2bfc70>
test-leadr-vtn-1  | Adding handler: on_create_party_registration <function on_create_party_registration at 0x7f215c758430>
test-leadr-vtn-1  | vtn add_handler on_create_party_registration
test-leadr-vtn-1  | Adding handler: on_register_report <function on_register_report at 0x7f215c63ac20>
test-leadr-vtn-1  | vtn add_handler on_register_report
test-leadr-vtn-1  | Configured server <openleadr.server.OpenADRServer object at 0x7f215f2bfc70>
test-leadr-vtn-1  | after new loop
test-leadr-vtn-1  | after set event loop
test-leadr-vtn-1  | 
test-leadr-vtn-1  | ********************************************************************************
test-leadr-vtn-1  |                        Your VTN Server is now running at                        
test-leadr-vtn-1  |                        http://:8080/OpenADR2/Simple/2.0b                        
test-leadr-vtn-1  | ********************************************************************************
test-leadr-vtn-1  | 
test-leadr-vtn-1  |                           //:8080/OpenADR2/Simple/2.0b                          
test-leadr-ven-1  | You did not provide a 'report_duration' parameter to 'add_report'. This parameter should indicate the size of the data buffer that can be built up. It will now default to 3600 seconds, which may or may not be appropriate for your use case.
test-leadr-ven-1  | After add_handler on_event
test-leadr-ven-1  | Created message: <?xml version="1.0" encoding="utf-8"?>
test-leadr-ven-1  | <oadr:oadrPayload xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07">
test-leadr-ven-1  | <oadr:oadrSignedObject xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07" oadr:Id="oadrSignedObject"><oadr:oadrCreatePartyRegistration ei:schemaVersion="2.0b" xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110"><requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">f71010af-6234-431c-a695-1faca3075de1</requestID><ei:venID>ven123_id</ei:venID><oadr:oadrProfileName>2.0b</oadr:oadrProfileName><oadr:oadrTransportName>simpleHttp</oadr:oadrTransportName><oadr:oadrTransportAddress>None</oadr:oadrTransportAddress><oadr:oadrReportOnly>false</oadr:oadrReportOnly><oadr:oadrXmlSignature>false</oadr:oadrXmlSignature><oadr:oadrVenName>ven123</oadr:oadrVenName><oadr:oadrHttpPullModel>true</oadr:oadrHttpPullModel></oadr:oadrCreatePartyRegistration></oadr:oadrSignedObject>
test-leadr-ven-1  | </oadr:oadrPayload>
test-leadr-ven-1  | Request error TimeoutError:
test-leadr-ven-1  | No RegistrationID received from the VTN, aborting.
robogeek commented 2 years ago

I found an example at https://github.com/bbartling/openadrtester which was easily able to run, including under the Docker setup I described.

After carefully comparing the code I found that the initialization of the event loop had to be this:

loop = asyncio.new_event_loop()
loop.set_debug(True)
asyncio.set_event_loop(loop)
loop.create_task(server.run())
# Using this line causes failure
# asyncio.run(server.run(), debug=True)
loop.run_forever()
stan-janssen commented 2 years ago

You got a TimeoutError, which seems to be related to a communication problem between the VEN and the VTN inside the Docker Container. Seems like you solved that problem; I think you have to configure your docker container to forward specific ports into your container so that they can be reached from the outside.