From cc9d3531c49551dfbab51d1f6584a11b62bb569b Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Sun, 24 Apr 2022 23:59:29 +0100 Subject: [PATCH] move dali driver interation to lamp --- dali2mqtt/__init__.py | 1 + dali2mqtt/consts.py | 5 +++-- dali2mqtt/dali2mqtt.py | 40 ++++++++++++++------------------- dali2mqtt/devicesnamesconfig.py | 2 +- dali2mqtt/lamp.py | 27 +++++++++++++--------- tests/test_lamp.py | 15 ++++++++----- 6 files changed, 48 insertions(+), 42 deletions(-) diff --git a/dali2mqtt/__init__.py b/dali2mqtt/__init__.py index e69de29..b26da2a 100644 --- a/dali2mqtt/__init__.py +++ b/dali2mqtt/__init__.py @@ -0,0 +1 @@ +"""DALI 2 MQTT package.""" diff --git a/dali2mqtt/consts.py b/dali2mqtt/consts.py index dcb1ed0..f662ffb 100644 --- a/dali2mqtt/consts.py +++ b/dali2mqtt/consts.py @@ -1,8 +1,9 @@ +"""Constants common the various modules.""" + import logging -"""Constants common the various modules.""" __author__ = "Diogo Gomes" -__version__ = "0.0.1" +__version__ = "0.0.3" __email__ = "diogogomes@gmail.com" HASSEB = "hasseb" diff --git a/dali2mqtt/dali2mqtt.py b/dali2mqtt/dali2mqtt.py index 10972c5..563572e 100644 --- a/dali2mqtt/dali2mqtt.py +++ b/dali2mqtt/dali2mqtt.py @@ -67,13 +67,15 @@ logger = logging.getLogger(__name__) -def dali_scan(driver): +def dali_scan(dali_driver): """Scan a maximum number of dali devices.""" lamps = [] for lamp in range(0, 63): try: logging.debug("Search for Lamp %s", lamp) - present = driver.send(gear.QueryControlGearPresent(address.Short(lamp))) + present = dali_driver.send( + gear.QueryControlGearPresent(address.Short(lamp)) + ) if isinstance(present, YesNoResponse) and present.value: lamps.append(lamp) logger.debug("Found lamp at address %d", lamp) @@ -126,13 +128,13 @@ def scan_groups(dali_driver, lamps): def initialize_lamps(data_object, client): """Initialize all lamps and groups.""" - driver_object = data_object["driver"] + driver = data_object["driver"] mqtt_base_topic = data_object["base_topic"] ha_prefix = data_object["ha_prefix"] log_level = data_object["log_level"] devices_names_config = data_object["devices_names_config"] devices_names_config.load_devices_names_file() - lamps = dali_scan(driver_object) + lamps = dali_scan(driver) logger.info( "Found %d lamps", len(lamps), @@ -142,15 +144,9 @@ def create_mqtt_lamp(address, name): try: lamp_object = Lamp( log_level, - driver_object, + driver, name, address, - min_physical_level=driver_object.send( - gear.QueryPhysicalMinimum(address) - ).value, - min_level=driver_object.send(gear.QueryMinLevel(address)).value, - max_level=driver_object.send(gear.QueryMaxLevel(address)).value, - level=driver_object.send(gear.QueryActualLevel(address)).value, ) data_object["all_lamps"][name] = lamp_object @@ -205,7 +201,7 @@ def create_mqtt_lamp(address, name): devices_names_config.get_friendly_name(short_address.address), ) - groups = scan_groups(driver_object, lamps) + groups = scan_groups(driver, lamps) for group in groups: logger.debug("Publishing group %d", group) @@ -234,7 +230,7 @@ def on_message_cmd(mqtt_client, data_object, msg): try: lamp_object = data_object["all_lamps"][light] logger.debug("Set light <%s> to %s", light, msg.payload) - data_object["driver"].send(gear.Off(lamp_object.short_address)) + lamp_object.off() mqtt_client.publish( MQTT_STATE_TOPIC.format(data_object["base_topic"], light), MQTT_PAYLOAD_OFF, @@ -280,7 +276,7 @@ def on_message_brightness_cmd(mqtt_client, data_object, msg): lamp_object.level = int(msg.payload.decode("utf-8")) if lamp_object.level == 0: # 0 in DALI is turn off with fade out - data_object["driver"].send(gear.Off(lamp_object.short_address)) + lamp_object.off() logger.debug("Set light <%s> to OFF", light) mqtt_client.publish( @@ -316,27 +312,25 @@ def on_message_brightness_get_cmd(mqtt_client, data_object, msg): lamp_object = get_lamp_object(data_object, light) try: - level = data_object["driver"].send( - gear.QueryActualLevel(lamp_object.short_address) - ) - logger.debug("Get light <%s> results in %d", light, level.value) + lamp_object.actual_level() + logger.debug("Get light <%s> results in %d", light, lamp_object.level) mqtt_client.publish( MQTT_BRIGHTNESS_STATE_TOPIC.format(data_object["base_topic"], light), - level.value, + lamp_object.level, retain=False, ) mqtt_client.publish( MQTT_STATE_TOPIC.format(data_object["base_topic"], light), - MQTT_PAYLOAD_ON if level.value != 0 else MQTT_PAYLOAD_OFF, + MQTT_PAYLOAD_ON if lamp_object.level != 0 else MQTT_PAYLOAD_OFF, retain=False, ) except ValueError as err: logger.error( "Can't convert <%s> to integer %d..%d: %s", - str(level), + lamp_object.level, lamp_object.min_level, lamp_object.max_level, err, @@ -374,7 +368,7 @@ def on_connect( def create_mqtt_client( - driver_object, + driver, mqtt_server, mqtt_port, mqtt_username, @@ -389,7 +383,7 @@ def create_mqtt_client( mqttc = mqtt.Client( client_id="dali2mqtt", userdata={ - "driver": driver_object, + "driver": driver, "base_topic": mqtt_base_topic, "ha_prefix": ha_prefix, "devices_names_config": devices_names_config, diff --git a/dali2mqtt/devicesnamesconfig.py b/dali2mqtt/devicesnamesconfig.py index 4b78ac9..4b861f2 100644 --- a/dali2mqtt/devicesnamesconfig.py +++ b/dali2mqtt/devicesnamesconfig.py @@ -40,7 +40,7 @@ def load_devices_names_file(self): except yaml.YAMLError as error: logger.error("In devices file %s: %s", self._path, error) raise DevicesNamesConfigLoadError() - except Exception as err: + except Exception: logger.error( "Could not load device names config <%s>, a new one will be created after successfull start", self._path, diff --git a/dali2mqtt/lamp.py b/dali2mqtt/lamp.py index c26b756..eddc285 100644 --- a/dali2mqtt/lamp.py +++ b/dali2mqtt/lamp.py @@ -14,8 +14,6 @@ MQTT_NOT_AVAILABLE, MQTT_PAYLOAD_OFF, MQTT_STATE_TOPIC, - __author__, - __email__, __version__, ) from slugify import slugify @@ -33,20 +31,19 @@ def __init__( driver, friendly_name, short_address, - min_physical_level, - min_level, - level, - max_level, ): """Initialize Lamp.""" self.driver = driver self.short_address = short_address self.friendly_name = friendly_name + self.device_name = slugify(friendly_name) - self.min_physical_level = min_physical_level - self.min_level = min_level - self.max_level = max_level - self.level = level + + self.min_physical_level = driver.send(gear.QueryPhysicalMinimum(short_address)).value + self.min_level = driver.send(gear.QueryMinLevel(short_address)).value + self.max_level = driver.send(gear.QueryMaxLevel(short_address)).value + self.level = driver.send(gear.QueryActualLevel(short_address)).value + logger.setLevel(ALL_SUPPORTED_LOG_LEVELS[log_level]) def gen_ha_config(self, mqtt_base_topic): @@ -79,6 +76,10 @@ def gen_ha_config(self, mqtt_base_topic): } return json.dumps(json_config) + def actual_level(self): + """Retrieve actual level from ballast.""" + self.__level = self.driver.send(gear.QueryActualLevel(self.short_address)) + @property def level(self): """Return brightness level.""" @@ -86,6 +87,7 @@ def level(self): @level.setter def level(self, value): + """Commit level to ballast.""" if not self.min_level <= value <= self.max_level and value != 0: raise ValueError self.__level = value @@ -94,5 +96,10 @@ def level(self, value): "Set lamp <%s> brightness level to %s", self.friendly_name, self.level ) + def off(self): + """Turn off ballast.""" + self.driver.send(gear.Off(self.short_address)) + def __str__(self): + """Serialize lamp information.""" return f"{self.device_name} - address: {self.short_address.address}, actual brightness level: {self.level} (minimum: {self.min_level}, max: {self.max_level}, physical minimum: {self.min_physical_level})" diff --git a/tests/test_lamp.py b/tests/test_lamp.py index 78260d4..4ecb3b5 100644 --- a/tests/test_lamp.py +++ b/tests/test_lamp.py @@ -11,12 +11,19 @@ MIN_BRIGHTNESS = 2 MAX_BRIGHTNESS = 250 +def generate_driver_values(results): + for res in results: + result = mock.Mock() + result.value = res + print(result.value) + yield result @pytest.fixture def fake_driver(): drive = mock.Mock() - drive.send = lambda x: 0x00 - yield drive + drive.dummy = generate_driver_values([MIN_BRIGHTNESS, MIN_BRIGHTNESS, MAX_BRIGHTNESS, 100, 100]) + drive.send = lambda x: next(drive.dummy) + return drive @pytest.fixture @@ -37,10 +44,6 @@ def test_ha_config(fake_driver, fake_address): driver=fake_driver, friendly_name=friendly_name, short_address=addr, - min_physical_level=2, - min_level=MIN_BRIGHTNESS, - level=100, - max_level=MAX_BRIGHTNESS, ) assert lamp1.device_name == slugify(friendly_name)