def get(self): """ Performs a fast query of a subset or all heat pump parameters representing a 'MP' data point. """ _LOGGER.info("*** [GET] %s", request.url) params = list(request.args.keys()) unknown = [name for name in params if name not in HtParams] if unknown: api.abort( 404, "Parameter(s) {} not found".format(", ".join( map(lambda name: "{!r}".format(name), unknown))), ) invalid = [name for name in params if HtParams[name].dp_type != "MP"] if invalid: api.abort( 400, "Parameter(s) {} doesn't represent a 'MP' data point".format( ", ".join(map(lambda name: "{!r}".format(name), invalid))), ) if not params: params = (name for name, param in HtParams.items() if param.dp_type == "MP") with HtContext(ht_heatpump): res = ht_heatpump.fast_query(*params) for name, value in res.items(): res[name] = bool_as_int(name, value) _LOGGER.debug("*** [GET] %s -> %s", request.url, res) return res
def test_fast_query_in_several_pieces(self, hthp: HtHeatpump): args = [] cmd = "" mp_data_points = [(name, param) for name, param in HtParams.items() if param.dp_type == "MP"] while len(cmd) < 255 * 2: # request has do be done in 3 parts name, param = random.choice(mp_data_points) cmd += ",{}".format(param.dp_number) args.append(name) values = hthp.fast_query(*args) assert isinstance(values, dict), "'values' must be of type dict" assert not args or len(values) == len(set(args)) for name, value in values.items(): assert name in HtParams assert not args or name in args assert value is not None assert HtParams[name].in_limits(value)
class TestAioHtHeatpump: @pytest.mark.run_if_connected def test_open_connection(self, hthp: AioHtHeatpump): assert hthp.is_open with pytest.raises(IOError): hthp.open_connection() # assert 0 @pytest.mark.parametrize( "action", [ VerifyAction.NONE(), {VerifyAction.NAME}, {VerifyAction.NAME, VerifyAction.MIN}, {VerifyAction.NAME, VerifyAction.MIN, VerifyAction.MAX}, {VerifyAction.NAME, VerifyAction.MIN, VerifyAction.MAX, VerifyAction.VALUE}, {VerifyAction.MIN, VerifyAction.MAX, VerifyAction.VALUE}, {VerifyAction.MAX, VerifyAction.VALUE}, {VerifyAction.VALUE}, VerifyAction.ALL(), ], ) def test_verify_param_action( self, cmdopt_device: str, cmdopt_baudrate: int, action: set ): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) val = hp.verify_param_action assert isinstance(val, set) hp.verify_param_action = action assert hp.verify_param_action == action hp.verify_param_action = val # assert 0 def test_verify_param_error(self, cmdopt_device: str, cmdopt_baudrate: int): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) val = hp.verify_param_error assert isinstance(val, bool) hp.verify_param_error = True assert hp.verify_param_error is True hp.verify_param_error = False assert hp.verify_param_error is False hp.verify_param_error = val # assert 0 @pytest.mark.asyncio async def test_send_request(self, cmdopt_device: str, cmdopt_baudrate: int): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) with pytest.raises(IOError): await hp.send_request_async(r"LIN") # assert 0 @pytest.mark.asyncio async def test_read_response(self, cmdopt_device: str, cmdopt_baudrate: int): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) with pytest.raises(IOError): await hp.read_response_async() # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_serial_number(self, hthp: AioHtHeatpump): rid = await hthp.get_serial_number_async() assert isinstance(rid, int), "'rid' must be of type int" assert rid > 0 # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_version(self, hthp: AioHtHeatpump): version = await hthp.get_version_async() # ( "3.0.20", 2321 ) assert isinstance(version, tuple), "'version' must be of type tuple" assert len(version) == 2 ver_str, ver_num = version assert isinstance(ver_str, str), "'ver_str' must be of type str" m = re.match(r"^(\d+).(\d+).(\d+)$", ver_str) assert m is not None, "invalid version string [{!r}]".format(ver_str) assert isinstance(ver_num, int), "'ver_num' must be of type int" assert ver_num > 0 await hthp.send_request_async(r"SP,NR=9") resp = await hthp.read_response_async() m = re.match(r"^SP,NR=9,.*NAME=([^,]+).*VAL=([^,]+).*$", resp) assert ( m is not None ), "invalid response for query of the software version [{!r}]".format(resp) assert ver_str == m.group(1).strip() assert ver_num == int(m.group(2)) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_date_time(self, hthp: AioHtHeatpump): date_time = await hthp.get_date_time_async() # (datetime.datetime(...), 2) # 2 = Tuesday assert isinstance(date_time, tuple), "'date_time' must be of type tuple" assert len(date_time) == 2 dt, weekday = date_time assert isinstance(dt, datetime.datetime), "'dt' must be of type datetime" assert isinstance(weekday, int), "'weekday' must be of type int" assert weekday in range(1, 8) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_set_date_time(self, hthp: AioHtHeatpump): pass # TODO # assert 0 @pytest.mark.asyncio async def test_set_date_time_raises_TypeError( self, cmdopt_device: str, cmdopt_baudrate: int ): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) with pytest.raises(TypeError): await hp.set_date_time_async(123) # type: ignore # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_last_fault(self, hthp: AioHtHeatpump): fault = await hthp.get_last_fault_async() # (29, 20, datetime.datetime(...), "EQ_Spreizung") assert isinstance(fault, tuple), "'fault' must be of type tuple" assert len(fault) == 4 index, error, dt, msg = fault assert isinstance(index, int), "'index' must be of type int" assert 0 <= index < await hthp.get_fault_list_size_async() assert isinstance(error, int), "'error' must be of type int" assert error >= 0 assert isinstance(dt, datetime.datetime), "'dt' must be of type datetime" assert isinstance(msg, str), "'msg' must be of type str" # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_fault_list_size(self, hthp: AioHtHeatpump): size = await hthp.get_fault_list_size_async() assert isinstance(size, int), "'size' must be of type int" assert size >= 0 # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_fault_list(self, hthp: AioHtHeatpump): fault_list = await hthp.get_fault_list_async() # [ { "index": 29, # fault list index # "error": 20, # error code # "datetime": datetime.datetime(...), # date and time of the entry # "message": "EQ_Spreizung", # error message # }, # # ... # ] assert isinstance(fault_list, list), "'fault_list' must be of type list" assert len(fault_list) == await hthp.get_fault_list_size_async() for entry in fault_list: assert isinstance(entry, dict), "'entry' must be of type dict" index = entry["index"] assert isinstance(index, int), "'index' must be of type int" assert 0 <= index < await hthp.get_fault_list_size_async() error = entry["error"] assert isinstance(error, int), "'error' must be of type int" assert error >= 0 dt = entry["datetime"] assert isinstance(dt, datetime.datetime), "'dt' must be of type datetime" msg = entry["message"] assert isinstance(msg, str), "'msg' must be of type str" # assert 0 # @pytest.mark.skip(reason="test needs a rework") @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_fault_list_in_several_pieces(self, hthp: AioHtHeatpump): args = [] cmd = "" fault_list_size = await hthp.get_fault_list_size_async() while len(cmd) < 255 * 2: # request has do be done in 3 parts item = random.randint(0, fault_list_size - 1) cmd += ",{}".format(item) args.append(item) fault_list = await hthp.get_fault_list_async(*args) # [ { "index": 29, # fault list index # "error": 20, # error code # "datetime": datetime.datetime(...), # date and time of the entry # "message": "EQ_Spreizung", # error message # }, # # ... # ] assert isinstance(fault_list, list), "'fault_list' must be of type list" assert len(fault_list) == len(args) for entry in fault_list: assert isinstance(entry, dict), "'entry' must be of type dict" index = entry["index"] assert isinstance(index, int), "'index' must be of type int" assert 0 <= index < fault_list_size error = entry["error"] assert isinstance(error, int), "'error' must be of type int" assert error >= 0 dt = entry["datetime"] assert isinstance(dt, datetime.datetime), "'dt' must be of type datetime" msg = entry["message"] assert isinstance(msg, str), "'msg' must be of type str" # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_fault_list_with_index(self, hthp: AioHtHeatpump): size = await hthp.get_fault_list_size_async() assert isinstance(size, int), "'size' must be of type int" assert size >= 0 for i in range(size): fault_list = await hthp.get_fault_list_async(i) assert isinstance(fault_list, list), "'fault_list' must be of type list" assert len(fault_list) == 1 entry = fault_list[0] assert isinstance(entry, dict), "'entry' must be of type dict" index = entry["index"] assert isinstance(index, int), "'index' must be of type int" assert 0 <= index < await hthp.get_fault_list_size_async() error = entry["error"] assert isinstance(error, int), "'error' must be of type int" assert error >= 0 dt = entry["datetime"] assert isinstance(dt, datetime.datetime), "'dt' must be of type datetime" msg = entry["message"] assert isinstance(msg, str), "'msg' must be of type str" # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_fault_list_with_index_raises_IOError(self, hthp: AioHtHeatpump): with pytest.raises(IOError): await hthp.get_fault_list_async(-1) with pytest.raises(IOError): await hthp.get_fault_list_async(await hthp.get_fault_list_size_async()) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_fault_list_with_indices(self, hthp: AioHtHeatpump): size = await hthp.get_fault_list_size_async() for cnt in range(size + 1): indices = random.sample(range(size), cnt) fault_list = await hthp.get_fault_list_async(*indices) assert isinstance(fault_list, list), "'fault_list' must be of type list" assert len(fault_list) == (cnt if cnt > 0 else size) for entry in fault_list: assert isinstance(entry, dict), "'entry' must be of type dict" index = entry["index"] assert isinstance(index, int), "'index' must be of type int" assert 0 <= index < await hthp.get_fault_list_size_async() error = entry["error"] assert isinstance(error, int), "'error' must be of type int" assert error >= 0 dt = entry["datetime"] assert isinstance( dt, datetime.datetime ), "'dt' must be of type datetime" msg = entry["message"] assert isinstance(msg, str), "'msg' must be of type str" # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize("name, param", HtParams.items()) @pytest.mark.asyncio async def test_get_param(self, hthp: AioHtHeatpump, name: str, param: HtParam): value = await hthp.get_param_async(name) assert value is not None, "'value' must not be None" assert param.in_limits(value) # assert 0 @pytest.mark.asyncio async def test_get_param_raises_KeyError( self, cmdopt_device: str, cmdopt_baudrate: int ): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) with pytest.raises(KeyError): await hp.get_param_async("BlaBlaBla") # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize("name, param", HtParams.items()) @pytest.mark.asyncio async def test_set_param(self, hthp: AioHtHeatpump, name: str, param: HtParam): pass # TODO # assert 0 @pytest.mark.asyncio async def test_set_param_raises_KeyError( self, cmdopt_device: str, cmdopt_baudrate: int ): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) with pytest.raises(KeyError): await hp.set_param_async("BlaBlaBla", 123) # assert 0 @pytest.mark.parametrize( "name, param", [ (name, param) for name, param in HtParams.items() if param.data_type in (HtDataTypes.INT, HtDataTypes.FLOAT) ], ) @pytest.mark.asyncio async def test_set_param_raises_ValueError( self, cmdopt_device: str, cmdopt_baudrate: int, name: str, param: HtParam ): # hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) # with pytest.raises(ValueError): # await hp.set_param_async(name, param.min_val - 1, ignore_limits=False) # type: ignore # with pytest.raises(ValueError): # await hp.set_param_async(name, param.max_val + 1, ignore_limits=False) # type: ignore pass # TODO # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_in_error(self, hthp: AioHtHeatpump): in_error = await hthp.in_error_async assert isinstance(in_error, bool), "'in_error' must be of type bool" assert in_error == await hthp.get_param_async("Stoerung") # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_query(self, hthp: AioHtHeatpump): values = await hthp.query_async() # { "HKR Soll_Raum": 21.0, # "Stoerung": False, # "Temp. Aussen": 8.8, # # ... # } assert isinstance(values, dict), "'values' must be of type dict" assert len(values) == len(HtParams) for name, value in values.items(): assert name in HtParams assert value is not None assert HtParams[name].in_limits(value) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize( "names", [ random.sample(sorted(HtParams.keys()), cnt) for cnt in range(len(HtParams) + 1) ], ) @pytest.mark.asyncio async def test_query_with_names(self, hthp: AioHtHeatpump, names: List[str]): values = await hthp.query_async(*names) # { "HKR Soll_Raum": 21.0, # "Stoerung": False, # "Temp. Aussen": 8.8, # # ... # } assert isinstance(values, dict), "'values' must be of type dict" assert not names or len(values) == len(set(names)) for name, value in values.items(): assert name in HtParams assert not names or name in names assert value is not None assert HtParams[name].in_limits(value) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_fast_query(self, hthp: AioHtHeatpump): values = await hthp.fast_query_async() assert isinstance(values, dict), "'values' must be of type dict" assert len(values) == len(HtParams.of_type("MP")) for name, value in values.items(): assert name in HtParams assert value is not None assert HtParams[name].in_limits(value) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize( "names", [ random.sample(sorted(HtParams.of_type("MP").keys()), cnt) for cnt in range(len(HtParams.of_type("MP")) + 1) ], ) @pytest.mark.asyncio async def test_fast_query_with_names(self, hthp: AioHtHeatpump, names: List[str]): values = await hthp.fast_query_async(*names) assert isinstance(values, dict), "'values' must be of type dict" assert not names or len(values) == len(set(names)) for name, value in values.items(): assert name in HtParams assert not names or name in names assert value is not None assert HtParams[name].in_limits(value) # assert 0 @pytest.mark.asyncio async def test_fast_query_with_names_raises_KeyError( self, cmdopt_device: str, cmdopt_baudrate: int ): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) with pytest.raises(KeyError): await hp.fast_query_async("BlaBlaBla") # assert 0 @pytest.mark.parametrize( "names", [ random.sample(sorted(HtParams.of_type("SP").keys()), cnt) for cnt in range(1, len(HtParams.of_type("SP")) + 1) ], ) @pytest.mark.asyncio async def test_fast_query_with_names_raises_ValueError( self, cmdopt_device: str, cmdopt_baudrate: int, names: List[str] ): hp = AioHtHeatpump(device=cmdopt_device, baudrate=cmdopt_baudrate) with pytest.raises(ValueError): await hp.fast_query_async(*names) # assert 0 # @pytest.mark.skip(reason="test needs a rework") @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_fast_query_in_several_pieces(self, hthp: AioHtHeatpump): args = [] cmd = "" mp_data_points = [ (name, param) for name, param in HtParams.items() if param.dp_type == "MP" ] while len(cmd) < 255 * 2: # request has do be done in 3 parts name, param = random.choice(mp_data_points) cmd += ",{}".format(param.dp_number) args.append(name) values = await hthp.fast_query_async(*args) assert isinstance(values, dict), "'values' must be of type dict" assert not args or len(values) == len(set(args)) for name, value in values.items(): assert name in HtParams assert not args or name in args assert value is not None assert HtParams[name].in_limits(value) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_get_time_progs(self, hthp: AioHtHeatpump): time_progs = await hthp.get_time_progs_async() assert isinstance(time_progs, List), "'time_progs' must be of type list" assert len(time_progs) > 0 assert all([isinstance(time_prog, TimeProgram) for time_prog in time_progs]) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize( "index", range(5) ) # TODO range(5) -> range(len(hthp.get_time_progs())) @pytest.mark.asyncio async def test_get_time_prog(self, hthp: AioHtHeatpump, index: int): time_prog = await hthp.get_time_prog_async(index, with_entries=False) assert isinstance( time_prog, TimeProgram ), "'time_prog' must be of type TimeProgram" time_prog = await hthp.get_time_prog_async(index, with_entries=True) assert isinstance( time_prog, TimeProgram ), "'time_prog' must be of type TimeProgram" # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize("index", [-1, 5]) @pytest.mark.asyncio async def test_get_time_prog_raises_IOError(self, hthp: AioHtHeatpump, index: int): with pytest.raises(IOError): await hthp.get_time_prog_async(index, with_entries=False) with pytest.raises(IOError): await hthp.get_time_prog_async(index, with_entries=True) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize( "index, day, num", [ # for ALL time program entries (index, day, num) for index in range(5) for day in range(7) for num in range(7) ], ) @pytest.mark.asyncio async def test_get_time_prog_entry( self, hthp: AioHtHeatpump, index: int, day: int, num: int ): entry = await hthp.get_time_prog_entry_async(index, day, num) assert isinstance(entry, TimeProgEntry), "'entry' must be of type TimeProgEntry" # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize( "index, day, num", [ (5, 0, 0), # index=5 is invalid (0, 7, 0), # day=7 is invalid (0, 0, 7), # num=7 is invalid ], ) @pytest.mark.asyncio async def test_get_time_prog_entry_raises_IOError( self, hthp: AioHtHeatpump, index: int, day: int, num: int ): with pytest.raises(IOError): await hthp.get_time_prog_entry_async(index, day, num) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_set_time_prog_entry(self, hthp: AioHtHeatpump): pass # TODO # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.asyncio async def test_set_time_prog(self, hthp: AioHtHeatpump): pass # TODO
class TestHtParam: @pytest.mark.parametrize( "s, data_type, exp_value, strict", [ ("0", HtDataTypes.BOOL, False, False), ("1", HtDataTypes.BOOL, True, False), ("123", HtDataTypes.INT, 123, False), ("-321", HtDataTypes.INT, -321, False), ("123.456", HtDataTypes.FLOAT, 123.456, False), ("-321.456", HtDataTypes.FLOAT, -321.456, False), ("789", HtDataTypes.FLOAT, 789.0, False), # -- should raise a 'ValueError': ("True", HtDataTypes.BOOL, None, False), ("False", HtDataTypes.BOOL, None, False), ("true", HtDataTypes.BOOL, None, False), ("false", HtDataTypes.BOOL, None, False), ("yes", HtDataTypes.BOOL, None, False), ("no", HtDataTypes.BOOL, None, False), ("y", HtDataTypes.BOOL, None, False), ("n", HtDataTypes.BOOL, None, False), ("TRUE", HtDataTypes.BOOL, None, False), ("FALSE", HtDataTypes.BOOL, None, False), ("YES", HtDataTypes.BOOL, None, False), ("NO", HtDataTypes.BOOL, None, False), ("Y", HtDataTypes.BOOL, None, False), ("N", HtDataTypes.BOOL, None, False), ("abc", HtDataTypes.BOOL, None, False), ("def", HtDataTypes.INT, None, False), ("--99", HtDataTypes.INT, None, False), ("12+55", HtDataTypes.INT, None, False), ("ghi", HtDataTypes.FLOAT, None, False), ("--99.0", HtDataTypes.FLOAT, None, False), ("12.3+55.9", HtDataTypes.FLOAT, None, False), ("789", HtDataTypes.FLOAT, None, True), # -- should raise a 'TypeError': (123, HtDataTypes.BOOL, None, False), (123, HtDataTypes.INT, None, False), (123, HtDataTypes.FLOAT, None, False), (123.123, HtDataTypes.BOOL, None, False), (123.123, HtDataTypes.INT, None, False), (123.123, HtDataTypes.FLOAT, None, False), (True, HtDataTypes.BOOL, None, False), (True, HtDataTypes.INT, None, False), (True, HtDataTypes.FLOAT, None, False), (False, HtDataTypes.BOOL, None, False), (False, HtDataTypes.INT, None, False), (False, HtDataTypes.FLOAT, None, False), (None, HtDataTypes.BOOL, None, False), (None, HtDataTypes.INT, None, False), (None, HtDataTypes.FLOAT, None, False), # ... ], ) def test_from_str_static( self, s: str, data_type: HtDataTypes, exp_value: Optional[HtParamValueType], strict: bool, ): if exp_value is None: with pytest.raises((TypeError, ValueError)): HtParam.from_str(s, data_type, strict) else: assert HtParam.from_str(s, data_type, strict) == exp_value # assert 0 @pytest.mark.parametrize("data_type", [None, "", 123, 123.123, True, False]) def test_from_str_static_assert(self, data_type): with pytest.raises(AssertionError): HtParam.from_str("", data_type) # assert 0 @pytest.mark.parametrize("param", HtParams.values()) def test_from_str_member(self, param: HtParam): assert param.from_str(param.to_str( param.min_val)) == param.min_val # type: ignore assert param.from_str(param.to_str( param.max_val)) == param.max_val # type: ignore # assert 0 @pytest.mark.parametrize( "val, data_type, exp_str", [ (False, HtDataTypes.BOOL, "0"), (True, HtDataTypes.BOOL, "1"), (123, HtDataTypes.INT, "123"), (-321, HtDataTypes.INT, "-321"), (123.456, HtDataTypes.FLOAT, "123.456"), (-321.456, HtDataTypes.FLOAT, "-321.456"), (789, HtDataTypes.FLOAT, "789.0"), (-789, HtDataTypes.FLOAT, "-789.0"), (789.0, HtDataTypes.FLOAT, "789.0"), (-789.0, HtDataTypes.FLOAT, "-789.0"), # -- should raise a 'TypeError': (None, HtDataTypes.BOOL, None), ("abc", HtDataTypes.BOOL, None), (123, HtDataTypes.BOOL, None), (123.123, HtDataTypes.BOOL, None), (None, HtDataTypes.INT, None), ("abc", HtDataTypes.INT, None), (123.123, HtDataTypes.INT, None), (None, HtDataTypes.FLOAT, None), ("abc", HtDataTypes.FLOAT, None), # ... ], ) def test_to_str_static(self, val: HtParamValueType, data_type: HtDataTypes, exp_str: str): if exp_str is None: with pytest.raises(TypeError): HtParam.to_str(val, data_type) else: assert HtParam.to_str(val, data_type) == exp_str # assert 0 @pytest.mark.parametrize("param", HtParams.values()) def test_to_str_member(self, param: HtParam): assert param.to_str(param.min_val) == HtParam.to_str( param.min_val, param.data_type) # type: ignore assert param.to_str(param.max_val) == HtParam.to_str( param.max_val, param.data_type) # type: ignore # assert 0 @pytest.mark.parametrize("name, param", HtParams.items()) def test_repr(self, name: str, param: HtParam): assert repr(param) == "HtParam({},{:d},{!r},{}[{},{}])".format( param.dp_type, param.dp_number, param.acl, param.data_type, param.min_val, param.max_val, ) # assert 0 @pytest.mark.parametrize("name, cmd", [(name, param.cmd()) for name, param in HtParams.items()]) def test_cmd(self, name: str, cmd: str): m = re.match(r"^[S|M]P,NR=(\d+)$", cmd) assert (m is not None ), "non valid command string for parameter {!r} [{!r}]".format( name, cmd) # assert 0 @pytest.mark.parametrize("name, param", HtParams.items()) def test_set_limits(self, name: str, param: HtParam): assert not param.set_limits(param.min_val, param.max_val) # assert 0 @pytest.mark.parametrize( "data_type, min_val, max_val", [ # -- should raise a 'TypeError': (HtDataTypes.BOOL, False, 123), (HtDataTypes.BOOL, False, 123.123), (HtDataTypes.BOOL, 123, True), (HtDataTypes.BOOL, 123.123, True), (HtDataTypes.BOOL, False, ""), (HtDataTypes.BOOL, "", True), (HtDataTypes.BOOL, "", ""), (HtDataTypes.BOOL, None, 123), (HtDataTypes.BOOL, 123, None), (HtDataTypes.INT, 123, 123.123), (HtDataTypes.INT, 122.123, 123), (HtDataTypes.INT, 122.123, 123.123), (HtDataTypes.INT, 123, ""), (HtDataTypes.INT, "", 123), (HtDataTypes.INT, "", ""), (HtDataTypes.INT, 123, True), (HtDataTypes.INT, False, 123), (HtDataTypes.INT, True, False), (HtDataTypes.INT, False, True), (HtDataTypes.INT, None, 123.123), (HtDataTypes.INT, 123.123, None), (HtDataTypes.FLOAT, 123, ""), (HtDataTypes.FLOAT, "", 123), (HtDataTypes.FLOAT, 123.123, ""), (HtDataTypes.FLOAT, "", 123.123), (HtDataTypes.FLOAT, "", ""), (HtDataTypes.FLOAT, 123, True), (HtDataTypes.FLOAT, False, 123), (HtDataTypes.FLOAT, 123.123, True), (HtDataTypes.FLOAT, False, 123.123), (HtDataTypes.FLOAT, True, False), (HtDataTypes.FLOAT, False, True), (HtDataTypes.FLOAT, None, True), (HtDataTypes.FLOAT, True, None), # ... ], ) def test_set_limits_raises_TypeError(self, data_type, min_val, max_val): param = HtParam("MP", 123, "r-", data_type) with pytest.raises(TypeError): param.set_limits(min_val, max_val) # assert 0 @pytest.mark.parametrize("name, param", HtParams.items()) def test_in_limits(self, name: str, param: HtParam): assert param.in_limits(param.min_val) assert param.in_limits(param.max_val) # assert 0 @pytest.mark.parametrize("param", HtParams.values()) def test_in_limits_None(self, param: HtParam): assert param.in_limits(None) # assert 0 @pytest.mark.parametrize( "val, data_type", [ (False, HtDataTypes.BOOL), (True, HtDataTypes.BOOL), (123, HtDataTypes.INT), (-321, HtDataTypes.INT), (123.456, HtDataTypes.FLOAT), (-321.456, HtDataTypes.FLOAT), (789, HtDataTypes.FLOAT), (-789, HtDataTypes.FLOAT), (789.0, HtDataTypes.FLOAT), (-789.0, HtDataTypes.FLOAT), # ... ], ) def test_check_value_type(self, val, data_type): HtParam.check_value_type(val, data_type) # assert 0 @pytest.mark.parametrize( "val, data_type", [ # -- should raise a 'TypeError': (None, HtDataTypes.BOOL), ("abc", HtDataTypes.BOOL), (123, HtDataTypes.BOOL), (123.123, HtDataTypes.BOOL), (None, HtDataTypes.INT), ("abc", HtDataTypes.INT), (123.123, HtDataTypes.INT), (None, HtDataTypes.FLOAT), ("abc", HtDataTypes.FLOAT), # ... ], ) def test_check_value_type_raises_TypeError(self, val, data_type): with pytest.raises(TypeError): HtParam.check_value_type(val, data_type)
class TestHtParams: @pytest.mark.parametrize("name, acl", [(name, param.acl) for name, param in HtParams.items()]) def test_acl(self, name: str, acl: str): assert acl is not None, "'acl' must not be None" m = re.match(r"^(r-|-w|rw)$", acl) assert m is not None, "invalid acl definition for parameter {!r} [{!r}]".format( name, acl) # assert 0 @pytest.mark.parametrize( "name, min_val, max_val", [(name, param.min_val, param.max_val) for name, param in HtParams.items()], ) def test_limits(self, name: str, min_val: HtParamValueType, max_val: HtParamValueType): assert ( min_val is not None ), "minimal value for parameter {!r} must not be None".format(name) assert ( max_val is not None ), "maximal value for parameter {!r} must not be None".format(name) assert min_val <= max_val assert max_val >= min_val # assert 0 @pytest.mark.parametrize("name, param", HtParams.items()) def test_get(self, name: str, param: HtParam): assert HtParams.get(name) == param # assert 0 def test_dump(self): assert HtParams.dump() is None # assert 0 def test_definition_file(self): assert HtParams.definition_file == path.normpath( path.join(path.dirname(path.abspath(__file__)), "../htheatpump/", "htparams.csv")) # assert 0 @pytest.mark.run_if_connected @pytest.mark.usefixtures("reconnect") @pytest.mark.parametrize("name, param", HtParams.items()) @pytest.mark.asyncio async def test_validate_param(self, hthp: AioHtHeatpump, name: str, param: HtParam): await hthp.send_request_async(param.cmd()) resp = await hthp.read_response_async() m = re.match( r"^{},.*NAME=([^,]+).*VAL=([^,]+).*MAX=([^,]+).*MIN=([^,]+).*$". format(param.cmd()), resp, ) assert ( m is not None ), "invalid response for query of parameter {!r} [{!r}]".format( name, resp) dp_name = m.group(1).strip() assert ( dp_name == name ), "data point name doesn't match with the parameter name {!r} [{!r}]".format( name, dp_name) dp_value = param.from_str(m.group(2)) assert dp_value is not None, "data point value must not be None [{}]".format( dp_value) dp_max = param.from_str(m.group(3)) assert ( dp_max == param.max_val ), "data point max value doesn't match with the parameter's one {!s} [{!s}]".format( param.max_val, dp_max) dp_min = param.from_str(m.group(4)) if name == "Verdichter laeuft seit" and dp_min == 10: dp_min = 0 # seems to be incorrect for the data point "Verdichter laeuft seit" [10 == 0] assert ( dp_min == param.min_val ), "data point min value doesn't match with the parameter's one {!s} [{!s}]".format( param.min_val, dp_min)