diff --git a/examples/read_cache.py b/examples/read_cache.py index 4595195..d94c4ff 100644 --- a/examples/read_cache.py +++ b/examples/read_cache.py @@ -2,7 +2,6 @@ from os import listdir from os.path import isfile, join -from velbusaio.const import CACHEDIR from velbusaio.helpers import get_cache_dir for fil in [f for f in listdir(get_cache_dir()) if isfile(join(get_cache_dir(), f))]: diff --git a/tests/module_status_test.py b/tests/module_status_test.py index 6f3d874..406ca0b 100644 --- a/tests/module_status_test.py +++ b/tests/module_status_test.py @@ -13,7 +13,6 @@ CHANNEL_SELECTED_PROGRAM, NO_RTR, PRIORITY_LOW, - RTR, ) from velbusaio.controller import Velbus from velbusaio.handler import PacketHandler @@ -24,7 +23,6 @@ ModuleStatusMessage2, ModuleStatusPirMessage, ) -from velbusaio.messages.select_program import SelectProgramMessage from velbusaio.module import Module # some modules to test diff --git a/tests/thermostat_operating_mode_test.py b/tests/thermostat_operating_mode_test.py index 71552f8..76cff2e 100644 --- a/tests/thermostat_operating_mode_test.py +++ b/tests/thermostat_operating_mode_test.py @@ -3,7 +3,6 @@ sleep_timer values are correctly stored into the module's temperature channel. """ -import logging import pathlib import pytest diff --git a/velbusaio/channels.py b/velbusaio/channels.py index 2bb395d..114aa61 100644 --- a/velbusaio/channels.py +++ b/velbusaio/channels.py @@ -136,17 +136,8 @@ def __getstate__(self): if k != "_writer" and k != "_on_status_update" and k != "_name_parts" } - def to_json(self) -> dict: - d = self.__dict__ - return { - k: d[k] - for k in d - if k != "_writer" - and k != "_on_status_update" - and k != "_name_parts" - and k != "_module" - and k != "__name__" - } + def to_cache(self) -> dict: + return {"name": self._name, "type": type(self).__name__} def __setstate__(self, state): self.__dict__.update(state) diff --git a/velbusaio/controller.py b/velbusaio/controller.py index 23d9d18..2a75b8c 100644 --- a/velbusaio/controller.py +++ b/velbusaio/controller.py @@ -7,7 +7,7 @@ import asyncio import logging import pathlib -import pickle +import json import re import ssl from urllib.parse import urlparse @@ -84,26 +84,19 @@ async def add_module( """ Add a found module to the module cache """ - mod = self._load_module_from_cache(self._cache_dir, addr) - if mod is not None: - self._log.info(f"Load module from CACHE: address:{addr}") - self._modules[addr] = mod - self._modules[addr].initialize(self.send) - await self._modules[addr].load(True) - else: - self._log.info(f"Load NEW module: type:{typ} address:{addr}") - self._modules[addr] = Module.factory( - addr, - typ, - data, - serial=serial, - build_year=build_year, - build_week=build_week, - memorymap=memorymap, - cache_dir=self._cache_dir, - ) - self._modules[addr].initialize(self.send) - await self._modules[addr].load() + self._log.info(f"Load NEW module: type:{typ} address:{addr}") + self._modules[addr] = Module.factory( + addr, + typ, + data, + serial=serial, + build_year=build_year, + build_week=build_week, + memorymap=memorymap, + cache_dir=self._cache_dir, + ) + self._modules[addr].initialize(self.send) + await self._modules[addr].load() async def add_submodules(self, addr: int, subList: dict[int, int]) -> None: for sub_num, sub_addr in subList.items(): @@ -114,17 +107,6 @@ async def add_submodules(self, addr: int, subList: dict[int, int]) -> None: self._modules[sub_addr] = self._modules[addr] self._modules[addr].cleanupSubChannels() - def _load_module_from_cache(self, cache_dir: str, address: int) -> None | Module: - try: - cfile = pathlib.Path(f"{cache_dir}/{address}.p") - with cfile.open("rb") as fl: - o = pickle.load(fl) - if isinstance(o, Module): - return o - except OSError: - pass - return None - def get_modules(self) -> dict: """ Return the module cache diff --git a/velbusaio/handler.py b/velbusaio/handler.py index c454433..909b9f0 100644 --- a/velbusaio/handler.py +++ b/velbusaio/handler.py @@ -8,7 +8,6 @@ import asyncio import json import logging -import re from typing import TYPE_CHECKING, Awaitable, Callable import pkg_resources @@ -107,14 +106,14 @@ async def handle(self, rawmsg: RawMessage) -> None: "NOT FOUND IN command_registry: addr={} cmd={} packet={}".format( address, command_value, - ":".join(format(str(x), "02x") for x in data), + ":".join(format(x, "02x") for x in data), ) ) elif self._scan_complete: # this should only happen once the scan is complete, of its not complete suspended the error message self._log.warning( "UNKNOWN module, you should initialize a full new velbus scan: packet={}, address={}, modules={}".format( - ":".join(format(str(x), "02x") for x in data), + ":".join(format(x, "02x") for x in data), address, self._velbus.get_modules().keys(), ) diff --git a/velbusaio/helpers.py b/velbusaio/helpers.py index a2ee1b2..031011a 100644 --- a/velbusaio/helpers.py +++ b/velbusaio/helpers.py @@ -6,7 +6,7 @@ import os import re -from typing import Any, Dict +from typing import Any from velbusaio.const import CACHEDIR diff --git a/velbusaio/message.py b/velbusaio/message.py index de186d0..188f172 100644 --- a/velbusaio/message.py +++ b/velbusaio/message.py @@ -5,7 +5,6 @@ from __future__ import annotations import json -from typing import Optional from velbusaio.const import PRIORITY_FIRMWARE, PRIORITY_HIGH, PRIORITY_LOW diff --git a/velbusaio/messages/__init__.py b/velbusaio/messages/__init__.py index d87b310..e69de29 100644 --- a/velbusaio/messages/__init__.py +++ b/velbusaio/messages/__init__.py @@ -1,105 +0,0 @@ -""" -:author: Thomas Delaet -""" - -from __future__ import annotations - -from velbusaio.messages.blind_status import BlindStatusMessage, BlindStatusNgMessage -from velbusaio.messages.bus_active import BusActiveMessage -from velbusaio.messages.bus_error_counter_status import BusErrorCounterStatusMessage -from velbusaio.messages.bus_error_counter_status_request import ( - BusErrorStatusRequestMessage, -) -from velbusaio.messages.bus_off import BusOffMessage -from velbusaio.messages.channel_name_part1 import ( - ChannelNamePart1Message, - ChannelNamePart1Message2, - ChannelNamePart1Message3, -) -from velbusaio.messages.channel_name_part2 import ( - ChannelNamePart2Message, - ChannelNamePart2Message2, - ChannelNamePart2Message3, -) -from velbusaio.messages.channel_name_part3 import ( - ChannelNamePart3Message, - ChannelNamePart3Message2, - ChannelNamePart3Message3, -) -from velbusaio.messages.channel_name_request import ( - ChannelNameRequestMessage, - ChannelNameRequestMessage2, -) -from velbusaio.messages.clear_led import ClearLedMessage -from velbusaio.messages.counter_status import CounterStatusMessage -from velbusaio.messages.counter_status_request import CounterStatusRequestMessage -from velbusaio.messages.cover_down import CoverDownMessage, CoverDownMessage2 -from velbusaio.messages.cover_off import CoverOffMessage, CoverOffMessage2 -from velbusaio.messages.cover_position import CoverPosMessage -from velbusaio.messages.cover_up import CoverUpMessage, CoverUpMessage2 -from velbusaio.messages.dali_device_settings import DaliDeviceSettingMsg -from velbusaio.messages.dimmer_channel_status import DimmerChannelStatusMessage -from velbusaio.messages.dimmer_status import DimmerStatusMessage -from velbusaio.messages.fast_blinking_led import FastBlinkingLedMessage -from velbusaio.messages.forced_off import ForcedOff -from velbusaio.messages.forced_on import ForcedOn -from velbusaio.messages.interface_status_request import InterfaceStatusRequestMessage -from velbusaio.messages.ir_receiver_status import IRReceiverStatusMessage -from velbusaio.messages.kwh_status import KwhStatusMessage -from velbusaio.messages.light_value_request import LightValueRequest -from velbusaio.messages.memo_text import MemoTextMessage -from velbusaio.messages.memory_data import MemoryDataMessage -from velbusaio.messages.memory_data_block import MemoryDataBlockMessage -from velbusaio.messages.memory_dump_request import MemoryDumpRequestMessage -from velbusaio.messages.raw import MeteoRawMessage, SensorRawMessage -from velbusaio.messages.module_status import ModuleStatusMessage, ModuleStatusMessage2 -from velbusaio.messages.module_status_request import ModuleStatusRequestMessage -from velbusaio.messages.module_subtype import ModuleSubTypeMessage -from velbusaio.messages.module_type import ModuleTypeMessage, ModuleType2Message -from velbusaio.messages.module_type_request import ModuleTypeRequestMessage -from velbusaio.messages.push_button_status import PushButtonStatusMessage -from velbusaio.messages.read_data_block_from_memory import ( - ReadDataBlockFromMemoryMessage, -) -from velbusaio.messages.read_data_from_memory import ReadDataFromMemoryMessage -from velbusaio.messages.realtime_clock_status_request import RealtimeClockStatusRequest -from velbusaio.messages.receive_buffer_full import ReceiveBufferFullMessage -from velbusaio.messages.receive_ready import ReceiveReadyMessage -from velbusaio.messages.relay_status import RelayStatusMessage -from velbusaio.messages.restore_dimmer import RestoreDimmerMessage -from velbusaio.messages.select_program import SelectProgramMessage -from velbusaio.messages.sensor_temp_request import SensorTempRequest -from velbusaio.messages.sensor_temperature import SensorTemperatureMessage -from velbusaio.messages.set_date import SetDate -from velbusaio.messages.set_daylight_saving import SetDaylightSaving -from velbusaio.messages.set_dimmer import SetDimmerMessage -from velbusaio.messages.set_led import SetLedMessage -from velbusaio.messages.set_realtime_clock import SetRealtimeClock -from velbusaio.messages.set_temperature import SetTemperatureMessage -from velbusaio.messages.slider_status import SliderStatusMessage -from velbusaio.messages.slow_blinking_led import SlowBlinkingLedMessage -from velbusaio.messages.start_relay_blinking_timer import StartRelayBlinkingTimerMessage -from velbusaio.messages.start_relay_timer import StartRelayTimerMessage -from velbusaio.messages.switch_relay_off import SwitchRelayOffMessage -from velbusaio.messages.switch_relay_on import SwitchRelayOnMessage -from velbusaio.messages.switch_to_comfort import SwitchToComfortMessage -from velbusaio.messages.switch_to_day import SwitchToDayMessage -from velbusaio.messages.switch_to_night import SwitchToNightMessage -from velbusaio.messages.switch_to_safe import SwitchToSafeMessage -from velbusaio.messages.temp_sensor_settings_part1 import TempSensorSettingsPart1 -from velbusaio.messages.temp_sensor_settings_part2 import TempSensorSettingsPart2 -from velbusaio.messages.temp_sensor_settings_part3 import TempSensorSettingsPart3 -from velbusaio.messages.temp_sensor_settings_part4 import TempSensorSettingsPart4 -from velbusaio.messages.temp_sensor_settings_request import TempSensorSettingsRequest -from velbusaio.messages.temp_sensor_status import TempSensorStatusMessage -from velbusaio.messages.temp_set_cooling import TempSetCoolingMessage -from velbusaio.messages.temp_set_heating import TempSetHeatingMessage -from velbusaio.messages.update_led_status import UpdateLedStatusMessage -from velbusaio.messages.very_fast_blinking_led import VeryFastBlinkingLedMessage -from velbusaio.messages.write_data_to_memory import WriteDataToMemoryMessage -from velbusaio.messages.write_memory_block import WriteMemoryBlockMessage -from velbusaio.messages.write_module_address_and_serial_number import ( - WriteModuleAddressAndSerialNumberMessage, -) - -# pylint: disable-msg=C0301 diff --git a/velbusaio/messages/cover_off.py b/velbusaio/messages/cover_off.py index 3a47338..6f27370 100644 --- a/velbusaio/messages/cover_off.py +++ b/velbusaio/messages/cover_off.py @@ -4,8 +4,6 @@ from __future__ import annotations -import struct - from velbusaio.command_registry import register from velbusaio.message import Message diff --git a/velbusaio/messages/cover_position.py b/velbusaio/messages/cover_position.py index a8e1fab..7f81549 100644 --- a/velbusaio/messages/cover_position.py +++ b/velbusaio/messages/cover_position.py @@ -4,8 +4,6 @@ from __future__ import annotations -import struct - from velbusaio.command_registry import register from velbusaio.message import Message diff --git a/velbusaio/module.py b/velbusaio/module.py index 6cb471f..ebdb90c 100644 --- a/velbusaio/module.py +++ b/velbusaio/module.py @@ -5,11 +5,10 @@ from __future__ import annotations import logging -import os import pathlib -import pickle import struct import sys +import json from typing import Awaitable, Callable from velbusaio.channels import ( @@ -37,7 +36,7 @@ ) from velbusaio.helpers import handle_match, keys_exists from velbusaio.message import Message -from velbusaio.messages import DaliDeviceSettingMsg +from velbusaio.messages.dali_device_settings import DaliDeviceSettingMsg from velbusaio.messages.blind_status import BlindStatusMessage, BlindStatusNgMessage from velbusaio.messages.channel_name_part1 import ( ChannelNamePart1Message, @@ -81,8 +80,6 @@ ModuleStatusPirMessage, ) from velbusaio.messages.module_status_request import ModuleStatusRequestMessage -from velbusaio.messages.module_subtype import ModuleSubTypeMessage -from velbusaio.messages.module_type import ModuleTypeMessage, ModuleType2Message from velbusaio.messages.push_button_status import PushButtonStatusMessage from velbusaio.messages.read_data_from_memory import ReadDataFromMemoryMessage from velbusaio.messages.relay_status import RelayStatusMessage, RelayStatusMessage2 @@ -188,9 +185,9 @@ def cleanupSubChannels(self) -> None: del self._channels[i] def _cache(self) -> None: - cfile = pathlib.Path(f"{self._cache_dir}/{self._address}.p") - with cfile.open("wb") as fl: - pickle.dump(self, fl) + cfile = pathlib.Path(f"{self._cache_dir}/{self._address}.json") + with cfile.open("w") as fl: + json.dump(self.to_cache(), fl, indent=4) def __getstate__(self) -> dict: d = self.__dict__ @@ -201,18 +198,17 @@ def __setstate__(self, state: dict) -> None: self.__dict__ = state def __repr__(self) -> str: - return "<{}: address:{{{}}} type:{{{}}} loaded:{{{}}} loading:{{{}}} channels{{:{}}}>".format( - self._name, - self._type, - self._address, - self.loaded, - self._is_loading, - self._channels, - ) + return f"<{self._name} type:{self._type} address:{self._address} loaded:{self.loaded} loading:{self._is_loading} channels: {self._channels}>" def __str__(self) -> str: return self.__repr__() + def to_cache(self) -> dict: + d = {"name": self._name, "channels": {}} + for num, chan in self._channels.items(): + d["channels"][num] = chan.to_cache() + return d + def get_addresses(self) -> list: """ Get all addresses for this module @@ -239,12 +235,7 @@ def get_name(self) -> str: return self._name def get_sw_version(self) -> str: - return "{}-{}.{}.{}".format( - self.serial, - self.memory_map_version, - self.build_year, - self.build_week, - ) + return f"{self.serial}-{self.memory_map_version}.{self.build_year}.{self.build_week}" def calc_channel_offset(self, address: int) -> int: _channel_offset = 0 @@ -547,14 +538,26 @@ async def load(self, from_cache: bool = False) -> None: self._log.info("Load Module") # start the loading self._is_loading = True + # see if we have a cache + cfile = pathlib.Path(f"{self._cache_dir}/{self._address}.json") + with cfile.open("r") as fl: + cache = json.load(fl) # load default channels await self.__load_default_channels() # load the data from memory ( the stuff that we need) - await self.__load_memory() + if "name" in cache and cache["name"] != "": + self._name = cache["name"] + else: + await self.__load_memory() # load the module status await self._request_module_status() # load the channel names - await self._request_channel_name() + if "channels" in cache: + for num, chan in cache["channels"].items(): + self._channels[int(num)]._name = chan["name"] + self._channels[int(num)]._is_loaded = True + else: + await self._request_channel_name() # load the module specific stuff self._load() # stop the loading diff --git a/velbusaio/util.py b/velbusaio/util.py index 6aa1f14..e360ec0 100644 --- a/velbusaio/util.py +++ b/velbusaio/util.py @@ -1,3 +1,7 @@ +""" +Some common utils. +""" + from typing import Union from velbusaio.const import MAXIMUM_MESSAGE_SIZE, MINIMUM_MESSAGE_SIZE