Skip to content

Commit

Permalink
AVM:
Browse files Browse the repository at this point in the history
- CallMonitor: bugfix join counter threads
- FritzHome: Add support for device statistics
- bump to 2.1.0
  • Loading branch information
sisamiwe committed Aug 10, 2023
1 parent 1aa9afb commit a14273c
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 24 deletions.
104 changes: 89 additions & 15 deletions avm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class AVM(SmartPlugin):
"""
Main class of the Plugin. Does all plugin specific stuff
"""
PLUGIN_VERSION = '2.0.9'
PLUGIN_VERSION = '2.1.0'

# ToDo: FritzHome.handle_updated_item: implement 'saturation'
# ToDo: FritzHome.handle_updated_item: implement 'unmapped_hue'
Expand Down Expand Up @@ -504,6 +504,9 @@ def get_monitor_index() -> bool:
if not get_aha_index():
return

if avm_data_type in AHA_STATS_ATTRIBUTES:
self.fritz_home.use_device_statistics = True

# handle items updated by tr-064 interface
elif avm_data_type in TR064_ATTRIBUTES:
if not self.fritz_device:
Expand Down Expand Up @@ -1937,6 +1940,9 @@ def __init__(self, host, ssl, verify, user, password, log_entry_count, plugin_in
self._timeout = 10
self.last_request = None
self.log_entry_count = log_entry_count
self.use_device_statistics = False
self.last_device_statistics_update = 0
self.device_statistics_min_grid = 0

# Login to test, if login is possible and get first sid
self.login()
Expand All @@ -1957,6 +1963,11 @@ def cyclic_item_update(self, read_all: bool = False):
self.logger.debug(f"Update of AHA-Device data took {update_time - start_time}s")
item_count = 0

# add device statistics to devices if activated and due
if self.use_device_statistics and (self.last_device_statistics_update + self.device_statistics_min_grid) <= update_time:
self.last_device_statistics_update = update_time
self.add_device_statistics_to_devices()

# iterate over items and get data
for item in self.item_list():
# get item config
Expand Down Expand Up @@ -2397,6 +2408,69 @@ def get_device_name(self, ain: str):
"""
return self.aha_request("getswitchname", ain=ain)

# statistics-related commands

def get_device_statistics(self, ain):
"""
Get device statistics.
"""
return self.aha_request("getbasicdevicestats", ain=ain)

def get_device_statistics_serie(self, ain: str, func: str = None):
"""
Get device statistics of device as list of lists for smartvisu like [[timestamp1, value1], [timestamp2, value2], ...]
"""

def get_series(_func):
element = dom.find(_func)
if element is not None:
stats = element.find("stats")
if stats is not None:
series = []
count = to_int(stats.attrib.get('count'))
grid = to_int(stats.attrib.get('grid'))
if self.device_statistics_min_grid == 0 or grid < self.device_statistics_min_grid:
self.device_statistics_min_grid = grid
datatime = to_int(stats.attrib.get('datatime'))
raw_values = stats.text.split(',')
raw_values = list(map(to_int, raw_values))
values = [val / scales[_func] for val in raw_values]
for value in values:
count -= 1
series.append([datatime - count * grid, value])
return series

scales = {
'temperature': 10, # Die Genauigkeit/Einheit der <temperature>-Werte ist 0,1°C.
'voltage': 1000, # Die Genauigkeit/Einheit der <voltage>-Werte ist 0,001V.
'power': 100, # Die Genauigkeit/Einheit der <power>-Werte ist 0,01W.
'energy': 1, # Die Genauigkeit/Einheit der <energy>-Werte ist 1 Wh.
'humidity': 1, # Die Genauigkeit/Einheit der <humidity>-Werte ist Prozent.
}

dom = self.get_device_statistics(ain)

if dom:
if func in ['temperature', 'humidity', 'voltage', 'power', 'energy']:
return get_series(func)

elif func == 'powermeter':
stats_voltage = get_series('voltage')
stats_power = get_series('power')
stats_energy = get_series('energy')
return stats_voltage, stats_power, stats_energy

def add_device_statistics_to_devices(self):
"""Add device statistics to self._devices"""

for device in self.get_devices():
if device.has_temperature_sensor:
device.statistics_temp = self.get_device_statistics_serie(ain=device.ain, func='temperature')
elif device.has_humidity_sensor:
device.statistics_hum = self.get_device_statistics_serie(ain=device.ain, func='humidity')
elif device.has_powermeter:
device.statistics_voltage, device.statistics_power, device.statistics_energy = self.get_device_statistics_serie(ain=device.ain, func='powermeter')

# switch-related commands

def get_switch_state(self, ain: str):
Expand Down Expand Up @@ -2548,12 +2622,6 @@ def get_eco_temperature(self, ain: str):
"""
return self._get_temperature(ain, "gethkrabsenk")

def get_device_statistics(self, ain):
"""
Get device statistics.
"""
return self.aha_request("getbasicdevicestats", ain=ain)

# Switch-related commands

def set_state_off(self, ain):
Expand Down Expand Up @@ -3893,7 +3961,7 @@ def disconnect(self):
self._stop_counter('incoming')
self._stop_counter('outgoing')

if self._listen_thread:
if self._listen_thread and self._listen_thread.is_alive():
try:
self._listen_thread.join(1)
except Exception as e: # AttributeError
Expand Down Expand Up @@ -4105,20 +4173,26 @@ def _start_counter(self, timestamp: str, direction: str):

def _stop_counter(self, direction: str):
"""
Stop counter to measure duration of a call, but only stop of thread is active
Stop counter to measure duration of a call, but only stop if thread is active
"""
if self._call_active[direction]:
self._call_active[direction] = False
if self.debug_log:
self.logger.debug(f'STOPPING {direction}')
try:
if direction == 'incoming':

if direction == 'incoming' and self._duration_counter_thread_incoming and self._duration_counter_thread_incoming.is_alive():
try:
self._duration_counter_thread_incoming.join(1)
elif direction == 'outgoing':
except Exception as e:
self.logger.warning(f"Error {e!r} occurred during stopping incoming counter of Callmonitor")
pass

elif direction == 'outgoing' and self._duration_counter_thread_outgoing and self._duration_counter_thread_outgoing.is_alive():
try:
self._duration_counter_thread_outgoing.join(1)
except Exception as e:
self.logger.warning(f"Error {e!r} occurred during stopping counter of Callmonitor")
pass
except Exception as e:
self.logger.warning(f"Error {e!r} occurred during stopping outgoing counter of Callmonitor")
pass

def _count_duration_incoming(self):
"""
Expand Down
5 changes: 3 additions & 2 deletions avm/item_attributes.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
ALL_ATTRIBUTES_WRITEABLE = ['reboot', 'set_target_temperature', 'set_window_open', 'set_hkr_boost', 'set_simpleonoff', 'set_level', 'set_levelpercentage', 'set_hue', 'set_saturation', 'set_colortemperature', 'switch_toggle', 'tam', 'wlanconfig', 'wps_active', 'deflection_enable', 'aha_device', 'target_temperature', 'window_open', 'hkr_boost', 'simpleonoff', 'level', 'levelpercentage', 'hue', 'saturation', 'colortemperature', 'unmapped_hue', 'unmapped_saturation', 'switch_state']
ALL_ATTRIBUTES_WRITEONLY = ['reboot', 'set_target_temperature', 'set_window_open', 'set_hkr_boost', 'set_simpleonoff', 'set_level', 'set_levelpercentage', 'set_hue', 'set_saturation', 'set_colortemperature', 'switch_toggle']
DEPRECATED_ATTRIBUTES = ['aha_device', 'hkr_device', 'set_temperature', 'temperature', 'set_temperature_reduced', 'set_temperature_comfort', 'firmware_version', 'boost_active']
AHA_ATTRIBUTES = ['device_id', 'manufacturer', 'product_name', 'fw_version', 'connected', 'device_name', 'tx_busy', 'device_functions', 'set_target_temperature', 'target_temperature', 'current_temperature', 'temperature_reduced', 'temperature_comfort', 'temperature_offset', 'set_window_open', 'window_open', 'windowopenactiveendtime', 'set_hkr_boost', 'hkr_boost', 'boost_active', 'boostactiveendtime', 'summer_active', 'holiday_active', 'battery_low', 'battery_level', 'lock', 'device_lock', 'errorcode', 'set_simpleonoff', 'simpleonoff', 'set_level', 'level', 'set_levelpercentage', 'levelpercentage', 'set_hue', 'hue', 'set_saturation', 'saturation', 'set_colortemperature', 'colortemperature', 'unmapped_hue', 'unmapped_saturation', 'color_mode', 'supported_color_mode', 'fullcolorsupport', 'mapped', 'switch_state', 'switch_mode', 'switch_toggle', 'power', 'energy', 'voltage', 'humidity', 'alert_state', 'blind_mode', 'endpositionsset']
AHA_RO_ATTRIBUTES = ['device_id', 'manufacturer', 'product_name', 'fw_version', 'connected', 'device_name', 'tx_busy', 'device_functions', 'current_temperature', 'temperature_reduced', 'temperature_comfort', 'temperature_offset', 'windowopenactiveendtime', 'boost_active', 'boostactiveendtime', 'summer_active', 'holiday_active', 'battery_low', 'battery_level', 'lock', 'device_lock', 'errorcode', 'color_mode', 'supported_color_mode', 'fullcolorsupport', 'mapped', 'switch_mode', 'power', 'energy', 'voltage', 'humidity', 'alert_state', 'blind_mode', 'endpositionsset']
AHA_ATTRIBUTES = ['device_id', 'manufacturer', 'product_name', 'fw_version', 'connected', 'device_name', 'tx_busy', 'device_functions', 'set_target_temperature', 'target_temperature', 'current_temperature', 'temperature_reduced', 'temperature_comfort', 'temperature_offset', 'set_window_open', 'window_open', 'windowopenactiveendtime', 'set_hkr_boost', 'hkr_boost', 'boost_active', 'boostactiveendtime', 'summer_active', 'holiday_active', 'battery_low', 'battery_level', 'lock', 'device_lock', 'errorcode', 'set_simpleonoff', 'simpleonoff', 'set_level', 'level', 'set_levelpercentage', 'levelpercentage', 'set_hue', 'hue', 'set_saturation', 'saturation', 'set_colortemperature', 'colortemperature', 'unmapped_hue', 'unmapped_saturation', 'color_mode', 'supported_color_mode', 'fullcolorsupport', 'mapped', 'switch_state', 'switch_mode', 'switch_toggle', 'power', 'energy', 'voltage', 'humidity', 'alert_state', 'blind_mode', 'endpositionsset', 'statistics_temp', 'statistics_hum', 'statistics_voltage', 'statistics_power', 'statistics_energy']
AHA_RO_ATTRIBUTES = ['device_id', 'manufacturer', 'product_name', 'fw_version', 'connected', 'device_name', 'tx_busy', 'device_functions', 'current_temperature', 'temperature_reduced', 'temperature_comfort', 'temperature_offset', 'windowopenactiveendtime', 'boost_active', 'boostactiveendtime', 'summer_active', 'holiday_active', 'battery_low', 'battery_level', 'lock', 'device_lock', 'errorcode', 'color_mode', 'supported_color_mode', 'fullcolorsupport', 'mapped', 'switch_mode', 'power', 'energy', 'voltage', 'humidity', 'alert_state', 'blind_mode', 'endpositionsset', 'statistics_temp', 'statistics_hum', 'statistics_voltage', 'statistics_power', 'statistics_energy']
AHA_WO_ATTRIBUTES = ['set_target_temperature', 'set_window_open', 'set_hkr_boost', 'set_simpleonoff', 'set_level', 'set_levelpercentage', 'set_hue', 'set_saturation', 'set_colortemperature', 'switch_toggle']
AHA_RW_ATTRIBUTES = ['target_temperature', 'window_open', 'hkr_boost', 'simpleonoff', 'level', 'levelpercentage', 'hue', 'saturation', 'colortemperature', 'unmapped_hue', 'unmapped_saturation', 'switch_state']
AHA_STATS_ATTRIBUTES = ['statistics_temp', 'statistics_hum', 'statistics_voltage', 'statistics_power', 'statistics_energy']
TR064_ATTRIBUTES = ['uptime', 'serial_number', 'software_version', 'hardware_version', 'manufacturer', 'product_class', 'manufacturer_oui', 'model_name', 'description', 'device_log', 'security_port', 'reboot', 'myfritz_status', 'call_direction', 'call_event', 'monitor_trigger', 'is_call_incoming', 'last_caller_incoming', 'last_call_date_incoming', 'call_event_incoming', 'last_number_incoming', 'last_called_number_incoming', 'is_call_outgoing', 'last_caller_outgoing', 'last_call_date_outgoing', 'call_event_outgoing', 'last_number_outgoing', 'last_called_number_outgoing', 'call_duration_incoming', 'call_duration_outgoing', 'tam', 'tam_name', 'tam_new_message_number', 'tam_old_message_number', 'tam_total_message_number', 'wan_connection_status', 'wan_connection_error', 'wan_is_connected', 'wan_uptime', 'wan_ip', 'wan_upstream', 'wan_downstream', 'wan_total_packets_sent', 'wan_total_packets_received', 'wan_current_packets_sent', 'wan_current_packets_received', 'wan_total_bytes_sent', 'wan_total_bytes_received', 'wan_current_bytes_sent', 'wan_current_bytes_received', 'wan_link', 'wlanconfig', 'wlanconfig_ssid', 'wlan_guest_time_remaining', 'wlan_associates', 'wps_active', 'wps_status', 'wps_mode', 'wlan_total_associates', 'hosts_count', 'hosts_info', 'mesh_topology', 'number_of_hosts', 'hosts_url', 'mesh_url', 'network_device', 'device_ip', 'device_connection_type', 'device_hostname', 'connection_status', 'is_host_active', 'host_info', 'number_of_deflections', 'deflections_details', 'deflection_details', 'deflection_enable', 'deflection_type', 'deflection_number', 'deflection_to_number', 'deflection_mode', 'deflection_outgoing', 'deflection_phonebook_id', 'aha_device', 'hkr_device', 'set_temperature', 'temperature', 'set_temperature_reduced', 'set_temperature_comfort', 'firmware_version']
TR064_RW_ATTRIBUTES = ['tam', 'wlanconfig', 'wps_active', 'deflection_enable', 'aha_device']
CALL_MONITOR_ATTRIBUTES = ['call_direction', 'call_event', 'monitor_trigger', 'is_call_incoming', 'last_caller_incoming', 'last_call_date_incoming', 'call_event_incoming', 'last_number_incoming', 'last_called_number_incoming', 'is_call_outgoing', 'last_caller_outgoing', 'last_call_date_outgoing', 'call_event_outgoing', 'last_number_outgoing', 'last_called_number_outgoing', 'call_duration_incoming', 'call_duration_outgoing']
Expand Down
Loading

0 comments on commit a14273c

Please sign in to comment.