def test_add_report_with_invalid_callback_signature(): client = OpenADRClient(ven_name='myven', vtn_url='http://localhost') with pytest.raises(TypeError): client.add_report(callback=wrong_sig, data_collection_mode='full', resource_id='myresource1', measurement='voltage')
async def test_client_event_cleanup(): now = datetime.datetime.now(datetime.timezone.utc) server = OpenADRServer(vtn_id='myvtn') server.add_handler('on_create_party_registration', on_create_party_registration) loop = asyncio.get_event_loop() event_1_callback_future = loop.create_future() event_2_callback_future = loop.create_future() server.add_event(ven_id='ven123', signal_name='simple', signal_type='level', intervals=[ objects.Interval( dtstart=now, duration=datetime.timedelta(seconds=1), signal_payload=1) ], callback=event_1_callback_future) await server.run() client = OpenADRClient( ven_name='ven123', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') client.add_handler('on_event', on_event_opt_in) await client.run() await asyncio.sleep(0.5) assert len(client.received_events) == 1 await asyncio.sleep(0.5) await client._event_cleanup() assert len(client.received_events) == 0 await server.stop() await client.stop()
def test_invalid_scale(): client = OpenADRClient(ven_name='myven', vtn_url='http://localhost') with pytest.raises(ValueError): client.add_report(callback=print, resource_id='myresource', measurement='voltage', scale='non_existant')
async def test_ssl_certificates_wrong_fingerprint(caplog): loop = asyncio.get_event_loop() registration_future = loop.create_future() server = OpenADRServer(vtn_id='myvtn', http_cert=VTN_CERT, http_key=VTN_KEY, http_ca_file=CA_CERT, cert=VTN_CERT, key=VTN_KEY, fingerprint_lookup=lookup_fingerprint) server.add_handler('on_create_party_registration', partial(on_create_party_registration, future=registration_future)) await server.run_async() #await asyncio.sleep(1) # Run the client client = OpenADRClient(ven_name='myven', vtn_url='https://localhost:8080/OpenADR2/Simple/2.0b', cert=VEN_CERT, key=VEN_KEY, ca_file=CA_CERT, vtn_fingerprint='00:11:22:33:44:55:66:77:88:99') await client.run() # Wait for the registration to be triggered result = await asyncio.wait_for(registration_future, 1.0) assert client.registration_id is None assert ("The certificate fingerprint was incorrect. Expected: 00:11:22:33:44:55:66:77:88:99; " "Received: 39:0F:7F:45:84:D6:24:49:FE:B7. Ignoring message.") in [rec.message for rec in caplog.records] await client.stop() await server.stop()
async def test_ssl_certificates_wrong_cert(): loop = asyncio.get_event_loop() registration_future = loop.create_future() server = OpenADRServer(vtn_id='myvtn', http_cert=VTN_CERT, http_key=VTN_KEY, http_ca_file=CA_CERT, cert=VTN_CERT, key=VTN_KEY, fingerprint_lookup=lookup_fingerprint) server.add_handler('on_create_party_registration', partial(on_create_party_registration, future=registration_future)) await server.run_async() #await asyncio.sleep(1) # Run the client client = OpenADRClient(ven_name='myven', vtn_url='https://localhost:8080/OpenADR2/Simple/2.0b', cert=VTN_CERT, key=VTN_KEY, ca_file=CA_CERT, vtn_fingerprint=vtn_fingerprint) await client.run() # Wait for the registration to be triggered with pytest.raises(asyncio.TimeoutError): await asyncio.wait_for(registration_future, timeout=0.5) assert client.registration_id is None await client.stop() await server.stop() await asyncio.sleep(0)
async def test_ssl_certificates(disable_signature): loop = asyncio.get_event_loop() registration_future = loop.create_future() server = OpenADRServer(vtn_id='myvtn', http_cert=VTN_CERT, http_key=VTN_KEY, http_ca_file=CA_CERT, cert=VTN_CERT, key=VTN_KEY, fingerprint_lookup=lookup_fingerprint) server.add_handler('on_create_party_registration', partial(on_create_party_registration, future=registration_future)) await server.run_async() #await asyncio.sleep(1) # Run the client client = OpenADRClient(ven_name='myven', vtn_url='https://localhost:8080/OpenADR2/Simple/2.0b', cert=VEN_CERT, key=VEN_KEY, ca_file=CA_CERT, vtn_fingerprint=vtn_fingerprint, disable_signature=disable_signature) await client.run() # Wait for the registration to be triggered result = await asyncio.wait_for(registration_future, 1.0) assert client.registration_id == 'reg5678' await client.stop() await server.stop()
async def test_openadr_error(start_server): client = OpenADRClient( vtn_url=f"http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b", ven_name=VEN_NAME) client.on_event = _client_on_event await client.run() await client.client_session.close()
async def test_request_event(): loop = asyncio.get_event_loop() client = OpenADRClient( ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') server = OpenADRServer(vtn_id='myvtn', requested_poll_freq=datetime.timedelta(seconds=1)) server.add_handler('on_create_party_registration', on_create_party_registration) event_id = server.add_event( ven_id='ven123', signal_name='simple', signal_type='level', intervals=[{ 'dtstart': datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(seconds=4), 'duration': datetime.timedelta(seconds=2), 'signal_payload': 1 }], ramp_up_period=datetime.timedelta(seconds=2), callback=partial(event_callback)) assert server.events['ven123'][0].event_descriptor.event_status == 'far' await server.run_async() await client.create_party_registration() message_type, message_payload = await client.request_event() assert message_type == 'oadrDistributeEvent' message_type, message_payload = await client.request_event() assert message_type == 'oadrDistributeEvent' await client.stop() await server.stop()
async def test_create_party_registration(start_server): client = OpenADRClient( ven_name=VEN_NAME, vtn_url=f"http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b") response_type, response_payload = await client.create_party_registration() assert response_type == 'oadrCreatedPartyRegistration' assert response_payload['ven_id'] == VEN_ID
def test_add_report_invalid_description(caplog): client = OpenADRClient(ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') with pytest.raises(ValueError): client.add_report(callback=print, report_specifier_id='myreport', measurement={'name': 'voltage', 'description': 'SomethingWrong', 'unit': 'V'}, resource_id='Device001', sampling_rate=timedelta(seconds=10))
async def test_cancel_event(): async def opt_in_to_event(event, future=None): if future: future.set_result(True) return 'optIn' async def on_update_event(event, future=None): if future: future.set_result(event) return 'optIn' now = datetime.datetime.now(datetime.timezone.utc) server = OpenADRServer(vtn_id='myvtn', requested_poll_freq=datetime.timedelta(seconds=1)) server.add_handler('on_create_party_registration', on_create_party_registration) loop = asyncio.get_event_loop() event_1_callback_future = loop.create_future() event_id = server.add_event( ven_id='ven123', signal_name='simple', signal_type='level', intervals=[ objects.Interval(dtstart=now, duration=datetime.timedelta(seconds=60), signal_payload=1) ], callback=event_1_callback_future, response_required='always') await server.run() client = OpenADRClient( ven_name='ven123', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') client.add_handler('on_event', opt_in_to_event) cancel_future = loop.create_future() client.add_handler('on_update_event', partial(on_update_event, future=cancel_future)) await client.run() await event_1_callback_future server.cancel_event('ven123', event_id) result = await cancel_future assert utils.getmember(result, 'event_descriptor.event_status') == 'cancelled' response_type, response_payload = await client.request_event() assert response_type == 'oadrResponse' await client._event_cleanup() assert len(client.responded_events) == 0 assert len(client.received_events) == 0 await server.stop() await client.stop()
def test_add_report_invalid_unit(caplog): client = OpenADRClient(ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') client.add_report(callback=print, report_specifier_id='myreport', measurement='voltage', resource_id='Device001', sampling_rate=timedelta(seconds=10), unit='A') assert caplog.record_tuples == [("openleadr", logging.WARNING, f"The supplied unit A for measurement voltage will be ignored, V will be used instead. Allowed units for this measurement are: V")]
def test_add_report_without_specifier_id(): client = OpenADRClient(ven_name='myven', vtn_url='http://localhost') client.add_report(callback=print, resource_id='myresource1', measurement='voltage') client.add_report(callback=print, resource_id='myresource2', measurement='voltage') assert len(client.reports) == 1
async def test_signature_error(start_server_with_signatures): client = OpenADRClient( vtn_url=f"http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b", ven_name=VEN_NAME, vtn_fingerprint="INVALID") client.on_event = _client_on_event await client.run() await asyncio.sleep(0) await client.client_session.close()
async def test_incremental_reports(): loop = asyncio.get_event_loop() client = OpenADRClient( ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') collect_futures = [loop.create_future() for i in range(2)] client.add_report(callback=partial(collect_data_multi, futures=collect_futures), report_specifier_id='myhistory', measurement='voltage', resource_id='mydevice', sampling_rate=timedelta(seconds=2)) server = OpenADRServer(vtn_id='myvtn') register_report_future = loop.create_future() update_report_future = loop.create_future() server.add_handler( 'on_register_report', partial(on_register_report, bundling=2, futures=[register_report_future], receive_futures=[update_report_future])) party_future = loop.create_future() server.add_handler( 'on_create_party_registration', partial(on_create_party_registration, future=party_future)) loop.create_task(server.run_async()) await asyncio.sleep(1) await client.run() print("Awaiting party future") await party_future print("Awaiting register report future") await register_report_future print("Awaiting first data collection future... ", end="") await collect_futures[0] print("check") await asyncio.sleep(1) print("Checking that the report was not yet sent... ", end="") assert update_report_future.done() is False print("check") print("Awaiting data collection second future... ", end="") await collect_futures[1] print("check") print("Awaiting report update future") result = await update_report_future assert len(result) == 2 await server.stop() await client.stop() await asyncio.sleep(0)
async def test_wrong_endpoint(start_server, caplog): message = messaging.create_message("oadrQueryRegistration", request_id='req1234') client = OpenADRClient( ven_name='myven', vtn_url=f'http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b') response_type, response_payload = await client._perform_request( 'OadrPoll', message) assert response_type == 'oadrResponse' assert response_payload['response']['response_code'] == 459
def test_add_report_invalid_scale(): client = OpenADRClient(ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') with pytest.raises(ValueError): client.add_report(callback=print, report_specifier_id='myreport', measurement='power_real', resource_id='Device001', sampling_rate=timedelta(seconds=10), unit='W', scale='xxx')
async def test_update_report_data_collection_mode_full(): loop = asyncio.get_event_loop() client = OpenADRClient( ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') data_collection_future = loop.create_future() client.add_report(callback=partial(collect_data_history, futures=[data_collection_future]), resource_id='Device001', measurement='power_real', data_collection_mode='full', sampling_rate=timedelta(seconds=1), unit='W') report_register_future = loop.create_future() report_received_future = loop.create_future() party_registration_future = loop.create_future() server = OpenADRServer(vtn_id='myvtn') server.add_handler( 'on_create_party_registration', partial(on_create_party_registration, future=party_registration_future)) server.add_handler( 'on_register_report', partial(on_register_report, bundling=2, futures=[report_register_future], receive_futures=[report_received_future])) await server.run_async() await asyncio.sleep(0.1) print(f"The time is now {datetime.now()}") t = time.time() wait_for = int(t / 2) * 2 + 2 - t await asyncio.sleep(wait_for) print(f"The time is now {datetime.now()}, running client") await client.run() await party_registration_future await report_register_future await asyncio.sleep(1) print( f"The time is now {datetime.now()}, checking if report was triggered") assert data_collection_future.done() is False print("Waiting for the data collection to occur") await data_collection_future print("Waiting for the report to be received") await report_received_future print("Done") await server.stop() await client.stop()
async def test_report_registration_with_status_report(): """ Test the registration of two reports with two r_ids each. """ # Create a server logger = logging.getLogger('openleadr') logger.setLevel(logging.DEBUG) server = OpenADRServer(vtn_id='testvtn') server.add_handler('on_register_report', on_register_report) server.add_handler('on_create_party_registration', on_create_party_registration) # Create a client client = OpenADRClient( ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b', ) # Add 4 reports client.add_report(callback=collect_data, report_specifier_id='CurrentReport', resource_id='Device001', measurement='current', unit='A') client.add_report(callback=collect_data, report_specifier_id='CurrentReport', resource_id='Device002', measurement='current', unit='A') client.add_report(callback=collect_data, report_specifier_id='VoltageReport', resource_id='Device001', measurement='voltage', unit='V') client.add_report(callback=collect_data, report_specifier_id='VoltageReport', resource_id='Device002', measurement='voltage', unit='V') client.add_report(callback=collect_status, report_name='TELEMETRY_STATUS', report_specifier_id='StatusReport', resource_id='Device001') asyncio.create_task(server.run_async()) await asyncio.sleep(1) # Register the client await client.create_party_registration() # Register the reports await client.register_reports(client.reports) assert len(client.report_requests) == 3 assert len(server.services['report_service'].report_callbacks) == 5 await client.stop() await server.stop()
async def test_raw_event(): now = datetime.datetime.now(datetime.timezone.utc) server = OpenADRServer(vtn_id='myvtn') server.add_handler('on_create_party_registration', on_create_party_registration) event = objects.Event( event_descriptor=objects.EventDescriptor( event_id='event001', modification_number=0, event_status='far', market_context='http://marketcontext01'), event_signals=[ objects.EventSignal( signal_id='signal001', signal_type='level', signal_name='simple', intervals=[ objects.Interval(dtstart=now, duration=datetime.timedelta(minutes=10), signal_payload=1) ]), objects.EventSignal( signal_id='signal002', signal_type='price', signal_name='ELECTRICITY_PRICE', intervals=[ objects.Interval(dtstart=now, duration=datetime.timedelta(minutes=10), signal_payload=1) ]) ], targets=[objects.Target(ven_id='ven123')]) loop = asyncio.get_event_loop() event_callback_future = loop.create_future() server.add_raw_event(ven_id='ven123', event=event, callback=partial(event_callback, future=event_callback_future)) on_event_future = loop.create_future() client = OpenADRClient( ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') client.add_handler('on_event', partial(on_event_opt_in, future=on_event_future)) await server.run_async() await client.run() event = await on_event_future assert len(event['event_signals']) == 2 result = await event_callback_future assert result == 'optIn' await client.stop() await server.stop()
def test_add_report_non_standard_measurement(): client = OpenADRClient(ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') client.add_report(callback=print, report_specifier_id='myreport', measurement='rainbows', resource_id='Device001', sampling_rate=timedelta(seconds=10), unit='A') assert len(client.reports) == 1 assert client.reports[0].report_descriptions[0].measurement.name == 'customUnit' assert client.reports[0].report_descriptions[0].measurement.description == 'rainbows'
async def test_throw_protocol_error(caplog): server = OpenADRServer(vtn_id=VTN_ID, http_port=SERVER_PORT) server.add_handler('on_create_party_registration', protocol_error_handler) await server.run_async() client = OpenADRClient( ven_name='myven', vtn_url=f'http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b') await client.run() #await asyncio.sleep(0.5) await client.stop() await server.stop() assert 'We got a non-OK OpenADR response from the server: 450: OUT OF SEQUENCE' in caplog.messages
def test_add_report_invalid_description(caplog): client = OpenADRClient( ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') client.add_report(callback=print, report_specifier_id='myreport', measurement={ 'name': 'voltage', 'description': 'SomethingWrong', 'unit': 'V' }, resource_id='mydevice', sampling_rate=timedelta(seconds=10)) msg = create_message('oadrRegisterReport', reports=client.reports)
async def test_conformance_021(): """ If venID, vtnID, or eventID value is included in the payload, the receiving entity MUST validate that the ID value is as expected and generate an error if an unexpected value is received. Exception: A VEN MUST NOT generate an error upon receipt of a canceled event whose eventID is not previously known. """ server = OpenADRServer(vtn_id='TestVTN', http_port=8001) server.add_handler('on_create_party_registration', on_create_party_registration) server.add_handler('on_poll', _on_poll) await server.run_async() client = OpenADRClient(ven_name="TestVEN", vtn_url="http://localhost:8001/OpenADR2/Simple/2.0b") await client.create_party_registration() event = {'event_descriptor': {'event_id': generate_id(), 'modification_number': 0, 'modification_date': datetime.now(), 'priority': 0, 'market_context': 'MarketContext001', 'created_date_time': datetime.now(), 'event_status': enums.EVENT_STATUS.FAR, 'test_event': False, 'vtn_comment': 'No Comment'}, 'active_period': {'dtstart': datetime.now() + timedelta(minutes=30), 'duration': timedelta(minutes=30)}, 'event_signals': [{'intervals': [{'duration': timedelta(minutes=10), 'signal_payload': 1}, {'duration': timedelta(minutes=10), 'signal_payload': 2}, {'duration': timedelta(minutes=10), 'signal_payload': 3}], 'signal_name': enums.SIGNAL_NAME.SIMPLE, 'signal_type': enums.SIGNAL_TYPE.DELTA, 'signal_id': generate_id(), 'current_value': 123 }], 'targets': [{'ven_id': '123'}] } add_event(ven_id=client.ven_id, event_id = event['event_descriptor']['event_id'], event=event) message_type, message_payload = await client.poll() assert message_type == 'oadrDistributeEvent' await client.stop() await server.stop()
def test_replay_protect_repeated_message(caplog): client = OpenADRClient( ven_name='myven', vtn_url=f'https://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b', cert=VEN_CERT, key=VEN_KEY, vtn_fingerprint=VTN_FINGERPRINT) message = client._create_message('oadrPoll', ven_id='ven123') tree = etree.fromstring(message.encode('utf-8')) messaging._verify_replay_protect(tree) with pytest.raises(ValueError) as err: messaging._verify_replay_protect(tree) assert str(err.value ) == 'This combination of timestamp and nonce was already used.'
def test_replay_protect_message_too_old(caplog): client = OpenADRClient( ven_name='myven', vtn_url=f'https://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b', cert=VEN_CERT, key=VEN_KEY, vtn_fingerprint=VTN_FINGERPRINT) _temp = messaging.REPLAY_PROTECT_MAX_TIME_DELTA messaging.REPLAY_PROTECT_MAX_TIME_DELTA = timedelta(seconds=0) message = client._create_message('oadrPoll', ven_id='ven123') tree = etree.fromstring(message.encode('utf-8')) with pytest.raises(ValueError) as err: messaging._verify_replay_protect(tree) assert str(err.value) == 'The message was signed too long ago.' messaging.REPLAY_PROTECT_MAX_TIME_DELTA = _temp
async def test_create_party_registration_with_signatures( start_server_with_signatures): with open(CERTFILE) as file: cert = file.read() client = OpenADRClient( ven_name=VEN_NAME, vtn_url=f"http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b", cert=CERTFILE, key=KEYFILE, vtn_fingerprint=certificate_fingerprint(cert)) response_type, response_payload = await client.create_party_registration() assert response_type == 'oadrCreatedPartyRegistration' assert response_payload['ven_id'] == VEN_ID await client.stop()
def test_replay_protect_missing_nonce(caplog): client = OpenADRClient( ven_name='myven', vtn_url=f'https://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b', cert=VEN_CERT, key=VEN_KEY, vtn_fingerprint=VTN_FINGERPRINT) message = client._create_message('oadrPoll', ven_id='ven123') message = re.sub('<dsp:nonce>.*?</dsp:nonce>', '', message) tree = etree.fromstring(message.encode('utf-8')) with pytest.raises(ValueError) as err: messaging._verify_replay_protect(tree) assert str( err.value ) == "Missing 'nonce' element in ReplayProtect in incoming message."
async def test_message(message_type, message_payload): server = OpenADRServer(vtn_id='myvtn') server.add_handler('on_create_party_registration', on_create_party_registration) server.add_handler( 'on_poll', partial(poll_responder, message_type=message_type, message_payload=message_payload)) client = OpenADRClient( ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b') await server.run_async() await client.create_party_registration() response_type, response_payload = await client.poll() await server.stop() assert response_type == message_type
async def test_server_handler_exception(caplog): server = OpenADRServer(vtn_id=VTN_ID, http_port=SERVER_PORT) server.add_handler('on_create_party_registration', problematic_handler) await server.run_async() client = OpenADRClient( ven_name='myven', vtn_url=f'http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b') await client.run() #await asyncio.sleep(0.5) await client.stop() await server.stop() for message in caplog.messages: if message.startswith('Non-OK status 500 when performing a request'): break else: assert False