diff --git a/requirements.py b/requirements.py index 1aea9ee560..26f7e32a77 100644 --- a/requirements.py +++ b/requirements.py @@ -107,4 +107,5 @@ 'argon2-cffi==21.3.0', 'Werkzeug==2.2.1', 'treelib==1.6.1'], - 'dnp3': ['dnp3-python==0.2.3b3']} + 'dnp3': ['dnp3-python==0.2.3b3'], + 'openadr': ['openleadr==0.5.30']} diff --git a/services/core/OpenADRVenAgent/requirements.txt b/services/core/OpenADRVenAgent/requirements.txt index 07e26550c2..070898a182 100644 --- a/services/core/OpenADRVenAgent/requirements.txt +++ b/services/core/OpenADRVenAgent/requirements.txt @@ -1,2 +1,2 @@ -openleadr==0.5.27 -cryptography==37.0.4 \ No newline at end of file +openleadr==0.5.30 +cryptography==37.0.4 diff --git a/services/core/OpenADRVenAgent/tests/test_openadr_ven_agent.py b/services/core/OpenADRVenAgent/tests/test_openadr_ven_agent.py index 81df7ea830..7a5f7dd588 100644 --- a/services/core/OpenADRVenAgent/tests/test_openadr_ven_agent.py +++ b/services/core/OpenADRVenAgent/tests/test_openadr_ven_agent.py @@ -37,7 +37,7 @@ async def test_handle_event_should_return_optIn(mock_openadr_ven): @pytest.fixture def mock_openadr_ven(): - config_path = str(Path("config_test.json",).absolute()) + config_path = f"{Path(__file__).parent.absolute()}/config_test.json" OpenADRVenAgent.__bases__ = ( AgentMock.imitate(Agent, OpenADRVenAgent(config_path)), ) @@ -67,4 +67,4 @@ def add_report( resource_id, measurement, ): - pass \ No newline at end of file + pass diff --git a/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/maps/maps.yaml b/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/maps/maps.yaml index 3ecf6f3237..ab387b700c 100644 --- a/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/maps/maps.yaml +++ b/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/maps/maps.yaml @@ -48,4 +48,4 @@ - addressing: offset endian: big file: battery_meter.csv - name: battery_meter \ No newline at end of file + name: battery_meter diff --git a/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/tests/test_battery_meter.py b/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/tests/test_battery_meter.py index 9c890fd779..5c7a868b66 100644 --- a/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/tests/test_battery_meter.py +++ b/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/tests/test_battery_meter.py @@ -3,8 +3,10 @@ import logging import time +from struct import pack, unpack + from volttron.platform import get_services_core, jsonapi -from volttrontesting.utils.utils import get_rand_ip_and_port +from volttrontesting.utils.utils import get_rand_ip_and_port, is_running_in_container from platform_driver.interfaces.modbus_tk.server import Server from platform_driver.interfaces.modbus_tk.maps import Map, Catalog from volttron.platform.agent.known_identities import PLATFORM_DRIVER @@ -332,7 +334,8 @@ def modbus_server(request): server_process = Server(address=IP, port=PORT) server_process.define_slave(1, modbus_client, unsigned=False) - + for k in registers_dict: + server_process.set_values(1, modbus_client().field_by_name(k), unpack('f', 0))) server_process.start() time.sleep(1) yield server_process @@ -384,6 +387,7 @@ def scrape_all(self, agent, device_name): return agent.vip.rpc.call(PLATFORM_DRIVER, 'scrape_all', device_name)\ .get(timeout=10) + @pytest.mark.xfail(is_running_in_container(), reason='Fails to set points on this test setup, only in Docker.') def test_scrape_all(self, agent): for key in registers_dict.keys(): self.set_point(agent, 'modbus_tk', key, registers_dict[key]) diff --git a/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/tests/test_driver_demo_board.py b/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/tests/test_driver_demo_board.py new file mode 100644 index 0000000000..ea58ded782 --- /dev/null +++ b/services/core/PlatformDriverAgent/platform_driver/interfaces/modbus_tk/tests/test_driver_demo_board.py @@ -0,0 +1,120 @@ +import os + +import gevent +import pytest +from volttron.platform.agent.known_identities import CONFIGURATION_STORE, PLATFORM_DRIVER +from volttron.platform import jsonapi +from volttrontesting.utils.platformwrapper import PlatformWrapper + +MODBUS_TEST_IP = "MODBUS_TEST_IP" + +# apply skipif to all tests +skip_msg = f"Env var {MODBUS_TEST_IP} not set. Please set the env var to the proper IP to run this integration test." +pytestmark = pytest.mark.skipif(os.environ.get(MODBUS_TEST_IP) is None, reason=skip_msg) + + +def test_get_point(publish_agent): + registers = ["SupplyTemp", "ReturnTemp", "OutsideTemp"] + for point_name in registers: + point_val = publish_agent.vip.rpc.call(PLATFORM_DRIVER, "get_point", "modbustk", + point_name).get(timeout=10) + print(f"Point: {point_name} has point value of {point_val}") + assert isinstance(point_val, int) + + +def test_set_point(publish_agent): + point_name = "SecondStageCoolingDemandSetPoint" + point_val = 42 + publish_agent.vip.rpc.call(PLATFORM_DRIVER, "set_point", "modbustk", point_name, + point_val).get(timeout=10) + assert publish_agent.vip.rpc.call(PLATFORM_DRIVER, "get_point", "modbustk", + point_name).get(timeout=10) == point_val + + +@pytest.fixture(scope="module") +def publish_agent(volttron_instance: PlatformWrapper): + assert volttron_instance.is_running() + vi = volttron_instance + assert vi is not None + assert vi.is_running() + + config = { + "driver_scrape_interval": 0.05, + "publish_breadth_first_all": "false", + "publish_depth_first": "false", + "publish_breadth_first": "false" + } + puid = vi.install_agent(agent_dir=Path(__file__).parent.parent.parent.parent.parent.absolute().resolve(), + config_file=config, + start=False, + vip_identity=PLATFORM_DRIVER) + assert puid is not None + gevent.sleep(1) + assert vi.start_agent(puid) + assert vi.is_agent_running(puid) + + # create the publish agent + publish_agent = volttron_instance.build_agent() + assert publish_agent.core.identity + gevent.sleep(1) + + capabilities = {"edit_config_store": {"identity": PLATFORM_DRIVER}} + volttron_instance.add_capabilities(publish_agent.core.publickey, capabilities) + gevent.sleep(1) + + # Add Modbus Driver TK registry map to Platform Driver + registry_config_string = """Register Name,Address,Type,Units,Writable + SupplyTemp,0,uint16,degC,FALSE + ReturnTemp,1,uint16,degC,FALSE + OutsideTemp,2,uint16,degC,FALSE + SecondStageCoolingDemandSetPoint,14,uint16,degC,TRUE""" + publish_agent.vip.rpc.call(CONFIGURATION_STORE, + "manage_store", + PLATFORM_DRIVER, + "m2000_rtu_TK_map.csv", + registry_config_string, + config_type="csv").get(timeout=10) + + # Add Modbus Driver registry to Platform Driver + registry_config_string = """Register Name,Volttron Point Name + SupplyTemp,SupplyTemp + ReturnTemp,ReturnTemp + OutsideTemp,OutsideTemp + SecondStageCoolingDemandSetPoint,SecondStageCoolingDemandSetPoint""" + publish_agent.vip.rpc.call(CONFIGURATION_STORE, + "manage_store", + PLATFORM_DRIVER, + "m2000_rtu_TK.csv", + registry_config_string, + config_type="csv").get(timeout=10) + + # Add Modbus Driver config to Platform Driver + device_address = os.environ.get(MODBUS_TEST_IP) + driver_config = { + "driver_config": { + "device_address": device_address, + "slave_id": 8, + "port": 502, + "register_map": "config://m2000_rtu_TK_map.csv" + }, + "campus": "PNNL", + "building": "DEMO", + "unit": "M2000", + "driver_type": "modbus_tk", + "registry_config": "config://m2000_rtu_TK.csv", + "interval": 60, + "timezone": "Pacific", + "heart_beat_point": "heartbeat" + } + + publish_agent.vip.rpc.call(CONFIGURATION_STORE, + "manage_store", + PLATFORM_DRIVER, + "devices/modbustk", + jsonapi.dumps(driver_config), + config_type='json').get(timeout=10) + + yield publish_agent + + volttron_instance.stop_agent(puid) + publish_agent.core.stop() diff --git a/volttrontesting/platform/control_tests/test_control.py b/volttrontesting/platform/control_tests/test_control.py index b12d896576..5477b92df3 100644 --- a/volttrontesting/platform/control_tests/test_control.py +++ b/volttrontesting/platform/control_tests/test_control.py @@ -111,13 +111,14 @@ def test_prioritize_agent_valid_input(volttron_instance): assert cn.vip.rpc.call('control', 'prioritize_agent', auuid, '99').get(timeout=2) is None -@pytest.mark.xfail(reason="bytes() calls (control.py:390|398) raise: TypeError('string argument without an encoding').") @pytest.mark.parametrize('uuid, priority, expected', [ - (34, '50', "expected a string for 'uuid'"), + pytest.param(34, '50', "expected a string for 'uuid'", + marks=pytest.mark.xfail(reason="bytes() calls raise: TypeError(string argument without an encoding)")), ('34/7', '50', 'invalid agent'), ('.', '50', 'invalid agent'), ('..', '50', 'invalid agent'), - ('foo', 2, "expected a string or null for 'priority'"), + pytest.param('foo', 2, "expected a string or null for 'priority'", + marks=pytest.mark.xfail(reason="bytes() calls raise: TypeError(string argument without an encoding)")), ('foo', '-1', 'Priority must be an integer from 0 - 99.'), ('foo', '4.5', 'Priority must be an integer from 0 - 99.'), ('foo', '100', 'Priority must be an integer from 0 - 99.'), diff --git a/volttrontesting/platform/test_instance_setup.py b/volttrontesting/platform/test_instance_setup.py index b8ae70aeb6..d4a6961b1f 100644 --- a/volttrontesting/platform/test_instance_setup.py +++ b/volttrontesting/platform/test_instance_setup.py @@ -8,13 +8,15 @@ from volttron.platform.instance_setup import _is_agent_installed from volttron.utils import get_hostname from volttron.platform.agent.utils import is_volttron_running -from volttrontesting.fixtures.rmq_test_setup import create_rmq_volttron_setup from volttrontesting.utils.platformwrapper import create_volttron_home from volttrontesting.utils.utils import get_rand_port HAS_RMQ = is_rabbitmq_available() RMQ_TIMEOUT = 600 +if HAS_RMQ: + from volttrontesting.fixtures.rmq_test_setup import create_rmq_volttron_setup + ''' Example variables to be used during each of the tests, depending on the prompts that will be asked diff --git a/volttrontesting/services/historian/test_multiplatform.py b/volttrontesting/services/historian/test_multiplatform.py index 94c4b76385..5af92514f8 100644 --- a/volttrontesting/services/historian/test_multiplatform.py +++ b/volttrontesting/services/historian/test_multiplatform.py @@ -49,16 +49,19 @@ import gevent import pytest -from volttron.platform import get_services_core, jsonapi +from volttron.platform import get_services_core, jsonapi, is_rabbitmq_available from volttron.platform.agent import utils from volttron.platform.messaging import headers as headers_mod from volttrontesting.fixtures.volttron_platform_fixtures import build_wrapper +from volttrontesting.skip_if_handlers import rmq_skipif from volttrontesting.utils.utils import get_rand_vip, get_hostname_and_random_port from volttrontesting.utils.platformwrapper import PlatformWrapper from volttrontesting.fixtures.volttron_platform_fixtures import get_rand_vip, \ get_rand_ip_and_port -from volttron.utils.rmq_setup import start_rabbit, stop_rabbit from volttron.platform.agent.utils import execute_command +HAS_RMQ = is_rabbitmq_available() +if HAS_RMQ: + from volttron.utils.rmq_setup import start_rabbit, stop_rabbit @pytest.fixture(scope="module") @@ -239,6 +242,7 @@ def test_all_platform_subscription_zmq(request, get_zmq_volttron_instances): @pytest.mark.historian @pytest.mark.multiplatform +@pytest.mark.skipif(rmq_skipif, reason="RMQ not installed.") def test_all_platform_subscription_rmq(request, federated_rmq_instances): try: upstream, downstream = federated_rmq_instances