Skip to content

Commit

Permalink
test new caching mechanisme
Browse files Browse the repository at this point in the history
  • Loading branch information
cereal2nd committed Apr 3, 2024
1 parent 0b8ac07 commit 6998753
Show file tree
Hide file tree
Showing 13 changed files with 50 additions and 185 deletions.
1 change: 0 additions & 1 deletion examples/read_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))]:
Expand Down
2 changes: 0 additions & 2 deletions tests/module_status_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
CHANNEL_SELECTED_PROGRAM,
NO_RTR,
PRIORITY_LOW,
RTR,
)
from velbusaio.controller import Velbus
from velbusaio.handler import PacketHandler
Expand All @@ -24,7 +23,6 @@
ModuleStatusMessage2,
ModuleStatusPirMessage,
)
from velbusaio.messages.select_program import SelectProgramMessage
from velbusaio.module import Module

# some modules to test
Expand Down
1 change: 0 additions & 1 deletion tests/thermostat_operating_mode_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
sleep_timer values are correctly stored into the module's temperature channel.
"""

import logging
import pathlib

import pytest
Expand Down
13 changes: 2 additions & 11 deletions velbusaio/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
46 changes: 14 additions & 32 deletions velbusaio/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import asyncio
import logging
import pathlib
import pickle
import json
import re
import ssl
from urllib.parse import urlparse
Expand Down Expand Up @@ -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():
Expand All @@ -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
Expand Down
5 changes: 2 additions & 3 deletions velbusaio/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import asyncio
import json
import logging
import re
from typing import TYPE_CHECKING, Awaitable, Callable
import pkg_resources

Expand Down Expand Up @@ -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(),
)
Expand Down
2 changes: 1 addition & 1 deletion velbusaio/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import os
import re
from typing import Any, Dict
from typing import Any

from velbusaio.const import CACHEDIR

Expand Down
1 change: 0 additions & 1 deletion velbusaio/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from __future__ import annotations

import json
from typing import Optional

from velbusaio.const import PRIORITY_FIRMWARE, PRIORITY_HIGH, PRIORITY_LOW

Expand Down
105 changes: 0 additions & 105 deletions velbusaio/messages/__init__.py
Original file line number Diff line number Diff line change
@@ -1,105 +0,0 @@
"""
:author: Thomas Delaet <[email protected]>
"""

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
2 changes: 0 additions & 2 deletions velbusaio/messages/cover_off.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

from __future__ import annotations

import struct

from velbusaio.command_registry import register
from velbusaio.message import Message

Expand Down
2 changes: 0 additions & 2 deletions velbusaio/messages/cover_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

from __future__ import annotations

import struct

from velbusaio.command_registry import register
from velbusaio.message import Message

Expand Down
51 changes: 27 additions & 24 deletions velbusaio/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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__
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 6998753

Please sign in to comment.