From 3a6e6833236367a884a150252dd5b9a806f5a765 Mon Sep 17 00:00:00 2001 From: spacemanspiff2007 <10754716+spacemanspiff2007@users.noreply.github.com> Date: Mon, 6 Nov 2023 14:09:06 +0100 Subject: [PATCH] - fix #425 - fix #424 --- .github/workflows/run-tox.yml | 2 +- run/conf_testing/rules/openhab/test_items.py | 15 +++- .../rules/openhab/test_persistence.py | 75 ++++++++++++------- .../openhab/connection/handler/handler.py | 6 +- .../openhab/connection/handler/helper.py | 10 ++- tests/test_openhab/test_items/test_number.py | 5 ++ .../test_rest/test_value_convert.py | 11 +++ 7 files changed, 90 insertions(+), 34 deletions(-) create mode 100644 tests/test_openhab/test_rest/test_value_convert.py diff --git a/.github/workflows/run-tox.yml b/.github/workflows/run-tox.yml index e13878f2..17106d8b 100644 --- a/.github/workflows/run-tox.yml +++ b/.github/workflows/run-tox.yml @@ -4,7 +4,7 @@ on: [push, pull_request] jobs: pre-commit: - name: + name: pre-commit runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/run/conf_testing/rules/openhab/test_items.py b/run/conf_testing/rules/openhab/test_items.py index 709a20b7..a152d811 100644 --- a/run/conf_testing/rules/openhab/test_items.py +++ b/run/conf_testing/rules/openhab/test_items.py @@ -6,7 +6,7 @@ from HABApp.core.events import ValueUpdateEventFilter from HABApp.core.types import HSB, RGB from HABApp.openhab.interface_async import async_get_items -from HABApp.openhab.items import GroupItem, StringItem, ColorItem +from HABApp.openhab.items import GroupItem, StringItem, ColorItem, NumberItem from HABAppTests import OpenhabTmpItem, TestBaseRule, ItemWaiter, EventWaiter @@ -21,6 +21,7 @@ def __init__(self): self.add_test('TestExisting', self.test_existing) self.add_test('TestColor', self.test_color) self.add_test('TestGroupFunction', self.test_group_func) + self.add_test('TestSmallValues', self.test_small_float_values) self.item_number = OpenhabTmpItem('Number') self.item_switch = OpenhabTmpItem('Switch') @@ -66,6 +67,18 @@ def test_api(self): self.openhab.get_item(self.item_group.name) asyncio.run_coroutine_threadsafe(async_get_items(), loop).result() + @OpenhabTmpItem.create('Number', arg_name='tmp_item') + def test_small_float_values(self, tmp_item: OpenhabTmpItem): + # https://github.com/spacemanspiff2007/HABApp/issues/425 + item = NumberItem.get_item(tmp_item.name) + assert item.value is None + + for i in range(3, 16, 3): + with ItemWaiter(item) as waiter: + value = 1 / 10 ** i + item.oh_post_update(value) + waiter.wait_for_state(value) + @OpenhabTmpItem.use('String', arg_name='oh_item') def test_tags(self, oh_item: OpenhabTmpItem): oh_item.create_item(tags=['tag1', 'tag2']) diff --git a/run/conf_testing/rules/openhab/test_persistence.py b/run/conf_testing/rules/openhab/test_persistence.py index be5827c6..983d204f 100644 --- a/run/conf_testing/rules/openhab/test_persistence.py +++ b/run/conf_testing/rules/openhab/test_persistence.py @@ -1,47 +1,66 @@ +from __future__ import annotations + from datetime import datetime, timedelta +from typing import Final, Any +from HABApp.openhab.definitions.helpers import OpenhabPersistenceData from HABApp.openhab.items import NumberItem from HABAppTests import TestBaseRule -class TestPersistence(TestBaseRule): - - def __init__(self): +class TestPersistenceBase(TestBaseRule): + def __init__(self, service_name: str, item_name: str): super().__init__() - self.item = 'RRD4J_Item' - self.add_test('RRD4J configured', self.test_configured) - self.add_test('RRD4J get', self.test_get) + self.config.skip_on_failure = True + self.item_name: Final = item_name + self.service_name: Final = service_name + + self.add_test(f'Persistence {service_name} available', self.test_service_available) def set_up(self): - i = NumberItem.get_item(self.item) - i.oh_post_update(i.value + 1 if i.value < 10 else 0) + i = NumberItem.get_item(self.item_name) + i.oh_post_update(int(i.value) + 1 if i.value < 10 else 0) - def test_configured(self): + def test_service_available(self): for cfg in self.oh.get_persistence_services(): - if cfg.id == 'rrd4j': + if cfg.id == self.service_name: break else: - raise ValueError('rrd4j not found!') + raise ValueError(f'Persistence service "{self.service_name}" not found!') + + def set_persistence_data(self, time: datetime, state: Any): + return self.openhab.set_persistence_data(self.item_name, self.service_name, time, state) + + def get_persistence_data(self, start_time: datetime | None, end_time: datetime | None) -> OpenhabPersistenceData: + return self.openhab.get_persistence_data(self.item_name, self.service_name, start_time, end_time) + + +class TestRRD4j(TestPersistenceBase): + + def __init__(self): + super().__init__('rrd4j', 'RRD4J_Item') + self.add_test('RRD4J get', self.test_get) def test_get(self): now = datetime.now() - d = self.openhab.get_persistence_data(self.item, 'rrd4j', now - timedelta(seconds=60), now) + d = self.get_persistence_data(now - timedelta(seconds=60), now) assert d.get_data() - # def test_set(self): - # now = datetime.now() - # d = self.openhab.get_persistence_data(self.item, 'mapdb', now - timedelta(seconds=5), now) - # was = d.get_data() - # - # assert list(was.values()) == [1] - # - # self.openhab.set_persistence_data(self.item, 'mapdb', now, 2) - # - # d = self.openhab.get_persistence_data(self.item, 'mapdb', now - timedelta(seconds=5), - # now + timedelta(seconds=5)) - # ist = d.get_data() - # assert list(ist.values()) == [2], ist - - -TestPersistence() + +TestRRD4j() + + +class TestMapDB(TestPersistenceBase): + + def __init__(self): + super().__init__('mapdb', 'RRD4J_Item') + self.add_test('MapDB get', self.test_get) + + def test_get(self): + now = datetime.now() + d = self.get_persistence_data(now - timedelta(seconds=60), now) + assert d.get_data() + + +TestMapDB() diff --git a/src/HABApp/openhab/connection/handler/handler.py b/src/HABApp/openhab/connection/handler/handler.py index 13d3b2bd..569c2d23 100644 --- a/src/HABApp/openhab/connection/handler/handler.py +++ b/src/HABApp/openhab/connection/handler/handler.py @@ -94,7 +94,7 @@ async def post(self, url: str, log_404=True, json=None, data=None, **kwargs: Any return None mgr = _RequestContextManager( - self.request(METH_POST, url, data=data, json=json, **kwargs, **self.options, **kwargs) + self.request(METH_POST, url, data=data, json=json, **self.options, **kwargs) ) if data is None: data = json @@ -105,7 +105,7 @@ async def put(self, url: str, log_404=True, json=None, data=None, **kwargs: Any) return None mgr = _RequestContextManager( - self.request(METH_PUT, url, data=data, json=json, **kwargs, **self.options, **kwargs) + self.request(METH_PUT, url, data=data, json=json, **self.options, **kwargs) ) if data is None: data = json @@ -116,7 +116,7 @@ async def delete(self, url: str, log_404=True, json=None, data=None, **kwargs: A return None mgr = _RequestContextManager( - self.request(METH_DELETE, url, data=data, json=json, **kwargs, **self.options, **kwargs) + self.request(METH_DELETE, url, data=data, json=json, **self.options, **kwargs) ) if data is None: data = json diff --git a/src/HABApp/openhab/connection/handler/helper.py b/src/HABApp/openhab/connection/handler/helper.py index 8f20e472..e413431c 100644 --- a/src/HABApp/openhab/connection/handler/helper.py +++ b/src/HABApp/openhab/connection/handler/helper.py @@ -8,9 +8,17 @@ def convert_to_oh_type(obj: Any) -> str: - if isinstance(obj, (str, int, float, bool)): + if isinstance(obj, (str, int, bool)): return str(obj) + if isinstance(obj, float): + v = str(obj) + if 'e-' not in v: + return v + + v = f'{obj:.{int(v.split("e-")[1]) + 6}f}' + return v.rstrip('0') + if isinstance(obj, datetime): # Add timezone (if not yet defined) to string, then remote anything below ms. # 2018-11-19T09:47:38.284000+0100 -> 2018-11-19T09:47:38.284+0100 diff --git a/tests/test_openhab/test_items/test_number.py b/tests/test_openhab/test_items/test_number.py index efecef75..2066fc6a 100644 --- a/tests/test_openhab/test_items/test_number.py +++ b/tests/test_openhab/test_items/test_number.py @@ -7,3 +7,8 @@ def test_number_item_unit(): assert NumberItem('test', 1).unit is None assert NumberItem('test', 1, metadata=Map(unit=MetaData('°C'))).unit == '°C' + + +def test_small_values(): + assert NumberItem('test', 1).unit is None + assert NumberItem('test', 1, metadata=Map(unit=MetaData('°C'))).unit == '°C' diff --git a/tests/test_openhab/test_rest/test_value_convert.py b/tests/test_openhab/test_rest/test_value_convert.py new file mode 100644 index 00000000..da031cc2 --- /dev/null +++ b/tests/test_openhab/test_rest/test_value_convert.py @@ -0,0 +1,11 @@ +from HABApp.openhab.connection.handler import convert_to_oh_type + + +def test_convert_to_oh_type(): + assert convert_to_oh_type(1 / 10 ** 3) == '0.001' + assert convert_to_oh_type(1 / 10 ** 6) == '0.000001' + assert convert_to_oh_type(1 / 10 ** 9) == '0.000000001' + + assert convert_to_oh_type(1.234 / 10 ** 3) == '0.001234' + assert convert_to_oh_type(1.234 / 10 ** 6) == '0.000001234' + assert convert_to_oh_type(1.234 / 10 ** 9) == '0.000000001234'