From ed917786755a91478ed973d4ed2ec5503acaaed5 Mon Sep 17 00:00:00 2001 From: gcobb321 Date: Sat, 8 Jun 2024 17:32:40 -0400 Subject: [PATCH] iCloud3 v3.0.5.2 --- README.md | 2 +- custom_components/icloud3/ChangeLog.txt | 6 ++ custom_components/icloud3/__init__.py | 1 - custom_components/icloud3/const.py | 2 +- custom_components/icloud3/device.py | 50 +++++---- .../icloud3-event-log-card.js.gz | Bin 22553 -> 22553 bytes custom_components/icloud3/global_variables.py | 4 +- custom_components/icloud3/helpers/common.py | 91 +++++++++++++++- .../icloud3/helpers/messaging.py | 18 +--- custom_components/icloud3/manifest.json | 2 +- .../icloud3/support/config_file.py | 97 +++++++++--------- .../icloud3/support/determine_interval.py | 32 +++--- .../icloud3/support/event_log.py | 3 +- custom_components/icloud3/support/hacs_ic3.py | 11 +- .../icloud3/support/icloud_data_handler.py | 7 +- .../icloud3/support/mobapp_data_handler.py | 6 +- .../icloud3/support/mobapp_interface.py | 13 ++- .../icloud3/support/pyicloud_ic3.py | 80 +++++++++------ .../icloud3/support/pyicloud_ic3_interface.py | 33 +++--- .../icloud3/support/restore_state.py | 54 +++++----- .../icloud3/support/service_handler.py | 3 +- .../icloud3/support/start_ic3.py | 69 ++++++++++--- .../icloud3/support/start_ic3_control.py | 37 +++---- .../icloud3/support/stationary_zone.py | 18 ++-- custom_components/icloud3/support/waze.py | 7 +- .../icloud3/support/waze_history.py | 24 ++--- .../icloud3/support/zone_handler.py | 12 +-- .../icloud3/translations/en.json | 10 +- 28 files changed, 408 insertions(+), 284 deletions(-) diff --git a/README.md b/README.md index a4c9d6d..0bdb508 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![CurrentVersion](https://img.shields.io/badge/Current_Version-v3.0.5-blue.svg)](https://github.com/gcobb321/icloud3) [![Type](https://img.shields.io/badge/Type-Custom_Component-orange.svg)](https://github.com/gcobb321/icloud3) [![HACS](https://img.shields.io/badge/HACS-Standard_Repository-orange.svg)](https://github.com/gcobb321/icloud3) -[![ProjectStage](https://img.shields.io/badge/Project_Stage-General_Availability-forestgreen.svg)](https://github/gcobb321/icloud3) [![Released](https://img.shields.io/badge/Released-May,_2024-forestgreen.svg)](https://github.com/gcobb321/icloud3) +[![ProjectStage](https://img.shields.io/badge/Project_Stage-General_Availability-forestgreen.svg)](https://github/gcobb321/icloud3) [![Released](https://img.shields.io/badge/Released-June,_2024-forestgreen.svg)](https://github.com/gcobb321/icloud3) diff --git a/custom_components/icloud3/ChangeLog.txt b/custom_components/icloud3/ChangeLog.txt index cef5df5..314988a 100644 --- a/custom_components/icloud3/ChangeLog.txt +++ b/custom_components/icloud3/ChangeLog.txt @@ -3,6 +3,12 @@ **Installing for the first time_** - See [here](https://gcobb321.github.io/icloud3_v3_docs/#/chapters/3.2-installing-and-configuring) for instructions on installing as a New Installation **iCloud3 v3 Documentation** - iCloud3 User Guide can be found [here](https://gcobb321.github.io/icloud3_v3_docs/#/) +3.0.5.2 +....................... +### Change Log - v3.0.5.2 (6/8/2024) +1. HA I/O ERROR FROM EVENT LOOP (Fixed) - HA was complaining about doing I/O (HACS file) outside of the Event Loop. Changed the method of doing I/O to use HA routines for the configuration file, restore state file and HACS file. +2. FROM_ZONE ERROR (Fixed) - Normally the TrackFrom Zone and NextUpdate Zone is the Home zone. Added a check to set it to Home if it had never been set. + 3.0.5.1 ....................... diff --git a/custom_components/icloud3/__init__.py b/custom_components/icloud3/__init__.py index dd96cc0..a52f7fc 100644 --- a/custom_components/icloud3/__init__.py +++ b/custom_components/icloud3/__init__.py @@ -135,7 +135,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): Gb.entry_id = entry.entry_id Gb.operating_mode = MODE_INTEGRATION Gb.PyiCloud = None - Gb.start_icloud3_inprocess_flag = True start_ic3.initialize_directory_filenames() diff --git a/custom_components/icloud3/const.py b/custom_components/icloud3/const.py index adbdfdb..310a983 100644 --- a/custom_components/icloud3/const.py +++ b/custom_components/icloud3/const.py @@ -10,7 +10,7 @@ # #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -VERSION = '3.0.5.1' +VERSION = '3.0.5.2' VERSION_BETA = '' #----------------------------------------- DOMAIN = 'icloud3' diff --git a/custom_components/icloud3/device.py b/custom_components/icloud3/device.py index dfe36bb..c07647f 100644 --- a/custom_components/icloud3/device.py +++ b/custom_components/icloud3/device.py @@ -95,8 +95,8 @@ def __init__(self, devicename, conf_device): self.FromZone_Home = None # DeviceFmZone object for the Home zone self.from_zone_names = [] # List of the from_zones in the FromZones_by_zone dictionary self.only_track_from_home = True # Track from only Home (True) or also track from other zones (False) - self.FromZone_BeingUpdated = None # DeviceFmZone object being updated in determine_interval for EvLog TfZ info - self.FromZone_NextToUpdate = None # Set to the DeviceFmZone when it's next_update_time is reached + self.FromZone_BeingUpdated = None # DeviceFmZone object being updated in determine_interval for EvLog TfZ info + self.FromZone_NextToUpdate = None # Set to the DeviceFmZone when it's next_update_time is reached self.FromZone_TrackFrom = None # DeviceFmZone object for the Closest tfz - used to set the Device's sensors self.FromZone_LastIn = None # DeviceFmZone object the device was last in self.TrackFromBaseZone = None # DeviceFmZone of Home or secondary tracked from zone @@ -572,8 +572,8 @@ def initialize_non_tracking_config_fields(self, conf_device): self.sensors[PICTURE] = picture if instr(picture, '/') else (f"/local/{picture}") self.sensor_badge_attrs[PICTURE] = self.sensors[PICTURE] - self.statzone_inzone_interval_secs = min(self.inzone_interval_secs, Gb.statzone_inzone_interval_secs) self.inzone_interval_secs = conf_device.get(CONF_INZONE_INTERVAL, 30) * 60 + self.statzone_inzone_interval_secs = min(self.inzone_interval_secs, Gb.statzone_inzone_interval_secs) self.fixed_interval_secs = conf_device.get(CONF_FIXED_INTERVAL, 0) * 60 self.device_type = conf_device.get(CONF_DEVICE_TYPE, 'iphone') self.log_zones = conf_device.get(CONF_LOG_ZONES, ['none']) @@ -696,9 +696,11 @@ def _validate_zone_parameters(self): self.conf_device[CONF_TRACK_FROM_ZONES] = list_del(self.conf_device[CONF_TRACK_FROM_ZONES], zone) # Check log-zone-activity - if self.conf_device[CONF_LOG_ZONES] in ['', []]: - self.conf_device[CONF_LOG_ZONES] = ['none'] - lza_zones += "Initialized" + if (self.conf_device[CONF_LOG_ZONES] in ['', []] + or (len(self.conf_device[CONF_LOG_ZONES]) == 1 + and self.conf_device[CONF_LOG_ZONES][0].startswith('name-'))): + self.conf_device[CONF_LOG_ZONES] = self.log_zones = ['none'] + for zone in self.conf_device[CONF_LOG_ZONES].copy(): if zone.startswith('name-') or zone == 'none': continue @@ -1471,7 +1473,8 @@ def set_passthru_zone_delay(self, data_source, zone_entered=None, zone_entered_s passthru_not_used_reason = 'Timer Expired' if passthru_not_used_reason: - post_event(self.devicename, f"Zone Enter Not Delayed > {passthru_not_used_reason}") + post_event(self.devicename, + f"Zone Enter Not Delayed > {passthru_not_used_reason}") return False # Activate Passthru zone @@ -1480,14 +1483,14 @@ def set_passthru_zone_delay(self, data_source, zone_entered=None, zone_entered_s self.passthru_zone_timer = Gb.this_update_secs + Gb.passthru_zone_interval_secs self.passthru_zone = zone_entered - event_msg =(f"Enter Zone Delayed > {zone_dname(self.passthru_zone)}, " + post_event(self.devicename, + f"Enter Zone Delayed > {zone_dname(self.passthru_zone)}, " f"DelayFor-{format_timer(Gb.passthru_zone_interval_secs)}") - post_event(self.devicename, event_msg) - info_msg = (f"Enter Zone Delayed - {zone_dname(self.passthru_zone)}, " + self.display_info_msg( + f"Enter Zone Delayed - {zone_dname(self.passthru_zone)}, " f"Expires-{secs_to_time(self.passthru_zone_timer)} " f"({format_timer(secs_to(self.passthru_zone_timer))})") - self.display_info_msg(info_msg) return True @@ -1521,6 +1524,15 @@ def is_next_update_time_reached(self): if self.icloud_initial_locate_done is False or self.is_tracking_resumed: return True + if self.FromZone_NextToUpdate is None: + FromZone = self.FromZone_Home + self.FromZone_LastIn = FromZone + self.FromZone_BeingUpdated = FromZone + self.FromZone_NextToUpdate = FromZone + self.FromZone_TrackFrom = FromZone + self.TrackFromBaseZone = FromZone + self.last_track_from_zone = FromZone.from_zone + return Gb.this_update_secs >= self.FromZone_NextToUpdate.next_update_secs # @@ -1813,7 +1825,8 @@ def is_location_data_rejected(self): elif self.loc_data_ispoorgps: reason_msg = (f"PoorGPS>{Gb.gps_accuracy_threshold}m") - event_msg =(f"Rejected #{self.old_loc_cnt} > " + post_event(self.devicename, + f"Rejected #{self.old_loc_cnt} > " f"{self.dev_data_source}-{self.loc_data_time_gps}, " f"{format_age(self.loc_data_secs)}, " f"{reason_msg}, " @@ -1821,8 +1834,6 @@ def is_location_data_rejected(self): f"({format_timer(interval)}), " f"LastUpdate-{format_age(self.last_update_loc_secs)}") - post_event(self.devicename, event_msg) - except Exception as err: log_exception(err) @@ -1984,8 +1995,8 @@ def display_battery_info_msg(self, force_display=False): self.last_battery_msg = battery_msg self.last_battery_msg_secs = time_now_secs() - event_msg = f"Battery Info > Level-{battery_msg} ({self.dev_data_battery_source})" - post_event(self.devicename, event_msg) + post_event(self.devicename, + f"Battery Info > Level-{battery_msg} ({self.dev_data_battery_source})") if Gb.EvLog.evlog_attrs["devicename"] == self.devicename: Gb.EvLog.update_event_log_display(self.devicename) @@ -2108,10 +2119,10 @@ def display_update_location_msg(self): return if self.isnotin_zone or self.loc_data_dist_moved_km > .015: - event_msg =(f"Selected > " + post_event(self.devicename, + f"Selected > " f"{self.last_loc_data_time_gps}" f"{RARROW}{self.dev_data_source}-{self.loc_data_time_gps}") - post_event(self.devicename,event_msg) #self.last_loc_data_time_gps = f"{self.dev_data_source}-{self.loc_data_time_gps} " @@ -2162,7 +2173,8 @@ def update_sensor_values_from_data_fields(self): self.sensors[MOVED_TIME_TO] = self.loc_data_time_moved_to self.sensors[ZONE_DATETIME] = secs_to_datetime(self.zone_change_secs) - if self.FromZone_NextToUpdate is None: self.FromZone_NextToUpdate = self.FromZone_Home + if self.FromZone_NextToUpdate is None: + self.FromZone_NextToUpdate = self.FromZone_Home self.interval_secs = self.FromZone_NextToUpdate.interval_secs self.interval_str = self.FromZone_NextToUpdate.interval_str self.next_update_secs = self.FromZone_NextToUpdate.next_update_secs diff --git a/custom_components/icloud3/event_log_card/icloud3-event-log-card.js.gz b/custom_components/icloud3/event_log_card/icloud3-event-log-card.js.gz index 148598d1827ccdb2936e010959213d3fb29032d7..3b709bacc42c630b6b24e31ed018703ef39ca76e 100644 GIT binary patch delta 18 ZcmbQafpO*rMt1pb4vx=$UK`nkA^<)Y1_J;9 delta 18 ZcmbQafpO*rMt1pb4i1$>qmArB5db)71up;q diff --git a/custom_components/icloud3/global_variables.py b/custom_components/icloud3/global_variables.py index da51c05..1b5284b 100644 --- a/custom_components/icloud3/global_variables.py +++ b/custom_components/icloud3/global_variables.py @@ -191,7 +191,8 @@ class GlobalVariables(object): # System Wide variables control iCloud3 start/restart procedures polling_5_sec_loop_running = False # Indicates the 5-sec polling loop is set up - start_icloud3_inprocess_flag = False + initial_icloud3_loading_flag = True + start_icloud3_inprocess_flag = True restart_icloud3_request_flag = False # iC3 needs to be restarted restart_ha_flag = False # HA needs to be restarted any_device_was_updated_reason = '' @@ -203,7 +204,6 @@ class GlobalVariables(object): get_FAMSHR_devices_retry_cnt = 0 # Retry count to connect to iCloud and retrieve FamShr devices reinitialize_icloud_devices_flag= False # Set when no devices are tracked and iC3 needs to automatically restart reinitialize_icloud_devices_cnt = 0 - initial_icloud3_loading_flag = False # Debug and trace flags log_debug_flag = False diff --git a/custom_components/icloud3/helpers/common.py b/custom_components/icloud3/helpers/common.py index b54da8c..e190a5c 100644 --- a/custom_components/icloud3/helpers/common.py +++ b/custom_components/icloud3/helpers/common.py @@ -3,7 +3,13 @@ from ..global_variables import GlobalVariables as Gb from ..const import (NOT_HOME, STATIONARY, CIRCLE_LETTERS_DARK, UNKNOWN, CRLF_DOT, CRLF, ) from collections import OrderedDict +from homeassistant.util import json as json_util +from homeassistant.helpers import json as json_helpers import os +import json +import logging +_LOGGER = logging.getLogger(__name__) +#_LOGGER = logging.getLogger(f"icloud3") #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> # @@ -274,6 +280,90 @@ def format_list(arg_list): def format_cnt(desc, n): return f", {desc}(#{n})" if n > 1 else '' +#-------------------------------------------------------------------- +async def async_load_json_file(filename): + if os.path.exists(filename) is False: + return {} + + try: + data = await Gb.hass.async_add_executor_job( + json_util.load_json, + filename) + return data + + except Exception as err: + #_LOGGER.exception(err) + pass + + return {} + +#-------------------------------------------------------------------- +def load_json_file(filename): + if os.path.exists(filename) is False: + return {} + + try: + if Gb.initial_icloud3_loading_flag: + data = json_util.load_json(filename) + else: + data = Gb.hass.async_add_executor_job( + json_util.load_json, + filename) + return data + + except RuntimeError as err: + if str(err) == 'no running event loop': + data = json_util.load_json(filename) + return data + + except Exception as err: + _LOGGER.exception(err) + pass + + return {} + +#-------------------------------------------------------------------- +async def async_save_json_file(filename, data): + + try: + await Gb.hass.async_add_executor_job( + json_helpers.save_json, + filename, + data) + return True + + except Exception as err: + _LOGGER.exception(err) + pass + + return False + +#-------------------------------------------------------------------- +def save_json_file(filename, data): + + try: + # The HA event loop has not been set up yet during initialization + if Gb.initial_icloud3_loading_flag: + json_helpers.save_json(filename, data) + else: + + Gb.hass.async_add_executor_job( + json_helpers.save_json, + filename, + data) + return True + + except RuntimeError as err: + if err == 'no running event loop': + json_helpers.save_json(filename, data) + return True + + except Exception as err: + _LOGGER.exception(err) + pass + + return False + #-------------------------------------------------------------------- def delete_file(file_desc, directory, filename, backup_extn=None, delete_old_sv_file=False): ''' @@ -401,4 +491,3 @@ def base64_decode(string): base64_bytes = string.encode('ascii') string_bytes = base64.b64decode(base64_bytes) return string_bytes.decode('ascii') - diff --git a/custom_components/icloud3/helpers/messaging.py b/custom_components/icloud3/helpers/messaging.py index be3aa69..9478b35 100644 --- a/custom_components/icloud3/helpers/messaging.py +++ b/custom_components/icloud3/helpers/messaging.py @@ -507,23 +507,7 @@ def log_start_finish_update_banner(start_finish, devicename, log_info_msg(log_msg) -#-------------------------------------------------------------------- -def write_debug_log(debug_log_title=None): - ''' - Cycle thru the debug_log and write all items to the icloud2-0.log file - ''' - if Gb.log_debug_flag is False or Gb.debug_log == {}: return - - if debug_log_title: - log_debug_msg(f"{format_header_box(debug_log_title)}") - - for field, values in Gb.debug_log.items(): - log_debug_msg(f"{field}={values}") - - if debug_log_title: - log_debug_msg(f"{format_header_box(debug_log_title)}") - Gb.debug_log = {} #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> # @@ -574,7 +558,7 @@ def filter_special_chars(recd, evlog_export=False): recd = recd.replace(NBSP6, ' ') recd = recd.strip() recd = recd.replace(CRLF, f"\n{indent}") - recd = recd.replace('◦', f" ◦") + recd = recd.replace('◦', f" ◦") recd = recd.replace('* >', '') recd = recd.replace('<', '<') diff --git a/custom_components/icloud3/manifest.json b/custom_components/icloud3/manifest.json index 0ea06da..537560e 100644 --- a/custom_components/icloud3/manifest.json +++ b/custom_components/icloud3/manifest.json @@ -10,5 +10,5 @@ "issue_tracker": "https://github.com/gcobb321/icloud3_v3/issues", "loggers": ["icloud3"], "requirements": [], - "version": "3.0" + "version": "3.0.5.2" } diff --git a/custom_components/icloud3/support/config_file.py b/custom_components/icloud3/support/config_file.py index fdea69e..42c8940 100644 --- a/custom_components/icloud3/support/config_file.py +++ b/custom_components/icloud3/support/config_file.py @@ -38,7 +38,8 @@ from ..support import start_ic3 from ..support import waze -from ..helpers.common import (instr, ordereddict_to_dict, isbetween, ) +from ..helpers.common import (instr, ordereddict_to_dict, isbetween, + load_json_file, async_load_json_file, save_json_file, ) from ..helpers.messaging import (log_exception, _trace, _traceha, log_info_msg, ) from ..helpers.time_util import (datetime_now, ) @@ -120,29 +121,32 @@ def read_storage_icloud3_configuration_file(filename_suffix=''): try: filename = f"{Gb.icloud3_config_filename}{filename_suffix}" - with open(filename, 'r') as f: - Gb.conf_file_data = json.load(f) + Gb.conf_file_data = load_json_file(filename) - Gb.conf_profile = Gb.conf_file_data['profile'] - Gb.conf_data = Gb.conf_file_data['data'] + if Gb.conf_file_data == {}: + return False - Gb.conf_tracking = Gb.conf_data['tracking'] - Gb.conf_devices = Gb.conf_data['tracking']['devices'] - Gb.conf_general = Gb.conf_data['general'] - Gb.conf_sensors = Gb.conf_data['sensors'] - Gb.log_level = Gb.conf_general[CONF_LOG_LEVEL] + Gb.conf_profile = Gb.conf_file_data['profile'] + Gb.conf_data = Gb.conf_file_data['data'] - Gb.conf_tracking[CONF_PASSWORD] = decode_password(Gb.conf_tracking[CONF_PASSWORD]) - set_conf_devices_index_by_devicename() - if instr(Gb.conf_tracking[CONF_DATA_SOURCE], FMF): - Gb.conf_tracking[CONF_DATA_SOURCE].pop(FMF) + Gb.conf_tracking = Gb.conf_data['tracking'] + Gb.conf_devices = Gb.conf_data['tracking']['devices'] + Gb.conf_general = Gb.conf_data['general'] + Gb.conf_sensors = Gb.conf_data['sensors'] + Gb.log_level = Gb.conf_general[CONF_LOG_LEVEL] - try: - config_file_add_new_parameters() + Gb.conf_tracking[CONF_PASSWORD] = decode_password(Gb.conf_tracking[CONF_PASSWORD]) + set_conf_devices_index_by_devicename() + if instr(Gb.conf_tracking[CONF_DATA_SOURCE], FMF): + Gb.conf_tracking[CONF_DATA_SOURCE].pop(FMF) - except Exception as err: - log_exception(err) - _LOGGER.error("iCloud3 > An error occured verifying the iCloud3 Configuration File. Will continue.") + try: + config_file_add_new_parameters() + + except Exception as err: + log_exception(err) + _LOGGER.error( "iCloud3 > An error occured verifying the iCloud3 " + "Configuration File. Will continue.") return True @@ -507,50 +511,52 @@ def write_storage_icloud3_configuration_file(filename_suffix=''): Update the config/.storage/.icloud3.configuration file Parameters: - filename_suffix: A suffix added to the filename that allows saving multiple copies of + filename_suffix: A suffix added to the filename that allows saving multiple copies o the configuration file + + The Gb.conf_tracking[CONF_PASSWORD] field contains the real password + while iCloud3 is running. This makes it easier logging into PyiCloud + and in config_flow. Save it, then put the encoded password in the file + update the file and then restore the real password ''' + Gb.conf_tracking[CONF_PASSWORD] = encode_password(Gb.conf_tracking[CONF_PASSWORD]) + Gb.conf_profile[CONF_UPDATE_DATE] = datetime_now() - try: - filename = f"{Gb.icloud3_config_filename}{filename_suffix}" - with open(filename, 'w', encoding='utf8') as f: - # The Gb.conf_tracking[CONF_PASSWORD] field contains the real password - # while iCloud3 is running. This makes it easier logging into PyiCloud - # and in config_flow. Save it, then put the encoded password in the file - # update the file and then restore the real password - Gb.conf_tracking[CONF_PASSWORD] = encode_password(Gb.conf_tracking[CONF_PASSWORD]) - Gb.conf_profile[CONF_UPDATE_DATE] = datetime_now() + Gb.conf_data['tracking']['devices'] = Gb.conf_devices + Gb.conf_data['tracking'] = Gb.conf_tracking + Gb.conf_data['general'] = Gb.conf_general + Gb.conf_data['sensors'] = Gb.conf_sensors - Gb.conf_data['tracking']['devices'] = Gb.conf_devices - Gb.conf_data['tracking'] = Gb.conf_tracking - Gb.conf_data['general'] = Gb.conf_general - Gb.conf_data['sensors'] = Gb.conf_sensors + Gb.conf_file_data['profile'] = Gb.conf_profile + Gb.conf_file_data['data'] = Gb.conf_data - Gb.conf_file_data['profile'] = Gb.conf_profile - Gb.conf_file_data['data'] = Gb.conf_data + try: + filename = f"{Gb.icloud3_config_filename}{filename_suffix}" + success = save_json_file(filename, Gb.conf_file_data) + # with open(filename, 'w', encoding='utf8') as f: + # json.dump(Gb.conf_file_data, f, indent=2, ensure_ascii=False) - json.dump(Gb.conf_file_data, f, indent=4, ensure_ascii=False) + except Exception as err: + log_exception(err) + return False - Gb.conf_tracking[CONF_PASSWORD] = decode_password(Gb.conf_tracking[CONF_PASSWORD]) + Gb.conf_tracking[CONF_PASSWORD] = decode_password(Gb.conf_tracking[CONF_PASSWORD]) - # rc9 Update conf_devices devicename index dictionary - if len(Gb.conf_devices) != len(Gb.conf_devices_idx_by_devicename): - set_conf_devices_index_by_devicename() + # Update conf_devices devicename index dictionary + if len(Gb.conf_devices) != len(Gb.conf_devices_idx_by_devicename): + set_conf_devices_index_by_devicename() - return True + return success - except Exception as err: - log_exception(err) - return False #-------------------------------------------------------------------- def set_conf_devices_index_by_devicename(): ''' Update the device name index position in the conf_devices parameter. This let you access a devices configuration without searching through - the devices list to get a specific device. + the devices list to get a specific device. idx = Gb.conf_devices_idx_by_devicename('gary_iphone') conf_device = Gb.conf_devices.index(idx) @@ -560,7 +566,6 @@ def set_conf_devices_index_by_devicename(): Gb.conf_devices_idx_by_devicename[conf_device[CONF_IC3_DEVICENAME]] = index def get_conf_device(devicename): - idx = Gb.conf_devices_idx_by_devicename.get(devicename, -1) if idx == -1: return None diff --git a/custom_components/icloud3/support/determine_interval.py b/custom_components/icloud3/support/determine_interval.py index 64faaa8..bdd4b28 100644 --- a/custom_components/icloud3/support/determine_interval.py +++ b/custom_components/icloud3/support/determine_interval.py @@ -86,7 +86,7 @@ # RETRY_INTERVAL_RANGE_1 = 30s*4=2m, 4*1.5m=6m=8m, 4*15m=1h=1h8m, 4*30m=2h=3h8m, 4*1h=4h=6.5h # RETRY_INTERVAL_RANGE_1 = {0:.25, 4:1, 8:5, 12:30, 16:60, 20:60} # RETRY_INTERVAL_RANGE_1 = 15s*5=1.25m, 5*1m=5m=6m, 5*5m=25m=30m, 5*30m=2.5h=3, 4*1h=4h=6h25h -RETRY_INTERVAL_RANGE_1 = {0:.25, 4:.5, 8:1, 12:5, 16:10, 20:15} +RETRY_INTERVAL_RANGE_1 = {0:.25, 4:.5, 8:1, 12:5, 16:15, 20:30, 22:60} MOBAPP_REQUEST_LOC_CNT = 2.1 RETRY_INTERVAL_RANGE_2 = {0:.5, 4:2, 8:30, 12:60, 16:60} # RETRY_INTERVAL_RANGE_2 = {0:.5, 4:2, 8:30, 12:60, 14:120, 16:180, 18:240, 20:240} @@ -117,10 +117,10 @@ def determine_interval(Device, FromZone): Device.FromZone_LastIn = FromZone if Device.offline_secs > 0 and Device.is_online: - event_msg =(f"{EVLOG_ALERT}Device back Online > " + post_event(devicename, + f"{EVLOG_ALERT}Device back Online > " f"WentOfflineAt-{format_time_age(Device.offline_secs)}, " f"DeviceStatus-{Device.device_status}") - post_event(devicename, event_msg) Device.offline_secs = 0 Device.display_info_msg(Device.format_info_msg, new_base_msg=True) @@ -631,8 +631,8 @@ def post_zone_time_dist_event_msg(Device, FromZone): travel_time = '' if FromZone.last_travel_time == '0 min' else FromZone.last_travel_time distance = FromZone.zone_distance_str - event_msg =(f"{EVLOG_TIME_RECD}{mobapp_state},{ic3_zone},{interval_str},{travel_time},{distance}") - post_event(Device, event_msg) + post_event(Device, + f"{EVLOG_TIME_RECD}{mobapp_state},{ic3_zone},{interval_str},{travel_time},{distance}") #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> # @@ -669,10 +669,10 @@ def determine_interval_monitored_device_offline(Device): update_all_device_fm_zone_sensors_interval(Device, interval_secs) - event_msg =(f"{RED_X}Offline > " + post_event(Device, + f"{RED_X}Offline > " f"Since-{format_time_age(Device.loc_data_secs)}, " f"CheckNext-{Device.sensors[NEXT_UPDATE_TIME]}") - post_event(Device, event_msg) return True @@ -714,10 +714,10 @@ def determine_interval_after_error(Device, counter=OLD_LOCATION_CNT): Device.reset_tracking_fields(interval_secs=5) interval_secs, error_cnt, max_error_cnt = get_error_retry_interval(Device, counter) - event_msg = (f"Location > Old > Tracking Reinitialized, " + post_event(Device, + f"Location > Old > Tracking Reinitialized, " f"LastLocated-{format_time_age(Device.loc_data_secs)}, " f"RetryAt-{Device.FromZone_Home.next_update_time}") - post_event(Device, event_msg) return if (Device.is_offline and Device.offline_secs == 0): @@ -939,8 +939,7 @@ def _get_distance_data(Device, FromZone): Device.display_info_msg(f"GetDistancesFrom-{FromZone.from_zone_dname}") if Device.no_location_data: - event_msg = "No location data available, will retry" - post_event(Device, event_msg) + post_event(Device, "No location data available, will retry") return (ERROR, {}) @@ -1030,8 +1029,7 @@ def _get_distance_data(Device, FromZone): waze_dist_from_zone_km = 0.0 if waze_source_msg: - event_msg = f"Waze Route Info > {waze_source_msg}" - post_event(Device, event_msg) + post_event(Device, f"Waze Route Info > {waze_source_msg}") #-------------------------------------------------------------------------------- # Get direction of travel @@ -1096,10 +1094,10 @@ def _get_distance_data(Device, FromZone): and Device.is_tracked): Device.statzone_reset_timer - event_msg =(f"StatZone Timer Reset > " + post_event(Device, + f"StatZone Timer Reset > " f"NewTime-{secs_to_time(Device.statzone_timer)}, " f"Moved-{km_to_um(Device.loc_data_dist_moved_km)}") - post_event(Device, event_msg) distance_data = [VALID_DATA, dist_from_zone_km, @@ -1180,9 +1178,9 @@ def used_near_device_results(Device, FromZone): Device.dist_apart_msg = Device.dist_apart_msg.replace(neardevice_fname, neardevice_fname_chk) Device.near_device_used = ( f"{Device.NearDevice.fname_devtype} " f"({m_to_um_ft(Device.near_device_distance)})") - event_msg =(f"Using Nearby Device Results > {Device.NearDevice.fname}, " + post_event(Device, + f"Using Nearby Device Results > {Device.NearDevice.fname}, " f"Distance-{m_to_um_ft(Device.near_device_distance)}") - post_event(Device, event_msg) copy_near_device_results(Device, FromZone) diff --git a/custom_components/icloud3/support/event_log.py b/custom_components/icloud3/support/event_log.py index 3f1ee0b..621be30 100644 --- a/custom_components/icloud3/support/event_log.py +++ b/custom_components/icloud3/support/event_log.py @@ -638,13 +638,12 @@ def _shrink_event_recds(self, shrink_cnt): del self.event_recds[event_recds_target_cnt:] if delete_cnt > 0: - event_msg = ( f"{EVLOG_MONITOR}Event Log Table Size Reduced > " + self.post_event(f"{EVLOG_MONITOR}Event Log Table Size Reduced > " f"RecdCnt-{event_recds_recd_cnt}{RARROW}" f"{len(self.event_recds)}, " f"Deleted-{delete_cnt} " f"(DevInfo-{delete_reg_cnt}, " f"Monitor-{delete_mon_cnt})") - self.post_event(event_msg) except Exception as err: log_exception(err) diff --git a/custom_components/icloud3/support/hacs_ic3.py b/custom_components/icloud3/support/hacs_ic3.py index d67a813..745702a 100644 --- a/custom_components/icloud3/support/hacs_ic3.py +++ b/custom_components/icloud3/support/hacs_ic3.py @@ -8,7 +8,7 @@ LAST_ZONE, LAST_ZONE_DNAME, LAST_ZONE_FNAME, LAST_ZONE_NAME, DIR_OF_TRAVEL, ) -from ..helpers.common import (instr, ) +from ..helpers.common import (instr, async_load_json_file, load_json_file, ) from ..helpers.messaging import (log_info_msg, log_debug_msg, log_exception, post_evlog_greenbar_msg, _trace, _traceha, ) from ..helpers.time_util import (datetime_now, secs_to_datetime, ) @@ -35,7 +35,7 @@ async def check_hacs_icloud3_update_available(): return None try: - hacs_ic3_items = _get_hacs_ic3_data(hacs_repository_file) + hacs_ic3_items = await _async_get_hacs_ic3_data(hacs_repository_file) Gb.version_hacs = '' if 'icloud3_v3' in hacs_ic3_items: @@ -58,7 +58,7 @@ async def check_hacs_icloud3_update_available(): return None #------------------------------------------------------------------------------------------- -def _get_hacs_ic3_data(hacs_repository_file): +async def _async_get_hacs_ic3_data(hacs_repository_file): ''' Read the config/.storage/.icloud3.restore_state file. - Extract the data into the Global Variables. @@ -67,8 +67,9 @@ def _get_hacs_ic3_data(hacs_repository_file): ''' try: - with open(hacs_repository_file, 'r') as f: - hacs_repository_file_data = json.load(f) + hacs_repository_file_data = await async_load_json_file(hacs_repository_file) + + if hacs_repository_file_data != {}: hacs_ic3_items = {hacs_item_data['full_name'].split('/')[1].replace(' ', '_'): hacs_item_data for hacs_id, hacs_item_data in hacs_repository_file_data['data'].items() if hacs_item_data['full_name'].startswith('gcobb321/icloud3')} diff --git a/custom_components/icloud3/support/icloud_data_handler.py b/custom_components/icloud3/support/icloud_data_handler.py index 6fd9f2b..e22f47e 100644 --- a/custom_components/icloud3/support/icloud_data_handler.py +++ b/custom_components/icloud3/support/icloud_data_handler.py @@ -348,11 +348,11 @@ def update_device_with_latest_raw_data(Device, all_devices=False): else: reason_msg = ( f"NewData-{_RawData.location_time}/±{_RawData.gps_accuracy:.0f}m " f"vs {_Device.loc_data_time_gps}, ") - event_msg =(f"Rejected #{Device.old_loc_cnt} > " + post_event(_Device, + f"Rejected #{Device.old_loc_cnt} > " f"{reason_msg}" f"Updated-{_RawData.data_source} data, " f"{Device.device_status_msg}") - post_event(_Device.devicename, event_msg) if (_RawData is None or (_RawData.location_secs == 0 and _Device.mobapp_data_secs == 0) @@ -620,14 +620,13 @@ def get_famshr_fmf_PyiCloud_RawData_to_use(_Device): _RawData = None _Device.data_source = MOBAPP - error_msg = (f"{EVLOG_ALERT}Data Exception > {_Device.devicename} > No iCloud FamShr " + post_event( f"{EVLOG_ALERT}Data Exception > {_Device.devicename} > No iCloud FamShr " f"or FmF Device Id was assigned to this device. This can be caused by " f"No location data was returned from iCloud when iCloud3 was started." f"{CRLF}Actions > Restart iCloud3. If the error continues, check the Event Log " f"(iCloud3 Initialization Stage 2) and verify that the device is valid and a " f"tracking method has been assigned. " f"The device will be tracked by the Mobile App.") - post_event(error_msg) error_msg = '' if _RawData is None: diff --git a/custom_components/icloud3/support/mobapp_data_handler.py b/custom_components/icloud3/support/mobapp_data_handler.py index 5eb2b6a..3d7ea4f 100644 --- a/custom_components/icloud3/support/mobapp_data_handler.py +++ b/custom_components/icloud3/support/mobapp_data_handler.py @@ -420,11 +420,10 @@ def get_mobapp_device_trkr_entity_attrs(Device): Device.mobapp_monitor_flag = False Device.mobapp_device_unavailable_flag = True Device.mobapp_data_invalid_error_cnt += 1 - alert_msg =(f"{EVLOG_ALERT}The Mobile App has returned a `not available` status " + post_event( f"{EVLOG_ALERT}The Mobile App has returned a `not available` status " f"and will not be used for tracking or zone enter/exit events" f"{CRLF_DOT}{Device.fname_devicename}{RARROW}{entity_id}" f"{more_info('mobapp_device_unavailable')}") - post_event(alert_msg) log_error_msg(f"iCloud3 Error ({Device.fname_devtype}) > " f"The Mobile App is not available and this device will not be monitored") return None @@ -434,12 +433,11 @@ def get_mobapp_device_trkr_entity_attrs(Device): if LATITUDE not in device_trkr_attrs or device_trkr_attrs[LATITUDE] == 0: Device.mobapp_data_invalid_error_cnt += 1 if Device.mobapp_data_invalid_error_cnt == 4: - alert_msg =(f"{EVLOG_ALERT}The Mobile App has not reported the gps " + post_event( f"{EVLOG_ALERT}The Mobile App has not reported the gps " f"location after 4 requests. It may be asleep, offline " f"or not available and should be reviewed." f"{CRLF_DOT}{Device.fname_devicename}{RARROW}{entity_id}" f"{more_info('mobapp_device_no_location')}") - post_event(alert_msg) log_error_msg(f"iCloud3 Alert ({Device.fname_devtype}) > " f"The Mobile App has not reported the gps location after 4 requests. " f"It may be asleep, offline or not available.") diff --git a/custom_components/icloud3/support/mobapp_interface.py b/custom_components/icloud3/support/mobapp_interface.py index a667b96..2d96da6 100644 --- a/custom_components/icloud3/support/mobapp_interface.py +++ b/custom_components/icloud3/support/mobapp_interface.py @@ -100,8 +100,8 @@ def get_entity_registry_mobile_app_devices(): battery_state_sensors_by_mobapp_devicename = _extract_sensor_entities( mobapp_devicename_by_mobapp_id, battery_state_sensors) - Gb.debug_log['_.mobapp_id_by_mobapp_devicename'] = mobapp_id_by_mobapp_devicename - Gb.debug_log['_.mobapp_devicename_by_mobapp_id'] = mobapp_devicename_by_mobapp_id + Gb.debug_log['_.mobapp_id_by_mobapp_devicename'] = {k: v[:10] for k, v in mobapp_id_by_mobapp_devicename.items()} + Gb.debug_log['_.mobapp_devicename_by_mobapp_id'] = {k[:10]: v for k, v in mobapp_devicename_by_mobapp_id.items()} Gb.debug_log['_.last_updt_trig_by_mobapp_devicename'] = last_updt_trig_by_mobapp_devicename Gb.debug_log['_.battery_level_sensors_by_mobapp_devicename'] = battery_level_sensors_by_mobapp_devicename Gb.debug_log['_.battery_state_sensors_by_mobapp_devicename'] = battery_state_sensors_by_mobapp_devicename @@ -206,9 +206,9 @@ def send_message_to_device(Device, service_data): return if service_data.get('message') != "request_location_update": - evlog_msg = (f"{EVLOG_NOTICE}Sending Message to Device > " + post_event(Device, + f"{EVLOG_NOTICE}Sending Message to Device > " f"Message-{service_data.get('message')}") - post_event(Device, evlog_msg) Gb.hass.services.call("notify", Device.mobapp[NOTIFY], service_data) @@ -273,7 +273,7 @@ def request_location(Device, is_alive_check=False, force_request=False): f"LastLocated-{format_time_age(Device.mobapp_data_secs)}") if Device.old_loc_cnt > 2: event_msg += f", OldThreshold-{format_timer(Device.old_loc_threshold_secs)}" - post_event(devicename, event_msg) + post_event(Device, event_msg) if Device.mobapp_request_loc_first_secs == 0: Device.mobapp_request_loc_first_secs = Gb.this_update_secs @@ -291,8 +291,7 @@ def request_location(Device, is_alive_check=False, force_request=False): else: Device.mobapp_request_loc_last_secs = 0 Device.mobapp_request_loc_sent_secs = 0 - event_msg = f"{EVLOG_NOTICE}{event_msg} > Failed to send message" - post_event(devicename, event_msg) + post_event(Device, f"{EVLOG_NOTICE}{event_msg} > Failed to send message") except Exception as err: log_exception(err) diff --git a/custom_components/icloud3/support/pyicloud_ic3.py b/custom_components/icloud3/support/pyicloud_ic3.py index 107087b..a3b1dc9 100644 --- a/custom_components/icloud3/support/pyicloud_ic3.py +++ b/custom_components/icloud3/support/pyicloud_ic3.py @@ -45,7 +45,6 @@ from uuid import uuid1 from requests import Session, adapters -from tempfile import gettempdir from os import path, mkdir from re import match import inspect @@ -453,6 +452,7 @@ def __init__( self, apple_id, password=None, self.requires_2fa = False # This is set during the authentication function self.token_password = password self.account_locked = False # set from the locked data item when authenticating with a token + self.account_name = '' self.verify_password = verify_password self.update_requested_by = '' self.endpoint_suffix = endpoint_suffix if endpoint_suffix else Gb.icloud_server_endpoint_suffix @@ -491,7 +491,8 @@ def __init__( self, apple_id, password=None, return if 'Authenticate' in self.init_step_needed: - post_monitor_msg(f"AUTHENTICATING iCloud Account Access, {obscure_field(apple_id)} ({instance})") + post_monitor_msg(f"AUTHENTICATING iCloud Account Access, {self.account_name} " + f"({obscure_field(apple_id)}), {instance}") self._set_step_inprocess('Authenticate') self.authenticate() self._set_step_completed('Authenticate') @@ -599,7 +600,8 @@ def authenticate(self, refresh_session=False, service=None): if "canLaunchWithOneFactor" in app and app["canLaunchWithOneFactor"] == True: log_debug_msg( f"AUTHENTICATING iCloud Account Access, " - f"{obscure_field(self.user['accountName'])}, " + f"{self.account_name} " + f"({obscure_field(self.user['accountName'])}), " f"Service-{service}") if self._authenticate_with_password_service(service): @@ -608,7 +610,8 @@ def authenticate(self, refresh_session=False, service=None): # Authenticate - Sign into icloud account (POST=/signin) if login_successful is False: - info_msg = f"Authenticating account {obscure_field(self.user['accountName'])} with token" + info_msg = (f"Authenticating account {self.account_name} " + f"({obscure_field(self.user['accountName'])}) with token") #if self.endpoint_suffix != '': if self.endpoint_suffix: info_msg += f", iCloudServerCountrySuffix-'{self.endpoint_suffix}' " @@ -667,7 +670,10 @@ def _authenticate_with_token(self): self.data = req.json() if 'dsInfo' in self.data: - self.account_locked = self.data['dsInfo'].get('locked', False) + _traceha(f"{self.account_name=} {self.data['dsInfo']=}") + if 'fullName' in self.data['dsInfo']: + self.account_name = self.data['dsInfo']['fullName'] + self.account_locked = self.data['dsInfo']['locked'] if 'webservices' not in self.data: if (self.data.get('success', False) is False @@ -1291,10 +1297,9 @@ def __init__(self, PyiCloud, log_exception(err) if self.is_service_not_available: - log_msg = ( f"{EVLOG_ALERT}iCLOUD ALERT > Family Sharing Data Source is not available. " + post_event( f"{EVLOG_ALERT}iCLOUD ALERT > Family Sharing Data Source is not available. " f"The web url providing location data returned a Service Not Available error " f"({self.PyiCloud.instance})") - post_event(log_msg) return fmip_endpoint = f"{service_root}/fmipservice/client/web" @@ -1411,10 +1416,9 @@ def refresh_client(self, requested_by_devicename=None, _device_id=None, if self.Session.response_status_code == 501: self._set_service_available(False) - log_msg = ( f"{EVLOG_ALERT}iCLOUD ALERT > Family Sharing Data Source is not available. " + post_event( f"{EVLOG_ALERT}iCLOUD ALERT > Family Sharing Data Source is not available. " f"The web url providing location data returned a Service Not Available error " f"({self.PyiCloud.instance})") - post_event(log_msg) return None Gb.pyicloud_refresh_time[FAMSHR] = time_now_secs() @@ -1438,21 +1442,32 @@ def update_device_location_data(self, requested_by_devicename=None, devices_data monitor_msg = f"UPDATED FamShr Data > RequestedBy-{requested_by_devicename}" for device_data in devices_data: + + # TEST CODE - Create duplicate device + # if device_data[NAME] == 'Gary-iPad': + # device_data[NAME] = 'Lillian-iPad' + # device_data[LOCATION] = {} + + device_data[NAME] = device_data_name = \ PyiCloud_RawData._remove_special_chars(device_data[NAME]) device_id = device_data[ID] + rawdata_hdr_msg = '' if (device_data_name in Gb.conf_famshr_devicenames and Gb.start_icloud3_inprocess_flag): pass + # only check tracked/monitored devices for location data elif (LOCATION not in device_data or device_data[LOCATION] == {} or device_data[LOCATION] is None): if device_id not in Gb.devices_without_location_data: Gb.devices_without_location_data.append(device_id) + rawdata_hdr_msg = 'NO LOCATION' if device_data[ICLOUD_DEVICE_STATUS] == 203: + rawdata_hdr_msg += ', OFFLINE' monitor_msg += f"{CRLF_STAR}OFFLINE > " else: monitor_msg += f"{CRLF_STAR}NO LOCATION > " @@ -1460,8 +1475,8 @@ def update_device_location_data(self, requested_by_devicename=None, devices_data f"{device_data['modelDisplayName']} " f"({device_data['rawDeviceModel']})") - log_rawdata(f"FamShr Device - Offline/No Location Data, {self.instance} " - f"<{device_data_name}>", device_data) + # log_rawdata(f"FamShr Device - Offline/No Location Data, {self.instance} " + # f"<{device_data_name}>", device_data) if device_id not in self.PyiCloud.RawData_by_device_id: # if device_data_name == 'Gary-iPad': @@ -1472,19 +1487,20 @@ def update_device_location_data(self, requested_by_devicename=None, devices_data continue # Non-tracked devices are not updated - if device_data_name not in Gb.devicenames_x_famshr_devices: + _RawData = self.PyiCloud.RawData_by_device_id[device_id] + _Device = _RawData.Device + if _RawData.Device is None: continue - _RawData = self.PyiCloud.RawData_by_device_id[device_id] _RawData.save_new_device_data(device_data) - devicename = Gb.devicenames_x_famshr_devices[device_data_name] - _Device = Gb.Devices_by_devicename[devicename] - Gb.Devices_by_icloud_device_id[device_id] = _Device - - if _RawData.location_secs ==0: + if _RawData.location_secs == 0: continue - elif _RawData.last_loc_time_gps == _RawData.loc_time_gps: + + log_rawdata(f"FamShr Data, {rawdata_hdr_msg} {self.instance} - " + f"<{device_data_name}/{_Device.devicename}>", _RawData.device_data) + + if _RawData.last_loc_time_gps == _RawData.loc_time_gps: last_loc_time_gps_msg = last_loc_time_msg = '' else: last_loc_time_gps_msg = f"{_RawData.last_loc_time_gps}{RARROW}" @@ -1512,8 +1528,7 @@ def update_device_location_data(self, requested_by_devicename=None, devices_data elif _RawData.location_secs > 0: post_event(_Device.devicename, event_msg) - log_rawdata(f"FamShr Data, {self.instance} - " - f"<{device_data_name}/{_Device.devicename}>", _RawData.device_data) + except Exception as err: log_exception(err) @@ -1563,6 +1578,7 @@ def _create_RawData_famshr_object(self, device_id, device_data_name, device_data self.set_famshr_rawdata_fields(device_id, _RawData) + log_debug_msg(f"Create RawData_famshr object {device_data_name}") log_rawdata(f"FamShr Data - <{_RawData.fname}>", _RawData.device_data) dup_msg = f" as {_RawData.fname}" if _RawData.fname_dup_suffix else '' @@ -1767,10 +1783,9 @@ def __init__(self, PyiCloud, self.is_service_available = False self.is_service_not_available = True if self.is_service_not_available: - # log_msg = ( f"{EVLOG_ALERT}iCLOUD ALERT > Find-my-Friends Data Source is not available. " + # post_event( f"{EVLOG_ALERT}iCLOUD ALERT > Find-my-Friends Data Source is not available. " # f"The web url providing location data returned a Service Not Available error " # f"({self.PyiCloud.instance})") - # post_event(log_msg) return self._friend_endpoint = f"{self._service_root}/fmipservice/client/fmfWeb/initClient" @@ -1778,10 +1793,9 @@ def __init__(self, PyiCloud, self.refresh_client() if self.is_service_not_available: - log_msg = ( f"{EVLOG_ALERT}iCLOUD ALERT > Find-my-Friends Data Source is not available. " + post_event( f"{EVLOG_ALERT}iCLOUD ALERT > Find-my-Friends Data Source is not available. " f"The web url providing location data returned a Service Not Available error " f"({self.PyiCloud.instance})") - post_event(log_msg) return self._update_fmf_email_tables() @@ -1790,11 +1804,10 @@ def __init__(self, PyiCloud, if devices_not_set_up == '': return - log_msg = ( f"{EVLOG_NOTICE}iCloud3 Notice > Some FmF devices were not " + post_event( f"{EVLOG_NOTICE}iCloud3 Notice > Some FmF devices were not " f"initialized, data was not received from iCloud " f"Location Svcs. Retrying..." f"{devices_not_set_up}") - post_event(log_msg) if self.PyiCloud.instance == 'initial': self.PyiCloud.init_step_needed.append('FmF') @@ -1805,13 +1818,11 @@ def __init__(self, PyiCloud, devices_not_set_up = self._conf_fmf_devices_not_set_up() if devices_not_set_up == '': - log_msg = f"{EVLOG_NOTICE}Find-my-Friends initialization retry successful" - post_event(log_msg) + post_event(f"{EVLOG_NOTICE}Find-my-Friends initialization retry successful") return - log_msg = ( f"{EVLOG_ALERT}iCLOUD ALERT > Find-my-Friends initialization retry failed " + post_event( f"{EVLOG_ALERT}iCLOUD ALERT > Find-my-Friends initialization retry failed " f"{devices_not_set_up}") - post_event(log_msg) #---------------------------------------------------------------------------- def _set_service_available(self, available): @@ -2119,8 +2130,11 @@ def __init__(self, device_id, self.fname_dup_suffix= '' # Suffix added to fname if duplicates self.evlog_alert_char= '' - self.Device = Gb.Devices_by_icloud_device_id.get(device_id) - self.ic3_devicename = self.Device.devicename if self.Device else '' + # self.Device = Gb.Devices_by_icloud_device_id.get(device_id) + # self.ic3_devicename = self.Device.devicename if self.Device else '' + self.ic3_devicename = Gb.devicenames_x_famshr_devices.get(self.fname, '') + self.Device = Gb.Devices_by_devicename.get(self.ic3_devicename) + self.update_secs = time_now_secs() self.location_secs = 0 self.location_time = HHMMSS_ZERO diff --git a/custom_components/icloud3/support/pyicloud_ic3_interface.py b/custom_components/icloud3/support/pyicloud_ic3_interface.py index 9b81ec4..a12fa1a 100644 --- a/custom_components/icloud3/support/pyicloud_ic3_interface.py +++ b/custom_components/icloud3/support/pyicloud_ic3_interface.py @@ -101,14 +101,13 @@ def verify_pyicloud_setup_status(): return True if Gb.get_FAMSHR_devices_retry_cnt == 0: - event_msg = f"iCloud Location Svcs > Setup Complete" - post_event(event_msg) + post_event(f"iCloud Location Svcs > Setup Complete") return else: if Gb.PyiCloud.FamilySharing: Gb.PyiCloud.FamilySharing.refresh_client() - event_msg = f"iCloud Location Svcs > Refreshing FamShr Data (#{Gb.get_FAMSHR_devices_retry_cnt})" - post_event(event_msg) + post_event( f"iCloud Location Svcs > Refreshing FamShr Data " + f"(#{Gb.get_FAMSHR_devices_retry_cnt})") return True else: Gb.PyiCloudInit.init_step_needed = ['FamShr'] @@ -312,21 +311,20 @@ def check_all_devices_online_status(): elif Device.is_offline: if Device.offline_secs == 0: Device.offline_secs = Gb.this_update_secs - event_msg = ( f"Device Offline and not available > " - f"OfflineSince-{format_time_age(Device.offline_secs)}") - post_event(Device, event_msg) + post_event(Device, + f"Device Offline and not available > " + f"OfflineSince-{format_time_age(Device.offline_secs)}") elif Device.is_pending: if Device.pending_secs == 0: Device.pending_secs = Gb.this_update_secs - event_msg = ( f"Device status is Pending/Unknown > " - f"PendingSince-{format_time_age(Device.pending_secs)}") - post_event(Device, event_msg) + post_event(Device, + f"Device status is Pending/Unknown > " + f"PendingSince-{format_time_age(Device.pending_secs)}") if any_device_online_flag == False: - event_msg = ( f"All Devices are offline or have a pending status. " - f"They may be in AirPlane Mode and not available") - post_event(event_msg) + post_event( f"All Devices are offline or have a pending status. " + f"They may be in AirPlane Mode and not available") #-------------------------------------------------------------------- def new_2fa_authentication_code_requested(PyiCloud, initial_setup=False): @@ -389,11 +387,10 @@ def pyicloud_reset_session(PyiCloud=None): Gb.authentication_alert_displayed_flag = True if requested_by == ' (Apple)': - alert_msg = (f"{EVLOG_NOTICE}Select `HA Notifications Bell`, then Select `Integration Requires " - f"Reconfiguration > Check it out`, then `iCloud3 > Reconfigure`." - f"{CRLF}Note: If the code is not accepted or has expired, request a " - f"new code and try again") - post_event(alert_msg) + post_event( f"{EVLOG_NOTICE}Select `HA Notifications Bell`, then Select `Integration Requires " + f"Reconfiguration > Check it out`, then `iCloud3 > Reconfigure`." + f"{CRLF}Note: If the code is not accepted or has expired, request a " + f"new code and try again") post_event(f"{EVLOG_NOTICE}iCLOUD ALERT > Apple ID Verification is needed {requested_by}") post_event(f"{EVLOG_NOTICE}Resetting iCloud Session Files") diff --git a/custom_components/icloud3/support/restore_state.py b/custom_components/icloud3/support/restore_state.py index 6b3fc94..87d9b95 100644 --- a/custom_components/icloud3/support/restore_state.py +++ b/custom_components/icloud3/support/restore_state.py @@ -8,7 +8,7 @@ LAST_ZONE, LAST_ZONE_DNAME, LAST_ZONE_FNAME, LAST_ZONE_NAME, DIR_OF_TRAVEL, ) -from ..helpers.common import (instr, ) +from ..helpers.common import (instr, load_json_file, save_json_file, ) from ..helpers.messaging import (log_info_msg, log_debug_msg, log_exception, _trace, _traceha, ) from ..helpers.time_util import (datetime_now, ) @@ -84,27 +84,33 @@ def read_storage_icloud3_restore_state_file(): ''' try: - with open(Gb.icloud3_restore_state_filename, 'r') as f: - Gb.restore_state_file_data = json.load(f) - Gb.restore_state_profile = Gb.restore_state_file_data['profile'] - Gb.restore_state_devices = Gb.restore_state_file_data['devices'] + Gb.restore_state_file_data = load_json_file(Gb.icloud3_restore_state_filename) - for devicename, devicename_data in Gb.restore_state_devices.items(): - sensors = devicename_data['sensors'] - sensors[DISTANCE_TO_OTHER_DEVICES] = {} - sensors[DISTANCE_TO_OTHER_DEVICES_DATETIME] = HHMMSS_ZERO - sensors[ALERT] = '' + if Gb.restore_state_file_data == {}: + return False - _reset_statzone_values_to_away(sensors) + # with open(Gb.icloud3_restore_state_filename, 'r') as f: + # Gb.restore_state_file_data = json.load(f) - from_zones = devicename_data['from_zone'] - for from_zone, from_zone_sensors in from_zones.items(): - _reset_from_zone_statzone_values_to_away(from_zone_sensors) + Gb.restore_state_profile = Gb.restore_state_file_data['profile'] + Gb.restore_state_devices = Gb.restore_state_file_data['devices'] + + for devicename, devicename_data in Gb.restore_state_devices.items(): + sensors = devicename_data['sensors'] + sensors[DISTANCE_TO_OTHER_DEVICES] = {} + sensors[DISTANCE_TO_OTHER_DEVICES_DATETIME] = HHMMSS_ZERO + sensors[ALERT] = '' + + _reset_statzone_values_to_away(sensors) + + from_zones = devicename_data['from_zone'] + for from_zone, from_zone_sensors in from_zones.items(): + _reset_from_zone_statzone_values_to_away(from_zone_sensors) return True - except json.decoder.JSONDecodeError: - pass + # except json.decoder.JSONDecodeError: + # pass except Exception as err: log_exception(err) return False @@ -117,15 +123,15 @@ def write_storage_icloud3_restore_state_file(): Update the config/.storage/.icloud3.restore_state file ''' - try: - with open(Gb.icloud3_restore_state_filename, 'w', encoding='utf8') as f: - Gb.restore_state_profile['last_update'] = datetime_now() - Gb.restore_state_file_data['profile'] = Gb.restore_state_profile - Gb.restore_state_file_data['devices'] = Gb.restore_state_devices - - json.dump(Gb.restore_state_file_data, f, indent=4) + Gb.restore_state_profile['last_update'] = datetime_now() + Gb.restore_state_file_data['profile'] = Gb.restore_state_profile + Gb.restore_state_file_data['devices'] = Gb.restore_state_devices - return True + try: + # with open(Gb.icloud3_restore_state_filename, 'w', encoding='utf8') as f: + # json.dump(Gb.restore_state_file_data, f, indent=4) + success = save_json_file(Gb.icloud3_restore_state_filename, Gb.restore_state_file_data) + return success except Exception as err: log_exception(err) diff --git a/custom_components/icloud3/support/service_handler.py b/custom_components/icloud3/support/service_handler.py index 8560f48..dcd99ae 100644 --- a/custom_components/icloud3/support/service_handler.py +++ b/custom_components/icloud3/support/service_handler.py @@ -435,8 +435,7 @@ def handle_action_log_level(action_option, change_conf_log_level=True): start_ic3.update_conf_file_log_level(new_log_level) log_level_fname = new_log_level.replace('-', ' ').title() - event_msg = f"Log Level Change > New Level: {log_level_fname}" - post_event(event_msg) + post_event(f"Log Level Change > New Level: {log_level_fname}") def _on_off_text(condition): return 'On' if condition else 'Off' diff --git a/custom_components/icloud3/support/start_ic3.py b/custom_components/icloud3/support/start_ic3.py index 2a07531..448a863 100644 --- a/custom_components/icloud3/support/start_ic3.py +++ b/custom_components/icloud3/support/start_ic3.py @@ -66,8 +66,8 @@ from ..support import service_handler from ..support import zone_handler from ..support import stationary_zone as statzone -from ..support.waze import Waze -from ..support.waze_history import WazeRouteHistory as WazeHist +from .waze import Waze +from .waze_history import WazeRouteHistory as WazeHist from ..helpers.common import (instr, format_gps, circle_letter, zone_dname, is_statzone, isnot_statzone, list_to_str, list_add, list_del, ) from ..helpers.messaging import (broadcast_info_msg, @@ -522,6 +522,7 @@ def initialize_icloud_data_source(): Gb.get_FAMSHR_devices_retry_cnt = 0 +#------------------------------------------------------------------------------ def icloud_server_endpoint_suffix(endpoint_suffix): ''' Determine the suffix to be used based on the country_code and the value of the @@ -1293,10 +1294,11 @@ def create_Devices_object(): except Exception as err: log_exception(err) - Gb.debug_log['Gb.Devices'] = Gb.Devices - Gb.debug_log['Gb.DevDevices_by_devicename'] = Gb.Devices_by_devicename - Gb.debug_log['Gb.conf_devicenames'] = Gb.conf_devicenames - Gb.debug_log['Gb.conf_famshr_devicenames'] = Gb.conf_famshr_devicenames + Gb.debug_log['Gb.Devices'] = Gb.Devices + Gb.debug_log['Gb.DevDevices_by_devicename'] = Gb.Devices_by_devicename + Gb.debug_log['Gb.conf_devicenames'] = Gb.conf_devicenames + Gb.debug_log['Gb.conf_famshr_devicenames'] = Gb.conf_famshr_devicenames + Gb.debug_log['Gb.devicenames_x_famshr_devices'] = Gb.devicenames_x_famshr_devices return @@ -1390,27 +1392,30 @@ def setup_tracked_devices_for_famshr(PyiCloud=None): return post_event(f"iCloud Location Service interface > Selected ({Gb.PyiCloud.instance})") - Gb.debug_log['Gb.PyiCloud.device_id_by_famshr_fname'] = {k: v[:10] for k, v in Gb.PyiCloud.device_id_by_famshr_fname.items()} - Gb.debug_log['Gb.PyiCloud.device_id_by_famshr_fname'] = {k[:10]: v for k, v in Gb.PyiCloud.device_id_by_famshr_fname.items()} _check_renamed_famshr_devices(_FamShr) _check_conf_famshr_devices_not_set_up(_FamShr) _check_duplicate_device_names(PyiCloud, _FamShr) _display_devices_verification_status(PyiCloud, _FamShr) + Gb.debug_log['Gb.PyiCloud.device_id_by_famshr_fname'] = {k: v[:10] for k, v in Gb.PyiCloud.device_id_by_famshr_fname.items()} + Gb.debug_log['Gb.PyiCloud.famshr_fname_by_device_id'] = {k[:10]: v for k, v in Gb.PyiCloud.famshr_fname_by_device_id.items()} + Gb.debug_log['Gb.Devices_by_icloud_device_id'] = {k[:10]: v for k, v in Gb.Devices_by_icloud_device_id.items()} + #---------------------------------------------------------------------------- def _check_renamed_famshr_devices(_FamShr): ''' Return with a list of famshr devices in the conf_devices that are not in _RawData ''' - renamed_devices = [(f"{conf_device[CONF_IC3_DEVICENAME]} > " - f"Renamed: {conf_device[CONF_FAMSHR_DEVICENAME]} " - f"{RARROW}{Gb.PyiCloud.device_id_by_famshr_fname[conf_device[CONF_FAMSHR_DEVICE_ID]]}") + renamed_devices = \ + [( f"{conf_device[CONF_IC3_DEVICENAME]} > " + f"Renamed: {conf_device[CONF_FAMSHR_DEVICENAME]} " + f"{RARROW}{Gb.PyiCloud.famshr_fname_by_device_id[conf_device[CONF_FAMSHR_DEVICE_ID]]}") for conf_device in Gb.conf_devices - if (conf_device[CONF_FAMSHR_DEVICE_ID] in Gb.PyiCloud.device_id_by_famshr_fname) + if (conf_device[CONF_FAMSHR_DEVICE_ID] in Gb.PyiCloud.famshr_fname_by_device_id) and conf_device[CONF_FAMSHR_DEVICENAME] != \ - Gb.PyiCloud.device_id_by_famshr_fname[conf_device[CONF_FAMSHR_DEVICE_ID]]] + Gb.PyiCloud.famshr_fname_by_device_id[conf_device[CONF_FAMSHR_DEVICE_ID]]] if renamed_devices == []: return @@ -1467,12 +1472,16 @@ def _check_conf_famshr_devices_not_set_up(_FamShr): Gb.debug_log['_.devices_not_set_up'] = devices_not_set_up + for devices_msg in devices_not_set_up: + devicename = devices_msg.split(' >')[0] + Device = Gb.Devices_by_devicename[devicename] + Device.set_fname_alert(YELLOW_ALERT) + devices_not_set_up_str = list_to_str(devices_not_set_up, CRLF_X) post_startup_alert( f"FamShr Config Error > Device not found" f"{devices_not_set_up_str.replace(CRLF_X, CRLF_DOT)}") - if _FamShr.devices_cnt == -1: - post_event( f"{EVLOG_ALERT}FAMSHR DEVICES ERROR > Your Apple iCloud Account Family Sharing List did " + post_event( f"{EVLOG_ALERT}FAMSHR DEVICES ERROR > Your Apple iCloud Account Family Sharing List did " f"not return any information for some of configured devices. FamShr will not be used " f"to track these devices." f"{devices_not_set_up_str}" @@ -1700,6 +1709,13 @@ def _check_duplicate_device_names(PyiCloud, _FamShr): f"Located-{format_age(_RawData.location_secs)} " f"({_RawData.device_data['rawDeviceModel']})") + # devicename = Gb.devicenames_x_famshr_devices.get(famshr_fname, '') + # _Device = Gb.Devices_by_devicename.get(devicename) + + if _RawData.Device: + _RawData.Device.set_fname_alert(YELLOW_ALERT) + post_startup_alert(f"Duplicate FamShr device found - {famshr_fname}") + if famshr_fname_base in famshr_fname_last_located_by_base_fname: dup_devices_msg += (f"{CRLF_HDOT}Last Located > {famshr_fname_last_located_by_base_fname[famshr_fname_base]}") except: @@ -1710,8 +1726,8 @@ def _check_duplicate_device_names(PyiCloud, _FamShr): if dup_devices_msg == "": return dups_found_msg =(f"{EVLOG_ALERT}DUPLICATE FAMSHR DEVICES > There are several devices in the " - f"iCloud Account Family Sharing list with the same or similar names. The unused devices should be reviewed and " - f"removed. The Devices are:" + f"iCloud Account Family Sharing list with the same or similar names. " + f"The unused devices should be reviewed and removed. The Devices are:" f"{dup_devices_msg}") # Cycle thru dup names, get conf_devices entry for the one matching the famshr_fname_base and update it @@ -2686,6 +2702,25 @@ def display_object_lists(): monitor_msg = (f"Zones-{list_to_str(Gb.Zones_by_zone.keys())}") post_monitor_msg(monitor_msg) +#-------------------------------------------------------------------- +def write_debug_log(debug_log_title=None): + ''' + Cycle thru the Gb.debug_log dictionary that contains internal lists and + dictionaries. Write all items to the icloud3-0.log file + ''' + if Gb.log_debug_flag is False or Gb.debug_log == {}: return + + if debug_log_title: + log_debug_msg(f"{format_header_box(debug_log_title)}") + + for field, values in Gb.debug_log.items(): + log_debug_msg(f"{field}={values}") + + if debug_log_title: + log_debug_msg(f"{format_header_box(debug_log_title)}") + + Gb.debug_log = {} + #------------------------------------------------------------------------------ def display_platform_operating_mode_msg(): if Gb.ha_config_platform_stmt is False: diff --git a/custom_components/icloud3/support/start_ic3_control.py b/custom_components/icloud3/support/start_ic3_control.py index 348eaf4..4f4f78d 100644 --- a/custom_components/icloud3/support/start_ic3_control.py +++ b/custom_components/icloud3/support/start_ic3_control.py @@ -21,7 +21,7 @@ log_start_finish_update_banner, log_debug_msg, log_warning_msg, log_info_msg, log_exception, log_rawdata, _trace, _traceha, more_info, format_filename, - write_debug_log, write_config_file_to_ic3log, + write_config_file_to_ic3log, open_ic3log_file, ) from ..helpers.time_util import (time_now_secs, calculate_time_zone_offset, ) @@ -147,7 +147,7 @@ def stage_2_prepare_configuration(): except Exception as err: log_exception(err) - write_debug_log() + #write_debug_log() #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> def stage_3_setup_configured_devices(): @@ -184,7 +184,7 @@ def stage_3_setup_configured_devices(): except Exception as err: log_exception(err) - write_debug_log() + #write_debug_log() post_event(f"{EVLOG_IC3_STAGE_HDR}{stage_title}") Gb.EvLog.update_event_log_display("") @@ -203,9 +203,8 @@ def stage_4_setup_data_sources(retry=False): Gb.conf_data_source_FMF = False Gb.primary_data_source_ICLOUD = False post_startup_alert('iCloud username/password invalid or not set up') - event_msg =(f"{EVLOG_ALERT}CONFIGURATION ALERT > The iCloud username or password has not been " + post_event( f"{EVLOG_ALERT}CONFIGURATION ALERT > The iCloud username or password has not been " f"set up or is incorrect. iCloud will not be used for location tracking") - post_event(event_msg) return_code = True Gb.EvLog.display_user_message(stage_title) @@ -213,7 +212,9 @@ def stage_4_setup_data_sources(retry=False): try: if Gb.primary_data_source_ICLOUD: - post_event(f"iCloud Account > Logged Into-{obscure_field(Gb.username)}") + account_name = Gb.PyiCloud.account_name if Gb.PyiCloud else '' + post_event(f"iCloud Account > Logging Into-{account_name} " + f"({obscure_field(Gb.username)})") start_ic3.setup_data_source_ICLOUD() if Gb.PyiCloud is None: @@ -235,7 +236,7 @@ def stage_4_setup_data_sources(retry=False): log_exception(err) return_code = False - write_debug_log() + # write_debug_log() post_event(f"{EVLOG_IC3_STAGE_HDR} {stage_title}") Gb.EvLog.update_event_log_display("") @@ -304,7 +305,7 @@ def stage_5_configure_tracked_devices(): except Exception as err: log_exception(err) - write_debug_log() + # write_debug_log() post_event(f"{EVLOG_IC3_STAGE_HDR}{stage_title}") Gb.EvLog.display_user_message('') @@ -325,6 +326,7 @@ def stage_6_initialization_complete(): try: start_ic3.display_object_lists() + start_ic3.write_debug_log() if Gb.startup_alerts: item_no = 1 @@ -340,10 +342,9 @@ def stage_6_initialization_complete(): Gb.startup_alerts_str = alerts_str Gb.EvLog.alert_message = 'Problems occured during startup up that should be reviewed' - alert_msg = (f"{EVLOG_ALERT}The following issues were detected when starting iCloud3. " + post_event( f"{EVLOG_ALERT}The following issues were detected when starting iCloud3. " f"Scroll through the Startup Log for more information: " f"{alert_msg}") - post_event(alert_msg) except Exception as err: log_exception(err) @@ -375,8 +376,7 @@ def stage_7_initial_locate(): Gb.this_update_secs = time_now_secs() Gb.this_update_time = dt_util.now().strftime('%H:%M:%S') post_event("Requesting Initial Locate") - event_msg =(f"{EVLOG_IC3_STARTING}iCloud3 v{Gb.version} > Start up Complete") - post_event(event_msg) + post_event(f"{EVLOG_IC3_STARTING}iCloud3 v{Gb.version} > Start up Complete") for Device in Gb.Devices: if Device.PyiCloud_RawData_famshr: @@ -389,13 +389,12 @@ def stage_7_initial_locate(): else: continue - event_msg =(f"{Device.dev_data_source} Trigger > Initial Locate@" + post_event(Device, + f"{Device.dev_data_source} Trigger > Initial Locate@" f"{Device.loc_data_time_gps}") - post_event(Device, event_msg) if Device.no_location_data: - event_msg = f"{EVLOG_ALERT}NO GPS DATA RETURNED FROM ICLOUD LOCATION SERVICE" - post_event(Device, event_msg) + post_event(Device, f"{EVLOG_ALERT}NO GPS DATA RETURNED FROM ICLOUD LOCATION SERVICE") error_msg = (f"iCloud3 > {Device.fname_devicename} > " "No GPS data was returned from iCloud Location " "Service on the initial locate") @@ -438,8 +437,7 @@ def reinitialize_icloud_devices(): post_event(alert_msg) - event_msg =(f"{EVLOG_IC3_STARTING}Restarting iCloud Location Service") - post_event(event_msg) + post_event(f"{EVLOG_IC3_STARTING}Restarting iCloud Location Service") if Gb.PyiCloud and Gb.PyiCloud.FamilySharing: Gb.PyiCloud.FamilySharing.refresh_client() @@ -454,10 +452,9 @@ def reinitialize_icloud_devices(): Gb.all_tracking_paused_flag = False if stage_4_success is False: - alert_msg =(f"{EVLOG_ALERT}UNVERIFIED DEVICES > One or more devices was still " + post_event( f"{EVLOG_ALERT}UNVERIFIED DEVICES > One or more devices was still " f"not verified" f"{more_info('unverified_devices_caused_by')}") - post_event(alert_msg) return False diff --git a/custom_components/icloud3/support/stationary_zone.py b/custom_components/icloud3/support/stationary_zone.py index b901964..2f25fd9 100644 --- a/custom_components/icloud3/support/stationary_zone.py +++ b/custom_components/icloud3/support/stationary_zone.py @@ -177,9 +177,9 @@ def exit_statzone(Device): remove_statzone(StatZone, Device) - event_msg =(f"Will Remove Stationary Zone > {StatZone.dname}, " + post_event(Device, + f"Will Remove Stationary Zone > {StatZone.dname}, " f"LastUsedBy-{Device.fname}") - post_event(Device, event_msg) #-------------------------------------------------------------------- def kill_and_recreate_unuseable_statzone(Device): @@ -205,9 +205,9 @@ def kill_and_recreate_unuseable_statzone(Device): for _Device in Devices_in_statzone: _Device.StatZone = _StatZone - event_msg =(f"Reassigned Stationary Zone > {StatZone.dname}{RARROW}" + post_event(_Device, + f"Reassigned Stationary Zone > {StatZone.dname}{RARROW}" f"{_StatZone.dname}") - post_event(_Device.devicename, event_msg) remove_statzone(StatZone) @@ -259,9 +259,9 @@ def remove_statzone(StatZone, Device=None): if Device: clear_statzone_timer_distance(Device) - event_msg =(f"Exited Stationary Zone > {StatZone.dname}, " + post_event(Device, + f"Exited Stationary Zone > {StatZone.dname}, " f"DevicesRemaining-{devices_in_statzone_count(StatZone)}") - post_event(Device, event_msg) #-------------------------------------------------------------------- def ha_statzones(): @@ -289,13 +289,11 @@ def _trigger_monitored_device_update(StatZone, Device, action): if action == ENTER_ZONE and _Device.StatZone is None: dist_apart_m = _Device.distance_m(Device.loc_data_latitude, Device.loc_data_longitude) if dist_apart_m <= Gb.statzone_radius_m: - event_msg = f"Trigger > Enter New Stationary Zone > {StatZone.dname}" - post_event(_Device.devicename, event_msg) + post_event(_Device, f"Trigger > Enter New Stationary Zone > {StatZone.dname}") elif action == EXIT_ZONE and _Device.StatZone is StatZone: _Device.StatZone = None - event_msg = f"Trigger > Exit Removed Stationary Zone > {StatZone.dname}" - post_event(_Device.devicename, event_msg) + post_event(_Device, f"Trigger > Exit Removed Stationary Zone > {StatZone.dname}") else: continue diff --git a/custom_components/icloud3/support/waze.py b/custom_components/icloud3/support/waze.py index 8a03dee..c499b26 100644 --- a/custom_components/icloud3/support/waze.py +++ b/custom_components/icloud3/support/waze.py @@ -166,9 +166,9 @@ def get_route_time_distance(self, Device, FromZone, check_hist_db=True): ZONE) if waze_status == WAZE_NO_DATA: - event_msg = (f"Waze Route Error > Problem connecting to Waze Servers. " + post_event(Device, + f"Waze Route Error > Problem connecting to Waze Servers. " f"Distance will be calculated, Travel Time not available") - post_event(Device, event_msg) return (WAZE_NO_DATA, 0, 0, 0) @@ -369,9 +369,8 @@ def _set_waze_not_available_error(self, err): self.waze_status = WAZE_NOT_USED err = "A problem occurred connecting to `www.waze.com`. Waze is not available at this time" - log_msg = (f"{EVLOG_ALERT}Alert > Waze Connection Error, Region-{self.waze_region} > {err}. " + post_event(f"{EVLOG_ALERT}Alert > Waze Connection Error, Region-{self.waze_region} > {err}. " "The route distance will be calculated, Travel Time is not available.") - post_event(log_msg) #-------------------------------------------------------------------- def __repr__(self): diff --git a/custom_components/icloud3/support/waze_history.py b/custom_components/icloud3/support/waze_history.py index c0fa08e..9b8dab2 100644 --- a/custom_components/icloud3/support/waze_history.py +++ b/custom_components/icloud3/support/waze_history.py @@ -614,9 +614,8 @@ def wazehist_recalculate_time_dist(self, all_zones_flag=False): self.total_recd_cnt = len(records) if self.connection is None: - event_msg = (f"{EVLOG_NOTICE}Waze History Database > Warning, Waze Time/Distance " + post_event( f"{EVLOG_NOTICE}Waze History Database > Warning, Waze Time/Distance " "is disabled in the iCloud3 configuration") - post_event(event_msg) # Set the Abort Flag which is picked up in the update routine that is running # in another thread or as an asyncio task @@ -665,8 +664,7 @@ def wazehist_recalculate_time_dist(self, all_zones_flag=False): self.compress_wazehist_database() running_time = time.perf_counter() - start_time - event_msg = (f"Waze History Completed > Total Time-{format_timer(running_time)}") - post_event(event_msg) + post_event(f"Waze History Completed > Total Time-{format_timer(running_time)}") self.wazehist_recalculate_time_dist_running_flag = False self.wazehist_recalculate_time_dist_abort_flag = False @@ -770,12 +768,11 @@ def _cycle_through_wazehist_records(self, zone_id, zone_dname, zone_from_loc): post_internal_error(traceback.format_exc) running_time = time.perf_counter() - start_time - log_msg = (f"{EVLOG_NOTICE}Waze History Completed > Recalculate Route Time/Dist > " + post_event( f"{EVLOG_NOTICE}Waze History Completed > Recalculate Route Time/Dist > " f"Zone-{zone_dname}, " f"Checked-{recd_cnt} of {self.total_recd_cnt}, " f"Updated-{update_cnt}, " f"Time-{format_timer(running_time)}") - post_event(log_msg) post_evlog_greenbar_msg('') refresh_event_log() @@ -896,9 +893,8 @@ def wazehist_update_track_sensor(self): if self.connection is None: return if self.is_refreshing_map_sensor: - event_msg =(f"HA Map Locations Refresh in process, " + post_event( f"HA Map Locations Refresh in process, " f"RecdsLeft-{self.sensor_map_recds_cnt-self.sensor_map_recd_cnt}") - post_event(event_msg) return self.sensor_map_recds_cnt = self.sensor_map_recd_cnt = 0 @@ -916,15 +912,13 @@ def wazehist_update_track_sensor(self): self.sensor_map_recds_cnt = len(records) if self.connection is None: - event_msg = (f"{EVLOG_NOTICE}Waze History Database is disabled in the " + post_event( f"{EVLOG_NOTICE}Waze History Database is disabled in the " "iCloud3 configuration") - post_event(event_msg) - event_msg = (f"Waze History > Refreshing HA Map locations for" - f"{CRLF_DOT}Sensor-sensor.icloud3_wazehist_track" - f"{CRLF_DOT}RecordCnt-{self.sensor_map_recds_cnt}, " - f"OrderedBy-{orderby_text}") - post_event(event_msg) + post_event( f"Waze History > Refreshing HA Map locations for" + f"{CRLF_DOT}Sensor-sensor.icloud3_wazehist_track" + f"{CRLF_DOT}RecordCnt-{self.sensor_map_recds_cnt}, " + f"OrderedBy-{orderby_text}") try: self.sensor_map_recd_cnt = 0 diff --git a/custom_components/icloud3/support/zone_handler.py b/custom_components/icloud3/support/zone_handler.py index d47fa70..c109833 100644 --- a/custom_components/icloud3/support/zone_handler.py +++ b/custom_components/icloud3/support/zone_handler.py @@ -275,8 +275,7 @@ def post_zone_selected_msg(Device, ZoneSelected, zone_selected, and NOT_SET not in zones_cnt_by_zone): for _Device in Gb.Devices: if Device is not _Device: - event_msg = f"Zone-Device Counts > {zones_cnt_msg}" - post_event(_Device.devicename, event_msg) + post_event(_Device, f"Zone-Device Counts > {zones_cnt_msg}") #-------------------------------------------------------------------- def closest_zone(latitude, longitude): @@ -397,8 +396,7 @@ def log_zone_enter_exit_activity(Device): if Device.log_zone == '': Device.log_zone = Device.loc_data_zone Device.log_zone_enter_secs = Gb.this_update_secs - event_msg = f"Log Zone Activity > Logging Started-{zone_dname(Device.log_zone)}" - post_event(Device, event_msg) + post_event(Device, f"Log Zone Activity > Logging Started-{zone_dname(Device.log_zone)}") return # Must be in the zone for at least 4-minutes @@ -424,8 +422,7 @@ def log_zone_enter_exit_activity(Device): f"{Device.devicename}" "\n") f.write(recd) - event_msg = f"Log Zone Activity > Logging Ended-{zone_dname(Device.log_zone)}" - post_event(Device, event_msg) + post_event(Device, f"Log Zone Activity > Logging Ended-{zone_dname(Device.log_zone)}") if Device.loc_data_zone in Device.log_zones: Device.log_zone = Device.loc_data_zone @@ -460,8 +457,7 @@ def request_update_devices_no_mobapp_same_zone_on_exit(Device): _Device.trigger = 'Check Zone Exit' _Device.check_zone_exit_secs = time_now_secs() det_interval.update_all_device_fm_zone_sensors_interval(_Device, 15) - event_msg = f"Trigger > Check Zone Exit, GeneratedBy-{Device.fname}" - post_event(_Device.devicename, event_msg) + post_event(_Device, f"Trigger > Check Zone Exit, GeneratedBy-{Device.fname}") #------------------------------------------------------------------------------ diff --git a/custom_components/icloud3/translations/en.json b/custom_components/icloud3/translations/en.json index 94183a1..3c5564b 100644 --- a/custom_components/icloud3/translations/en.json +++ b/custom_components/icloud3/translations/en.json @@ -223,7 +223,7 @@ "fname": "FRIENDLY NAME - Displayed in HA device_tracker and sensor names and on the Event Log", "device_type": "DEVICE TYPE - iPhone, iPad, Watch, etc.", "tracking_mode": "TRACKING MODE - How location requests should be done (Full tracking, Monitor, Inactive)", - "mobapp": "MOBILE APP INSTALLED - The HA Mobile App is installed on this device ", + "mobapp": "MOBILE APP INSTALLED - The HA Mobile App is installed on this device ", "action_items": "═════════════════════════════════════════════════════ ACTION COMMANDS" }, "data_description": { @@ -344,7 +344,7 @@ "ipad": "IPAD", "watch": "APPLE WATCH", "airpods": "AIRPODS", - "no_mobapp": "MOBILE APP IS NOT INSTALLED ", + "no_mobapp": "MOBILE APP IS NOT INSTALLED", "other": "OTHER DEVICE TYPE", "distance_between_devices": "Determine the distance between devices. Use a near by device's tracking results", "action_items": "═════════════════════════════════════════════════════ ACTION COMMANDS" @@ -379,10 +379,10 @@ "data": { "stat_zone_header": "═════════════════════════════════════════════════════ STATIONARY ZONE", "stat_zone_fname": "FRIENDLY NAME BASE - Name to display when in a Stationary Zone (StatZone)", - "stat_zone_still_time": "NO MOVEMENT TIME ", - "stat_zone_inzone_interval": "INZONE INTERVAL ", + "stat_zone_still_time": "NO MOVEMENT TIME", + "stat_zone_inzone_interval": "INZONE INTERVAL", "passthru_zone_header": "═════════════════════════════════════════════════════ ENTER ZONE DELAY", - "passthru_zone_time": "ENTER ZONE DELAY TIME ", + "passthru_zone_time": "ENTER ZONE DELAY TIME", "track_from_base_zone_used": "═════════════════════════════════════════════════════ PRIMARY TRACK-FROM-HOME ZONE OVERRIDE", "track_from_base_zone": "TRACK FROM ZONE - Use this zone instead of Home for tracking results for all devices. Global setting", "track_from_home_zone": "TRACK FROM HOME ZONE - Keep tracking from the Home zone when the Primary Track From Zone is not Home",