diff --git a/custom_components/lednetwf_ble/__init__.py b/custom_components/lednetwf_ble/__init__.py index 923fc0d..1ea84d0 100644 --- a/custom_components/lednetwf_ble/__init__.py +++ b/custom_components/lednetwf_ble/__init__.py @@ -5,7 +5,7 @@ from homeassistant.const import CONF_MAC, EVENT_HOMEASSISTANT_STOP from homeassistant.const import Platform -from .const import DOMAIN, CONF_RESET, CONF_DELAY, CONF_LEDCOUNT, CONF_LEDTYPE, CONF_COLORORDER +from .const import DOMAIN, CONF_DELAY from .lednetwf import LEDNETWFInstance import logging @@ -20,9 +20,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: config = entry.data options = entry.options instance = LEDNETWFInstance(entry.data[CONF_MAC], hass, config, options) - # reset = entry.options.get(CONF_RESET, None) or entry.data.get(CONF_RESET, None) delay = entry.options.get(CONF_DELAY, None) or entry.data.get(CONF_DELAY, None) - # LOGGER.debug("Config Reset data: %s and config delay data: %s", reset, delay) hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = instance diff --git a/custom_components/lednetwf_ble/config_flow.py b/custom_components/lednetwf_ble/config_flow.py index 016ceeb..e190b7e 100644 --- a/custom_components/lednetwf_ble/config_flow.py +++ b/custom_components/lednetwf_ble/config_flow.py @@ -18,6 +18,7 @@ from home_assistant_bluetooth import BluetoothServiceInfo import importlib import pkgutil +import sys from .const import ( DOMAIN, @@ -36,12 +37,35 @@ SUPPORTED_MODELS = [] package = __package__ -for _, module_name, _ in pkgutil.iter_modules([f"{package.replace('.', '/')}/models"]): +filename = __file__ + +# LOGGER.debug(f"Package: {package}") +LOGGER.debug(f"File: {__file__}") +my_name = filename[filename.rfind('/')+1:] +models_path = f"{filename.replace(my_name, 'models')}" +LOGGER.debug(f"Models path: {models_path}") + +# old Working vvvv +# for _, module_name, _ in pkgutil.iter_modules([f"{package.replace('.', '/')}/models"]): +# # for _, module_name, _ in pkgutil.iter_modules([models_path]): +# LOGGER.debug(f"Module name: {module_name}") +# if module_name.startswith('model_0x'): +# module = importlib.import_module(f'.models.{module_name}', package) +# LOGGER.debug(f"Importing module: {models_path}/{module_name}") +# # module = importlib.import_module(f'{models_path}/{module_name}') +# if hasattr(module, "SUPPORTED_MODELS"): +# LOGGER.debug(f"Supported models: {getattr(module, 'SUPPORTED_MODELS')}") +# SUPPORTED_MODELS.extend(getattr(module, "SUPPORTED_MODELS")) +# old Working ^^^^ + +for _, module_name, _ in pkgutil.iter_modules([models_path]): + LOGGER.debug(f"Module name: {module_name}") if module_name.startswith('model_0x'): - module = importlib.import_module(f'.models.{module_name}', package) - if hasattr(module, "SUPPORTED_MODELS"): - LOGGER.debug(f"Supported models: {getattr(module, 'SUPPORTED_MODELS')}") - SUPPORTED_MODELS.extend(getattr(module, "SUPPORTED_MODELS")) + m = importlib.import_module(f'{package}.models.{module_name}') + if hasattr(m, "SUPPORTED_MODELS"): + LOGGER.debug(f"Supported models: {getattr(m, 'SUPPORTED_MODELS')}") + SUPPORTED_MODELS.extend(getattr(m, "SUPPORTED_MODELS")) + LOGGER.debug(f"All supported modules: {SUPPORTED_MODELS}") class DeviceData(BluetoothData): @@ -216,7 +240,7 @@ async def toggle_light(self): await self._instance.update() LOGGER.debug(f"Sending initial packets") await self._instance.send_initial_packets() - await self._instance._write_packet(self._instance._model_interface.GET_LED_SETTINGS_PACKET) + await self._instance._write(self._instance._model_interface.GET_LED_SETTINGS_PACKET) # await asyncio.sleep(1) for n in range(3): LOGGER.debug(f"Turning on and off: {n}") diff --git a/custom_components/lednetwf_ble/const.py b/custom_components/lednetwf_ble/const.py index b1ce803..3ac6960 100644 --- a/custom_components/lednetwf_ble/const.py +++ b/custom_components/lednetwf_ble/const.py @@ -8,8 +8,6 @@ CONF_LEDTYPE = "ledtype" CONF_COLORORDER = "colororder" CONF_MODEL = "model" -# SUPPORTED_MODELS = [0x00, 0x53, 0x54, 0x56, 0x62] - class LedTypes_StripLight(Enum): WS2812B = 0x01 diff --git a/custom_components/lednetwf_ble/lednetwf.py b/custom_components/lednetwf_ble/lednetwf.py index 2eeb828..d2ede7b 100644 --- a/custom_components/lednetwf_ble/lednetwf.py +++ b/custom_components/lednetwf_ble/lednetwf.py @@ -38,17 +38,38 @@ # Iterate through all modules in the current package package = __package__ -for _, module_name, _ in pkgutil.iter_modules([f"{package.replace('.', '/')}/models"]): +filename = __file__ +# LOGGER.debug(f"Package: {package}") +LOGGER.debug(f"File: {__file__}") +my_name = filename[filename.rfind('/')+1:] +models_path = f"{filename.replace(my_name, 'models')}" +LOGGER.debug(f"Models path: {models_path}") + +# for _, module_name, _ in pkgutil.iter_modules([f"{package.replace('.', '/')}/models"]): +# LOGGER.debug(f"Module name: {module_name}") +# if module_name.startswith('model_0x'): +# module = importlib.import_module(f'.models.{module_name}', package) +# # module = importlib.import_module(f'{models_path}/{module_name}.py') +# LOGGER.debug(f"Module: {module}") +# LOGGER.debug(f"Dir: {dir(module)}") +# class_name = f'Model{module_name.split("_")[1]}' +# if hasattr(module, class_name): +# globals()[class_name] = getattr(module, class_name) +# if hasattr(module, "SUPPORTED_MODELS"): +# LOGGER.debug(f"Supported models: {getattr(module, 'SUPPORTED_MODELS')}") +# SUPPORTED_MODELS[class_name] = getattr(module, "SUPPORTED_MODELS") + + +for _, module_name, _ in pkgutil.iter_modules([models_path]): + LOGGER.debug(f"Module name: {module_name}") if module_name.startswith('model_0x'): - module = importlib.import_module(f'.models.{module_name}', package) - LOGGER.debug(f"Module: {module}") - LOGGER.debug(f"Dir: {dir(module)}") + m = importlib.import_module(f'{package}.models.{module_name}') class_name = f'Model{module_name.split("_")[1]}' - if hasattr(module, class_name): - globals()[class_name] = getattr(module, class_name) - if hasattr(module, "SUPPORTED_MODELS"): - LOGGER.debug(f"Supported models: {getattr(module, 'SUPPORTED_MODELS')}") - SUPPORTED_MODELS[class_name] = getattr(module, "SUPPORTED_MODELS") + if hasattr(m, class_name): + globals()[class_name] = getattr(m, class_name) + if hasattr(m, "SUPPORTED_MODELS"): + LOGGER.debug(f"Supported models: {getattr(m, 'SUPPORTED_MODELS')}") + SUPPORTED_MODELS[class_name] = getattr(m, "SUPPORTED_MODELS") LOGGER.debug(f"All supported modules: {SUPPORTED_MODELS}") diff --git a/custom_components/lednetwf_ble/manifest.json b/custom_components/lednetwf_ble/manifest.json index 826c744..8541034 100644 --- a/custom_components/lednetwf_ble/manifest.json +++ b/custom_components/lednetwf_ble/manifest.json @@ -23,5 +23,5 @@ "bleak>=0.17.0", "bluetooth-sensor-state-data>=1.5.0" ], - "version": "0.0.13" + "version": "0.0.14-beta.1" } diff --git a/custom_components/lednetwf_ble/models/__init__.py b/custom_components/lednetwf_ble/models/__init__.py new file mode 100644 index 0000000..0a54053 --- /dev/null +++ b/custom_components/lednetwf_ble/models/__init__.py @@ -0,0 +1 @@ +# Creating this file should help things recognize the models folder as a module diff --git a/custom_components/lednetwf_ble/models/model_0x53.py b/custom_components/lednetwf_ble/models/model_0x53.py index 43a255b..d551db4 100644 --- a/custom_components/lednetwf_ble/models/model_0x53.py +++ b/custom_components/lednetwf_ble/models/model_0x53.py @@ -10,7 +10,7 @@ EFFECT_OFF ) -SUPPORTED_MODELS = [0x00, 0x53, 0x55] +SUPPORTED_MODELS = [0x00, 0x53, 0x55] # Probably 0x55 is not supported here, but in 0x54 instead EFFECTS_LIST_0x53 = [ "Gold Ring", diff --git a/custom_components/lednetwf_ble/models/model_0x56.py b/custom_components/lednetwf_ble/models/model_0x56.py index bfa581a..5253393 100644 --- a/custom_components/lednetwf_ble/models/model_0x56.py +++ b/custom_components/lednetwf_ble/models/model_0x56.py @@ -42,6 +42,8 @@ def __init__(self, manu_data): self.icon = "mdi:led-strip-variant" self.effect_list = EFFECT_LIST_0x56 + if isinstance(self.manu_data, str): + self.manu_data = [ord(c) for c in self.manu_data] LOGGER.debug(f"Manu data: {[hex(x) for x in self.manu_data]}") LOGGER.debug(f"Manu data 15: {hex(self.manu_data[15])}") LOGGER.debug(f"Manu data 16: {hex(self.manu_data[16])}") @@ -57,10 +59,10 @@ def __init__(self, manu_data): if self.manu_data[16] != 0xf0: # We're not in a colour mode, so set the effect self.effect_speed = self.manu_data[17] - if 0x02 <= self.manu_data[16] <= 0x0a: + if 0x01 <= self.manu_data[16] <= 0x0a: self.effect = EFFECT_ID_TO_NAME_0x56[self.manu_data[16] << 8] else: - self._effect = EFFECT_OFF + self.effect = EFFECT_OFF elif self.manu_data[15] == 0x62: # Music reactive mode. self._color_mode = ColorMode.BRIGHTNESS @@ -89,7 +91,7 @@ def set_color(self, hs_color, brightness): self.color_mode = ColorMode.HS self.hs_color = hs_color self.brightness = brightness - self.effect = EFFECT_OFF + #self.effect = EFFECT_OFF # The effect is NOT actually off when setting a colour. Static effect 1 is close to effect off, but it's still an effect. rgb_color = self.hsv_to_rgb((hs_color[0], hs_color[1], self.brightness)) LOGGER.debug(f"Setting RGB colour: {rgb_color}") background_col = [0,0,0] # Consider adding support for this in the future? For now, set black @@ -209,7 +211,7 @@ def notification_handler(self, data): return None payload = bytearray.fromhex(payload) LOGGER.debug(f"N: Response Payload: {' '.join([f'{byte:02X}' for byte in payload])}") - # return + if payload[0] == 0x81: # Status request response power = payload[2] @@ -225,23 +227,29 @@ def notification_handler(self, data): hsv_color = super().rgb_to_hsv(rgb_color) self.hs_color = tuple(hsv_color[0:2]) self.brightness = int(hsv_color[2]) + LOGGER.debug("Light is in colour mode") LOGGER.debug(f"RGB colour: {rgb_color}") LOGGER.debug(f"HS colour: {self.hs_color}") LOGGER.debug(f"Brightness: {self.brightness}") self.effect = EFFECT_OFF self.color_mode = ColorMode.HS self.color_temperature_kelvin = None - elif selected_effect == 0x01: + # elif selected_effect == 0x01: # We don't really need this any more, deal with it below instead + # self.color_mode = ColorMode.HS + # # self.effect = EFFECT_OFF + # self.effect = EFFECT_ID_TO_NAME_0x56[selected_effect << 8] # Effect 1 is still an effect + # hs_color = self.rgb_to_hsv(payload[6:9]) + # self.hs_color = hs_color[0:2] + # self.brightness = hs_color[2] + elif 0x01 <= selected_effect <= 0x0a: self.color_mode = ColorMode.HS - self.effect = EFFECT_OFF + self.effect = EFFECT_ID_TO_NAME_0x56[selected_effect << 8] + self.effect_speed = payload[5] hs_color = self.rgb_to_hsv(payload[6:9]) + rgb_color = tuple(int(b) for b in payload[6:9]) + LOGGER.debug(f"RGB Color: {rgb_color}, HS colour: {hs_color}, Brightness: {hs_color[2]}") self.hs_color = hs_color[0:2] self.brightness = hs_color[2] - elif 0x02 <= selected_effect <= 0x0a: - self.color_mode = ColorMode.HS - self.effect = EFFECT_ID_TO_NAME_0x56[selected_effect << 8] - self.effect_speed = payload[5] - # TODO: What about colours and brightness? elif mode == 0x62: # Music reactive mode # TODO: Brightness? diff --git a/custom_components/lednetwf_ble/models/model_abstractions.py b/custom_components/lednetwf_ble/models/model_abstractions.py index f09c9c5..d787a3c 100644 --- a/custom_components/lednetwf_ble/models/model_abstractions.py +++ b/custom_components/lednetwf_ble/models/model_abstractions.py @@ -50,7 +50,7 @@ def process_manu_data(self, manu_data): self.is_on = True if self.manu_data[14] == 0x23 else False else: LOGGER.debug("No manu data") - self.manu_data = chr(0) * 25 # Mock manu_data to prevent truth testing errors in the future + self.manu_data = bytearray(25) self.fw_major = 0x00 self.fw_minor = "Unknown version" self.led_count = None @@ -87,7 +87,6 @@ def set_brightness(self): def set_color_temp_kelvin(self): return NotImplementedError("This method should be implemented by the subclass") def notification_handler(self): - LOGGER.debug("ZZZ Notification handler not implemented") raise NotImplementedError("This method should be implemented by the subclass") def rgb_to_hsv(self,rgb): # Home Assistant expects HS in the range 0-360, 0-100 diff --git a/custom_components/lednetwf_ble/translations/en.json b/custom_components/lednetwf_ble/translations/en.json index a882fb4..45572f7 100644 --- a/custom_components/lednetwf_ble/translations/en.json +++ b/custom_components/lednetwf_ble/translations/en.json @@ -6,14 +6,14 @@ "mac": "Bluetooth MAC address", "name": "Name" }, - "title": "Pick LEDnetWF light" + "title": "Select LEDnetWF light" }, "validate": { "data": { - "retry": "Retry validate connection?", + "retry": "Retry?", "flicker": "Did the light blink?" }, - "title": "Validate LEDnetWF connection" + "title": "Validate connection" }, "manual": { "data": { @@ -45,7 +45,7 @@ }, "init" : { "data": { - "reset": "Reset color when led turn on", + "reset": "Reset color when led turns on", "delay": "Disconnect delay (0 = never disconnect)", "ledcount": "Number of LEDs", "name": "Name",