From ce3247ab89a7f305fae3382d68b23e9557efcd49 Mon Sep 17 00:00:00 2001 From: kwindrem <58538395+kwindrem@users.noreply.github.com> Date: Wed, 17 Jul 2024 14:28:00 -0700 Subject: [PATCH] dropping support for firmware earlier than v3.10 --- PackageManager.py | 70 +- ReadMe | 7 + blindInstall/SetupHelperVersion | 2 +- changes | 4 + updatePackage | 73 +- velib_python/{latest => }/dbusmonitor.py | 0 velib_python/{latest => }/oldestVersion | 0 velib_python/{latest => }/settingsdevice.py | 0 velib_python/v2.73/dbusmonitor.py | 535 --------------- velib_python/v2.73/oldestVersion | 1 - velib_python/v2.73/settingsdevice.py | 115 ---- velib_python/v2.73/ve_utils.py | 253 ------- velib_python/v2.73/vedbus.py | 501 -------------- velib_python/v2.94/dbusmonitor.py | 592 ---------------- velib_python/v2.94/oldestVersion | 1 - velib_python/v2.94/settingsdevice.py | 118 ---- velib_python/v2.94/ve_utils.py | 265 ------- velib_python/v2.94/vedbus.py | 599 ---------------- velib_python/v3.40~37/dbusmonitor.py | 554 --------------- velib_python/v3.40~37/oldestVersion | 1 - velib_python/v3.40~37/settingsdevice.py | 118 ---- velib_python/v3.40~37/ve_utils.py | 262 ------- velib_python/v3.40~37/vedbus.py | 611 ----------------- velib_python/v3.40~38/dbusmonitor.py | 587 ---------------- velib_python/v3.40~38/oldestVersion | 1 - velib_python/v3.40~38/settingsdevice.py | 118 ---- velib_python/v3.40~38/ve_utils.py | 276 -------- velib_python/v3.40~38/vedbus.py | 642 ----------------- velib_python/{latest => }/ve_utils.py | 0 velib_python/{latest => }/vedbus.py | 0 .../velib_python/latest/dbusmonitor.py | 587 ---------------- .../velib_python/latest/oldestVersion | 1 - .../velib_python/latest/settingsdevice.py | 118 ---- velib_python/velib_python/latest/ve_utils.py | 276 -------- velib_python/velib_python/latest/vedbus.py | 646 ------------------ .../velib_python/v2.73/dbusmonitor.py | 535 --------------- velib_python/velib_python/v2.73/oldestVersion | 1 - .../velib_python/v2.73/settingsdevice.py | 115 ---- velib_python/velib_python/v2.73/ve_utils.py | 253 ------- velib_python/velib_python/v2.73/vedbus.py | 501 -------------- .../velib_python/v2.94/dbusmonitor.py | 592 ---------------- velib_python/velib_python/v2.94/oldestVersion | 1 - .../velib_python/v2.94/settingsdevice.py | 118 ---- velib_python/velib_python/v2.94/ve_utils.py | 265 ------- velib_python/velib_python/v2.94/vedbus.py | 599 ---------------- .../velib_python/v3.40~37/dbusmonitor.py | 554 --------------- .../velib_python/v3.40~37/oldestVersion | 1 - .../velib_python/v3.40~37/settingsdevice.py | 118 ---- .../velib_python/v3.40~37/ve_utils.py | 262 ------- velib_python/velib_python/v3.40~37/vedbus.py | 611 ----------------- venus-data-UninstallPackages.tgz | Bin 1141 -> 1142 bytes venus-data.tgz | Bin 345349 -> 213048 bytes version | 2 +- 53 files changed, 64 insertions(+), 12398 deletions(-) rename velib_python/{latest => }/dbusmonitor.py (100%) rename velib_python/{latest => }/oldestVersion (100%) rename velib_python/{latest => }/settingsdevice.py (100%) delete mode 100644 velib_python/v2.73/dbusmonitor.py delete mode 100644 velib_python/v2.73/oldestVersion delete mode 100644 velib_python/v2.73/settingsdevice.py delete mode 100644 velib_python/v2.73/ve_utils.py delete mode 100644 velib_python/v2.73/vedbus.py delete mode 100644 velib_python/v2.94/dbusmonitor.py delete mode 100644 velib_python/v2.94/oldestVersion delete mode 100644 velib_python/v2.94/settingsdevice.py delete mode 100644 velib_python/v2.94/ve_utils.py delete mode 100644 velib_python/v2.94/vedbus.py delete mode 100644 velib_python/v3.40~37/dbusmonitor.py delete mode 100644 velib_python/v3.40~37/oldestVersion delete mode 100644 velib_python/v3.40~37/settingsdevice.py delete mode 100644 velib_python/v3.40~37/ve_utils.py delete mode 100644 velib_python/v3.40~37/vedbus.py delete mode 100644 velib_python/v3.40~38/dbusmonitor.py delete mode 100644 velib_python/v3.40~38/oldestVersion delete mode 100644 velib_python/v3.40~38/settingsdevice.py delete mode 100644 velib_python/v3.40~38/ve_utils.py delete mode 100644 velib_python/v3.40~38/vedbus.py rename velib_python/{latest => }/ve_utils.py (100%) rename velib_python/{latest => }/vedbus.py (100%) delete mode 100644 velib_python/velib_python/latest/dbusmonitor.py delete mode 100644 velib_python/velib_python/latest/oldestVersion delete mode 100644 velib_python/velib_python/latest/settingsdevice.py delete mode 100644 velib_python/velib_python/latest/ve_utils.py delete mode 100644 velib_python/velib_python/latest/vedbus.py delete mode 100644 velib_python/velib_python/v2.73/dbusmonitor.py delete mode 100644 velib_python/velib_python/v2.73/oldestVersion delete mode 100644 velib_python/velib_python/v2.73/settingsdevice.py delete mode 100644 velib_python/velib_python/v2.73/ve_utils.py delete mode 100644 velib_python/velib_python/v2.73/vedbus.py delete mode 100644 velib_python/velib_python/v2.94/dbusmonitor.py delete mode 100644 velib_python/velib_python/v2.94/oldestVersion delete mode 100644 velib_python/velib_python/v2.94/settingsdevice.py delete mode 100644 velib_python/velib_python/v2.94/ve_utils.py delete mode 100644 velib_python/velib_python/v2.94/vedbus.py delete mode 100644 velib_python/velib_python/v3.40~37/dbusmonitor.py delete mode 100644 velib_python/velib_python/v3.40~37/oldestVersion delete mode 100644 velib_python/velib_python/v3.40~37/settingsdevice.py delete mode 100644 velib_python/velib_python/v3.40~37/ve_utils.py delete mode 100644 velib_python/velib_python/v3.40~37/vedbus.py diff --git a/PackageManager.py b/PackageManager.py index 03d30f8..7e79aaf 100755 --- a/PackageManager.py +++ b/PackageManager.py @@ -368,20 +368,13 @@ import time import re import glob +import queue +from gi.repository import GLib +# add the path to our own packages for import +sys.path.insert(1, "/data/SetupHelper/velib_python") +from vedbus import VeDbusService +from settingsdevice import SettingsDevice -# accommodate both Python 2 (prior to v2.80) and 3 -# note subprocess.run and subprocess.DEVNULL do not exist in python 2 -# so subprocess.Popen and subprocess.PIPE and subprocess.communicate () -# are used in all subprodess calls even if process output is not needed -# or if it is not necessary to wait for the command to finish - -PythonVersion = sys.version_info -if PythonVersion >= (3, 0): - import queue - from gi.repository import GLib -else: - import Queue as queue - import gobject as GLib global DownloadGitHub global InstallPackages @@ -483,42 +476,6 @@ def VersionToNumber (version): VenusVersionNumber = VersionToNumber (VenusVersion) file.close() -# add the path to our own packages for import -# use an established Victron service to maintain compatiblity -setupHelperVeLibPath = "/data/SetupHelper/velib_python" -veLibPath = "" -if os.path.exists ( setupHelperVeLibPath ): - for libVersion in os.listdir ( setupHelperVeLibPath ): - # use 'latest' for newest versions even if not specifically checked against this verison when created - if libVersion == "latest": - newestVersionNumber = VersionToNumber ( "v9999.9999.9999" ) - else: - newestVersionNumber = VersionToNumber ( libVersion ) - oldestVersionPath = os.path.join (setupHelperVeLibPath, libVersion, "oldestVersion" ) - if os.path.exists ( oldestVersionPath ): - try: - fd = open (oldestVersionPath, 'r') - oldestVersionNumber = VersionToNumber ( fd.readline().strip () ) - fd.close() - except: - oldestVersionNumber = 0 - else: - oldestVersionNumber = 0 - if VenusVersionNumber >= oldestVersionNumber and VenusVersionNumber <= newestVersionNumber: - veLibPath = os.path.join (setupHelperVeLibPath, libVersion) - break - -# no SetupHelper velib - use one in systemcalc -if veLibPath == "": - veLibPath = os.path.join('/opt/victronenergy/dbus-systemcalc-py', 'ext', 'velib_python') - -logging.warning ("using " + veLibPath + " for velib_python") -sys.path.insert(1, veLibPath) - -from vedbus import VeDbusService -from settingsdevice import SettingsDevice - - # PushAction # # some actions are pushed to one of three queues: @@ -1241,13 +1198,7 @@ def __init__(self): # check firmware version and delay dbus service registration for v3.40~38 and beyond global VenusVersionNumber global VersionToNumber - versionThreshold = VersionToNumber ("v3.40~28") - if VenusVersionNumber >= versionThreshold: - self.DbusService = VeDbusService ('com.victronenergy.packageManager', bus = dbus.SystemBus(), register=False) - delayedRegistration = True - else: - self.DbusService = VeDbusService ('com.victronenergy.packageManager', bus = dbus.SystemBus()) - delayedRegistration = False + self.DbusService = VeDbusService ('com.victronenergy.packageManager', bus = dbus.SystemBus(), register=False) self.DbusService.add_mandatory_paths ( processname = 'PackageManager', processversion = 1.0, connection = 'none', @@ -1289,8 +1240,8 @@ def __init__(self): self.DbusService.add_path ( '/PmStatus', "", writeable = True ) global Platform self.DbusService.add_path ( '/Platform', Platform ) - if delayedRegistration: - self.DbusService.register () + + self.DbusService.register () # RemoveDbusService @@ -4055,9 +4006,6 @@ def main(): # Have a mainloop, so we can send/receive asynchronous calls to and from dbus DBusGMainLoop(set_as_default=True) - global PythonVersion - if PythonVersion < (3, 0): - GLib.threads_init() # get platform global Platform diff --git a/ReadMe b/ReadMe index ca1a42f..2908ab6 100644 --- a/ReadMe +++ b/ReadMe @@ -22,6 +22,13 @@ The SetupHelper package provides: Restart or initialize PackageManager Restart the GUI +NOTE: Support for firmware prior to v3.10 has been dropped starting with SetupHelper v8.10 + if you are running older versions, change the branch/tag to preV3.10support + for any packages you wish to run on that firmware + + While this branch will remain active, there will be no features added to it + and only serious bug fixes will be applied. + SetupHelper v8 adds the ability for multiple packages to modify the same file Packages must be written to "patch" a file rather than "replace" it diff --git a/blindInstall/SetupHelperVersion b/blindInstall/SetupHelperVersion index 1416d7e..5eb381b 100644 --- a/blindInstall/SetupHelperVersion +++ b/blindInstall/SetupHelperVersion @@ -1 +1 @@ -v8.9 +v8.10 diff --git a/changes b/changes index 4c682ed..f5f631d 100644 --- a/changes +++ b/changes @@ -1,3 +1,7 @@ +v8.10: + moved velib_python in SetupHelper to a single version + dropping support for firmware earlier than v3.10 + v8.9: fixed: further changes for the remote GUI issue diff --git a/updatePackage b/updatePackage index b934c84..58d5baf 100755 --- a/updatePackage +++ b/updatePackage @@ -876,9 +876,15 @@ for package in $packageList; do oldReplacementVersion="-" oldReplacementIsFile=false oldReplacementIsUseOrig=false + blockIsUnused=true for (( i1 = start; i1 < $allFileSetsLength; i1++ )); do IFS=':' read version versionNumber <<< "${allFileSets[$i1]}" fileSet="$workingFiles/$version" + if [ -e "$fileSet/INCOMPATIBLE_VERSION" ] || [ -e "$fileSet/UNUSED_FILE_SET" ]; then + fileSetUnused=true + else + fileSetUnused=false + fi replacement="$fileSet/$baseName" stockFileSet="$stockFiles/$version" orig="$fileSet/$baseName.orig" @@ -939,6 +945,10 @@ for package in $packageList; do break fi + if ! $fileSetUnused ; then + blockIsUnused=false + fi + # save version of old replacement files for next loop if $replacementIsFile ; then if ! $oldReplacementIsFile || [ "$oldReplacementVersion" == "-" ]; then @@ -958,24 +968,16 @@ for package in $packageList; do # first compatible file set - move replacements here # unused file sets are permitted for the destination file set # but if a used file set is later found, it is preferred - if [ -e "$fileSet/INCOMPATIBLE_VERSION" ]; then - updateTo=false - elif (( to == -1 )); then - updateTo=true - elif ! [ -e "$fileSet/UNUSED_FILE_SET" ] && [ -e "$toFileSet/UNUSED_FILE_SET" ]; then - updateTo=true - else - updateTo=false - fi - if $updateTo ; then + if (( to == -1 )) && ! $fileSetUnused; then (( to = i1 )) toFileSet="$fileSet" toVersion=$( basename "$toFileSet" ) fi done # end locate block - if (( to == -1 )); then - logMessage "ERROR $package: $baseName no destination file set - can't relocate files" + if ! $blockIsUnused; then + logMessage "ERROR $package: $baseName no destination file set for block $startVersion $endVersion - can't relocate files" + fi else toReplacement="$toFileSet/$baseName" oldReplacement="$workingFiles/$oldReplacementVersion/$baseName" @@ -1099,29 +1101,40 @@ for package in $packageList; do break fi done - # LINKS_ONLY is not used for anything but helps identify file sets - # that don't contain real files + # LINKS_ONLY is not used for anything but helps identify file sets that don't contain real files if ! $replacementFilesExist ; then touch "$fileSet/LINKS_ONLY" fi + fileSetInUse=true # remove file sets for incompatible Venus OS versions if [ -e "$fileSet/INCOMPATIBLE_VERSION" ]; then - if [ ! -f "$fileSet/NEW_FILE_SET" ]; then - logMessage "WARNING $package: not compatible with Venus $version - file set removed" + fileSetInUse=false + if $replacementFilesExist ; then + logMessage "WARNING $package: $version not compatible with Venus $version but file set not empty" + else + if [ ! -f "$fileSet/NEW_FILE_SET" ]; then + logMessage "WARNING $package: not compatible with Venus $version - file set removed" + fi + rm -Rf "$fileSet" fi - rm -Rf "$fileSet" # remove empty unused file sets elif [ -f "$fileSet/UNUSED_FILE_SET" ]; then - # log removal of a previous file set if not created with this run - # if it was created with this run, delete it silently - if [ ! -f "$fileSet/NEW_FILE_SET" ]; then - logMessage "WARNING $package: $version - removing unused file set" + fileSetInUse=false + if $replacementFilesExist ; then + logMessage "WARNING $package: $version no longer used but file set not empty" + else + # log removal of a previous file set if not created with this run + # if it was created with this run, delete it silently + if [ ! -f "$fileSet/NEW_FILE_SET" ]; then + logMessage "WARNING $package: $version - removing unused file set" + fi + rm -Rf "$fileSet" fi - rm -Rf "$fileSet" + fi # do final checks on versioned files only # and for file sets that still exist - else + if [ -e "$fileSet" ] && $fileSetInUse; then if [ -e "$fileSet/NEW_FILE_SET" ]; then logMessage "$package: $version new file set" fi @@ -1172,7 +1185,6 @@ for package in $packageList; do logMessage "ERROR $package $baseName: no replacement for $version" fi - # validate sym link symLinkReplacement=false badLink=false @@ -1181,19 +1193,18 @@ for package in $packageList; do # resolive symlink then check to make sure that file is valid linkedFile=$( realpath "$replacement" 2> /dev/null ) if [ -z "$linkedFile" ]; then - badLink=true + logMessage "ERROR $package: $baseName $version no linked file $linkedFile" + touch "$replacement.BAD_LINK" else linkedFileSet=$( dirname "$linkedFile" ) if [ -z "$linkedFileSet" ]; then - badLink=true + logMessage "ERROR $package: $baseName $version no linked file set" + touch "$replacement.BAD_LINK" elif [ -f "$linkedFileSet/UNUSED_FILE_SET" ] || [ -f "$linkedFileSet/INCOMPATIBLE_VERSION" ]; then - badLink=true + logMessage "ERROR $package: $baseName $version links to unused file set $linkedFileSet" + touch "$replacement.BAD_LINK" fi fi - if $badLink ; then - logMessage "ERROR $package: $baseName $version bad link" - touch "$replacement.BAD_LINK" - fi fi # flag file set incomplete diff --git a/velib_python/latest/dbusmonitor.py b/velib_python/dbusmonitor.py similarity index 100% rename from velib_python/latest/dbusmonitor.py rename to velib_python/dbusmonitor.py diff --git a/velib_python/latest/oldestVersion b/velib_python/oldestVersion similarity index 100% rename from velib_python/latest/oldestVersion rename to velib_python/oldestVersion diff --git a/velib_python/latest/settingsdevice.py b/velib_python/settingsdevice.py similarity index 100% rename from velib_python/latest/settingsdevice.py rename to velib_python/settingsdevice.py diff --git a/velib_python/v2.73/dbusmonitor.py b/velib_python/v2.73/dbusmonitor.py deleted file mode 100644 index fc8785d..0000000 --- a/velib_python/v2.73/dbusmonitor.py +++ /dev/null @@ -1,535 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -import gobject -from gobject import idle_add -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from vedbus import VeDbusItemExport, VeDbusItemImport -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - whentologoptions = ['configChange', 'onIntervalAlwaysAndOnEvent', - 'onIntervalOnlyWhenChanged', 'onIntervalAlways', 'never'] - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - self.configChange = [] - self.onIntervalAlwaysAndOnEvent = [] - self.onIntervalOnlyWhenChanged = [] - self.onIntervalAlways = [] - self.never = [] - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, vebusDeviceInstance0=False): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - self.vebusDeviceInstance0 = vebusDeviceInstance0 - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()).add_signal_receiver( - self.dbus_name_owner_changed, - signal_name='NameOwnerChanged') - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - deviceInstance = service['deviceInstance'] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - # for vebus.ttyO1, this is workaround, since VRM Portal expects the main vebus - # devices at instance 0. Not sure how to fix this yet. - if serviceName == 'com.victronenergy.vebus.ttyO1' and self.vebusDeviceInstance0: - di = 0 - elif serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = Service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.iteritems(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - # check that the whenToLog setting is set to something we expect - assert options['whenToLog'] is None or options['whenToLog'] in Service.whentologoptions - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - if options['whenToLog']: - service[options['whenToLog']].append(path) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def handler_value_changes(self, changes, path, senderId): - try: - service = self.servicesById[senderId] - a = service.paths[path] - except KeyError: - # Either senderId or path isn't there, which means - # it hasn't been scanned yet. - return - - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - service.set_seen(path) - - # First update our store to the new value - changes['Value'] = unwrap_dbus_value(changes['Value']) - if a.value == changes['Value']: - return - - a.value = changes['Value'] - try: - a.text = changes['Text'] - except KeyError: - # Some services don't send Text with their PropertiesChanged events. - a.text = str(a.value) - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - idle_add(exit_on_error, self._execute_value_changes, service.name, path, changes, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.iteritems() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - # Parameter categoryfilter is to be a list, containing the categories you want (configChange, - # onIntervalAlways, etc). - # Returns a dictionary, keys are codes + instance, in VRM querystring format. For example vvt[0]. And - # values are the value. - def get_values(self, categoryfilter, converter=None): - - result = {} - - for serviceName in self.servicesByName: - result.update(self.get_values_for_service(categoryfilter, serviceName, converter)) - - return result - - # same as get_values above, but then for one service only - def get_values_for_service(self, categoryfilter, servicename, converter=None): - deviceInstance = self.get_device_instance(servicename) - result = {} - - service = self.servicesByName[servicename] - - for category in categoryfilter: - - for path in service[category]: - - value, text, options = service.paths[path] - - if value is not None: - - value = value if converter is None else converter.convert(path, options['code'], value, text) - - precision = options.get('precision') - if precision: - value = round(value, precision) - - result[options['code'] + "[" + str(deviceInstance) + "]"] = value - - return result - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - self.serviceWatches[serviceName].append( - self.dbusConn.add_signal_receiver( - partial(callback, *args, **kwargs), - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName)) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print len([o for o in objects if type(o).__name__ == 'VeDbusItemImport']) - print len([o for o in objects if type(o).__name__ == 'SignalMatch']) - print len(objects) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print "All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - # logger.info("==configchange values==") - # logger.info(pprint.pformat(d.get_values(['configChange']))) - - # logger.info("==onIntervalAlways and onIntervalOnlyWhenChanged==") - # logger.info(pprint.pformat(d.get_values(['onIntervalAlways', 'onIntervalAlwaysAndOnEvent']))) - - gobject.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = gobject.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/v2.73/oldestVersion b/velib_python/v2.73/oldestVersion deleted file mode 100644 index c4da1d4..0000000 --- a/velib_python/v2.73/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v2.71 diff --git a/velib_python/v2.73/settingsdevice.py b/velib_python/v2.73/settingsdevice.py deleted file mode 100644 index b525375..0000000 --- a/velib_python/v2.73/settingsdevice.py +++ /dev/null @@ -1,115 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - for setting, options in supportedSettings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - logging.debug("===== Settings device init finished =====") - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/v2.73/ve_utils.py b/velib_python/v2.73/ve_utils.py deleted file mode 100644 index c5cfb74..0000000 --- a/velib_python/v2.73/ve_utils.py +++ /dev/null @@ -1,253 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using gobject.idle_add and also gobject.timeout_add. -# Without this, the code will just keep running, since gobject does not stop the mainloop on an -# exception. -# Example: gobject.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print 'exit_on_error: there was an exception. Printing stacktrace will be tried and then exit' - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # For the CCGX, the definition of the VRM Portal ID is that it is the mac address of the onboard- - # ethernet port (eth0), stripped from its colons (:) and lower case. - - # nice coincidence is that this also works fine when running on your (linux) development computer. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - # First try the method that works if we don't have a data partition. This will fail - # when the current user is not root. - try: - __vrm_portal_id = check_output("/sbin/get-unique-id").strip() - return __vrm_portal_id - except (CalledProcessError, OSError): - pass - - # Attempt to get the id from /data/venus/unique-id where venus puts it - # on startup. - try: - __vrm_portal_id = open('/data/venus/unique-id').read().strip() - except IOError: - pass - else: - return __vrm_portal_id - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - __vrm_portal_id = ''.join(['%02x' % ord(char) for char in info[18:24]]) - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception, ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def get_load_averages(): - c = read_file('/proc/loadavg') - return c.split(' ')[:3] - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip() - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip() - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception, ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, unicode): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, long): - return dbus.Int64(value, variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return unicode(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([str(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val diff --git a/velib_python/v2.73/vedbus.py b/velib_python/v2.73/vedbus.py deleted file mode 100644 index 7fbe55d..0000000 --- a/velib_python/v2.73/vedbus.py +++ /dev/null @@ -1,501 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(servicename, self._dbusconn, do_not_queue=True) - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = self._create_tree_export(self._dbusconn, '/', self._get_tree_dict) - - logging.info("registered ourselves on D-Bus as %s" % servicename) - - def _get_tree_dict(self, path, get_text=False): - logging.debug("_get_tree_dict called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in self._dbusnodes.values(): - node.__del__() - self._dbusnodes.clear() - for item in self._dbusobjects.values(): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - item = VeDbusItemExport( - self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = self._create_tree_export(self._dbusconn, subPath, self._get_tree_dict) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - def _create_tree_export(self, bus, objectPath, get_value_handler): - return VeDbusTreeExport(bus, objectPath, get_value_handler) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in self._dbusnodes.keys(): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match != None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, get_value_handler): - dbus.service.Object.__init__(self, bus, objectPath) - self._get_value_handler = get_value_handler - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.local_set_value(None) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - if self._value == newvalue: - return - - self._value = newvalue - - changes = {} - changes['Value'] = wrap_dbus_value(newvalue) - changes['Text'] = self.GetText() - self.PropertiesChanged(changes) - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/velib_python/v2.94/dbusmonitor.py b/velib_python/v2.94/dbusmonitor.py deleted file mode 100644 index 5f8e153..0000000 --- a/velib_python/v2.94/dbusmonitor.py +++ /dev/null @@ -1,592 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - whentologoptions = ['configChange', 'onIntervalAlwaysAndOnEvent', - 'onIntervalOnlyWhenChanged', 'onIntervalAlways', 'never'] - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - self.configChange = [] - self.onIntervalAlwaysAndOnEvent = [] - self.onIntervalOnlyWhenChanged = [] - self.onIntervalAlways = [] - self.never = [] - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, vebusDeviceInstance0=False): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - self.vebusDeviceInstance0 = vebusDeviceInstance0 - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()).add_signal_receiver( - self.dbus_name_owner_changed, - signal_name='NameOwnerChanged') - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - # Subscribe to ItemsChanged for all services - self.dbusConn.add_signal_receiver(self.handler_item_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', path='/', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - GLib.idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - deviceInstance = service['deviceInstance'] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - # for vebus.ttyO1, this is workaround, since VRM Portal expects the main vebus - # devices at instance 0. Not sure how to fix this yet. - if serviceName == 'com.victronenergy.vebus.ttyO1' and self.vebusDeviceInstance0: - di = 0 - elif serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = Service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.items(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - # check that the whenToLog setting is set to something we expect - assert options['whenToLog'] is None or options['whenToLog'] in Service.whentologoptions - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - if options['whenToLog']: - service[options['whenToLog']].append(path) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def handler_item_changes(self, items, senderId): - if not isinstance(items, dict): - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - for path, changes in items.items(): - try: - v = unwrap_dbus_value(changes['Value']) - except (KeyError, TypeError): - continue - - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def handler_value_changes(self, changes, path, senderId): - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - v = unwrap_dbus_value(changes['Value']) - # Some services don't send Text with their PropertiesChanged events. - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def _handler_value_changes(self, service, path, value, text): - try: - a = service.paths[path] - except KeyError: - # path isn't there, which means it hasn't been scanned yet. - return - - service.set_seen(path) - - # First update our store to the new value - if a.value == value: - return - - a.value = value - a.text = text - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - GLib.idle_add(exit_on_error, self._execute_value_changes, service.name, path, { - 'Value': value, 'Text': text}, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.items() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - # Parameter categoryfilter is to be a list, containing the categories you want (configChange, - # onIntervalAlways, etc). - # Returns a dictionary, keys are codes + instance, in VRM querystring format. For example vvt[0]. And - # values are the value. - def get_values(self, categoryfilter, converter=None): - - result = {} - - for serviceName in self.servicesByName: - result.update(self.get_values_for_service(categoryfilter, serviceName, converter)) - - return result - - # same as get_values above, but then for one service only - def get_values_for_service(self, categoryfilter, servicename, converter=None): - deviceInstance = self.get_device_instance(servicename) - result = {} - - service = self.servicesByName[servicename] - - for category in categoryfilter: - - for path in service[category]: - - value, text, options = service.paths[path] - - if value is not None: - - value = value if converter is None else converter.convert(path, options['code'], value, text) - - precision = options.get('precision') - if precision: - value = round(value, precision) - - result[options['code'] + "[" + str(deviceInstance) + "]"] = value - - return result - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - cb = partial(callback, *args, **kwargs) - - def root_tracker(items): - # Check if objectPath in dict - try: - v = items[objectPath] - _v = unwrap_dbus_value(v['Value']) - except (KeyError, TypeError): - return # not in this dict - - try: - t = v['Text'] - except KeyError: - cb({'Value': _v }) - else: - cb({'Value': _v, 'Text': t}) - - # Track changes on the path, and also on root - self.serviceWatches[serviceName].extend(( - self.dbusConn.add_signal_receiver(cb, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName), - self.dbusConn.add_signal_receiver(root_tracker, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', - path="/", bus_name=serviceName), - )) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print (len([o for o in objects if type(o).__name__ == 'VeDbusItemImport'])) - print (len([o for o in objects if type(o).__name__ == 'SignalMatch'])) - print (len(objects)) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print ("All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d)) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - # logger.info("==configchange values==") - # logger.info(pprint.pformat(d.get_values(['configChange']))) - - # logger.info("==onIntervalAlways and onIntervalOnlyWhenChanged==") - # logger.info(pprint.pformat(d.get_values(['onIntervalAlways', 'onIntervalAlwaysAndOnEvent']))) - - GLib.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = GLib.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/v2.94/oldestVersion b/velib_python/v2.94/oldestVersion deleted file mode 100644 index 366edb3..0000000 --- a/velib_python/v2.94/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v2.80 diff --git a/velib_python/v2.94/settingsdevice.py b/velib_python/v2.94/settingsdevice.py deleted file mode 100644 index a207e8b..0000000 --- a/velib_python/v2.94/settingsdevice.py +++ /dev/null @@ -1,118 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - self.addSettings(supportedSettings) - - logging.debug("===== Settings device init finished =====") - - def addSettings(self, settings): - for setting, options in settings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/v2.94/ve_utils.py b/velib_python/v2.94/ve_utils.py deleted file mode 100644 index e8d847d..0000000 --- a/velib_python/v2.94/ve_utils.py +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import sys -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -class NoVrmPortalIdError(Exception): - pass - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using GLib.idle_add and also GLib.timeout_add. -# Without this, the code will just keep running, since GLib does not stop the mainloop on an -# exception. -# Example: GLib.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print ('exit_on_error: there was an exception. Printing stacktrace will be tried and then exit') - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # The original definition of the VRM Portal ID is that it is the mac - # address of the onboard- ethernet port (eth0), stripped from its colons - # (:) and lower case. This may however differ between platforms. On Venus - # the task is therefore deferred to /sbin/get-unique-id so that a - # platform specific method can be easily defined. - # - # If /sbin/get-unique-id does not exist, then use the ethernet address - # of eth0. This also handles the case where velib_python is used as a - # package install on a Raspberry Pi. - # - # On a Linux host where the network interface may not be eth0, you can set - # the VRM_IFACE environment variable to the correct name. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - portal_id = None - - # First try the method that works if we don't have a data partition. This - # will fail when the current user is not root. - try: - portal_id = check_output("/sbin/get-unique-id").decode("utf-8", "ignore").strip() - if not portal_id: - raise NoVrmPortalIdError("get-unique-id returned blank") - __vrm_portal_id = portal_id - return portal_id - except CalledProcessError: - # get-unique-id returned non-zero - raise NoVrmPortalIdError("get-unique-id returned non-zero") - except OSError: - # File doesn't exist, use fallback - pass - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0').encode('ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - except IOError: - raise NoVrmPortalIdError("ioctl failed for eth0") - - __vrm_portal_id = info[18:24].hex() - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception as ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def get_load_averages(): - c = read_file('/proc/loadavg') - return c.split(' ')[:3] - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r', encoding='UTF-8') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip() - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception as ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return str(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([bytes(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val diff --git a/velib_python/v2.94/vedbus.py b/velib_python/v2.94/vedbus.py deleted file mode 100644 index d6dac60..0000000 --- a/velib_python/v2.94/vedbus.py +++ /dev/null @@ -1,599 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from collections import defaultdict -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - self._ratelimiters = [] - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(servicename, self._dbusconn, do_not_queue=True) - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = VeDbusRootExport(self._dbusconn, '/', self) - - logging.info("registered ourselves on D-Bus as %s" % servicename) - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in list(self._dbusnodes.values()): - node.__del__() - self._dbusnodes.clear() - for item in list(self._dbusobjects.values()): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - item = VeDbusItemExport( - self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = VeDbusTreeExport(self._dbusconn, subPath, self) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in list(self._dbusnodes.keys()): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - - def __enter__(self): - l = ServiceContext(self) - self._ratelimiters.append(l) - return l - - def __exit__(self, *exc): - # pop off the top one and flush it. If with statements are nested - # then each exit flushes its own part. - if self._ratelimiters: - self._ratelimiters.pop().flush() - -class ServiceContext(object): - def __init__(self, parent): - self.parent = parent - self.changes = {} - - def __getitem__(self, path): - return self.parent[path] - - def __setitem__(self, path, newvalue): - c = self.parent._dbusobjects[path]._local_set_value(newvalue) - if c is not None: - self.changes[path] = c - - def flush(self): - if self.changes: - self.parent._dbusnodes['/'].ItemsChanged(self.changes) - -class TrackerDict(defaultdict): - """ Same as defaultdict, but passes the key to default_factory. """ - def __missing__(self, key): - self[key] = x = self.default_factory(key) - return x - -class VeDbusRootTracker(object): - """ This tracks the root of a dbus path and listens for PropertiesChanged - signals. When a signal arrives, parse it and unpack the key/value changes - into traditional events, then pass it to the original eventCallback - method. """ - def __init__(self, bus, serviceName): - self.importers = defaultdict(weakref.WeakSet) - self.serviceName = serviceName - self._match = bus.get_object(serviceName, '/', introspect=False).connect_to_signal( - "ItemsChanged", weak_functor(self._items_changed_handler)) - - def __del__(self): - self._match.remove() - self._match = None - - def add(self, i): - self.importers[i.path].add(i) - - def _items_changed_handler(self, items): - if not isinstance(items, dict): - return - - for path, changes in items.items(): - try: - v = changes['Value'] - except KeyError: - continue - - try: - t = changes['Text'] - except KeyError: - t = str(unwrap_dbus_value(v)) - - for i in self.importers.get(path, ()): - i._properties_changed_handler({'Value': v, 'Text': t}) - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - def __new__(cls, bus, serviceName, path, eventCallback=None, createsignal=True): - instance = object.__new__(cls) - - # If signal tracking should be done, also add to root tracker - if createsignal: - if "_roots" not in cls.__dict__: - cls._roots = TrackerDict(lambda k: VeDbusRootTracker(bus, k)) - - return instance - - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - self._roots[serviceName].add(self) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match is not None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, service): - dbus.service.Object.__init__(self, bus, objectPath) - self._service = service - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - def _get_value_handler(self, path, get_text=False): - logging.debug("_get_value_handler called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._service._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - -class VeDbusRootExport(VeDbusTreeExport): - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sa{sv}}') - def ItemsChanged(self, changes): - pass - - @dbus.service.method('com.victronenergy.BusItem', out_signature='a{sa{sv}}') - def GetItems(self): - return { - path: { - 'Value': wrap_dbus_value(item.local_get_value()), - 'Text': item.GetText() } - for path, item in self._service._dbusobjects.items() - } - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.local_set_value(None) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - changes = self._local_set_value(newvalue) - if changes is not None: - self.PropertiesChanged(changes) - - def _local_set_value(self, newvalue): - if self._value == newvalue: - return None - - self._value = newvalue - return { - 'Value': wrap_dbus_value(newvalue), - 'Text': self.GetText() - } - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/velib_python/v3.40~37/dbusmonitor.py b/velib_python/v3.40~37/dbusmonitor.py deleted file mode 100644 index cb2185d..0000000 --- a/velib_python/v3.40~37/dbusmonitor.py +++ /dev/null @@ -1,554 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, namespace="com.victronenergy"): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - # NOTE: this is on a different bus then the one above! - standardBus = (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()) - - self.add_name_owner_changed_receiver(standardBus, self.dbus_name_owner_changed) - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - # Subscribe to ItemsChanged for all services - self.dbusConn.add_signal_receiver(self.handler_item_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', path='/', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - @staticmethod - def make_service(serviceId, serviceName, deviceInstance): - """ Override this to use a different kind of service object. """ - return Service(serviceId, serviceName, deviceInstance) - - def make_monitor(self, service, path, value, text, options): - """ Override this to do more things with monitoring. """ - return MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - GLib.idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - @staticmethod - # When supported, only name owner changes for the the given namespace are reported. This - # prevents spending cpu time at irrelevant changes, like scripts accessing the bus temporarily. - def add_name_owner_changed_receiver(dbus, name_owner_changed, namespace="com.victronenergy"): - # support for arg0namespace is submitted upstream, but not included at the time of - # writing, Venus OS does support it, so try if it works. - if namespace is None: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') - else: - try: - dbus.add_signal_receiver(name_owner_changed, - signal_name='NameOwnerChanged', arg0namespace=namespace) - except TypeError: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, service.deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - if serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = self.make_service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.items(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = self.make_monitor(service, path, unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def handler_item_changes(self, items, senderId): - if not isinstance(items, dict): - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - for path, changes in items.items(): - try: - v = unwrap_dbus_value(changes['Value']) - except (KeyError, TypeError): - continue - - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def handler_value_changes(self, changes, path, senderId): - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - v = unwrap_dbus_value(changes['Value']) - # Some services don't send Text with their PropertiesChanged events. - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def _handler_value_changes(self, service, path, value, text): - try: - a = service.paths[path] - except KeyError: - # path isn't there, which means it hasn't been scanned yet. - return - - service.set_seen(path) - - # First update our store to the new value - if a.value == value: - return - - a.value = value - a.text = text - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - GLib.idle_add(exit_on_error, self._execute_value_changes, service.name, path, { - 'Value': value, 'Text': text}, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.items() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - cb = partial(callback, *args, **kwargs) - - def root_tracker(items): - # Check if objectPath in dict - try: - v = items[objectPath] - _v = unwrap_dbus_value(v['Value']) - except (KeyError, TypeError): - return # not in this dict - - try: - t = v['Text'] - except KeyError: - cb({'Value': _v }) - else: - cb({'Value': _v, 'Text': t}) - - # Track changes on the path, and also on root - self.serviceWatches[serviceName].extend(( - self.dbusConn.add_signal_receiver(cb, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName), - self.dbusConn.add_signal_receiver(root_tracker, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', - path="/", bus_name=serviceName), - )) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print (len([o for o in objects if type(o).__name__ == 'VeDbusItemImport'])) - print (len([o for o in objects if type(o).__name__ == 'SignalMatch'])) - print (len(objects)) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print ("All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d)) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - GLib.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = GLib.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/v3.40~37/oldestVersion b/velib_python/v3.40~37/oldestVersion deleted file mode 100644 index 3f6c1a0..0000000 --- a/velib_python/v3.40~37/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v3.00~32 diff --git a/velib_python/v3.40~37/settingsdevice.py b/velib_python/v3.40~37/settingsdevice.py deleted file mode 100644 index a207e8b..0000000 --- a/velib_python/v3.40~37/settingsdevice.py +++ /dev/null @@ -1,118 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - self.addSettings(supportedSettings) - - logging.debug("===== Settings device init finished =====") - - def addSettings(self, settings): - for setting, options in settings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/v3.40~37/ve_utils.py b/velib_python/v3.40~37/ve_utils.py deleted file mode 100644 index 63a915b..0000000 --- a/velib_python/v3.40~37/ve_utils.py +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import sys -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -class NoVrmPortalIdError(Exception): - pass - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using GLib.idle_add and also GLib.timeout_add. -# Without this, the code will just keep running, since GLib does not stop the mainloop on an -# exception. -# Example: GLib.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print ('exit_on_error: there was an exception. Printing stacktrace will be tried and then exit') - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # The original definition of the VRM Portal ID is that it is the mac - # address of the onboard- ethernet port (eth0), stripped from its colons - # (:) and lower case. This may however differ between platforms. On Venus - # the task is therefore deferred to /sbin/get-unique-id so that a - # platform specific method can be easily defined. - # - # If /sbin/get-unique-id does not exist, then use the ethernet address - # of eth0. This also handles the case where velib_python is used as a - # package install on a Raspberry Pi. - # - # On a Linux host where the network interface may not be eth0, you can set - # the VRM_IFACE environment variable to the correct name. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - portal_id = None - - # First try the method that works if we don't have a data partition. This - # will fail when the current user is not root. - try: - portal_id = check_output("/sbin/get-unique-id").decode("utf-8", "ignore").strip() - if not portal_id: - raise NoVrmPortalIdError("get-unique-id returned blank") - __vrm_portal_id = portal_id - return portal_id - except CalledProcessError: - # get-unique-id returned non-zero - raise NoVrmPortalIdError("get-unique-id returned non-zero") - except OSError: - # File doesn't exist, use fallback - pass - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0').encode('ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - except IOError: - raise NoVrmPortalIdError("ioctl failed for eth0") - - __vrm_portal_id = info[18:24].hex() - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception as ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r', encoding='UTF-8') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008', - 'Maxi GX': 'C009', - 'Cerbo GX': 'C00A' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception as ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return str(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([bytes(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val diff --git a/velib_python/v3.40~37/vedbus.py b/velib_python/v3.40~37/vedbus.py deleted file mode 100644 index 8c101ea..0000000 --- a/velib_python/v3.40~37/vedbus.py +++ /dev/null @@ -1,611 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from collections import defaultdict -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - self._ratelimiters = [] - self._dbusname = None - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(servicename, self._dbusconn, do_not_queue=True) - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = VeDbusRootExport(self._dbusconn, '/', self) - - logging.info("registered ourselves on D-Bus as %s" % servicename) - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in list(self._dbusnodes.values()): - node.__del__() - self._dbusnodes.clear() - for item in list(self._dbusobjects.values()): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None, valuetype=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - item = VeDbusItemExport( - self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted, valuetype=valuetype) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = VeDbusTreeExport(self._dbusconn, subPath, self) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in list(self._dbusnodes.keys()): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - - def __enter__(self): - l = ServiceContext(self) - self._ratelimiters.append(l) - return l - - def __exit__(self, *exc): - # pop off the top one and flush it. If with statements are nested - # then each exit flushes its own part. - if self._ratelimiters: - self._ratelimiters.pop().flush() - -class ServiceContext(object): - def __init__(self, parent): - self.parent = parent - self.changes = {} - - def __getitem__(self, path): - return self.parent[path] - - def __setitem__(self, path, newvalue): - c = self.parent._dbusobjects[path]._local_set_value(newvalue) - if c is not None: - self.changes[path] = c - - def flush(self): - if self.changes: - self.parent._dbusnodes['/'].ItemsChanged(self.changes) - -class TrackerDict(defaultdict): - """ Same as defaultdict, but passes the key to default_factory. """ - def __missing__(self, key): - self[key] = x = self.default_factory(key) - return x - -class VeDbusRootTracker(object): - """ This tracks the root of a dbus path and listens for PropertiesChanged - signals. When a signal arrives, parse it and unpack the key/value changes - into traditional events, then pass it to the original eventCallback - method. """ - def __init__(self, bus, serviceName): - self.importers = defaultdict(weakref.WeakSet) - self.serviceName = serviceName - self._match = bus.get_object(serviceName, '/', introspect=False).connect_to_signal( - "ItemsChanged", weak_functor(self._items_changed_handler)) - - def __del__(self): - self._match.remove() - self._match = None - - def add(self, i): - self.importers[i.path].add(i) - - def _items_changed_handler(self, items): - if not isinstance(items, dict): - return - - for path, changes in items.items(): - try: - v = changes['Value'] - except KeyError: - continue - - try: - t = changes['Text'] - except KeyError: - t = str(unwrap_dbus_value(v)) - - for i in self.importers.get(path, ()): - i._properties_changed_handler({'Value': v, 'Text': t}) - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - def __new__(cls, bus, serviceName, path, eventCallback=None, createsignal=True): - instance = object.__new__(cls) - - # If signal tracking should be done, also add to root tracker - if createsignal: - if "_roots" not in cls.__dict__: - cls._roots = TrackerDict(lambda k: VeDbusRootTracker(bus, k)) - - return instance - - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - self._roots[serviceName].add(self) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match is not None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, service): - dbus.service.Object.__init__(self, bus, objectPath) - self._service = service - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - def _get_value_handler(self, path, get_text=False): - logging.debug("_get_value_handler called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._service._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - -class VeDbusRootExport(VeDbusTreeExport): - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sa{sv}}') - def ItemsChanged(self, changes): - pass - - @dbus.service.method('com.victronenergy.BusItem', out_signature='a{sa{sv}}') - def GetItems(self): - return { - path: { - 'Value': wrap_dbus_value(item.local_get_value()), - 'Text': item.GetText() } - for path, item in self._service._dbusobjects.items() - } - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None, - valuetype=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - self._type = valuetype - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - changes = self._local_set_value(newvalue) - if changes is not None: - self.PropertiesChanged(changes) - - def _local_set_value(self, newvalue): - if self._value == newvalue: - return None - - self._value = newvalue - return { - 'Value': wrap_dbus_value(newvalue), - 'Text': self.GetText() - } - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - # If value type is enforced, cast it. If the type can be coerced - # python will do it for us. This allows ints to become floats, - # or bools to become ints. Additionally also allow None, so that - # a path may be invalidated. - if self._type is not None and newvalue is not None: - try: - newvalue = self._type(newvalue) - except (ValueError, TypeError): - return 1 # NOT OK - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/velib_python/v3.40~38/dbusmonitor.py b/velib_python/v3.40~38/dbusmonitor.py deleted file mode 100644 index fd25700..0000000 --- a/velib_python/v3.40~38/dbusmonitor.py +++ /dev/null @@ -1,587 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value, add_name_owner_changed_receiver -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, namespace="com.victronenergy", ignoreServices=[]): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - self.ignoreServices = ignoreServices - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - # NOTE: this is on a different bus then the one above! - standardBus = (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()) - - add_name_owner_changed_receiver(standardBus, self.dbus_name_owner_changed) - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - # Subscribe to ItemsChanged for all services - self.dbusConn.add_signal_receiver(self.handler_item_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', path='/', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - @staticmethod - def make_service(serviceId, serviceName, deviceInstance): - """ Override this to use a different kind of service object. """ - return Service(serviceId, serviceName, deviceInstance) - - def make_monitor(self, service, path, value, text, options): - """ Override this to do more things with monitoring. """ - return MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - GLib.idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, service.deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - if (len(self.ignoreServices) != 0 and any(serviceName.startswith(x) for x in self.ignoreServices)): - logger.debug("Ignoring service %s" % serviceName) - return False - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - # Try to fetch everything with a GetItems, then fall back to older - # methods if that fails - try: - values = self.dbusConn.call_blocking(serviceName, '/', None, 'GetItems', '', []) - except dbus.exceptions.DBusException: - logger.info("GetItems failed, trying legacy methods") - else: - return self.scan_dbus_service_getitems_done(serviceName, serviceId, values) - - if serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = self.make_service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.items(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = self.make_monitor(service, path, unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def scan_dbus_service_getitems_done(self, serviceName, serviceId, values): - # Keeping these exceptions for legacy reasons - if serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = values['/DeviceInstance']['Value'] - except KeyError: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = self.make_service(serviceId, serviceName, di) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), {}) - for path, options in paths.items(): - item = values.get(path, notfound) - if item is notfound: - service.paths[path] = self.make_monitor(service, path, None, None, options) - else: - service.set_seen(path) - value = item.get('Value', None) - text = item.get('Text', None) - service.paths[path] = self.make_monitor(service, path, unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - return True - - def handler_item_changes(self, items, senderId): - if not isinstance(items, dict): - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - for path, changes in items.items(): - try: - v = unwrap_dbus_value(changes['Value']) - except (KeyError, TypeError): - continue - - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def handler_value_changes(self, changes, path, senderId): - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - v = unwrap_dbus_value(changes['Value']) - # Some services don't send Text with their PropertiesChanged events. - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def _handler_value_changes(self, service, path, value, text): - try: - a = service.paths[path] - except KeyError: - # path isn't there, which means it hasn't been scanned yet. - return - - service.set_seen(path) - - # First update our store to the new value - if a.value == value: - return - - a.value = value - a.text = text - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - GLib.idle_add(exit_on_error, self._execute_value_changes, service.name, path, { - 'Value': value, 'Text': text}, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.items() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - cb = partial(callback, *args, **kwargs) - - def root_tracker(items): - # Check if objectPath in dict - try: - v = items[objectPath] - _v = unwrap_dbus_value(v['Value']) - except (KeyError, TypeError): - return # not in this dict - - try: - t = v['Text'] - except KeyError: - cb({'Value': _v }) - else: - cb({'Value': _v, 'Text': t}) - - # Track changes on the path, and also on root - self.serviceWatches[serviceName].extend(( - self.dbusConn.add_signal_receiver(cb, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName), - self.dbusConn.add_signal_receiver(root_tracker, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', - path="/", bus_name=serviceName), - )) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print (len([o for o in objects if type(o).__name__ == 'VeDbusItemImport'])) - print (len([o for o in objects if type(o).__name__ == 'SignalMatch'])) - print (len(objects)) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print ("All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d)) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - GLib.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = GLib.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/v3.40~38/oldestVersion b/velib_python/v3.40~38/oldestVersion deleted file mode 100644 index 8aa0dc8..0000000 --- a/velib_python/v3.40~38/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v3.40~38 diff --git a/velib_python/v3.40~38/settingsdevice.py b/velib_python/v3.40~38/settingsdevice.py deleted file mode 100644 index a207e8b..0000000 --- a/velib_python/v3.40~38/settingsdevice.py +++ /dev/null @@ -1,118 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - self.addSettings(supportedSettings) - - logging.debug("===== Settings device init finished =====") - - def addSettings(self, settings): - for setting, options in settings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/v3.40~38/ve_utils.py b/velib_python/v3.40~38/ve_utils.py deleted file mode 100644 index f5a2f85..0000000 --- a/velib_python/v3.40~38/ve_utils.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import sys -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -class NoVrmPortalIdError(Exception): - pass - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using GLib.idle_add and also GLib.timeout_add. -# Without this, the code will just keep running, since GLib does not stop the mainloop on an -# exception. -# Example: GLib.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print ('exit_on_error: there was an exception. Printing stacktrace will be tried and then exit') - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # The original definition of the VRM Portal ID is that it is the mac - # address of the onboard- ethernet port (eth0), stripped from its colons - # (:) and lower case. This may however differ between platforms. On Venus - # the task is therefore deferred to /sbin/get-unique-id so that a - # platform specific method can be easily defined. - # - # If /sbin/get-unique-id does not exist, then use the ethernet address - # of eth0. This also handles the case where velib_python is used as a - # package install on a Raspberry Pi. - # - # On a Linux host where the network interface may not be eth0, you can set - # the VRM_IFACE environment variable to the correct name. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - portal_id = None - - # First try the method that works if we don't have a data partition. This - # will fail when the current user is not root. - try: - portal_id = check_output("/sbin/get-unique-id").decode("utf-8", "ignore").strip() - if not portal_id: - raise NoVrmPortalIdError("get-unique-id returned blank") - __vrm_portal_id = portal_id - return portal_id - except CalledProcessError: - # get-unique-id returned non-zero - raise NoVrmPortalIdError("get-unique-id returned non-zero") - except OSError: - # File doesn't exist, use fallback - pass - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0').encode('ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - except IOError: - raise NoVrmPortalIdError("ioctl failed for eth0") - - __vrm_portal_id = info[18:24].hex() - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception as ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r', encoding='UTF-8') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008', - 'Maxi GX': 'C009', - 'Cerbo GX': 'C00A' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception as ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return str(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([bytes(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val - -# When supported, only name owner changes for the the given namespace are reported. This -# prevents spending cpu time at irrelevant changes, like scripts accessing the bus temporarily. -def add_name_owner_changed_receiver(dbus, name_owner_changed, namespace="com.victronenergy"): - # support for arg0namespace is submitted upstream, but not included at the time of - # writing, Venus OS does support it, so try if it works. - if namespace is None: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') - else: - try: - dbus.add_signal_receiver(name_owner_changed, - signal_name='NameOwnerChanged', arg0namespace=namespace) - except TypeError: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') diff --git a/velib_python/v3.40~38/vedbus.py b/velib_python/v3.40~38/vedbus.py deleted file mode 100644 index 0407f6c..0000000 --- a/velib_python/v3.40~38/vedbus.py +++ /dev/null @@ -1,642 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from collections import defaultdict -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - self._ratelimiters = [] - self._dbusname = None - self.name = servicename - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = VeDbusRootExport(self._dbusconn, '/', self) - - def register(self): - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(self.name, self._dbusconn, do_not_queue=True) - logging.info("registered ourselves on D-Bus as %s" % self.name) - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in list(self._dbusnodes.values()): - node.__del__() - self._dbusnodes.clear() - for item in list(self._dbusobjects.values()): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - def get_name(self): - return self._dbusname.get_name() - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None, valuetype=None, itemtype=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - itemtype = itemtype or VeDbusItemExport - item = itemtype(self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted, valuetype=valuetype) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = VeDbusTreeExport(self._dbusconn, subPath, self) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - return item - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in list(self._dbusnodes.keys()): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - - def __enter__(self): - l = ServiceContext(self) - self._ratelimiters.append(l) - return l - - def __exit__(self, *exc): - # pop off the top one and flush it. If with statements are nested - # then each exit flushes its own part. - if self._ratelimiters: - self._ratelimiters.pop().flush() - -class ServiceContext(object): - def __init__(self, parent): - self.parent = parent - self.changes = {} - - def __contains__(self, path): - return path in self.parent - - def __getitem__(self, path): - return self.parent[path] - - def __setitem__(self, path, newvalue): - c = self.parent._dbusobjects[path]._local_set_value(newvalue) - if c is not None: - self.changes[path] = c - - def __delitem__(self, path): - if path in self.changes: - del self.changes[path] - del self.parent[path] - - def flush(self): - if self.changes: - self.parent._dbusnodes['/'].ItemsChanged(self.changes) - self.changes.clear() - - def add_path(self, path, value, *args, **kwargs): - self.parent.add_path(path, value, *args, **kwargs) - self.changes[path] = { - 'Value': wrap_dbus_value(value), - 'Text': self.parent._dbusobjects[path].GetText() - } - - def del_tree(self, root): - root = root.rstrip('/') - for p in list(self.parent._dbusobjects.keys()): - if p == root or p.startswith(root + '/'): - self[p] = None - self.parent._dbusobjects[p].__del__() - - def get_name(self): - return self.parent.get_name() - -class TrackerDict(defaultdict): - """ Same as defaultdict, but passes the key to default_factory. """ - def __missing__(self, key): - self[key] = x = self.default_factory(key) - return x - -class VeDbusRootTracker(object): - """ This tracks the root of a dbus path and listens for PropertiesChanged - signals. When a signal arrives, parse it and unpack the key/value changes - into traditional events, then pass it to the original eventCallback - method. """ - def __init__(self, bus, serviceName): - self.importers = defaultdict(weakref.WeakSet) - self.serviceName = serviceName - self._match = bus.get_object(serviceName, '/', introspect=False).connect_to_signal( - "ItemsChanged", weak_functor(self._items_changed_handler)) - - def __del__(self): - self._match.remove() - self._match = None - - def add(self, i): - self.importers[i.path].add(i) - - def _items_changed_handler(self, items): - if not isinstance(items, dict): - return - - for path, changes in items.items(): - try: - v = changes['Value'] - except KeyError: - continue - - try: - t = changes['Text'] - except KeyError: - t = str(unwrap_dbus_value(v)) - - for i in self.importers.get(path, ()): - i._properties_changed_handler({'Value': v, 'Text': t}) - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - def __new__(cls, bus, serviceName, path, eventCallback=None, createsignal=True): - instance = object.__new__(cls) - - # If signal tracking should be done, also add to root tracker - if createsignal: - if "_roots" not in cls.__dict__: - cls._roots = TrackerDict(lambda k: VeDbusRootTracker(bus, k)) - - return instance - - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - self._roots[serviceName].add(self) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match is not None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, service): - dbus.service.Object.__init__(self, bus, objectPath) - self._service = service - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - def _get_value_handler(self, path, get_text=False): - logging.debug("_get_value_handler called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._service._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - -class VeDbusRootExport(VeDbusTreeExport): - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sa{sv}}') - def ItemsChanged(self, changes): - pass - - @dbus.service.method('com.victronenergy.BusItem', out_signature='a{sa{sv}}') - def GetItems(self): - return { - path: { - 'Value': wrap_dbus_value(item.local_get_value()), - 'Text': item.GetText() } - for path, item in self._service._dbusobjects.items() - } - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None, - valuetype=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - self._type = valuetype - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - changes = self._local_set_value(newvalue) - if changes is not None: - self.PropertiesChanged(changes) - - def _local_set_value(self, newvalue): - if self._value == newvalue: - return None - - self._value = newvalue - return { - 'Value': wrap_dbus_value(newvalue), - 'Text': self.GetText() - } - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - # If value type is enforced, cast it. If the type can be coerced - # python will do it for us. This allows ints to become floats, - # or bools to become ints. Additionally also allow None, so that - # a path may be invalidated. - if self._type is not None and newvalue is not None: - try: - newvalue = self._type(newvalue) - except (ValueError, TypeError): - return 1 # NOT OK - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/velib_python/latest/ve_utils.py b/velib_python/ve_utils.py similarity index 100% rename from velib_python/latest/ve_utils.py rename to velib_python/ve_utils.py diff --git a/velib_python/latest/vedbus.py b/velib_python/vedbus.py similarity index 100% rename from velib_python/latest/vedbus.py rename to velib_python/vedbus.py diff --git a/velib_python/velib_python/latest/dbusmonitor.py b/velib_python/velib_python/latest/dbusmonitor.py deleted file mode 100644 index fd25700..0000000 --- a/velib_python/velib_python/latest/dbusmonitor.py +++ /dev/null @@ -1,587 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value, add_name_owner_changed_receiver -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, namespace="com.victronenergy", ignoreServices=[]): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - self.ignoreServices = ignoreServices - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - # NOTE: this is on a different bus then the one above! - standardBus = (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()) - - add_name_owner_changed_receiver(standardBus, self.dbus_name_owner_changed) - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - # Subscribe to ItemsChanged for all services - self.dbusConn.add_signal_receiver(self.handler_item_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', path='/', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - @staticmethod - def make_service(serviceId, serviceName, deviceInstance): - """ Override this to use a different kind of service object. """ - return Service(serviceId, serviceName, deviceInstance) - - def make_monitor(self, service, path, value, text, options): - """ Override this to do more things with monitoring. """ - return MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - GLib.idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, service.deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - if (len(self.ignoreServices) != 0 and any(serviceName.startswith(x) for x in self.ignoreServices)): - logger.debug("Ignoring service %s" % serviceName) - return False - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - # Try to fetch everything with a GetItems, then fall back to older - # methods if that fails - try: - values = self.dbusConn.call_blocking(serviceName, '/', None, 'GetItems', '', []) - except dbus.exceptions.DBusException: - logger.info("GetItems failed, trying legacy methods") - else: - return self.scan_dbus_service_getitems_done(serviceName, serviceId, values) - - if serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = self.make_service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.items(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = self.make_monitor(service, path, unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def scan_dbus_service_getitems_done(self, serviceName, serviceId, values): - # Keeping these exceptions for legacy reasons - if serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = values['/DeviceInstance']['Value'] - except KeyError: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = self.make_service(serviceId, serviceName, di) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), {}) - for path, options in paths.items(): - item = values.get(path, notfound) - if item is notfound: - service.paths[path] = self.make_monitor(service, path, None, None, options) - else: - service.set_seen(path) - value = item.get('Value', None) - text = item.get('Text', None) - service.paths[path] = self.make_monitor(service, path, unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - return True - - def handler_item_changes(self, items, senderId): - if not isinstance(items, dict): - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - for path, changes in items.items(): - try: - v = unwrap_dbus_value(changes['Value']) - except (KeyError, TypeError): - continue - - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def handler_value_changes(self, changes, path, senderId): - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - v = unwrap_dbus_value(changes['Value']) - # Some services don't send Text with their PropertiesChanged events. - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def _handler_value_changes(self, service, path, value, text): - try: - a = service.paths[path] - except KeyError: - # path isn't there, which means it hasn't been scanned yet. - return - - service.set_seen(path) - - # First update our store to the new value - if a.value == value: - return - - a.value = value - a.text = text - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - GLib.idle_add(exit_on_error, self._execute_value_changes, service.name, path, { - 'Value': value, 'Text': text}, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.items() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - cb = partial(callback, *args, **kwargs) - - def root_tracker(items): - # Check if objectPath in dict - try: - v = items[objectPath] - _v = unwrap_dbus_value(v['Value']) - except (KeyError, TypeError): - return # not in this dict - - try: - t = v['Text'] - except KeyError: - cb({'Value': _v }) - else: - cb({'Value': _v, 'Text': t}) - - # Track changes on the path, and also on root - self.serviceWatches[serviceName].extend(( - self.dbusConn.add_signal_receiver(cb, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName), - self.dbusConn.add_signal_receiver(root_tracker, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', - path="/", bus_name=serviceName), - )) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print (len([o for o in objects if type(o).__name__ == 'VeDbusItemImport'])) - print (len([o for o in objects if type(o).__name__ == 'SignalMatch'])) - print (len(objects)) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print ("All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d)) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - GLib.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = GLib.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/velib_python/latest/oldestVersion b/velib_python/velib_python/latest/oldestVersion deleted file mode 100644 index bdea676..0000000 --- a/velib_python/velib_python/latest/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v3.40~39 diff --git a/velib_python/velib_python/latest/settingsdevice.py b/velib_python/velib_python/latest/settingsdevice.py deleted file mode 100644 index a207e8b..0000000 --- a/velib_python/velib_python/latest/settingsdevice.py +++ /dev/null @@ -1,118 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - self.addSettings(supportedSettings) - - logging.debug("===== Settings device init finished =====") - - def addSettings(self, settings): - for setting, options in settings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/velib_python/latest/ve_utils.py b/velib_python/velib_python/latest/ve_utils.py deleted file mode 100644 index f5a2f85..0000000 --- a/velib_python/velib_python/latest/ve_utils.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import sys -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -class NoVrmPortalIdError(Exception): - pass - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using GLib.idle_add and also GLib.timeout_add. -# Without this, the code will just keep running, since GLib does not stop the mainloop on an -# exception. -# Example: GLib.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print ('exit_on_error: there was an exception. Printing stacktrace will be tried and then exit') - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # The original definition of the VRM Portal ID is that it is the mac - # address of the onboard- ethernet port (eth0), stripped from its colons - # (:) and lower case. This may however differ between platforms. On Venus - # the task is therefore deferred to /sbin/get-unique-id so that a - # platform specific method can be easily defined. - # - # If /sbin/get-unique-id does not exist, then use the ethernet address - # of eth0. This also handles the case where velib_python is used as a - # package install on a Raspberry Pi. - # - # On a Linux host where the network interface may not be eth0, you can set - # the VRM_IFACE environment variable to the correct name. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - portal_id = None - - # First try the method that works if we don't have a data partition. This - # will fail when the current user is not root. - try: - portal_id = check_output("/sbin/get-unique-id").decode("utf-8", "ignore").strip() - if not portal_id: - raise NoVrmPortalIdError("get-unique-id returned blank") - __vrm_portal_id = portal_id - return portal_id - except CalledProcessError: - # get-unique-id returned non-zero - raise NoVrmPortalIdError("get-unique-id returned non-zero") - except OSError: - # File doesn't exist, use fallback - pass - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0').encode('ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - except IOError: - raise NoVrmPortalIdError("ioctl failed for eth0") - - __vrm_portal_id = info[18:24].hex() - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception as ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r', encoding='UTF-8') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008', - 'Maxi GX': 'C009', - 'Cerbo GX': 'C00A' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception as ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return str(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([bytes(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val - -# When supported, only name owner changes for the the given namespace are reported. This -# prevents spending cpu time at irrelevant changes, like scripts accessing the bus temporarily. -def add_name_owner_changed_receiver(dbus, name_owner_changed, namespace="com.victronenergy"): - # support for arg0namespace is submitted upstream, but not included at the time of - # writing, Venus OS does support it, so try if it works. - if namespace is None: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') - else: - try: - dbus.add_signal_receiver(name_owner_changed, - signal_name='NameOwnerChanged', arg0namespace=namespace) - except TypeError: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') diff --git a/velib_python/velib_python/latest/vedbus.py b/velib_python/velib_python/latest/vedbus.py deleted file mode 100644 index cb95ba1..0000000 --- a/velib_python/velib_python/latest/vedbus.py +++ /dev/null @@ -1,646 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from collections import defaultdict -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None, register=True): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - self._ratelimiters = [] - self._dbusname = None - self.name = servicename - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = VeDbusRootExport(self._dbusconn, '/', self) - - # Immediately register the service unless requested not to - if register: - self.register() - - def register(self): - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(self.name, self._dbusconn, do_not_queue=True) - logging.info("registered ourselves on D-Bus as %s" % self.name) - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in list(self._dbusnodes.values()): - node.__del__() - self._dbusnodes.clear() - for item in list(self._dbusobjects.values()): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - def get_name(self): - return self._dbusname.get_name() - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None, valuetype=None, itemtype=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - itemtype = itemtype or VeDbusItemExport - item = itemtype(self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted, valuetype=valuetype) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = VeDbusTreeExport(self._dbusconn, subPath, self) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - return item - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in list(self._dbusnodes.keys()): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - - def __enter__(self): - l = ServiceContext(self) - self._ratelimiters.append(l) - return l - - def __exit__(self, *exc): - # pop off the top one and flush it. If with statements are nested - # then each exit flushes its own part. - if self._ratelimiters: - self._ratelimiters.pop().flush() - -class ServiceContext(object): - def __init__(self, parent): - self.parent = parent - self.changes = {} - - def __contains__(self, path): - return path in self.parent - - def __getitem__(self, path): - return self.parent[path] - - def __setitem__(self, path, newvalue): - c = self.parent._dbusobjects[path]._local_set_value(newvalue) - if c is not None: - self.changes[path] = c - - def __delitem__(self, path): - if path in self.changes: - del self.changes[path] - del self.parent[path] - - def flush(self): - if self.changes: - self.parent._dbusnodes['/'].ItemsChanged(self.changes) - self.changes.clear() - - def add_path(self, path, value, *args, **kwargs): - self.parent.add_path(path, value, *args, **kwargs) - self.changes[path] = { - 'Value': wrap_dbus_value(value), - 'Text': self.parent._dbusobjects[path].GetText() - } - - def del_tree(self, root): - root = root.rstrip('/') - for p in list(self.parent._dbusobjects.keys()): - if p == root or p.startswith(root + '/'): - self[p] = None - self.parent._dbusobjects[p].__del__() - - def get_name(self): - return self.parent.get_name() - -class TrackerDict(defaultdict): - """ Same as defaultdict, but passes the key to default_factory. """ - def __missing__(self, key): - self[key] = x = self.default_factory(key) - return x - -class VeDbusRootTracker(object): - """ This tracks the root of a dbus path and listens for PropertiesChanged - signals. When a signal arrives, parse it and unpack the key/value changes - into traditional events, then pass it to the original eventCallback - method. """ - def __init__(self, bus, serviceName): - self.importers = defaultdict(weakref.WeakSet) - self.serviceName = serviceName - self._match = bus.get_object(serviceName, '/', introspect=False).connect_to_signal( - "ItemsChanged", weak_functor(self._items_changed_handler)) - - def __del__(self): - self._match.remove() - self._match = None - - def add(self, i): - self.importers[i.path].add(i) - - def _items_changed_handler(self, items): - if not isinstance(items, dict): - return - - for path, changes in items.items(): - try: - v = changes['Value'] - except KeyError: - continue - - try: - t = changes['Text'] - except KeyError: - t = str(unwrap_dbus_value(v)) - - for i in self.importers.get(path, ()): - i._properties_changed_handler({'Value': v, 'Text': t}) - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - def __new__(cls, bus, serviceName, path, eventCallback=None, createsignal=True): - instance = object.__new__(cls) - - # If signal tracking should be done, also add to root tracker - if createsignal: - if "_roots" not in cls.__dict__: - cls._roots = TrackerDict(lambda k: VeDbusRootTracker(bus, k)) - - return instance - - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - self._roots[serviceName].add(self) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match is not None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, service): - dbus.service.Object.__init__(self, bus, objectPath) - self._service = service - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - def _get_value_handler(self, path, get_text=False): - logging.debug("_get_value_handler called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._service._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - -class VeDbusRootExport(VeDbusTreeExport): - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sa{sv}}') - def ItemsChanged(self, changes): - pass - - @dbus.service.method('com.victronenergy.BusItem', out_signature='a{sa{sv}}') - def GetItems(self): - return { - path: { - 'Value': wrap_dbus_value(item.local_get_value()), - 'Text': item.GetText() } - for path, item in self._service._dbusobjects.items() - } - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None, - valuetype=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - self._type = valuetype - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - changes = self._local_set_value(newvalue) - if changes is not None: - self.PropertiesChanged(changes) - - def _local_set_value(self, newvalue): - if self._value == newvalue: - return None - - self._value = newvalue - return { - 'Value': wrap_dbus_value(newvalue), - 'Text': self.GetText() - } - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - # If value type is enforced, cast it. If the type can be coerced - # python will do it for us. This allows ints to become floats, - # or bools to become ints. Additionally also allow None, so that - # a path may be invalidated. - if self._type is not None and newvalue is not None: - try: - newvalue = self._type(newvalue) - except (ValueError, TypeError): - return 1 # NOT OK - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/velib_python/velib_python/v2.73/dbusmonitor.py b/velib_python/velib_python/v2.73/dbusmonitor.py deleted file mode 100644 index fc8785d..0000000 --- a/velib_python/velib_python/v2.73/dbusmonitor.py +++ /dev/null @@ -1,535 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -import gobject -from gobject import idle_add -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from vedbus import VeDbusItemExport, VeDbusItemImport -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - whentologoptions = ['configChange', 'onIntervalAlwaysAndOnEvent', - 'onIntervalOnlyWhenChanged', 'onIntervalAlways', 'never'] - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - self.configChange = [] - self.onIntervalAlwaysAndOnEvent = [] - self.onIntervalOnlyWhenChanged = [] - self.onIntervalAlways = [] - self.never = [] - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, vebusDeviceInstance0=False): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - self.vebusDeviceInstance0 = vebusDeviceInstance0 - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()).add_signal_receiver( - self.dbus_name_owner_changed, - signal_name='NameOwnerChanged') - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - deviceInstance = service['deviceInstance'] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - # for vebus.ttyO1, this is workaround, since VRM Portal expects the main vebus - # devices at instance 0. Not sure how to fix this yet. - if serviceName == 'com.victronenergy.vebus.ttyO1' and self.vebusDeviceInstance0: - di = 0 - elif serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = Service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.iteritems(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - # check that the whenToLog setting is set to something we expect - assert options['whenToLog'] is None or options['whenToLog'] in Service.whentologoptions - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - if options['whenToLog']: - service[options['whenToLog']].append(path) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def handler_value_changes(self, changes, path, senderId): - try: - service = self.servicesById[senderId] - a = service.paths[path] - except KeyError: - # Either senderId or path isn't there, which means - # it hasn't been scanned yet. - return - - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - service.set_seen(path) - - # First update our store to the new value - changes['Value'] = unwrap_dbus_value(changes['Value']) - if a.value == changes['Value']: - return - - a.value = changes['Value'] - try: - a.text = changes['Text'] - except KeyError: - # Some services don't send Text with their PropertiesChanged events. - a.text = str(a.value) - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - idle_add(exit_on_error, self._execute_value_changes, service.name, path, changes, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.iteritems() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - # Parameter categoryfilter is to be a list, containing the categories you want (configChange, - # onIntervalAlways, etc). - # Returns a dictionary, keys are codes + instance, in VRM querystring format. For example vvt[0]. And - # values are the value. - def get_values(self, categoryfilter, converter=None): - - result = {} - - for serviceName in self.servicesByName: - result.update(self.get_values_for_service(categoryfilter, serviceName, converter)) - - return result - - # same as get_values above, but then for one service only - def get_values_for_service(self, categoryfilter, servicename, converter=None): - deviceInstance = self.get_device_instance(servicename) - result = {} - - service = self.servicesByName[servicename] - - for category in categoryfilter: - - for path in service[category]: - - value, text, options = service.paths[path] - - if value is not None: - - value = value if converter is None else converter.convert(path, options['code'], value, text) - - precision = options.get('precision') - if precision: - value = round(value, precision) - - result[options['code'] + "[" + str(deviceInstance) + "]"] = value - - return result - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - self.serviceWatches[serviceName].append( - self.dbusConn.add_signal_receiver( - partial(callback, *args, **kwargs), - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName)) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print len([o for o in objects if type(o).__name__ == 'VeDbusItemImport']) - print len([o for o in objects if type(o).__name__ == 'SignalMatch']) - print len(objects) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print "All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - # logger.info("==configchange values==") - # logger.info(pprint.pformat(d.get_values(['configChange']))) - - # logger.info("==onIntervalAlways and onIntervalOnlyWhenChanged==") - # logger.info(pprint.pformat(d.get_values(['onIntervalAlways', 'onIntervalAlwaysAndOnEvent']))) - - gobject.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = gobject.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/velib_python/v2.73/oldestVersion b/velib_python/velib_python/v2.73/oldestVersion deleted file mode 100644 index c4da1d4..0000000 --- a/velib_python/velib_python/v2.73/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v2.71 diff --git a/velib_python/velib_python/v2.73/settingsdevice.py b/velib_python/velib_python/v2.73/settingsdevice.py deleted file mode 100644 index b525375..0000000 --- a/velib_python/velib_python/v2.73/settingsdevice.py +++ /dev/null @@ -1,115 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - for setting, options in supportedSettings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - logging.debug("===== Settings device init finished =====") - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/velib_python/v2.73/ve_utils.py b/velib_python/velib_python/v2.73/ve_utils.py deleted file mode 100644 index c5cfb74..0000000 --- a/velib_python/velib_python/v2.73/ve_utils.py +++ /dev/null @@ -1,253 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using gobject.idle_add and also gobject.timeout_add. -# Without this, the code will just keep running, since gobject does not stop the mainloop on an -# exception. -# Example: gobject.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print 'exit_on_error: there was an exception. Printing stacktrace will be tried and then exit' - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # For the CCGX, the definition of the VRM Portal ID is that it is the mac address of the onboard- - # ethernet port (eth0), stripped from its colons (:) and lower case. - - # nice coincidence is that this also works fine when running on your (linux) development computer. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - # First try the method that works if we don't have a data partition. This will fail - # when the current user is not root. - try: - __vrm_portal_id = check_output("/sbin/get-unique-id").strip() - return __vrm_portal_id - except (CalledProcessError, OSError): - pass - - # Attempt to get the id from /data/venus/unique-id where venus puts it - # on startup. - try: - __vrm_portal_id = open('/data/venus/unique-id').read().strip() - except IOError: - pass - else: - return __vrm_portal_id - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - __vrm_portal_id = ''.join(['%02x' % ord(char) for char in info[18:24]]) - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception, ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def get_load_averages(): - c = read_file('/proc/loadavg') - return c.split(' ')[:3] - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip() - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip() - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception, ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, unicode): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, long): - return dbus.Int64(value, variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return unicode(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([str(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val diff --git a/velib_python/velib_python/v2.73/vedbus.py b/velib_python/velib_python/v2.73/vedbus.py deleted file mode 100644 index 7fbe55d..0000000 --- a/velib_python/velib_python/v2.73/vedbus.py +++ /dev/null @@ -1,501 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(servicename, self._dbusconn, do_not_queue=True) - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = self._create_tree_export(self._dbusconn, '/', self._get_tree_dict) - - logging.info("registered ourselves on D-Bus as %s" % servicename) - - def _get_tree_dict(self, path, get_text=False): - logging.debug("_get_tree_dict called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in self._dbusnodes.values(): - node.__del__() - self._dbusnodes.clear() - for item in self._dbusobjects.values(): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - item = VeDbusItemExport( - self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = self._create_tree_export(self._dbusconn, subPath, self._get_tree_dict) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - def _create_tree_export(self, bus, objectPath, get_value_handler): - return VeDbusTreeExport(bus, objectPath, get_value_handler) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in self._dbusnodes.keys(): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match != None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, get_value_handler): - dbus.service.Object.__init__(self, bus, objectPath) - self._get_value_handler = get_value_handler - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.local_set_value(None) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - if self._value == newvalue: - return - - self._value = newvalue - - changes = {} - changes['Value'] = wrap_dbus_value(newvalue) - changes['Text'] = self.GetText() - self.PropertiesChanged(changes) - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/velib_python/velib_python/v2.94/dbusmonitor.py b/velib_python/velib_python/v2.94/dbusmonitor.py deleted file mode 100644 index 5f8e153..0000000 --- a/velib_python/velib_python/v2.94/dbusmonitor.py +++ /dev/null @@ -1,592 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - whentologoptions = ['configChange', 'onIntervalAlwaysAndOnEvent', - 'onIntervalOnlyWhenChanged', 'onIntervalAlways', 'never'] - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - self.configChange = [] - self.onIntervalAlwaysAndOnEvent = [] - self.onIntervalOnlyWhenChanged = [] - self.onIntervalAlways = [] - self.never = [] - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, vebusDeviceInstance0=False): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - self.vebusDeviceInstance0 = vebusDeviceInstance0 - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()).add_signal_receiver( - self.dbus_name_owner_changed, - signal_name='NameOwnerChanged') - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - # Subscribe to ItemsChanged for all services - self.dbusConn.add_signal_receiver(self.handler_item_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', path='/', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - GLib.idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - deviceInstance = service['deviceInstance'] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - # for vebus.ttyO1, this is workaround, since VRM Portal expects the main vebus - # devices at instance 0. Not sure how to fix this yet. - if serviceName == 'com.victronenergy.vebus.ttyO1' and self.vebusDeviceInstance0: - di = 0 - elif serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = Service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.items(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - # check that the whenToLog setting is set to something we expect - assert options['whenToLog'] is None or options['whenToLog'] in Service.whentologoptions - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - if options['whenToLog']: - service[options['whenToLog']].append(path) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def handler_item_changes(self, items, senderId): - if not isinstance(items, dict): - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - for path, changes in items.items(): - try: - v = unwrap_dbus_value(changes['Value']) - except (KeyError, TypeError): - continue - - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def handler_value_changes(self, changes, path, senderId): - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - v = unwrap_dbus_value(changes['Value']) - # Some services don't send Text with their PropertiesChanged events. - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def _handler_value_changes(self, service, path, value, text): - try: - a = service.paths[path] - except KeyError: - # path isn't there, which means it hasn't been scanned yet. - return - - service.set_seen(path) - - # First update our store to the new value - if a.value == value: - return - - a.value = value - a.text = text - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - GLib.idle_add(exit_on_error, self._execute_value_changes, service.name, path, { - 'Value': value, 'Text': text}, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.items() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - # Parameter categoryfilter is to be a list, containing the categories you want (configChange, - # onIntervalAlways, etc). - # Returns a dictionary, keys are codes + instance, in VRM querystring format. For example vvt[0]. And - # values are the value. - def get_values(self, categoryfilter, converter=None): - - result = {} - - for serviceName in self.servicesByName: - result.update(self.get_values_for_service(categoryfilter, serviceName, converter)) - - return result - - # same as get_values above, but then for one service only - def get_values_for_service(self, categoryfilter, servicename, converter=None): - deviceInstance = self.get_device_instance(servicename) - result = {} - - service = self.servicesByName[servicename] - - for category in categoryfilter: - - for path in service[category]: - - value, text, options = service.paths[path] - - if value is not None: - - value = value if converter is None else converter.convert(path, options['code'], value, text) - - precision = options.get('precision') - if precision: - value = round(value, precision) - - result[options['code'] + "[" + str(deviceInstance) + "]"] = value - - return result - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - cb = partial(callback, *args, **kwargs) - - def root_tracker(items): - # Check if objectPath in dict - try: - v = items[objectPath] - _v = unwrap_dbus_value(v['Value']) - except (KeyError, TypeError): - return # not in this dict - - try: - t = v['Text'] - except KeyError: - cb({'Value': _v }) - else: - cb({'Value': _v, 'Text': t}) - - # Track changes on the path, and also on root - self.serviceWatches[serviceName].extend(( - self.dbusConn.add_signal_receiver(cb, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName), - self.dbusConn.add_signal_receiver(root_tracker, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', - path="/", bus_name=serviceName), - )) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print (len([o for o in objects if type(o).__name__ == 'VeDbusItemImport'])) - print (len([o for o in objects if type(o).__name__ == 'SignalMatch'])) - print (len(objects)) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print ("All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d)) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - # logger.info("==configchange values==") - # logger.info(pprint.pformat(d.get_values(['configChange']))) - - # logger.info("==onIntervalAlways and onIntervalOnlyWhenChanged==") - # logger.info(pprint.pformat(d.get_values(['onIntervalAlways', 'onIntervalAlwaysAndOnEvent']))) - - GLib.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = GLib.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/velib_python/v2.94/oldestVersion b/velib_python/velib_python/v2.94/oldestVersion deleted file mode 100644 index 366edb3..0000000 --- a/velib_python/velib_python/v2.94/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v2.80 diff --git a/velib_python/velib_python/v2.94/settingsdevice.py b/velib_python/velib_python/v2.94/settingsdevice.py deleted file mode 100644 index a207e8b..0000000 --- a/velib_python/velib_python/v2.94/settingsdevice.py +++ /dev/null @@ -1,118 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - self.addSettings(supportedSettings) - - logging.debug("===== Settings device init finished =====") - - def addSettings(self, settings): - for setting, options in settings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/velib_python/v2.94/ve_utils.py b/velib_python/velib_python/v2.94/ve_utils.py deleted file mode 100644 index e8d847d..0000000 --- a/velib_python/velib_python/v2.94/ve_utils.py +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import sys -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -class NoVrmPortalIdError(Exception): - pass - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using GLib.idle_add and also GLib.timeout_add. -# Without this, the code will just keep running, since GLib does not stop the mainloop on an -# exception. -# Example: GLib.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print ('exit_on_error: there was an exception. Printing stacktrace will be tried and then exit') - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # The original definition of the VRM Portal ID is that it is the mac - # address of the onboard- ethernet port (eth0), stripped from its colons - # (:) and lower case. This may however differ between platforms. On Venus - # the task is therefore deferred to /sbin/get-unique-id so that a - # platform specific method can be easily defined. - # - # If /sbin/get-unique-id does not exist, then use the ethernet address - # of eth0. This also handles the case where velib_python is used as a - # package install on a Raspberry Pi. - # - # On a Linux host where the network interface may not be eth0, you can set - # the VRM_IFACE environment variable to the correct name. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - portal_id = None - - # First try the method that works if we don't have a data partition. This - # will fail when the current user is not root. - try: - portal_id = check_output("/sbin/get-unique-id").decode("utf-8", "ignore").strip() - if not portal_id: - raise NoVrmPortalIdError("get-unique-id returned blank") - __vrm_portal_id = portal_id - return portal_id - except CalledProcessError: - # get-unique-id returned non-zero - raise NoVrmPortalIdError("get-unique-id returned non-zero") - except OSError: - # File doesn't exist, use fallback - pass - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0').encode('ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - except IOError: - raise NoVrmPortalIdError("ioctl failed for eth0") - - __vrm_portal_id = info[18:24].hex() - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception as ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def get_load_averages(): - c = read_file('/proc/loadavg') - return c.split(' ')[:3] - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r', encoding='UTF-8') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip() - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception as ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return str(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([bytes(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val diff --git a/velib_python/velib_python/v2.94/vedbus.py b/velib_python/velib_python/v2.94/vedbus.py deleted file mode 100644 index d6dac60..0000000 --- a/velib_python/velib_python/v2.94/vedbus.py +++ /dev/null @@ -1,599 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from collections import defaultdict -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - self._ratelimiters = [] - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(servicename, self._dbusconn, do_not_queue=True) - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = VeDbusRootExport(self._dbusconn, '/', self) - - logging.info("registered ourselves on D-Bus as %s" % servicename) - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in list(self._dbusnodes.values()): - node.__del__() - self._dbusnodes.clear() - for item in list(self._dbusobjects.values()): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - item = VeDbusItemExport( - self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = VeDbusTreeExport(self._dbusconn, subPath, self) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in list(self._dbusnodes.keys()): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - - def __enter__(self): - l = ServiceContext(self) - self._ratelimiters.append(l) - return l - - def __exit__(self, *exc): - # pop off the top one and flush it. If with statements are nested - # then each exit flushes its own part. - if self._ratelimiters: - self._ratelimiters.pop().flush() - -class ServiceContext(object): - def __init__(self, parent): - self.parent = parent - self.changes = {} - - def __getitem__(self, path): - return self.parent[path] - - def __setitem__(self, path, newvalue): - c = self.parent._dbusobjects[path]._local_set_value(newvalue) - if c is not None: - self.changes[path] = c - - def flush(self): - if self.changes: - self.parent._dbusnodes['/'].ItemsChanged(self.changes) - -class TrackerDict(defaultdict): - """ Same as defaultdict, but passes the key to default_factory. """ - def __missing__(self, key): - self[key] = x = self.default_factory(key) - return x - -class VeDbusRootTracker(object): - """ This tracks the root of a dbus path and listens for PropertiesChanged - signals. When a signal arrives, parse it and unpack the key/value changes - into traditional events, then pass it to the original eventCallback - method. """ - def __init__(self, bus, serviceName): - self.importers = defaultdict(weakref.WeakSet) - self.serviceName = serviceName - self._match = bus.get_object(serviceName, '/', introspect=False).connect_to_signal( - "ItemsChanged", weak_functor(self._items_changed_handler)) - - def __del__(self): - self._match.remove() - self._match = None - - def add(self, i): - self.importers[i.path].add(i) - - def _items_changed_handler(self, items): - if not isinstance(items, dict): - return - - for path, changes in items.items(): - try: - v = changes['Value'] - except KeyError: - continue - - try: - t = changes['Text'] - except KeyError: - t = str(unwrap_dbus_value(v)) - - for i in self.importers.get(path, ()): - i._properties_changed_handler({'Value': v, 'Text': t}) - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - def __new__(cls, bus, serviceName, path, eventCallback=None, createsignal=True): - instance = object.__new__(cls) - - # If signal tracking should be done, also add to root tracker - if createsignal: - if "_roots" not in cls.__dict__: - cls._roots = TrackerDict(lambda k: VeDbusRootTracker(bus, k)) - - return instance - - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - self._roots[serviceName].add(self) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match is not None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, service): - dbus.service.Object.__init__(self, bus, objectPath) - self._service = service - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - def _get_value_handler(self, path, get_text=False): - logging.debug("_get_value_handler called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._service._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - -class VeDbusRootExport(VeDbusTreeExport): - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sa{sv}}') - def ItemsChanged(self, changes): - pass - - @dbus.service.method('com.victronenergy.BusItem', out_signature='a{sa{sv}}') - def GetItems(self): - return { - path: { - 'Value': wrap_dbus_value(item.local_get_value()), - 'Text': item.GetText() } - for path, item in self._service._dbusobjects.items() - } - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.local_set_value(None) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - changes = self._local_set_value(newvalue) - if changes is not None: - self.PropertiesChanged(changes) - - def _local_set_value(self, newvalue): - if self._value == newvalue: - return None - - self._value = newvalue - return { - 'Value': wrap_dbus_value(newvalue), - 'Text': self.GetText() - } - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/velib_python/velib_python/v3.40~37/dbusmonitor.py b/velib_python/velib_python/v3.40~37/dbusmonitor.py deleted file mode 100644 index cb2185d..0000000 --- a/velib_python/velib_python/v3.40~37/dbusmonitor.py +++ /dev/null @@ -1,554 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -## @package dbus_vrm -# This code takes care of the D-Bus interface (not all of below is implemented yet): -# - on startup it scans the dbus for services we know. For each known service found, it searches for -# objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a -# value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger. -# we know. -# - after startup, it continues to monitor the dbus: -# 1) when services are added we do the same check on that -# 2) when services are removed, we remove any items that we had that referred to that service -# 3) if an existing services adds paths we update ourselves as well: on init, we make a -# VeDbusItemImport for a non-, or not yet existing objectpaths as well1 -# -# Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo. - -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib -import dbus -import dbus.service -import inspect -import logging -import argparse -import pprint -import traceback -import os -from collections import defaultdict -from functools import partial - -# our own packages -from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value -notfound = object() # For lookups where None is a valid result - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class SystemBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM) - -class SessionBus(dbus.bus.BusConnection): - def __new__(cls): - return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION) - -class MonitoredValue(object): - def __init__(self, value, text, options): - super(MonitoredValue, self).__init__() - self.value = value - self.text = text - self.options = options - - # For legacy code, allow treating this as a tuple/list - def __iter__(self): - return iter((self.value, self.text, self.options)) - -class Service(object): - def __init__(self, id, serviceName, deviceInstance): - super(Service, self).__init__() - self.id = id - self.name = serviceName - self.paths = {} - self._seen = set() - self.deviceInstance = deviceInstance - - # For legacy code, attributes can still be accessed as if keys from a - # dictionary. - def __setitem__(self, key, value): - self.__dict__[key] = value - def __getitem__(self, key): - return self.__dict__[key] - - def set_seen(self, path): - self._seen.add(path) - - def seen(self, path): - return path in self._seen - - @property - def service_class(self): - return '.'.join(self.name.split('.')[:3]) - -class DbusMonitor(object): - ## Constructor - def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None, - deviceRemovedCallback=None, namespace="com.victronenergy"): - # valueChangedCallback is the callback that we call when something has changed. - # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance): - # in which changes is a tuple with GetText() and GetValue() - self.valueChangedCallback = valueChangedCallback - self.deviceAddedCallback = deviceAddedCallback - self.deviceRemovedCallback = deviceRemovedCallback - self.dbusTree = dbusTree - - # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info - # indexed by service name (eg. com.victronenergy.settings). - self.servicesByName = {} - - # Same values as self.servicesByName, but indexed by service id (eg. :1.30) - self.servicesById = {} - - # Keep track of services by class to speed up calls to get_service_list - self.servicesByClass = defaultdict(list) - - # Keep track of any additional watches placed on items - self.serviceWatches = defaultdict(list) - - # For a PC, connect to the SessionBus - # For a CCGX, connect to the SystemBus - self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus() - - # subscribe to NameOwnerChange for bus connect / disconnect events. - # NOTE: this is on a different bus then the one above! - standardBus = (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \ - else dbus.SystemBus()) - - self.add_name_owner_changed_receiver(standardBus, self.dbus_name_owner_changed) - - # Subscribe to PropertiesChanged for all services - self.dbusConn.add_signal_receiver(self.handler_value_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', path_keyword='path', - sender_keyword='senderId') - - # Subscribe to ItemsChanged for all services - self.dbusConn.add_signal_receiver(self.handler_item_changes, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', path='/', - sender_keyword='senderId') - - logger.info('===== Search on dbus for services that we will monitor starting... =====') - serviceNames = self.dbusConn.list_names() - for serviceName in serviceNames: - self.scan_dbus_service(serviceName) - - logger.info('===== Search on dbus for services that we will monitor finished =====') - - @staticmethod - def make_service(serviceId, serviceName, deviceInstance): - """ Override this to use a different kind of service object. """ - return Service(serviceId, serviceName, deviceInstance) - - def make_monitor(self, service, path, value, text, options): - """ Override this to do more things with monitoring. """ - return MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - def dbus_name_owner_changed(self, name, oldowner, newowner): - if not name.startswith("com.victronenergy."): - return - - #decouple, and process in main loop - GLib.idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner) - - @staticmethod - # When supported, only name owner changes for the the given namespace are reported. This - # prevents spending cpu time at irrelevant changes, like scripts accessing the bus temporarily. - def add_name_owner_changed_receiver(dbus, name_owner_changed, namespace="com.victronenergy"): - # support for arg0namespace is submitted upstream, but not included at the time of - # writing, Venus OS does support it, so try if it works. - if namespace is None: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') - else: - try: - dbus.add_signal_receiver(name_owner_changed, - signal_name='NameOwnerChanged', arg0namespace=namespace) - except TypeError: - dbus.add_signal_receiver(name_owner_changed, signal_name='NameOwnerChanged') - - def _process_name_owner_changed(self, name, oldowner, newowner): - if newowner != '': - # so we found some new service. Check if we can do something with it. - newdeviceadded = self.scan_dbus_service(name) - if newdeviceadded and self.deviceAddedCallback is not None: - self.deviceAddedCallback(name, self.get_device_instance(name)) - - elif name in self.servicesByName: - # it disappeared, we need to remove it. - logger.info("%s disappeared from the dbus. Removing it from our lists" % name) - service = self.servicesByName[name] - del self.servicesById[service.id] - del self.servicesByName[name] - for watch in self.serviceWatches[name]: - watch.remove() - del self.serviceWatches[name] - self.servicesByClass[service.service_class].remove(service) - if self.deviceRemovedCallback is not None: - self.deviceRemovedCallback(name, service.deviceInstance) - - def scan_dbus_service(self, serviceName): - try: - return self.scan_dbus_service_inner(serviceName) - except: - logger.error("Ignoring %s because of error while scanning:" % (serviceName)) - traceback.print_exc() - return False - - # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and - # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service - # disappears while its being scanned. Which might happen, but is not really - # normal either, so letting them go into the logs. - - # Scans the given dbus service to see if it contains anything interesting for us. If it does, add - # it to our list of monitored D-Bus services. - def scan_dbus_service_inner(self, serviceName): - - # make it a normal string instead of dbus string - serviceName = str(serviceName) - - paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None) - if paths is None: - logger.debug("Ignoring service %s, not in the tree" % serviceName) - return False - - logger.info("Found: %s, scanning and storing items" % serviceName) - serviceId = self.dbusConn.get_name_owner(serviceName) - - # we should never be notified to add a D-Bus service that we already have. If this assertion - # raises, check process_name_owner_changed, and D-Bus workings. - assert serviceName not in self.servicesByName - assert serviceId not in self.servicesById - - if serviceName == 'com.victronenergy.settings': - di = 0 - elif serviceName.startswith('com.victronenergy.vecan.'): - di = 0 - else: - try: - di = self.dbusConn.call_blocking(serviceName, - '/DeviceInstance', None, 'GetValue', '', []) - except dbus.exceptions.DBusException: - logger.info(" %s was skipped because it has no device instance" % serviceName) - return False # Skip it - else: - di = int(di) - - logger.info(" %s has device instance %s" % (serviceName, di)) - service = self.make_service(serviceId, serviceName, di) - - # Let's try to fetch everything in one go - values = {} - texts = {} - try: - values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', [])) - texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', [])) - except: - pass - - for path, options in paths.items(): - # path will be the D-Bus path: '/Ac/ActiveIn/L1/V' - # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'} - - # Try to obtain the value we want from our bulk fetch. If we - # cannot find it there, do an individual query. - value = values.get(path[1:], notfound) - if value != notfound: - service.set_seen(path) - text = texts.get(path[1:], notfound) - if value is notfound or text is notfound: - try: - value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', []) - service.set_seen(path) - text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', []) - except dbus.exceptions.DBusException as e: - if e.get_dbus_name() in ( - 'org.freedesktop.DBus.Error.ServiceUnknown', - 'org.freedesktop.DBus.Error.Disconnected'): - raise # This exception will be handled below - - # TODO org.freedesktop.DBus.Error.UnknownMethod really - # shouldn't happen but sometimes does. - logger.debug("%s %s does not exist (yet)" % (serviceName, path)) - value = None - text = None - - service.paths[path] = self.make_monitor(service, path, unwrap_dbus_value(value), unwrap_dbus_value(text), options) - - - logger.debug("Finished scanning and storing items for %s" % serviceName) - - # Adjust self at the end of the scan, so we don't have an incomplete set of - # data if an exception occurs during the scan. - self.servicesByName[serviceName] = service - self.servicesById[serviceId] = service - self.servicesByClass[service.service_class].append(service) - - return True - - def handler_item_changes(self, items, senderId): - if not isinstance(items, dict): - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - for path, changes in items.items(): - try: - v = unwrap_dbus_value(changes['Value']) - except (KeyError, TypeError): - continue - - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def handler_value_changes(self, changes, path, senderId): - # If this properyChange does not involve a value, our work is done. - if 'Value' not in changes: - return - - try: - service = self.servicesById[senderId] - except KeyError: - # senderId isn't there, which means it hasn't been scanned yet. - return - - v = unwrap_dbus_value(changes['Value']) - # Some services don't send Text with their PropertiesChanged events. - try: - t = changes['Text'] - except KeyError: - t = str(v) - self._handler_value_changes(service, path, v, t) - - def _handler_value_changes(self, service, path, value, text): - try: - a = service.paths[path] - except KeyError: - # path isn't there, which means it hasn't been scanned yet. - return - - service.set_seen(path) - - # First update our store to the new value - if a.value == value: - return - - a.value = value - a.text = text - - # And do the rest of the processing in on the mainloop - if self.valueChangedCallback is not None: - GLib.idle_add(exit_on_error, self._execute_value_changes, service.name, path, { - 'Value': value, 'Text': text}, a.options) - - def _execute_value_changes(self, serviceName, objectPath, changes, options): - # double check that the service still exists, as it might have - # disappeared between scheduling-for and executing this function. - if serviceName not in self.servicesByName: - return - - self.valueChangedCallback(serviceName, objectPath, - options, changes, self.get_device_instance(serviceName)) - - # Gets the value for a certain servicename and path - # The default_value is returned when: - # 1. When the service doesn't exist. - # 2. When the path asked for isn't being monitored. - # 3. When the path exists, but has dbus-invalid, ie an empty byte array. - # 4. When the path asked for is being monitored, but doesn't exist for that service. - def get_value(self, serviceName, objectPath, default_value=None): - service = self.servicesByName.get(serviceName, None) - if service is None: - return default_value - - value = service.paths.get(objectPath, None) - if value is None or value.value is None: - return default_value - - return value.value - - # returns if a dbus exists now, by doing a blocking dbus call. - # Typically seen will be sufficient and doesn't need access to the dbus. - def exists(self, serviceName, objectPath): - try: - self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', []) - return True - except dbus.exceptions.DBusException as e: - return False - - # Returns if there ever was a successful GetValue or valueChanged event. - # Unlike get_value this return True also if the actual value is invalid. - # - # Note: the path might no longer exists anymore, but that doesn't happen in - # practice. If a service really wants to reconfigure itself typically it should - # reconnect to the dbus which causes it to be rescanned and seen will be updated. - # If it is really needed to know if a path still exists, use exists. - def seen(self, serviceName, objectPath): - try: - return self.servicesByName[serviceName].seen(objectPath) - except KeyError: - return False - - # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue - # method. If the underlying item does not exist (the service does not exist, or the objectPath was not - # registered) the function will return -1 - def set_value(self, serviceName, objectPath, value): - # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no - # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport - # objects for registers items only. - service = self.servicesByName.get(serviceName, None) - if service is None: - return -1 - if objectPath not in service.paths: - return -1 - # We do not catch D-Bus exceptions here, because the previous implementation did not do that either. - return self.dbusConn.call_blocking(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)]) - - # Similar to set_value, but operates asynchronously - def set_value_async(self, serviceName, objectPath, value, - reply_handler=None, error_handler=None): - service = self.servicesByName.get(serviceName, None) - if service is not None: - if objectPath in service.paths: - self.dbusConn.call_async(serviceName, objectPath, - dbus_interface='com.victronenergy.BusItem', - method='SetValue', signature=None, - args=[wrap_dbus_value(value)], - reply_handler=reply_handler, error_handler=error_handler) - return - - if error_handler is not None: - error_handler(TypeError('Service or path not found, ' - 'service=%s, path=%s' % (serviceName, objectPath))) - - # returns a dictionary, keys are the servicenames, value the instances - # optionally use the classfilter to get only a certain type of services, for - # example com.victronenergy.battery. - def get_service_list(self, classfilter=None): - if classfilter is None: - return { servicename: service.deviceInstance \ - for servicename, service in self.servicesByName.items() } - - if classfilter not in self.servicesByClass: - return {} - - return { service.name: service.deviceInstance \ - for service in self.servicesByClass[classfilter] } - - def get_device_instance(self, serviceName): - return self.servicesByName[serviceName].deviceInstance - - def track_value(self, serviceName, objectPath, callback, *args, **kwargs): - """ A DbusMonitor can watch specific service/path combos for changes - so that it is not fully reliant on the global handler_value_changes - in this class. Additional watches are deleted automatically when - the service disappears from dbus. """ - cb = partial(callback, *args, **kwargs) - - def root_tracker(items): - # Check if objectPath in dict - try: - v = items[objectPath] - _v = unwrap_dbus_value(v['Value']) - except (KeyError, TypeError): - return # not in this dict - - try: - t = v['Text'] - except KeyError: - cb({'Value': _v }) - else: - cb({'Value': _v, 'Text': t}) - - # Track changes on the path, and also on root - self.serviceWatches[serviceName].extend(( - self.dbusConn.add_signal_receiver(cb, - dbus_interface='com.victronenergy.BusItem', - signal_name='PropertiesChanged', - path=objectPath, bus_name=serviceName), - self.dbusConn.add_signal_receiver(root_tracker, - dbus_interface='com.victronenergy.BusItem', - signal_name='ItemsChanged', - path="/", bus_name=serviceName), - )) - - -# ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ====== - -# Example function that can be used as a starting point to use this code -def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance): - logger.debug("0 ----------------") - logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath)) - logger.debug("2 vrm dict : %s" % dict) - logger.debug("3 changes-text: %s" % changes['Text']) - logger.debug("4 changes-value: %s" % changes['Value']) - logger.debug("5 deviceInstance: %s" % deviceInstance) - logger.debug("6 - end") - - -def nameownerchange(a, b): - # used to find memory leaks in dbusmonitor and VeDbusItemImport - import gc - gc.collect() - objects = gc.get_objects() - print (len([o for o in objects if type(o).__name__ == 'VeDbusItemImport'])) - print (len([o for o in objects if type(o).__name__ == 'SignalMatch'])) - print (len(objects)) - - -def print_values(dbusmonitor): - a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000) - b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000) - c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000) - d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000) - - print ("All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d)) - return True - -# We have a mainloop, but that is just for developing this code. Normally above class & code is used from -# some other class, such as vrmLogger or the pubsub Implementation. -def main(): - # Init logging - logging.basicConfig(level=logging.DEBUG) - logger.info(__file__ + " is starting up") - - # Have a mainloop, so we can send/receive asynchronous calls to and from dbus - DBusGMainLoop(set_as_default=True) - - import os - import sys - sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../')) - - dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None} - monitorlist = {'com.victronenergy.dummyservice': { - '/Connected': dummy, - '/ProductName': dummy, - '/Mgmt/Connection': dummy, - '/Dc/0/Voltage': dummy, - '/Dc/0/Current': dummy, - '/Dc/0/Temperature': dummy, - '/Load/I': dummy, - '/FirmwareVersion': dummy, - '/DbusInvalid': dummy, - '/NonExistingButMonitored': dummy}} - - d = DbusMonitor(monitorlist, value_changed_on_dbus, - deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange) - - GLib.timeout_add(1000, print_values, d) - - # Start and run the mainloop - logger.info("Starting mainloop, responding on only events") - mainloop = GLib.MainLoop() - mainloop.run() - -if __name__ == "__main__": - main() diff --git a/velib_python/velib_python/v3.40~37/oldestVersion b/velib_python/velib_python/v3.40~37/oldestVersion deleted file mode 100644 index 3f6c1a0..0000000 --- a/velib_python/velib_python/v3.40~37/oldestVersion +++ /dev/null @@ -1 +0,0 @@ -v3.00~32 diff --git a/velib_python/velib_python/v3.40~37/settingsdevice.py b/velib_python/velib_python/v3.40~37/settingsdevice.py deleted file mode 100644 index a207e8b..0000000 --- a/velib_python/velib_python/v3.40~37/settingsdevice.py +++ /dev/null @@ -1,118 +0,0 @@ -import dbus -import logging -import time -from functools import partial - -# Local imports -from vedbus import VeDbusItemImport - -## Indexes for the setting dictonary. -PATH = 0 -VALUE = 1 -MINIMUM = 2 -MAXIMUM = 3 -SILENT = 4 - -## The Settings Device class. -# Used by python programs, such as the vrm-logger, to read and write settings they -# need to store on disk. And since these settings might be changed from a different -# source, such as the GUI, the program can pass an eventCallback that will be called -# as soon as some setting is changed. -# -# The settings are stored in flash via the com.victronenergy.settings service on dbus. -# See https://github.com/victronenergy/localsettings for more info. -# -# If there are settings in de supportSettings list which are not yet on the dbus, -# and therefore not yet in the xml file, they will be added through the dbus-addSetting -# interface of com.victronenergy.settings. -class SettingsDevice(object): - ## The constructor processes the tree of dbus-items. - # @param bus the system-dbus object - # @param name the dbus-service-name of the settings dbus service, 'com.victronenergy.settings' - # @param supportedSettings dictionary with all setting-names, and their defaultvalue, min, max and whether - # the setting is silent. The 'silent' entry is optional. If set to true, no changes in the setting will - # be logged by localsettings. - # @param eventCallback function that will be called on changes on any of these settings - # @param timeout Maximum interval to wait for localsettings. An exception is thrown at the end of the - # interval if the localsettings D-Bus service has not appeared yet. - def __init__(self, bus, supportedSettings, eventCallback, name='com.victronenergy.settings', timeout=0): - logging.debug("===== Settings device init starting... =====") - self._bus = bus - self._dbus_name = name - self._eventCallback = eventCallback - self._values = {} # stored the values, used to pass the old value along on a setting change - self._settings = {} - - count = 0 - while True: - if 'com.victronenergy.settings' in self._bus.list_names(): - break - if count == timeout: - raise Exception("The settings service com.victronenergy.settings does not exist!") - count += 1 - logging.info('waiting for settings') - time.sleep(1) - - # Add the items. - self.addSettings(supportedSettings) - - logging.debug("===== Settings device init finished =====") - - def addSettings(self, settings): - for setting, options in settings.items(): - silent = len(options) > SILENT and options[SILENT] - busitem = self.addSetting(options[PATH], options[VALUE], - options[MINIMUM], options[MAXIMUM], silent, callback=partial(self.handleChangedSetting, setting)) - self._settings[setting] = busitem - self._values[setting] = busitem.get_value() - - def addSetting(self, path, value, _min, _max, silent=False, callback=None): - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - if busitem.exists and (value, _min, _max, silent) == busitem._proxy.GetAttributes(): - logging.debug("Setting %s found" % path) - else: - logging.info("Setting %s does not exist yet or must be adjusted" % path) - - # Prepare to add the setting. Most dbus types extend the python - # type so it is only necessary to additionally test for Int64. - if isinstance(value, (int, dbus.Int64)): - itemType = 'i' - elif isinstance(value, float): - itemType = 'f' - else: - itemType = 's' - - # Add the setting - # TODO, make an object that inherits VeDbusItemImport, and complete the D-Bus settingsitem interface - settings_item = VeDbusItemImport(self._bus, self._dbus_name, '/Settings', createsignal=False) - setting_path = path.replace('/Settings/', '', 1) - if silent: - settings_item._proxy.AddSilentSetting('', setting_path, value, itemType, _min, _max) - else: - settings_item._proxy.AddSetting('', setting_path, value, itemType, _min, _max) - - busitem = VeDbusItemImport(self._bus, self._dbus_name, path, callback) - - return busitem - - def handleChangedSetting(self, setting, servicename, path, changes): - oldvalue = self._values[setting] if setting in self._values else None - self._values[setting] = changes['Value'] - - if self._eventCallback is None: - return - - self._eventCallback(setting, oldvalue, changes['Value']) - - def setDefault(self, path): - item = VeDbusItemImport(self._bus, self._dbus_name, path, createsignal=False) - item.set_default() - - def __getitem__(self, setting): - return self._settings[setting].get_value() - - def __setitem__(self, setting, newvalue): - result = self._settings[setting].set_value(newvalue) - if result != 0: - # Trying to make some false change to our own settings? How dumb! - assert False diff --git a/velib_python/velib_python/v3.40~37/ve_utils.py b/velib_python/velib_python/v3.40~37/ve_utils.py deleted file mode 100644 index 63a915b..0000000 --- a/velib_python/velib_python/v3.40~37/ve_utils.py +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import sys -from traceback import print_exc -from os import _exit as os_exit -from os import statvfs -from subprocess import check_output, CalledProcessError -import logging -import dbus -logger = logging.getLogger(__name__) - -VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1) - -class NoVrmPortalIdError(Exception): - pass - -# Use this function to make sure the code quits on an unexpected exception. Make sure to use it -# when using GLib.idle_add and also GLib.timeout_add. -# Without this, the code will just keep running, since GLib does not stop the mainloop on an -# exception. -# Example: GLib.idle_add(exit_on_error, myfunc, arg1, arg2) -def exit_on_error(func, *args, **kwargs): - try: - return func(*args, **kwargs) - except: - try: - print ('exit_on_error: there was an exception. Printing stacktrace will be tried and then exit') - print_exc() - except: - pass - - # sys.exit() is not used, since that throws an exception, which does not lead to a program - # halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230. - os_exit(1) - - -__vrm_portal_id = None -def get_vrm_portal_id(): - # The original definition of the VRM Portal ID is that it is the mac - # address of the onboard- ethernet port (eth0), stripped from its colons - # (:) and lower case. This may however differ between platforms. On Venus - # the task is therefore deferred to /sbin/get-unique-id so that a - # platform specific method can be easily defined. - # - # If /sbin/get-unique-id does not exist, then use the ethernet address - # of eth0. This also handles the case where velib_python is used as a - # package install on a Raspberry Pi. - # - # On a Linux host where the network interface may not be eth0, you can set - # the VRM_IFACE environment variable to the correct name. - - global __vrm_portal_id - - if __vrm_portal_id: - return __vrm_portal_id - - portal_id = None - - # First try the method that works if we don't have a data partition. This - # will fail when the current user is not root. - try: - portal_id = check_output("/sbin/get-unique-id").decode("utf-8", "ignore").strip() - if not portal_id: - raise NoVrmPortalIdError("get-unique-id returned blank") - __vrm_portal_id = portal_id - return portal_id - except CalledProcessError: - # get-unique-id returned non-zero - raise NoVrmPortalIdError("get-unique-id returned non-zero") - except OSError: - # File doesn't exist, use fallback - pass - - # Fall back to getting our id using a syscall. Assume we are on linux. - # Allow the user to override what interface is used using an environment - # variable. - import fcntl, socket, struct, os - - iface = os.environ.get('VRM_IFACE', 'eth0').encode('ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15])) - except IOError: - raise NoVrmPortalIdError("ioctl failed for eth0") - - __vrm_portal_id = info[18:24].hex() - return __vrm_portal_id - - -# See VE.Can registers - public.docx for definition of this conversion -def convert_vreg_version_to_readable(version): - def str_to_arr(x, length): - a = [] - for i in range(0, len(x), length): - a.append(x[i:i+length]) - return a - - x = "%x" % version - x = x.upper() - - if len(x) == 5 or len(x) == 3 or len(x) == 1: - x = '0' + x - - a = str_to_arr(x, 2); - - # remove the first 00 if there are three bytes and it is 00 - if len(a) == 3 and a[0] == '00': - a.remove(0); - - # if we have two or three bytes now, and the first character is a 0, remove it - if len(a) >= 2 and a[0][0:1] == '0': - a[0] = a[0][1]; - - result = '' - for item in a: - result += ('.' if result != '' else '') + item - - - result = 'v' + result - - return result - - -def get_free_space(path): - result = -1 - - try: - s = statvfs(path) - result = s.f_frsize * s.f_bavail # Number of free bytes that ordinary users - except Exception as ex: - logger.info("Error while retrieving free space for path %s: %s" % (path, ex)) - - return result - - -def _get_sysfs_machine_name(): - try: - with open('/sys/firmware/devicetree/base/model', 'r') as f: - return f.read().rstrip('\x00') - except IOError: - pass - - return None - -# Returns None if it cannot find a machine name. Otherwise returns the string -# containing the name -def get_machine_name(): - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-name").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back to sysfs - name = _get_sysfs_machine_name() - if name is not None: - return name - - # Fall back to venus build machine name - try: - with open('/etc/venus/machine', 'r', encoding='UTF-8') as f: - return f.read().strip() - except IOError: - pass - - return None - - -def get_product_id(): - """ Find the machine ID and return it. """ - - # First try calling the venus utility script - try: - return check_output("/usr/bin/product-id").strip().decode('UTF-8') - except (CalledProcessError, OSError): - pass - - # Fall back machine name mechanism - name = _get_sysfs_machine_name() - return { - 'Color Control GX': 'C001', - 'Venus GX': 'C002', - 'Octo GX': 'C006', - 'EasySolar-II': 'C007', - 'MultiPlus-II': 'C008', - 'Maxi GX': 'C009', - 'Cerbo GX': 'C00A' - }.get(name, 'C003') # C003 is Generic - - -# Returns False if it cannot open the file. Otherwise returns its rstripped contents -def read_file(path): - content = False - - try: - with open(path, 'r') as f: - content = f.read().rstrip() - except Exception as ex: - logger.debug("Error while reading %s: %s" % (path, ex)) - - return content - - -def wrap_dbus_value(value): - if value is None: - return VEDBUS_INVALID - if isinstance(value, float): - return dbus.Double(value, variant_level=1) - if isinstance(value, bool): - return dbus.Boolean(value, variant_level=1) - if isinstance(value, int): - try: - return dbus.Int32(value, variant_level=1) - except OverflowError: - return dbus.Int64(value, variant_level=1) - if isinstance(value, str): - return dbus.String(value, variant_level=1) - if isinstance(value, list): - if len(value) == 0: - # If the list is empty we cannot infer the type of the contents. So assume unsigned integer. - # A (signed) integer is dangerous, because an empty list of signed integers is used to encode - # an invalid value. - return dbus.Array([], signature=dbus.Signature('u'), variant_level=1) - return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1) - if isinstance(value, dict): - # Wrapping the keys of the dictionary causes D-Bus errors like: - # 'arguments to dbus_message_iter_open_container() were incorrect, - # assertion "(type == DBUS_TYPE_ARRAY && contained_signature && - # *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || - # _dbus_check_is_valid_signature (contained_signature))" failed in file ...' - return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1) - return value - - -dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64) - - -def unwrap_dbus_value(val): - """Converts D-Bus values back to the original type. For example if val is of type DBus.Double, - a float will be returned.""" - if isinstance(val, dbus_int_types): - return int(val) - if isinstance(val, dbus.Double): - return float(val) - if isinstance(val, dbus.Array): - v = [unwrap_dbus_value(x) for x in val] - return None if len(v) == 0 else v - if isinstance(val, (dbus.Signature, dbus.String)): - return str(val) - # Python has no byte type, so we convert to an integer. - if isinstance(val, dbus.Byte): - return int(val) - if isinstance(val, dbus.ByteArray): - return "".join([bytes(x) for x in val]) - if isinstance(val, (list, tuple)): - return [unwrap_dbus_value(x) for x in val] - if isinstance(val, (dbus.Dictionary, dict)): - # Do not unwrap the keys, see comment in wrap_dbus_value - return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()]) - if isinstance(val, dbus.Boolean): - return bool(val) - return val diff --git a/velib_python/velib_python/v3.40~37/vedbus.py b/velib_python/velib_python/v3.40~37/vedbus.py deleted file mode 100644 index 8c101ea..0000000 --- a/velib_python/velib_python/v3.40~37/vedbus.py +++ /dev/null @@ -1,611 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import dbus.service -import logging -import traceback -import os -import weakref -from collections import defaultdict -from ve_utils import wrap_dbus_value, unwrap_dbus_value - -# vedbus contains three classes: -# VeDbusItemImport -> use this to read data from the dbus, ie import -# VeDbusItemExport -> use this to export data to the dbus (one value) -# VeDbusService -> use that to create a service and export several values to the dbus - -# Code for VeDbusItemImport is copied from busitem.py and thereafter modified. -# All projects that used busitem.py need to migrate to this package. And some -# projects used to define there own equivalent of VeDbusItemExport. Better to -# use VeDbusItemExport, or even better the VeDbusService class that does it all for you. - -# TODOS -# 1 check for datatypes, it works now, but not sure if all is compliant with -# com.victronenergy.BusItem interface definition. See also the files in -# tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps -# something similar should also be done in VeDbusBusItemExport? -# 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object? -# 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking -# changes possible. Does everybody first invalidate its data before leaving the bus? -# And what about before taking one object away from the bus, instead of taking the -# whole service offline? -# They should! And after taking one value away, do we need to know that someone left -# the bus? Or we just keep that value in invalidated for ever? Result is that we can't -# see the difference anymore between an invalidated value and a value that was first on -# the bus and later not anymore. See comments above VeDbusItemImport as well. -# 9 there are probably more todos in the code below. - -# Some thoughts with regards to the data types: -# -# Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types -# --- -# Variants are represented by setting the variant_level keyword argument in the -# constructor of any D-Bus data type to a value greater than 0 (variant_level 1 -# means a variant containing some other data type, variant_level 2 means a variant -# containing a variant containing some other data type, and so on). If a non-variant -# is passed as an argument but introspection indicates that a variant is expected, -# it'll automatically be wrapped in a variant. -# --- -# -# Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass -# of Python int. dbus.String is a subclass of Python standard class unicode, etcetera -# -# So all together that explains why we don't need to explicitly convert back and forth -# between the dbus datatypes and the standard python datatypes. Note that all datatypes -# in python are objects. Even an int is an object. - -# The signature of a variant is 'v'. - -# Export ourselves as a D-Bus service. -class VeDbusService(object): - def __init__(self, servicename, bus=None): - # dict containing the VeDbusItemExport objects, with their path as the key. - self._dbusobjects = {} - self._dbusnodes = {} - self._ratelimiters = [] - self._dbusname = None - - # dict containing the onchange callbacks, for each object. Object path is the key - self._onchangecallbacks = {} - - # Connect to session bus whenever present, else use the system bus - self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) - - # make the dbus connection available to outside, could make this a true property instead, but ach.. - self.dbusconn = self._dbusconn - - # Register ourselves on the dbus, trigger an error if already in use (do_not_queue) - self._dbusname = dbus.service.BusName(servicename, self._dbusconn, do_not_queue=True) - - # Add the root item that will return all items as a tree - self._dbusnodes['/'] = VeDbusRootExport(self._dbusconn, '/', self) - - logging.info("registered ourselves on D-Bus as %s" % servicename) - - # To force immediate deregistering of this dbus service and all its object paths, explicitly - # call __del__(). - def __del__(self): - for node in list(self._dbusnodes.values()): - node.__del__() - self._dbusnodes.clear() - for item in list(self._dbusobjects.values()): - item.__del__() - self._dbusobjects.clear() - if self._dbusname: - self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code - self._dbusname = None - - # @param callbackonchange function that will be called when this value is changed. First parameter will - # be the path of the object, second the new value. This callback should return - # True to accept the change, False to reject it. - def add_path(self, path, value, description="", writeable=False, - onchangecallback=None, gettextcallback=None, valuetype=None): - - if onchangecallback is not None: - self._onchangecallbacks[path] = onchangecallback - - item = VeDbusItemExport( - self._dbusconn, path, value, description, writeable, - self._value_changed, gettextcallback, deletecallback=self._item_deleted, valuetype=valuetype) - - spl = path.split('/') - for i in range(2, len(spl)): - subPath = '/'.join(spl[:i]) - if subPath not in self._dbusnodes and subPath not in self._dbusobjects: - self._dbusnodes[subPath] = VeDbusTreeExport(self._dbusconn, subPath, self) - self._dbusobjects[path] = item - logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable)) - - # Add the mandatory paths, as per victron dbus api doc - def add_mandatory_paths(self, processname, processversion, connection, - deviceinstance, productid, productname, firmwareversion, hardwareversion, connected): - self.add_path('/Mgmt/ProcessName', processname) - self.add_path('/Mgmt/ProcessVersion', processversion) - self.add_path('/Mgmt/Connection', connection) - - # Create rest of the mandatory objects - self.add_path('/DeviceInstance', deviceinstance) - self.add_path('/ProductId', productid) - self.add_path('/ProductName', productname) - self.add_path('/FirmwareVersion', firmwareversion) - self.add_path('/HardwareVersion', hardwareversion) - self.add_path('/Connected', connected) - - # Callback function that is called from the VeDbusItemExport objects when a value changes. This function - # maps the change-request to the onchangecallback given to us for this specific path. - def _value_changed(self, path, newvalue): - if path not in self._onchangecallbacks: - return True - - return self._onchangecallbacks[path](path, newvalue) - - def _item_deleted(self, path): - self._dbusobjects.pop(path) - for np in list(self._dbusnodes.keys()): - if np != '/': - for ip in self._dbusobjects: - if ip.startswith(np + '/'): - break - else: - self._dbusnodes[np].__del__() - self._dbusnodes.pop(np) - - def __getitem__(self, path): - return self._dbusobjects[path].local_get_value() - - def __setitem__(self, path, newvalue): - self._dbusobjects[path].local_set_value(newvalue) - - def __delitem__(self, path): - self._dbusobjects[path].__del__() # Invalidates and then removes the object path - assert path not in self._dbusobjects - - def __contains__(self, path): - return path in self._dbusobjects - - def __enter__(self): - l = ServiceContext(self) - self._ratelimiters.append(l) - return l - - def __exit__(self, *exc): - # pop off the top one and flush it. If with statements are nested - # then each exit flushes its own part. - if self._ratelimiters: - self._ratelimiters.pop().flush() - -class ServiceContext(object): - def __init__(self, parent): - self.parent = parent - self.changes = {} - - def __getitem__(self, path): - return self.parent[path] - - def __setitem__(self, path, newvalue): - c = self.parent._dbusobjects[path]._local_set_value(newvalue) - if c is not None: - self.changes[path] = c - - def flush(self): - if self.changes: - self.parent._dbusnodes['/'].ItemsChanged(self.changes) - -class TrackerDict(defaultdict): - """ Same as defaultdict, but passes the key to default_factory. """ - def __missing__(self, key): - self[key] = x = self.default_factory(key) - return x - -class VeDbusRootTracker(object): - """ This tracks the root of a dbus path and listens for PropertiesChanged - signals. When a signal arrives, parse it and unpack the key/value changes - into traditional events, then pass it to the original eventCallback - method. """ - def __init__(self, bus, serviceName): - self.importers = defaultdict(weakref.WeakSet) - self.serviceName = serviceName - self._match = bus.get_object(serviceName, '/', introspect=False).connect_to_signal( - "ItemsChanged", weak_functor(self._items_changed_handler)) - - def __del__(self): - self._match.remove() - self._match = None - - def add(self, i): - self.importers[i.path].add(i) - - def _items_changed_handler(self, items): - if not isinstance(items, dict): - return - - for path, changes in items.items(): - try: - v = changes['Value'] - except KeyError: - continue - - try: - t = changes['Text'] - except KeyError: - t = str(unwrap_dbus_value(v)) - - for i in self.importers.get(path, ()): - i._properties_changed_handler({'Value': v, 'Text': t}) - -""" -Importing basics: - - If when we power up, the D-Bus service does not exist, or it does exist and the path does not - yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its - initial value, which VeDbusItemImport will receive and use to update local cache. And, when set, - call the eventCallback. - - If when we power up, save it - - When using get_value, know that there is no difference between services (or object paths) that don't - exist and paths that are invalid (= empty array, see above). Both will return None. In case you do - really want to know ifa path exists or not, use the exists property. - - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals - with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged- - signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this - class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this - class. - -Read when using this class: -Note that when a service leaves that D-Bus without invalidating all its exported objects first, for -example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport, -make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor, -because that takes care of all of that for you. -""" -class VeDbusItemImport(object): - def __new__(cls, bus, serviceName, path, eventCallback=None, createsignal=True): - instance = object.__new__(cls) - - # If signal tracking should be done, also add to root tracker - if createsignal: - if "_roots" not in cls.__dict__: - cls._roots = TrackerDict(lambda k: VeDbusRootTracker(bus, k)) - - return instance - - ## Constructor - # @param bus the bus-object (SESSION or SYSTEM). - # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1' - # @param path the object-path, for example '/Dc/V' - # @param eventCallback function that you want to be called on a value change - # @param createSignal only set this to False if you use this function to one time read a value. When - # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal - # elsewhere. See also note some 15 lines up. - def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True): - # TODO: is it necessary to store _serviceName and _path? Isn't it - # stored in the bus_getobjectsomewhere? - self._serviceName = serviceName - self._path = path - self._match = None - # TODO: _proxy is being used in settingsdevice.py, make a getter for that - self._proxy = bus.get_object(serviceName, path, introspect=False) - self.eventCallback = eventCallback - - assert eventCallback is None or createsignal == True - if createsignal: - self._match = self._proxy.connect_to_signal( - "PropertiesChanged", weak_functor(self._properties_changed_handler)) - self._roots[serviceName].add(self) - - # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to - # None, same as when a value is invalid - self._cachedvalue = None - try: - v = self._proxy.GetValue() - except dbus.exceptions.DBusException: - pass - else: - self._cachedvalue = unwrap_dbus_value(v) - - def __del__(self): - if self._match is not None: - self._match.remove() - self._match = None - self._proxy = None - - def _refreshcachedvalue(self): - self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue()) - - ## Returns the path as a string, for example '/AC/L1/V' - @property - def path(self): - return self._path - - ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1 - @property - def serviceName(self): - return self._serviceName - - ## Returns the value of the dbus-item. - # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1) - # this is not a property to keep the name consistant with the com.victronenergy.busitem interface - # returns None when the property is invalid - def get_value(self): - return self._cachedvalue - - ## Writes a new value to the dbus-item - def set_value(self, newvalue): - r = self._proxy.SetValue(wrap_dbus_value(newvalue)) - - # instead of just saving the value, go to the dbus and get it. So we have the right type etc. - if r == 0: - self._refreshcachedvalue() - - return r - - ## Resets the item to its default value - def set_default(self): - self._proxy.SetDefault() - self._refreshcachedvalue() - - ## Returns the text representation of the value. - # For example when the value is an enum/int GetText might return the string - # belonging to that enum value. Another example, for a voltage, GetValue - # would return a float, 12.0Volt, and GetText could return 12 VDC. - # - # Note that this depends on how the dbus-producer has implemented this. - def get_text(self): - return self._proxy.GetText() - - ## Returns true of object path exists, and false if it doesn't - @property - def exists(self): - # TODO: do some real check instead of this crazy thing. - r = False - try: - r = self._proxy.GetValue() - r = True - except dbus.exceptions.DBusException: - pass - - return r - - ## callback for the trigger-event. - # @param eventCallback the event-callback-function. - @property - def eventCallback(self): - return self._eventCallback - - @eventCallback.setter - def eventCallback(self, eventCallback): - self._eventCallback = eventCallback - - ## Is called when the value of the imported bus-item changes. - # Stores the new value in our local cache, and calls the eventCallback, if set. - def _properties_changed_handler(self, changes): - if "Value" in changes: - changes['Value'] = unwrap_dbus_value(changes['Value']) - self._cachedvalue = changes['Value'] - if self._eventCallback: - # The reason behind this try/except is to prevent errors silently ending up the an error - # handler in the dbus code. - try: - self._eventCallback(self._serviceName, self._path, changes) - except: - traceback.print_exc() - os._exit(1) # sys.exit() is not used, since that also throws an exception - - -class VeDbusTreeExport(dbus.service.Object): - def __init__(self, bus, objectPath, service): - dbus.service.Object.__init__(self, bus, objectPath) - self._service = service - logging.debug("VeDbusTreeExport %s has been created" % objectPath) - - def __del__(self): - # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection, - # so we need a copy. - path = self._get_path() - if path is None: - return - self.remove_from_connection() - logging.debug("VeDbusTreeExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - def _get_value_handler(self, path, get_text=False): - logging.debug("_get_value_handler called for %s" % path) - r = {} - px = path - if not px.endswith('/'): - px += '/' - for p, item in self._service._dbusobjects.items(): - if p.startswith(px): - v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value()) - r[p[len(px):]] = v - logging.debug(r) - return r - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - value = self._get_value_handler(self._get_path()) - return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1) - - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetText(self): - return self._get_value_handler(self._get_path(), True) - - def local_get_value(self): - return self._get_value_handler(self.path) - -class VeDbusRootExport(VeDbusTreeExport): - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sa{sv}}') - def ItemsChanged(self, changes): - pass - - @dbus.service.method('com.victronenergy.BusItem', out_signature='a{sa{sv}}') - def GetItems(self): - return { - path: { - 'Value': wrap_dbus_value(item.local_get_value()), - 'Text': item.GetText() } - for path, item in self._service._dbusobjects.items() - } - - -class VeDbusItemExport(dbus.service.Object): - ## Constructor of VeDbusItemExport - # - # Use this object to export (publish), values on the dbus - # Creates the dbus-object under the given dbus-service-name. - # @param bus The dbus object. - # @param objectPath The dbus-object-path. - # @param value Value to initialize ourselves with, defaults to None which means Invalid - # @param description String containing a description. Can be called over the dbus with GetDescription() - # @param writeable what would this do!? :). - # @param callback Function that will be called when someone else changes the value of this VeBusItem - # over the dbus. First parameter passed to callback will be our path, second the new - # value. This callback should return True to accept the change, False to reject it. - def __init__(self, bus, objectPath, value=None, description=None, writeable=False, - onchangecallback=None, gettextcallback=None, deletecallback=None, - valuetype=None): - dbus.service.Object.__init__(self, bus, objectPath) - self._onchangecallback = onchangecallback - self._gettextcallback = gettextcallback - self._value = value - self._description = description - self._writeable = writeable - self._deletecallback = deletecallback - self._type = valuetype - - # To force immediate deregistering of this dbus object, explicitly call __del__(). - def __del__(self): - # self._get_path() will raise an exception when retrieved after the - # call to .remove_from_connection, so we need a copy. - path = self._get_path() - if path == None: - return - if self._deletecallback is not None: - self._deletecallback(path) - self.remove_from_connection() - logging.debug("VeDbusItemExport %s has been removed" % path) - - def _get_path(self): - if len(self._locations) == 0: - return None - return self._locations[0][1] - - ## Sets the value. And in case the value is different from what it was, a signal - # will be emitted to the dbus. This function is to be used in the python code that - # is using this class to export values to the dbus. - # set value to None to indicate that it is Invalid - def local_set_value(self, newvalue): - changes = self._local_set_value(newvalue) - if changes is not None: - self.PropertiesChanged(changes) - - def _local_set_value(self, newvalue): - if self._value == newvalue: - return None - - self._value = newvalue - return { - 'Value': wrap_dbus_value(newvalue), - 'Text': self.GetText() - } - - def local_get_value(self): - return self._value - - # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ==== - - ## Dbus exported method SetValue - # Function is called over the D-Bus by other process. It will first check (via callback) if new - # value is accepted. And it is, stores it and emits a changed-signal. - # @param value The new value. - # @return completion-code When successful a 0 is return, and when not a -1 is returned. - @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i') - def SetValue(self, newvalue): - if not self._writeable: - return 1 # NOT OK - - newvalue = unwrap_dbus_value(newvalue) - - # If value type is enforced, cast it. If the type can be coerced - # python will do it for us. This allows ints to become floats, - # or bools to become ints. Additionally also allow None, so that - # a path may be invalidated. - if self._type is not None and newvalue is not None: - try: - newvalue = self._type(newvalue) - except (ValueError, TypeError): - return 1 # NOT OK - - if newvalue == self._value: - return 0 # OK - - # call the callback given to us, and check if new value is OK. - if (self._onchangecallback is None or - (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))): - - self.local_set_value(newvalue) - return 0 # OK - - return 2 # NOT OK - - ## Dbus exported method GetDescription - # - # Returns the a description. - # @param language A language code (e.g. ISO 639-1 en-US). - # @param length Lenght of the language string. - # @return description - @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s') - def GetDescription(self, language, length): - return self._description if self._description is not None else 'No description given' - - ## Dbus exported method GetValue - # Returns the value. - # @return the value when valid, and otherwise an empty array - @dbus.service.method('com.victronenergy.BusItem', out_signature='v') - def GetValue(self): - return wrap_dbus_value(self._value) - - ## Dbus exported method GetText - # Returns the value as string of the dbus-object-path. - # @return text A text-value. '---' when local value is invalid - @dbus.service.method('com.victronenergy.BusItem', out_signature='s') - def GetText(self): - if self._value is None: - return '---' - - # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we - # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from - # the application itself, as all data from the D-Bus should have been unwrapped by now. - if self._gettextcallback is None and type(self._value) == dbus.Byte: - return str(int(self._value)) - - if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId': - return "0x%X" % self._value - - if self._gettextcallback is None: - return str(self._value) - - return self._gettextcallback(self.__dbus_object_path__, self._value) - - ## The signal that indicates that the value has changed. - # Other processes connected to this BusItem object will have subscribed to the - # event when they want to track our state. - @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}') - def PropertiesChanged(self, changes): - pass - -## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference -## to the object which method is to be called. -## Use this object to break circular references. -class weak_functor: - def __init__(self, f): - self._r = weakref.ref(f.__self__) - self._f = weakref.ref(f.__func__) - - def __call__(self, *args, **kargs): - r = self._r() - f = self._f() - if r == None or f == None: - return - f(r, *args, **kargs) diff --git a/venus-data-UninstallPackages.tgz b/venus-data-UninstallPackages.tgz index f55c4d11b489000fe5c3dcf529b088f883d9f2a2..3d3fae2f3790931b607a7ce5fe74f40bdbac3c9f 100644 GIT binary patch literal 1142 zcmV-+1d00}iwFQiHkf7r1MODtZ`(Ey?N{rsxX8v52b1OeXbLQFhN4A>0!>^rNxu|B zKuaf!uuKXhWv}b{zwby&vh1YkmleaX5J)VG$H#YfkB?T#^{9{uE1vzhF&>X!Jbw=M zlg94n`1I`P7>-WQPS3_CCr9HG7#|(KI6iv@;~&VW9hEjr5fvq+c`R<7BR*E7-Q@lw zqrVr=xQJ&==Rwd1lXDF^QM@!jPbE_ZWCjevS;0jLw^whku5Vtxdlv#zNzPXY>zpU~ zX5t!HQP9F4~z+WJRe+;hDJk zC8nI&0u*u%EHQk=&F6r=yyj{W#w(^``Vw!G3~j(00-b~d9~vi>QYcIq(Dr-q37Uxz zem|$;q6m7+MamUK?>BQn#x2q%YE7_kFbuu~Jxp?0SN&GhY5f9&!|;(Q_zMi4OQpcNuX_E;qE0JQR%S9dh-GQw6;F(!7=dd3Ii@a_DFsJfqB?dwBL7m4bPkcs zGD-;{%A`u@!$k~jKMoFH@GDFvFoxl<=|;=QWiZtfqbdw~dVT9KKcdoH3S#4mKG@<& zOtY#1zQl!(l+FG%cZ{ z0D~s-oXQvUD78-{wkV^P*E8|T!*^uYOQfKV+vI4oULAPFmPq^2@kc?AE%Y$x^=)7M zd972idTAQ{b4N4v8pmW02D_<4OTjTEo-vw)DAH`)s-!MRH0UtvuK-K3sIzwhk`C;$}^rYLyQ*sHa62i8H%^4R# zstBW2bWBsRLx{bk-J}z=4+F2~dS|lT%>p0c$w&5BjHqX$`JZ9XiYgq`3%jE4s>UT| zsog`d_s_PS!di-bW0UcTSYa(!&};#Zb8BImyKlpmq_t^%vsvq&k@rI?$&6OcmAj~j zT=!Z|7zv|5`d^U-XdeIIhWymzk}N6ZT2-a9b}9j_&CJ?fyxttkoi~AfT_BclbPoTFcl)`0xF9RURV*s1)laT+?gT&PPqhtir({>zpwVdb zP3AsocTeljecPN`6y1h6fxupK5}j$Q=4bW&s~1K3z{MK||MoAzr|~qN#{X^n4Z=kD ICIAos0Bsc>cK`qY literal 1141 zcmV-*1d96~iwFRW{FY__1MOB}Z`(Ey?N{qpTx4U3gUNCNCjk~XL$RVofyOSHq+g05 zprw;VSSAgUve$L}?>mx`EIVoXWyLTo1QN^Q@$uc=jb6a;2XbmgsSQ&^MM-I%ireIfPZeoDx&O%M z9>g;);u+I<5Ol%hT!T&&Um2jM6;lRe1`NVk!9@ypled$b+n4X&g}_vj^EJXI=SjYu zxB*rav@lt)IckD@Up>+S1R)J5T*@`3Fe?o#nOe}JmUY-Q6ZBs}Drtp{W~Gt9g|Vmw zGpK?tfqq0$YM9=@hSPgi5WoxxnG0k+ENWj%q z3;t`+h7Y4C0xNpM#TpKDjfRoSV5-MPl^AsN=FVY$M5VbD#Ksl9x5JUj z%{B`-{IXIcQ0Prwe?9C6SZI6%H)HPoK5!@~Ij4Z2E;?;iXoymXDUij-{eV)bTS7+x zdUfO_l`rT}YM)4KQARDVX5zJnZ^^EcNI@O9$8`i!7(MCF`9%Z(rnzQq$)_%YcXrF@3a-%Y;75}7lbx) zTLq1#T!k&BDQ2iX;EcT9KffvY2Xu$Q84WGB#j$@~@}>ongOF=|$D8)5U}Q;#xMlHb zdOw-o-oL!No!-~(8Cc!hgXGQ79lDlxiOk|cLTw>$q(W?vXe_zbZkAk1u7J&GWuTVd zspzo_QKXK?g05xCGoCO*kvjB@oDyn#e`u5T*sl~4kn#5MwyHp;98LgZvcTo|! z_O+Za5=Mdaza$ONJpREA`KiezSyIZiDp$_hsRXn(GaGyHdW*C+`0ew#TdYS8z4gBx z`=W$|%!!9}-UJSHfw+Q`OZaEJ+s_@s6Jy(rR0F5WQsw|@yfkLU3`{%_-NsrJIr H01yBGaEvSi diff --git a/venus-data.tgz b/venus-data.tgz index 0541a5cc76e158105cb345daa6b74994d06e0920..ef0954a2c2b07a9fd1f76cc49ff670272534e6b9 100644 GIT binary patch literal 213048 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

ocl&m%HwzmNMce$J5R^d5}KFYj$1d>Lj46A1 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 literal 345349 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 >_AsDHcoMoQ#p z)r5-UeCkMFa6eJ6y#7(x3~Xi~)1BHiJ6t>LtINj8SQ!|7Yz__2Y>=ap6-j0Ruamre zk^h-ZOL~Zd_}#Tk_|#8`oEMw{#=)i>2pbzFAv$C#V>p_py*jj$^&4K^nDBaWlid~3 z2_Tw&^pfJ-$nO}v@Bo*-&a(l&&wlg_fH@h7@6$PSik>H>a63=itCNWDiH4Iw5F+Q=n*W-!V~#`gs(|G)C7Kl7(7950nuK9d*<8R)78W?GvQf z(K-fP3m@HeZYvb@JH*I$CMWn5-=(Ap$8Hz`!YGp*O<~TF0LUH5eZmWoP}ZiIcJ7;r zT5a#sG*cqAPngsu9R3oBaB?Ja-NZv!4$6C?qO>T#+{xOASF;XGz(^RTEdoS4ga4Y- z3aok}R0})dIC)>@@MP7>7K+D=mWOqINcJ&I0H6z+>XU^u?Jh$M@A_cycI~+OteSS88T1L=mz;_ST^!IS3ajeVZ^YjLa{N z4ZFdk0gfa25e5y9oOI-GK!S?>@I zM)5Vz43af+<;sugSrE#u`F(Dh_vu1JuShZFICaDv!!J?PKbNpY4scUp-No)DA%1ac z36U*pWDP@a5w!)jdxupn=YB-eRstz#qn{)$`Mqj!;sJ)(QXZ7}7S5b7AD$?yf|`9u zMV~Q_=ky8)>6#bpbd!m6h=7SiitDK#@O_<}^v#dbGOm?mc zg~$!=Xk`}UUjuAV5DUFX(%cIqbOPo6C7kd(1!w{x)CLe|+&oOnIHCsnYecQL+qBo~ zS=znb@uYGS`GYt`kTIH$sty*gfsBD-E)!!MO~L_r1B=C>RK#wPzIgT6W!JMDyay!Y zaEFD%QYWWx&yHTdJbZS9A+b0H(H7!TonD2!Sj3fr{g^XN^aDTh>PX(&L#|<%4n-hl z$Jwf4VlU7k;J#UiBH2WwugATetzUMYxK__jU%h^LbaBKuLkJ7w4x)c2OWkQW6MiK69nSGuq-;qH|IxhPtT6OIzBmk8OV}A zN0NNxRjR7ER}dJ>9bU#LP4)2@Q1l`xj?QX_H3(5Ln-b560LM^(=W64FkI`VET_eOzkhdk*Bipum)ZLskhXp?81=8R{^k2U zfT7##{9pgtx}9!4*&5%a)Beq0^U=Fxe(-MRlfh29`{~s`ucm|fKd%Y^i@WLe-lu;V zjxhZPE*j~Em(1X`julCZ1mU!dvAP&JNaeT8PaG4@q>{3Mnj2{%HnIc>mJ~p4_;9^( zI)&Q|!16LrNiKDZctoGttx|@D5?>KZbt=#Dqr`QH*u!2SD!if2jFgawuHzaKr``de zFa?Z_oeJ;-od|*&Z>u&68fl2;A`KBCr;1RDjJvA_9B~>z^et=B;Dk2GfFCSIRNuCV*-%s-VQ{ zE-KVG%|KWjx%tSWa4<+vZMW>m7oIL|&!KOGMFLy4(v5v$0E6MPNGIs~L}d*F$K)QF z72?_`x=&Q1#wK1}rX<}eu}kQShr!}5z>$P2H~l(O6aNMEq>E?TZ-{r8_z9X{GX`{C z9i+F}qBMdz@F{q_D3A`|Vbl*(Z4`VfjD(|pBxo3s7+#4}b2xQYneEqPn%np9d-M4( zKmJHdHso4$Bp^gKXjEAN1pvVeN!K_n5~H$^<~R{(;^9hOq3X9)z`*B1t9lHZgMW4# zK;AEwu(Z58rp<&B>Rm)1xrk+;t49|yd=M}q->3kGYEOmvWZ<#cC>mCX=<=a+uth!{ z7EEG;uy`H33 zFbJBp#^f4@_#u^B*zWIQyNWT@xMUcn(RCW05LjqpvY&9Ox<`Yy%1 zb5qgx)5CPbQ*MTs6^t#^T=;}UtkNK)p)!S-OTB>Rf{rUV9CQO@8^RlM7(sEj8xN&}@yUYM?G zUW8L;zVzsQd6CDH0^Z0uoG@&Ck!F=9+I9vp%g_#E5NF3IORi&z3V2TAyvsVe4eqyP ziF*TWr<-KE7oYPatFumG4nPFtSuWv@R7q*9LX@J7rhnYPsvx9^3O1BM2-xUlB5taV zi`mc^*v{4PJc;B#y=e*umjf!i8;H9S&tTNdB;qAtSP)8fRk3mm^Oz)`=q^X5b($4v zL5wzU*QhD+&!^=24o%C%<$*fYkO0KxbfKf{y6FAL`eU*~-0@&fRf17fjF4H$bu=RN z4=!|_tryzvOKQgV|JZN<^aLWGNQO_{;ix$JG09rRndJi4e`g4)J-_xx_2NVcOv-%U0R&ZR7{SH1)RCDiLv0*Yf!Fws9=aO@0^DbH3IbB z^@3;N%$G=5^7-L4(Dv&X4Sws>+2~(0fRT*`R8`{*=qa)v zkg&i&9MbC>RB^$xDXcP>ls)efm*2P`4>5@^;$NIX7kxH7x{$oqt&m6)7SN&U$-Q(L z`U^cM)V;MS#71qvj^r|$Lg@+pWB4`=rC~ml7kea^$teeh?^Dz)oK*^l#d~tJ1@<+Bdb0g#DDen@0`&;iEIXaSQntX8HV-`l0-q(p!>a<&k3ddxZ2oI|3d7yGZ;e6oHS{3DRt{nUc{)Mtf3m;(T+W=XMKV z8Y4S3NU4$sthtL<-UF=H6Aw?+G$i~|^VvY%py@Qvl6d$^0C4x0JvU8-o|&i-6_xyQ zVfZgIcz!tE@yYSU@!`w=JW@z}`|9un{y8(Mvqpd-A^q`e@gSV@S9!Zk%TYcMv> z2K}lYFNn>AFVv-KLTGoqo2)dcaam5U(1QjStP;#cS6;HV1K*37{i^Z#><@~V9v)~< z5Aw~4yv*QrRuK&z4$OHhsjXQ@jYtG#v-){$)_nr#Y&=-t|2vMrySxX!{gNeFFc&8_ zLPH}VMzv2lzc+q(Br9DZDl9ShgpKqVc*0|BDph4%emMeS9+8R(&UOk75WBFW3;~?i z0uL1wgIJp6pU4`MI|zGOutvtyR;MO!d7U*`R}s0qI=nc3rcDZ+Qy302fpOJ_A&@5* z{ebWfWNwogb(9_Q%MVw#cxux)fXHWgc-(^{R=(Y8s(KH_67}T8fI$q zrJ*s5_9>^kT~*l7e0t14t-d^Poys`oL0Nan0T&yWaj#B-SdbAS5;lvX*xS=Yw zrqi~n6-Q(#CtjRiC(h77V?ME5Q$>I3Jy_Yg1xFaNxh~gPy9O?PL)WMy&K!V)SZBw4U{xq{|iJ83#V&3&L+iO)rHxu1fErR--{J zLSAgaV61@D2N)*&iDHgyDh49L%|lg5BFaOgU7=hp-nljzsarJ}ssi}|4w~X=&_)s{ zGDT&f%0JZ9P|ih1VV$RUa7^^*YkJSXj>4>jQOG?%eT&&Idc7WDGasEG+U{m{H6#4_ z$uEx|cL_+lJG(SHq7DS_s3c_}Je+KZngbD8P%aeD5u?GYGB)Y;q$|4t^kmUV=rKf2 zx!UaMzBgUt^@iXsYHf->g+oITRsCj2tM0j2U}04XBP%AZJVZEm03&#`g%fw`;r@=} zOO0Prt*saD>>ENExYas6dHMI~_=V(jiUliL{Ss^%kx{tOySP~MP8NtpetEoyPCwd( z1qmyP{ElLl`vt9xL(&_;*FjTZV+kcB@)(lI z-Z6?bbli*%YJ5HA^@;}=nU&GuN%6dD+&zy))}7nG_5R-b&&>$`9m>D4{CoMIx>Sdl zoIw}QjQo~J*brdeA2EmRdmoS@nkS{sWAt1LC=kY!pi-VaB`Nuj zJtfB`A_9(a@0*-MjN&1HA3A+?q)t(eH?mwe$(9tbTS#RXa!M4*cz~KtbWuaM3BrFx ze499=Mr;848~HKWm$>DG4&r*qanl8R!mr;U!qHs_Lr_SX0=KD6mvqjGvkRkse)AR^-YaWL+L z_~+O-3L7u7Ddy-GyPFLOZVrT(b5>1cbT}NI6Tj)=5ev!*hu$mr@<<}OVM`?DeIR3u zn)S$)h|NMMUs33gQkkmZ07>~ia%OpXIWD?HRPcIh=b|SdXb1#R#F%}X{Z35Uo;W&R z2C}@0rXRs-I3x$2A*!TEX7y3+>m7nMFs&GQ{V)u($+%Ni*!m$vigdu`btq1luwBdg~ERNC6@g%Mf1l$uqEJq2`6Zhsm z#Aj-Vme3wi_X1Xn)^Xtyx}`65qq4Nhx(-d`quPW7A#z|{Qw!b95ucSaSBuTbfnBtY zewvgnG0$e#H#HMH?hY1MH8RT zT6fyu4qBntp$Sp5?DMnNZ;<*FvoYJR=#79Q|bQK zeN@QBERG_7Spik1NCf$))@BzlT1{MMZ(6aGcGPqrsCqpV-guR!PWrsqZaxKFm~BK0peWr!mMHni744|Dcjyi3QV zgOpHe@lmp}Vno62hTB&WqxUpiTTL4AP*;;)U09_CVrZIRMM-#x#0gWj zPhETA-73hf_9_MgrsE{J(?2P&UJ@&*hQJ4YigP9j41_;jbBEF=a3gGtVU28Ll0Drd8I9+`9=Qj&wE0-U8YiEq3mZurtZ4PKLYsOLrb%sq~8 z^$`eLme2Qrp-J9jcn-XGcHktV(CktaYdw7Sl-)$qT=0bqoZ5d=%uN{_=h#(D417Me ze))vhccz>bKTC&yYHmwdunXvQ%mN#}Gs(E8<~gSAZON)P^dp-*cWg9o!`aOk0OKgf zoEAR!g_dliD0<#P?Yp%oD64ZtXS*cCePvtX(*#K6jXx5?l&Ac2ZAN1 zSrNxT0?xn#i%zE!b-{g{a%Y-~q+4qy0f|a0o$gUh#I|x#yM>i(F1~!OrYVz<&Pfv4 zwc0&gwxCep6dMp@ueS4(uBGS*O>MPgv`zV6>xz)ymSc2z{@1OY?cFEU`VWu)tpD)G ze7Jnq^P?AsZ(d%odcm81Bswc;sMQ68965aIkeYJjcU;3u?WTc}Kx-pVr?@D{3@up< zFbhd?=k*XPuJ|`RjfsmKTp=2mUQcLrihhdGO36B!6{%_Kt-ckXITl$anqkHzG1QKT zdnQ90d zl4`(I6SJ);cf(I()4Kcf!lvhvBwQq=WuqGWd*1@irs;D|9A(=tYWmeQ%_`$IHnmwV z?`hhuD}3<--;x}ar-NVx7s;5^3&?%R=OP_H-~RNI?O@n?^a6e~fFWq=oWz4qW77st z@kLE*PU4G4tvj{j=RD2dj8a_=YR=lMt;&kGlj}Tt=YHaduVfTlmQUDaJ}+m36hLk3 zi68U78_WIqS@db5|A9aB?=Z(b^`9OC)eq_a_S4<%-9PF7AMug;Pxb1bmC8lz5MW&D z*{ege|6Cl1OjVARMz`9dDE&bv7x;dP>s|Gul*_g8sag%6Pd2xwYG_81(^`oEZ$U@(c*`_^jSm)KfN19-Ph4Zr+pLVKdsiduB1opxQa!q^^T1-ik7vnM!0qm8Z?ZMi;I+; zL&asnSDhx7Ji533Q5a#N$sjuIcBLAOIP&0<8jKRAFozxd+1c^M@w3C1`+>I|Dqb2j zkiL=_-gT@&F|I+UU8}4fmJRUbQ@=d&uy^!4N>Xa~h)z!-W&!MS0TkCv!vhvP7D)!n zN@)p`r4&48{qNLE_zeEO$k0>xJJk1a1@}kMs?6|$!+2a}llxXE?~x39KApCds^_99 ztI`y&D;y*!t7K2pYJu_>v8HaJG-!Z^)Y@Ek31$nBL3)B_eEREgOo3>m^NBkBq#X2#PwUrlU$wk_`1Y>S zNs8H!n``h?^W&Ay_%!r}J9z+7-!FVQQW)n?hVOsMr-}a~RQx;6aS#8u11w;L|J!@I z^C$oJhkPpa-z^1|0y_np%}^~gD={}FT8PP{bvdt6Ml#{#Nj#R);6D73l2(VA;0vkT zE-5!jC+@Hbhr)Y{a$L>+35#uV>n>CwM8-X}i3f$_ubi7o6igOWtdBWAB(E^#lxC6_ zCY=B~gli%z*7b~yE~=^~t~89l7Jtkd(nmKNRaJG%PWEABX3#iQuchPzd0`doVuQq&2!wV|Ji#|)&D%*`Lq7tAM#nK z|53Cg=;Ex3r$Vwz#D(&O0Cl>H^I@b8ER;=qvxd3F#mo{)??%1S;`D}!5IKz1x8~ekIX+u8_mi!8FCqErPAKidO@i;YQQy*SGlPck7MnY)0Na$V3Z_O#+Vj# zLZ0~nfKeema%AaBS|s&J=|n#RUz9}MSh<8skvf#}v3mM8N#!f3)45B?^%Q}6Gn|LL z8U>oWa?vgoZ6Rm)Ldr87tVeY%V?9;gbK_#^zujoNIAMUJ)t|zlzyH5K{G01|d-Y(0 z(sK2xQagH?hLamRrN@#3k5)NX`GZb*kG0e6ik!#+#VrX%fH? z%8z?X{ftLb zOB6{%SBb8n4o*0gEkwZ$m_U* za=wIIM^sl*?FTIkenDK!N`Rn4_@U#KDM2=C>yW4kMYtb_8~6k9SItT=%}PmWF+^MD zpbEFFFvJ5&1{x`ZN1><`=<35oa3LUo^lmxOBAF!l^}Ofu)GP~>=8W3YxtKc(=S&u) ze+d&c)ND@Ivy_*5Chq>En$jdoRU4IU=;CeyU$EOxP!YxgM$94=t1%y5v)YA}YS|Qw z3Me_Mw?nc(M?(li%|~fXI+CUtF1@U*>1l6^R~1JMP~|VVXC_DGtW@8dN1R&Q!y0+` z)oiWsU5qQF0$|Tgb;OROo;Wqn1jna@UvvPNfj%5gH*XEXSsoZTtEEq@#HH!7TTfxFZtCPCMwf0pVZfsrngV3k+`CdU34>o7MR?1jRio}6AB?MH_e?|L!KY;aQ( zblF|{MDAP^N{eu(6ONXL8*E8>_aeawyX@lWZ%fX?l~RNi9bZ{kkUT@FWW)0n;Y4(7 z$cq$YZs4j587J$!puj6XyK4EREHFQL1eS2{pzdm$Pb>i9Cji7MH=DWuTG1SFv6a;o znNpA&fr+CkHCsaPMaH@Ni-t02E;7H}Zqa%I{}(PG;BFY@{ARlctJu*(^P^tsUAt8) z&=#6GBA>^~8FeYxlipo$QhUAk?N+<>f`Ec<6jS1F8q~u{-YGv2#}43Tc#$emxLiGe z!P=T4fL@KNr{kcKOSLF4OCA*k2hD@qqQoP($a88gueVTzO%d_CDl{V@SDJy|z3599 zWRpsh*y*y`HW~}FkD1C2y89kZd%>sfRZE`G3B0=Xy9zJM^!hLj{d`VW+-tYLuIlbv zry+hrMUR%0yYa%IZ~!$w?$*~;?Ou_Nrz0gFGVEH#WF*B<*_wdK*fiBexWC`x1@kaOC|D_eRz9i=6m^ZTz ze`7s~oP&rcnP`D-M)SxRp#t+DQ}s>|k_lonb4Jeb2eW9h5wk0{q%z4lny$yJ#`cD* zhg{7PE6xRuXlO067{bPv$c$C18M`VE+_| zbJQu~D_|Fd5v8ax<&G)W|7BJpw}reT%#h~MYtB(RLGb$uSv4#x(Q37nR*N5+6j2>& z)H2nS!A;>xh$KdQ5IY-;Lef%$n8;NsL*hgMTcf$8gh8};{v2~Q3{`d*1FJ{TcPK*O zXpc7}zb)BPIrXiCNB<2@gnW+HDLwNhRY;^-)Em@wcSB=w!{#x^q#-E#1PWBkhJ55b z4~T;Re=yHxbPbx1D$I(dOokL8q3MEy+_!b%&axr$8}a=IV?%&H z-P*+LUL1QJr1hlY771Vm9&m5bbpiZi8c#{P@?<0W?(5^1N0nB{tZ*`^O-Zc~U3`5M zy*he+d}t&c6V=bX2(TSAVf;a?D)*Mr| zW{qd2Ffep@<=8^?<#b2AKt``t1E6eNzc)bfi1kcnzTPUMZ3Q7k-`BvC%q|IYYm`Tz zyU*jhK6*R!!=YuqXNPYtj!#eaEpTiiaB%5XN2$4(3S~s9Iz3Z4LS5CdhrbzRGxhE8 zDh1-a6S232Y`QV36PS{gQaIXXkA`JdBycy-31^9l!;F)}#}E~+P6TUneV6#$RKbCV z!;p4r3J~W9aoOPAEIs#YyL~7!&OMaSr+f9wX!ha}$Z`(~9&zgqEgRi`okraU!;I*T z`W(@s`B{FZG$!5mKVHF5-DjF9e0#AEf;+p!&l$895 z^09|pp0GFqV}ivpp)F!gl3yw&C~1vP$9&S#Ns;Cz{z!kv-ELw8VR)+w$Lfflm_P=SR@ zjE2DYXE^B7oG=WI;8d2lFy`qrmEV*k7b>;~FV^Wl`L~e<`#Y<>doaCvhH#F2NJ>mB z?F1Ank(*<|?(KF_+(evYX`i%1gaGi6-1k!04gLmZnk?&B7>7=p<1B}g{E;$;5-+sb zMh+m6#O=`Zu9DjnP+>kKXR|rxx=SW(N5{-6LdbgU!?KJuJ|0AFOwvc$TPKYD#CWa| z47yk{z4JA(QgX9x)*&nhfcu)%pu=RBB?-&~9B}g&0q)Wo!0vVndo;`l7Flh9u&PNS zayeGsrs^MG{SDL58Br$GZX${sAu1aTuHWw?%lnq6X-k}*omtAsdWws=@=Fb@$h!&%~46>44&@S{oCB-O7}yCRh(L zqqnnMb%B#?f-enY@!_a2ugbbj_`1;pj1jr&xSM!oxy$y;o{g%Z(2Obt75Ea8!n4Cw zzQ9})o6$Nc4KVMMGKiAf11+}X)UPZVruOXNJ3w}EQ^7?5MX>{JlNO!8ns0LU%0Q(_ zPM47LT?t%ns*X?*fy-#th}u~PS7e*6y*FT>`jl-7vF3krq%}{tC-x%tE=G;jRbmqk zP)buIN1S{_Wh)~_N!&8cXUE-kf1B z#A=BvMtHbHT$U?$rzzY^tzqKS_^{ z0WpOa@7^>f6LSx66H}Eqxh0@Bp;FIys@lAD<`NN50m9209W+uVi=t`^Fca%mOC=uEAD36SV7#FQ&9WxMw+@i?ME+k zntpYenf$=1w#-@Mv*Po`F^_B5+W+n!2;*N@6^vvTp2ww1Z{j}@ocn-O`T-K|!%k_R zUAaKyO}a8r4~}rB&HRp=88$;Ara9Cgn_Iy1+Pxwy;d4{)QYzdc4Q)1IHIXT7_@L#I z?V_t+OSLdCO-V1RB}9Zr3^Vb0P<1z}hvLv*vUSPUITx}UyB zC^gC^kzfo8N4?FEvU(-JA`+89hVOlcudG6gfG8x7p0IO5aC5){S!9Yh4tNhCx7EIB z={UW#@N2^ttb8WoA6R}lZ{RlnH3Ni?SJ2kn|6?)CfbWuBthu6vW+b<3

UodX#!c;x4QaR-tJ!oRPRVN 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

  • iAJ}g;Vfx!8jU_Dp0d^7qDi-Zj$nR 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 diff --git a/version b/version index 1416d7e..5eb381b 100644 --- a/version +++ b/version @@ -1 +1 @@ -v8.9 +v8.10
  • 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%0D~H^FZ9ABR+aJV2Es$A2d4pu#Jm<(@3A4&9N5+ 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%0D6rlt~8yTBh1k2 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%0DlOxGcXl}8w1J+z`F%q{U6&apo2r^ESbt0zX zzP&6!i0b>+J>rM=*!@ADe50LPtEfkX!vNlNBBLJJ5ab)oq@t!{=Y;pF3bqRv6GKKV zCiifwVal81Yc}i@xprD-jUs7ajGT~0%X>8c?bg!VZLSq2Yz5{ds&6?ZFRk{>R0Pe%(0rX&+A6qXeG-Pww0 z#yM*?b#~5JiE*mqYJj-rL?#3VDwB;vFZeCKc7nbspwL}MLFc2 z#R+iTPF_09x+V>w36=9+IImTzu?#toZr+c!94nJeLsQ;5jNL=qFBS$lR7gh_Ej@Q! zq`c&*SP>~IjW%gDbWayDwxvq-v=RPr#H0jDtWRk)K-G^LUl88^dUO6zX@`VzOPfP2>R>zZvCiKWT zYK*LXg_Mvd+%+)_1!pp3w-eZZp&ll^JU#^hkb!GpC)DiB zc3bhX(iD;Xh}tS%Cc+S5khv71(XpH0b>VF(x;REOMDvwOlCXYtJ~ zTGcjb*FY_16&;6}AXE+qDq$UhM9DWcLu?t?LDJ ze6|R1Fp}0*iwn(doD7`)?Dp`{q-v@&s-s8pO03xo_T#T$PZqXanG0l)W*4Y=f!M>G ztdoyd=#!f71-LcfP9z>8vd@FuC`c{*buG8@L#Z<0gEHPR-S|5*~Y$Q-3(y+}{@ zA^5^?yypJlv&oEoF=88P(f32cN&CFHO~4F>gxeK2MALb)l{=l?%6Mh$TAGV(HCu$2 zqN2MGMBKfN6Oq;t^}DMoJ^}_aS6q%LtN@yvM}tJz)wfJt)F!0jUNN7r;&`^U-Z(6` zAJSH<^Gr%479^5<$EI`mT;(AEGAY>d%_QIfQ8|Q8J2neVm3Nv{qMFenwgn0AO!e|~ zuEfw0S>eITi5=aKs;$6J9z8Z))p}0T1ml<~XD5I%_;&*9r%#;z@KpaqEo1=b7-MnU zi`&jxtB$?ic*ld=?zwH8irbe-JhjbPc{tC{=6Q8tnpr=1f9MO^d#=wL*&FO`RXBnH zWx_j7eS_FP*m}N$J>oB_k8>lv-@Iui=VbKtH$_O0sZ5df*EYAgtDJ@!n_QzMW}>fX zkd(E;1o+pgh5_jdYR9W4S$G8BMMbSz?I zv-AtWTMN=W79RN4(j^k&5WxA&qs<=%p>?f1u>oUc79n+Aa9p%^oSA0aad1P^uz7ff zjqliG&o&Q=t+{6Vo!8d3W^(S;r?G!Z|`<&H% z*f5LpivwI$G%hQPwT_uC{g;bb3(D#d6uCHm|7feNkNuAsPH2e}BB_GTH);Y38 zYyfyZJ;xA~f}wR!tCqGuWpJ~+ZXnsnugb|HBV3LOCaUS$fO?Rzyv*GC+If_2zjMX; zNU9AQ*|Iy2l6OxI=+ioD8wNnj=(Bu=>{zZNE?_^AdCG2Z*EC}MEvRvq3`wV_(y%sy zuc;~IRJKx+8ly31kz(vGo`M~2B~^UG*4hwjTt2*AwW@K+8Yr?varlo7+`yrGp8b<- z7KAR5<@QX-9CdrGFTrSg#a+>F9=6psR)+VTpGk5nL1S)0&q`MvJ%a6QQ)}4Nb3xkd zD*Nb)@v7^4e~B$~6*SLP)z#E?vuHo0R=O@YtZJCK+MXjeTm-E_f_lUP_0AEgYE=x0 z14wr{w?;^wSDdu4VRsyGG9rb&-DMT#uT{^Ms66YK8tXW08*f?NF5aq%)C=`jsbOta zcCT(lpTmcI=I(c^ph9*u$b4Ub{}B%!{1T zwMdlPMeb3#qVNw1oivQWaL9`mo+Q! z2r;+WFmhdyOLGnWnB4^Hg?J8UHz{ceKpc6nkt_EHfS1&1IPj40Xr{(sDeFU|L9}3| z*-bzA6miDz+5^dF{a%i_sEbjQZ=j7>Hq4J_$22zdf)kR$SB<`!8?Qg@%zug2DEq#9 zE#^gumF*5Fj$`NpiT1izgx#f4^ooO@DJsyzylxJ%o$sb;Xcbv%$(KLB?TJz!-pipV z`e(0OxpuT1wtnFce7jl={P5=u5)J;K+Ui62pju^#)-f9*z3U5|s*SrrOip)pgXx0o zr^@~B>gS)eD;f}(SW^%U@RPf~@m@Cscy*(Er49Q4IMa}$(A zB6JXv>9}HI;~?)nN8cW*X~WlTVjGe~B1faBTvH%T4zj6rY+Ol~;3Hv(`Hs%!{()ZK zyvf7w$&U;_Cl0B63N1hTCfSWVKzgWgrJsE;%0`3Zu`wuYrFM)cXrjrAqW84@L|@d5 z(vhHIV)xMVjJAdj8#B@KY=n+FOOktp>Lec%q4OcN6R#C7ijCOeE1w**(}->H5v-r0 z<2G>REg?Nxw$>_Fw06ap)NNOcO$r4zD`3xdkuTvp$=&zAo9FHKqY8WBBZ2`n*2~6I z-z(nl7f{ww%ZC*9k5$(9_F9zn5bPIsWV`1eF63eNxLF6oVk&;@alph({C7AGxV`U4 z4XECDIJT*Rf{8M)3?L2!!nOb%$H3#gU{Ms=m0uQ%MMxXRvM&k+5i@~iwbQI`9Bl8g zHB={MO0HpB%=X(PJc7t4XPGyZW7EPO$IJ{8+X7R?p*79dhr7j$9zffnU+;oTE8wwh z>NOmYJ#VFuIdG2#`N=M_XwTnnOo@ir(vmghZlyx!Uks_P8XW2jMp@`#574{4r^B_~ zwSNEk^W@nNFAv@xzIu6-eEanIs~?lM-ya?&&ktWdO@2Idx4(Uw9JpdnpCsS@J$d!^ z`=@V`*Kb}OJUu#kdX&6+=l*op5(>9Rl|0vJ1qLV+Yskrwv4%f0GqbLaFiPt5R+vL1 zZY_1nxrM&5VYqiyWPUrwDU&yCWAMjjOhLO?a5N7G>>jQZgiQ;GTs~qd+~g(JP~o8H zg{WQJmd*v$R8AkXiRA>Za$!_SrzSNAp&xS%v!G9kg)QMS1gZW8I&M;tJUX?(P6 z961U-Y8=_)Y;$^pM=Rbo?bO~O(;Vfzdi7VD;reu|Vbn(TtntYBWn*Tet$v%T=c+dX z#I!9uP0YdU9XPX=J#qe$6z8|Asv51zY!E___5uY|p6(Rzv0v`?MwRneU8l{s146Ae##ZQ4Lu-Vz9B zv`VAln2Tm^;MmfASw^QZ%+>DQBjv?m!(AWsR?rS0G_Z#XbeAOLwQ7d}%lxmke@V02 zAsK$j-|^kFd9{8vaPNztQm;B#YsZi^aUcI|idNO#+}!MPKe6+u3C{WCuBld9&T9HW z)4I*=WBDdta3Na)DGn4qG>LUk^LZJSK_BN`W5!%*Q{s3tomf8_s@O(!1#v9e85grHnjWWU6Zhd!Vcn8G z{GOG2JUP{d@YQhL;k4BLDZ9S|H|Xejupo zS-UObtT%5||KE>j{hs{a4G{4|-f=ho_s-7FmtWNQzaM}3_|b3t-@nF>;qzX_<6T_l z%)-qpwG1@e6l7my6XG;{4*iC&S4!Fq3#62-hs!{o9ZtvjOw znDj-Xry#Dd&5Pa1?IGvx@L6@9?tFV;T1!DuA-dtr_2WfC_KtSAtbfe27>m1^Sab6n)VI~{*4BBkxLBU1 zu7a(of-UIFz80Dv0H{D$zhL7f9zAZ{;hDr{qG4LFpyQnDtr<-*Kln(g&N~=bBqX_W z#9K)HqQvJQaSpl5QR?P$0^03?s0NBr29FfsewODK;gH}i%iB8}hS1xo#;f}(^@J1r zH&0m;Rwi@W^6>`UhtYmH-r>=~Rn3!_1SZQ(;~p@D0Eupol9EG^?`sP&AGAeFX-OOM zBtw&r{osr}0D;|p8N!Ki6Ymx43iFYQM^caqm&KHVS#H#ZMT4hEax>D9uL)bXl?ufkO#sLTh>~c^uEtv4$@5ow%pXF%rnl1T zMsApjNidVzz??cKz7)~3DMpvy2m`#dZo@0>!KfUj8E*j8l0-At zrfCX0@!opSAZb$XHE3Rk!s0l!!C7~sQ6rN(bG;-!K+K~kllsk5dn9JZZ42yixANDvwe8i~QwfW}#hu|q{Sc=5*y`35ttV%{t zlctlT*O-+NiR*_a7Nu*bF5GbHtnzdm;T1WPHB0?UttuA=B91B>xfkKwSbn(yCWoLD z?k9gvMEQXsj;|i`B|v*Md__(&p+Q>3G3i++{`JSuwocfGuh&HHGNnZOIvI$J9eDHj zp6G^b31D269B_~HQ|0??Fr9w#vHWtvYf(5HqZQRsByCcInJ=|)N7+Dz*g=MF3(+qS z>_Yesk3k4s*ogf0tH$yY52q$j(tCyY{HX1f06!YE-pVGynxs#J0D}F+VqUl-ykDTT zX)2#h9_KT+g2on~=_B-Feq!@Tyb@VmnzQu{S`P&T#ja~wVXxUyTN0z}BPJai@xDLbCMS9PUV_T#SLixgg>k+@TD zG-2}>a-=jF2E@(8?ma_|;RQuKLX8#--x+?))a`B^g}pY4n)boI`T`rMoVrOcaqsVi z=ZQV3>;AvvNn|mzl?T?eQ75?Tvm=zz)!XfQfiaBMuy(m!I{kQ5R=(lm>W&5KCrN`~ zM^!1uVyjJH##={?@IQ`qpwD(%M2roti%pJFVI?_o$ye+|iUMbwGPe;yVr|N;aosg? zsPrjQ~hqUN^}Y{&!;aJXav7Rd<*=HOe@7k!g_UtTBU<>l#T zREdQ7b3ELCwXN&7pXSd!?Z1XI=ix~pKal_N5#{`@*?+gc`Yr$Kuk!QI{Er(jJ|LH0 z!tVC@Wk(%T0PjT{Nx7dsFzm zf(aCdvY&otrA#fajGfXfAG`2p<0ZTmt8M2x|3Cj5W*^rTNUkXHq*FBlWNe-E@-?5Q zQ7pMwr=P<(%_*X^;pjNV;7Z>On6{7E65+a&rR@9C_4eA@PG4E|q)(9}3ieH;XJQ=| zlnFpOi3y7yebn}-z*~u0MSh1ti&L#=s82Ga<%kgp&Y>v9hh-;usJDmW_xXg;_ zq%3FYxs%uGXQ5E>?_Rh&&)pp^d|r@BURDK&@ul2%&x_Mei}%Mmw)L7j4H3uB3I|a( zKL?Gh{yjr9?OkbL@16JcE{~IH9wLpZ_Dr#$pf0CF1RD?TlQ`B5ID~~~TI=;WDUAE> z^8IoKrky#f$D9}qP#)2rIvsWxk%30e)=rt@InWzIy(C{W7b0csIYrU+wCv%_XRrF| z2k<$dFeZSLEUSXz*fr4cXPiZXBi{`%=qnA8FdwohvHU(+1sc=PRf!6Gal zGal?tT5cI@La2D#6$1;FPV4E#RY^{f5MSbL!>utNfPL+uZoQ-?yghwaN2x$2`FS?F zO*l!O+X9ItgAN%U;+*f&?Yfj@LOjzQ zN!VA2YktMS)IA|f&VYA>F;XehuL4I;^PsF8>(L?ERuC)z7^L>J40H!fY&N#0t$1sy z1S;5BMSeBJT52rEZmJoRbgpUcrL@~W-hF)HS0Sk!B6VW_Zp3=ovNXmLb1WS!lcGj& z$a8X^G`IK;jA4>1=nZRUwMW7H6(`8qHk1Gxt*_MtjH4KKAY=_bsFHQ*7{f<1%6%nA zUn@I`+pg(5vCkYua==~SNJNoU-a6DOBgla%ZhsSvBl6Y9m`eDuP#(SWv^+tq)<1Wz zwHIO$5%s>86VcW9f!cWZM{3voLoyL0S>juhw6JXqsm(2y*)R5-oe&e@jU{qUQLj@a z#9^}-31;u^(o|EtE6#F_S=D%wx24m10N9YBAgGU|AvUyh041(=3HH68PTTbDt?*@P zK2KzN5W^)wTAGCilB~DUfU?OLQFqQmNKLlD z_AP&KwhEe2pO~oif2x0>nXMIRx7cPp6hixX&-*UDjd_Sey-)MUo?Se|xQ9AlZdX43 z$bNhSJIsey0BCr6)kmYXb;dXR{66YKSbg_ctcS-V1Zv`9YX3C3d&nTiM`yWjIf8$&4~jt*T~*~)EF}#k zgxD`9W88$31i#tPLe|g%Wzc$akk{)OO*Y2)s9b_y5y>1Fe@9(J))+Do%v>oluDG+u zBp;FjTC+j0f+QLh(Ck1z$5kbKH5NcW_A_s_O<> zbG`cLp&)5ub;-9eI*^@c#Y&H-V1w0K_FZ$SR#s+H?VO?K$`(n;PTDwyl_vx>N884; zZiY^=K^a*ZQ5VYef;{Q1AD&OkxxjWborO~sIr}<80O=LP!Lv(qDyo>Va;u0CrJ3x$ zX&t-e{5(B#r;c%6y|GB%@oJjeH0hiUUf&Dk z7YtOMfu<0)2w7E?d?tZrnEW0eOmX%OEQ16opTu%OYf$ZVRJgd1HNrz{l3H2hcJb;nJ!J%iV9gw2m zVW}gIAmG^D&|a#+GREL4m+tBb)tr*htl$tK{sHX+341jWo%~%wMQpVRNugEW_|={k z9afPx%UDVLBi2r`O@@*|qJ%5L_fkb55?KI(bn^>9`~CB3py^5!7S92Y(SmBs?nr7s zqit{(Rq5*CZE3;p!a=L0R{8UA+|aUU3kn-{qsKOAJCT@Fw%u9(pdjk%Ihj;p(zHVq z6PR*r1gyz~zF_*H4QB3v$%HoYyYvtGPDu|`&fg21U9lW?>}`V5czbA+cOBAR`f$u& zPb&kqtMaHlq8bN1hIAkDisFOt{gd_k-AW`@i}3nYJbwWA6#EQyP7;jI0vRKwZpR_Znh7r;{UX0vgg-R72a2TZ z9PizCpgHH|%28#-fnN8i6@yGDs@JGG%5xrwAq_wt8$*PS-(WMoM%4uP3DZ_~xAsTw ze+#!&A5JyZ20f*fn$#2C(XpHS)Fqcm*FFD^8tSc^bfw|k`k8BFDeD8+gGJN^CULZp zIY#9o&^iG-r&xRQ+7p{8r~Up^=UQ6#?};AwmgiP^N=k`k^~gEw-JeBHmy`EA1vxFV zC||TEmJ7kfNS?$29SXB40{E|r@zTlXe=KvjiULus%tpfLo#&L?NJwUC{3ns6E=+6L}_3K-nyndlJU)6jERk$}t$?Vzkxw&9H# zOV;6M7+;^<@hWN83uZJ3=KvT&poMX|LYzP7#DG;=kokom{HenJiz2mkLCz=Lc zT&CpO{$sp4l>_ z?LBS$AfX5l{3;UZmrFc-WkTOt9WXlPK5oq&i~6+zuRmbeWAw3T>FlGez4Y8<7 zx5Ji8qPVV|fm8%A)XZn-!pu+$?G^LIS%-SmnP zma4X>w6;;}t?C4NzKKU#>2->&?_}WpE+S(V0Q$&@lPq{%r1l!JpE$ z;-F__bN$gb_!PE&J+viUykiYqot9wsNFWvR37m;(&3fqCRfrtHr^=L&0`&#&eD@GY64n!P#O@b#5IF3<&k5?cYsZ6B;K`rd@IK-+NN+b5hp8&8#i)qZ+9b=;a@#p#1Z5n?;|^`hX}Cp=`-U zi)9P(sLkNG8`d35;c1x=?+9{93O~Uuu`lt;!#dMJl=E>x>5DVM=8&k z#0e<4t(!aTsc%=V^?*p<2w0Zzp~Ar6Nh&Q))Tewm?TrHcz%4ZwqaxnGoD~Hp93C?p zsd%0jybh7kp3e}JGO;L^CJHhWb2O&1v8!kNeX(wK858M-= zJSR!=KmZ^;!s}zNdla^l!1@{h_^u?8f$kl*TkB3(DLg7J3t~+LhG3!LYBYi9qzQK1 zth$|!E?k3L-%M_6%VCJS_gWMK9;MmjRu7F54S*9!bnTZ@i=qQiJd;{yQQHQupLoYe zJ`~8gwsy}^T)T4&rA*wZ(O>o6jsCJ8OX1as?l(Fxy4&*xt6o>E@QK*V@RY=wA zT|a$ma6G`qExc9%in1zN6$CYCCO>zYO=&;Y!k8R2?`Na-`?jVZZmenRs`nh5_M9Y| z0jB-r+XjiduWHnYwA)Bt`)q1N7k*yOZ^H<&R+s@ZHLz*uI8q743nxU0%^nWVo{iZX zU}Dx>y8}vH&$%Yv+&%ZnU0fx9Fi|qD^9Z#9cc`GN&IoI@h~xUNt`^7JCm@aWiDSZY z;saalZ0k+FQ5Ou9YCp{5j$w!43DFAlUS%MmCnHyXXu;4`z*F7#ccF zhF+*zmHE6RJ1wvL*~6*z)M`5T>bxY$Q16qdMeY3)Ex|@-wL)p{w&*BUx7Nvb?v}^q z*%KWSZ7FBuvaRO4E$aL*8|AT9GS1GpR%=EtPs-D5((X%=ng9>c zyaOq*+110(NIr2gJ$L$EE=niXR^eU zCB)k^l8; z`VL2@y`Q{s-?i}P8rfa#zOnrOEIyRCh$b{V!)pIABqi=D^=v10R4X_?+L)Qhu@?uq ztqi*wow9EHP`&&^VPz-;?bR+f#jWgFtz&S%mfD&13$!_o3Jc9$-&((;owQGOI6%*7dagl@P`$tDo2i5jew2hdGdc+BN zmlFG*`AD*4Ru-HHWvNL%NOX2SDsr2q{heXkF>+)(*{uB#DR5k7C;7bk+((rIYO}Hd z{l?Reh@=P20=#oqKq!Dg)XP5BhHui|rA2E_-NsX2_@~$lS$`}DllZwWYrW%}RtrI? zJ@!?yN$412AI1>TyaK?RU)amsbOYUhXPyR#?=rt6onw+`@0myc)Kk7eEHn*JLa}o` z>a3lQQsMKVz!5b|?YVoY9>fyu7@;RdtSm==7SG<>GMq_97SkfkOLNy>9diyzU-fHU34uYWh_8 zx4vC2JnU`7EB$z`?^94Phg3MpMt66UA8BM19m@e8EuF?U%;#yz)`sZH#M*Mw&9#fB zRRq$4>63wJ9w=ZuDo&^Z<3^KsOq@{V%=@*OChR3*bI1xp2O=RI_%~+VQ`#})L)+l! zO=c5Av5-K-6OyS3UYN)ZBhzY%sZXu!v7|U8c5~(Z@~qLPSyhYu?> z?GN7t$pirXa7g(x+!Az3HB;%y_OhIerQ@Cx6v)6k}Zz5$NH@o=a&n8kWOB;+fPPY+gtC-$s#*%Jc@e<%Q@w*X}$M0zl8mIId44s zyv)X1hxMz^iut8e`SW+2matK&kwCRutE7e$`x&+>*PE7&$Mo}{UAY-}+d#~)Q`=?- z?ffnEVm$GqIFr3So)JQ_%UciUsEA84(Ox=ZLsD;SEHb?sh1ZE1ZEJ68Fi646wTgV| z;f-jc{WAliya!m^))qzIZlU)E7r(Z?RCxC!FL9pY!@bX;(b z4Oo~Nwnv|-#oPozd%P$y_fq#xq9rLnd*>C5_2H0842SExT(`%TX%!z% z{`)^ZnE&nTFTVb&#{c{1@mD*)@&EoBKM&;pHJc>!7-;0UC+O4wa=u@BBF-Vf8c72w zEBso&Pnk8Z&ZJtWk$7eez6~hh(8+_@(h24RWJ`L@MPM6Q!A%NP;9iWJop(>c{&V>9 z-Tw2#C!(~b`vg+!9iLbyAanlcpFK)vPJ6|i>}o^SgLXXC+spFZ{E~xJ56A43^LQcB ztt7W+$e$Sw<;uIh6!Skcy?-nz${op}lI4`6#Rwmyb*9OS@DQKa3(6#i5c(wms}bBZ zn0)F|mzacqEZls6ic0VW-v|IPpsrH>P?Ee;PDz09T&gG_KB|S2p;j()<2xIs&A}$I zo7@S8y}YIF8IS{g2mgK4?+9Eh6zg%B76Yr8+C(p>V!ei4(L^7rWloM0-RLd50^|aQ zYibAJH5ErZ`ogUYERhhAI9Il3_%f(QHf+bt3oQ|l8?@>uV+^s?iAk4q{(;Xf2$=1> zypG$WAZ$M%6AI}^c34Ru*x?M#lZ8$aCb-T5ypK(=#APrFw5+pR4X}UBTLtM+iQ78n z8F|(Q3~+h$c$*Lzvg(nGsWT)#dORsTvi)?DP2VFi zTvLjKZVjxi;gWb$nz{pH0$03`h~WR3&k5D{;I`_s>wZ^BULBcNJ|oha2+7V!)3ZSK zDbjy~u%2!M0lO*yG0a83oD+v7Z|fOt5CCH*`&G5PL@am4sc0v(T7X>GXV&S9oJXHR zz@4a?7qqK$_9aK(6b~c~) zZU&Tp@LW*NnG#PUVuQ4TIXn&9DAl{^N2S*?4QRbNE_RDQ@U4@6ShShzr5ji0`sX)f zRn<1*+D*Eg5%qVUB`w!ahwd*EFkI`OkK;dg=*{$ece|VXA-UEx2kB$oQaUP3fYNt7_E+hqVqw@Zi#PGe^4yP_`lh>044!mE80s6VV`lsQhh zxqTIzI~~8CAq@Dm==l;t+N<=;Ra6!K%#+{akJIdm_CEUANM0^4Ps#LsmYjtS=4>l- zchsd6gCrFzztrQnUIlUKLeyAOvl6bJr=au&ou&+J8fw5~ifU(H0)qlA=6M z+ej2}heCruGn8!Z}-5RV&{}Fjoko3g0atXs=8ES~LE zotEXKQPa2XVxCPOSd}}Qv_;ivUf;)$R@djxUv5KnA9vk|r3=Y{AJ`~2>W$Ak!she9 zia^LO;Rd9^@nDk5rU^ME@D5I3qC!F}H9N=|SxD9JGeSNsI0O?~lq}Afe$-PI%)8cF-Ke}3Hx;+5%FI^pC0W>^SqT84= zm*RH0hHf@LU(z`mzy&n$l2Tls=bY+^#LiF@7dq>>L8j=!so0@_pRS4V~PlP^_ z$JW;wuXK!)ZljCZtLriN1zD1!@4Z*2uk6q#CQu5(RHW$>jt1tsy+~DW(3AJo*j)@oW6h@b3KoU>^VW^Kn1-T>n=&1mnk`zdp47zxev` z7u)sqzrFoi{`X(yrxpLTI{o_{Nuq1WtG2w)^4oQuy`Sf2?FpOjk)hc&kLP2^slg5t zAg+jka-*5nd-KmBdI=;%*_d7CQ9d5flyOU9g_J?h$vjq-9jTDr7hzEQEXT zwp^yviNq3pE8EfT~{VTQSxYmDzYWI=Hln_>@gn*Qyi|jqa#g)7&$*!~8 zAVgS(guFRY-rYi_*B9l)Fc+Mi(Ma+8-d^OlG9;hj<-A7C3)!Me?*q}k$vy_|GA2ND zqfBKd`Pl;1>Nh2?=JZ4WZKAjsiKnJ_1g+qD@0;WeyH$&jnQxT2@khlp3)$#(CX`vq z6XyYMSzNEQA1*xQf}vW;sE#4R&f}ZR__|DKPNZ^PE^;swa)_n~bX8vGL`%4l{K@$3 zome`}PA9j?C6mUE%Sthfz_o%x9)bbPzl41~zgSev(lyV|-Q*2&81t0mgxha;1c^JA zX2NcAu~^J@x3;hrECGEvKi?XcBiz^&4U7I>EQt%udJ|Qn-p$QT{QHhg zR~&CY&u8ulwVYk41O`O9ipc`slJz~Js&Nkml9~+;T(4mq8hWdIAx+H;r2gQ=PUmw*q_NUqs6e5IgYz=ue#-OaoIUPtbx(Yk@Ud%1MTe|<_Ua8n zmMXqTunH7qQV8+mQzQ|izyc9y+^M|ovntMOGL^h09+c&)mgUZVf822z#U5}8{ay1` zfe*wFW3`F)#_#jsI95afS;++J#*s| zo&!ho78DVLY<9}yxS*4OJ5MO-4A{+6xm7b_6}(ND_^61#%!u&M zZ!5Y-ti?Pw>co`wAW;uR6%a8J(VYt7YvySL=~4G0CKX$g1ajD-G-3#yM6Gs0Vw^-d zCnWwwTc^isVe#~}f})$W>Jb1bID1IMID?&Fox(grHffqhL{CJ`hy;WJ6LQ9+x$oaw zUnhsS8)Vu}Sa1jvX?;HxhF1zCa0@WH%2a{Gn^k+J!8*EPtM>V+>UU5tP1L=Hioz+y z>N0rMhnlY(m=)grm%VEI)*NNy1(R*$Bt>nGmZcmmYIQ4?-+;}7 zmY~jSHlF&~LNy^IDRZ_6$$LDG#p5###XF!`@vrdoc)#40L0;gf*$S4e1@HbB|bKv*&SN~z$}sS z?P~Z#;&pn`XWXoOkKY4ZWMeCt&Q2l)u~`J4GoAUqpsfS_F|7AQ)WeOPq^aBc8mpEX zYvX=*r6DUsW9aDH+MBzo%1FgM^akxJgzhBj#F&RRkV-1H$% zn&LDI($r4Hc+4!AyR>mvC4=D!%wJyOkPKH**7$NEEc=kkPInLRhaYfYP90 z_7|&wu!K#=Z2T!TUmWI!6M>@(_ErwKXWV2N&^!3pa*;C$kjl_>WhYjdgxqa%`YH~T z_49dP+%k)h9>h9Kd}=dwgZ0P|Zw{G#bzhR##WgVu1#XLp6WCyeRrmG;nT_mPe7u5> zq@O0=mYN#d03%a3qd7#MBICy;y~SkgF`02Po8>FPIacD8(Pw;F?Nh1mm74hz&Nf*p z>fV!qYxwE(*sYXLoY{x|g9(C(Ar{R{lL8Ke!fJBMOB1gPZ%fg|vG**RuT+whjaS6c zCA?Rg^df%eXWx9*Cqu$1NQ_5Ib{|Z~fvN?@XYIn}{2Z1@rs&8tqY%v#IGohcUST7| zB!qET4Q{?^)vC5hy9RoCsAvP8F2MB6LdhpvQ2T~|P1@DdKs7&ra?`l!Tg-&9V8#5Vce)q-ngUshz9VTeJYZ+HCv9)&cNv$ zM0+jknyEDoLG@;aSMq#Kk&bTRF*`n>jH+I?kuH(@oM@03Bb2Fe=SNVPixo!^1Dt-0 zG|EA8&uP{&%Y3z@mx0a1fI_CU3gO}0`4Yg6%1OGk)lY=uK}0<-A!N3P#qz`b#P4T& zJNuIe5wnX7RSQXCMd2(YC6Q=#XsUcyyq*CVx9?8&zfR2kQBUzSjNLjhETS~W(lcQ=_yYt zEKggIKwoP}PDm3~GlE11(vZo}kC&~$PYaC{ysGty=2H@NmplRm-Gwa zdkWJ2LbCF<#8`~+4Cq9g-3y|~Ge-sYvsr-6RJ+ZNGt-Pa4hCTwHt#>N0M|{nF}Edn zjI03j+Pc=HZN2(5_D_k-G7vpzbX7nA%Hi$2j4-{l*HIoaA`Cbx17Qofrja!j!<#Qg zl6-m|0(ZHAElV-Vfu!@P(o~-8>@FFt$h_5>s9gI+F4xzz?~5mLKiKnEw4yeX;gt0V zv&=H>Y25Bc6kzBlh!@Y`i&|c85u8SxzLH*6KG=|SxXK85H$BG?Xf{XpwCY~_Q$}~m z>jskG^olvC2R>~s_|A;iEs?;+L9+8G-6qOvJ|}5|Mz-wEqvYL_1DhFF&+g}%t3C^>B(m|U1JhI%FCcy;Z-?g>k?gKI?M~s*8%J3%S zGhwb5pvq=Qjofyi2nL-^tzpyTiLZB+eRRcm)wQ_4#O9(3`sAwWYRb4-v>#FyT^Afy zHK%rM&*8uYM(sm_dc!?4Wji&kihb6=FD>WRGRE^tSoQ11Fk(a_$)o3w)ykn}UE>C* zy0ea{v5w4Ue23XIYN=3KHIbHlDeX#3y`Xwuo88PdaAp^EtDvIOetyA>F?3v<-)_mQ z<-;Roq9y%S0{SZ=kt0(}&LrYX-g*@|C6)V}od(Q^j1IW(vp=;>gI+`H7#Phc^e!9q z17|E%E8#b3Oe{-KfGSlkRx)VcgH=|76B^XAola!LFpjF0Ab=Iv#(R3iS}IKMt|{z! zjT$L2P5oLEURD1n@@`-_6VuuBNpzTs#*+M0j`yhae z+=FW5I4~p^-Y|ArZ%DK`44WAR0Rh%2$LD$zjPtCS(NsIH{bhLgA>GB*i~}moz~5s1 zU*hz+u_TtTOBfmy%luT6%)U62+L3II<_+_xw&k7qR`Yfd05ech>~*gQ`awvI!B3NvJjPXHRnln)y^^g%YNY7)k?~TKW~sIYLjZK`}Q7Gt4xuGh4gOW z5}QlgqRK?I^Hl4iRE0>s9!NB+i~c}^?hG`x;{g)k7^=qC<#a5|lpWj+>uOpz-!h^c zn}OoYLx~_#Ou0>CQ?-TBQmXKso}$EAMkI&A+ zx|}Qh?1Sh(4T|C{r4lYy)1C^NXtGM^J#9bH7d6p?5==r-ovOxZYe>hM3EIjc2i5YM z+yg?Gd<=5%L%S_rD<)x!B;+ffj3sPf?m~LqPuS2KsFD__q1pUxt9a|TSA0p8=gKc4 zPIj{b_G}mV626n%egC_8-hMx-uopf8n5-C78%J|5?C~$4g`k!XX(Au1h3xIMXdwZF z9Cu_p7Bw#9K{vQrM}}Z3eypBj5L5ph^qdW%gxb`E_FB3U2q7VDv(Te9@`{B1i28v;TL(H-4QB*LQQAiL5MX^V5_P+cCu79_83 zxN3U-{c)JQ4&QF1 zIXTJhM<29_$qqMHwL}`fv*m;sx~VN(n$0VauWY^F+zB_4o8#dseKCzS`i7EUsFHtV zPchBa0Ct0TQ?s&Y2OQe3-X^d9N^@VIZnf4}+}#?Fj9+DDHrnd9sd}z@BY?5mprc}= z(gfeeoK?9B!~)-2p)3UdD%6=fis=R;z@xTe@-%-r@5~VN!=dTjK8IAaZ$nldwDg2r zc@%a1szny-*K*vkhW%J!H*IEqwp z=I>9QyMHb`Y}{AECjMx>L`u}B&i1NkPWQ^3Y3+G~C%rZ;N=gtzRgKPP^bd2<%nfF~ ze_2LnCCt_C-6Q42VZ(8L0jfs zW5x^?Q)1pQomfA(sn`Y%nV4_vjEgyNOpg;sCy{5`!n!4W_&qCyI}&M_AQt<|_3fL_ z|HkpYR_XfS8|%%kt*D0O%+_(&Hq>01p37h&lOSfd2n&+VH5x35%v)9`%c~Ii;>n<7 z*{Ep^a~K2ev2c2jp!(RGqRy;z9bT*d9Gk?fZe&Q2)kbHwoY{aSy}cuRG$DEq;3+@ zDm+Z@(vTVHIkC&3B7eSOZ8@dlEmlkfcqF4@K8l-GDd&WRceT4?ER2BsB*N9^&c|mx znqYK?(q(Fyvz9XS0;JT`um;y?|ALTjQIj$n53FZ@N|_yDu9UKMoIAwp;dGqewf)0WOq*IUCi5rLsT{F0n!s% zhZw0O6RKfY!X`Ms+~kZM1J4ooGJ){_0m#fl;lK>7&p~*${UKsntm!4PVF-Ak3 zsu5p;GP7Wx>ud-!LfoqFemEQ`81I~YAyfDsa15wnUm6~f&V~)d0{%yP-7q77-RbRx zX)Q%F1YGx->&J_P%rEVbLjRbjx)Z0T%3T8EKgHc!B$kk7SwlN3(XHu zwh`Y7H}25pWAgHD#nPY9PjW5 z%BtpeOac+ortu}1LV%67$A`$7%=fj0;SSp3M6{$0_K=~;$9`~3(hT?rGsFSnCf-~5 z?03an-IwAozbvK%+&Dn#QkRu7;A|Wdo}?{93n+Zpza0~ ztEc8&nFLy?@PyC=fP8=`iKgsoJldUPC8ftjahB{`>2)JFOvRF{J9&}a6qic@@Lpwb z&Rk~&#~a1Xa^lFic|g21CpuP9`zg4N-w12H)>nv8Ct8$oSRZFTSkRd;&qzw#=6CrZ z8}ndL2b$5?@7*=42KxPb+imPfd$4hbX~r7>wS>tjsA!tPY`wQ06k3|pdkvPbp-|CG zZCJ|Ph`q>bzz%}MhsO9LRyFVxxie;~bqj6cxiSe9%i&Hs^)%qg2hYg&DLvY#Tp}&i zw)>qkOOe}Hqss5<&k$Hlf|_I|zFK3_L-;s_pYU7ubWGi2n`8};faxx~%eHOXwr$(C zZQHhOyUVt1YwMkv-D~p~8S31Q#{$e z)gxU?#p*FZk-G`Wu>FdQbxj#<3n&gTniTZOQI^N${$l`CPa}s>Vl`?3Z8Ri5*<4Gq z-&tYr0Fzj{+{coC@F>P~Vpx7}5>mv7FRoNHed zWY?Sf-7!1tbI;qR#NJ?%6+iF)huJIn*>nrow-kt?3*T_-NW%ZNci2(#qZW}m&iNRe z!N-q4*8@Rsq2%q*@&*5c!m)z`&4YJ1Gwm)e#*~o`OLb+qvsda>0ZcO+^Q6oKK1kw$ z=bQhC9PVP%ruhV{d`k9WX-}QqghbO6Va4@Fdia+vx}Q9BK9d#g{!fGK6#rRq0n(j& z)-)ZMZo(j*UM3MW$pYJxr_t{C*S3=bq%q?t<3Sft3=>A)PLf6aThhD@k%V6tLKdim zGmle%rbN~7*@$_dorrgdBxzELYtM&y=wA9)7L=lh#E2_X1%{vy-bV<0Lnz@^iOCd zIbRN2RFMB%VVKFv)nMZlWCf_XR}CdQcc&mt@n2IgpL4bj)0L@|HBYan;A9`B1x_q>C)X z*+lYjO+I^q&$HhhqQ%<@F&g5)?O<1I+I9vb;>U!ahhF_Bdu@MUE(8ZwWlX-25pmj_ z2luR5#i)f@_Dm*Il=zUs1GHL7Z&tmI>hi>!fSRP_{|~gU)%}8Y(Lcx1a<7e$QDqLh zHA4Zyu{;)@N_lldysQsGiWok^A7^m*QWq)@I3ZgXy0 z#6E{X$CL&;rA&C85Dd6TP)s4tE){7G7K`X1Yz=7&!q7nn6mVGp=>ca0wMpl$dT}B= zB-5T=|L56n>Hf#F#{e2>&`_bdt^AK?m-_YWWLTa5d3J>M|JSo4uAH0Xo2~z!XLsJq zicCkHoxpwP+k0HhzZj8;BprL-`~~gm@C)ORroW)w6>MxGH3$FwwkAu@Y@sYm3eEoN zOSm95-uZQKn{>%Qh{?MTpctYEgQk2r$Os9OovKtY$cg11ruB%_(Gm1MWB?(JsbqF@ zwWf9AWfHwj>bU)|_{fNKXln#Rt8|ctl!0#iY`Z*>E80VltnE-MRq9^G)>CFqkDJ=_ z^?t3g#{QsyLPXU;&X*5 z^sU~@Q>PATY82Y8lMyI1ikaW0>nb`PL9&$fX}{u?Zyt7!YP(|-!vGL#1Lu5M(jszm z!PPm*PCp^nv~VNHvA#_^sSW%z?STF%3(();#U>tN#TTX+8J9)Q%c*?@$~v(T$+y&6 zVh7rg+Yn;>TlkDb&+OTL#hT4@m_65T+(S+Vb~v++w|&N@^6Tt%DaoORs>A4j=|xwX zv=ul%Wx;V{&RWtS7;lHY zI$@(Nd_~1;1A81zG0f3-cy9GS@17UWC&hz>)0s)C57CUfq@8|Dzoi0a1&3DTLZa3o z81kM2b7W4rJuxEz!dXcc5~3y-+Bd0I?U+`~;!g5zJ6;avl#t zoPT}3pMl)s(2k4rMf@%DrVopB^VC+Yzmgl$r#KDHYomy6&CI*n5q z%xIoahWs1)$~imPri=7Wxc4zx0?;)e7*9mi{d2hrdcFVD!JofwvURDoJVnX~8Q}F& zc)Sn>&EM^w)!lHBVP!AfSz$FJu!|#uyb7JyxC!BSYaZJfRqWP=V%9e8Q#s8im!SD! zFakCR_4#I}Vx9mDv&A zxoG15fpTvnvs^AV8N)$ z8PNguqxJ4SY`0*)VqnE!37GAS;l3tt*^UNXKf}`pzDqsWGR_9#O#G^s1@{_qUb=3UG}}Y#pkA#=FVjZ^ zqq52zqg{>;VlPKo`~G=-g8+w?s(LeNXqswGJ%qLO?rUKzn%DwZ06Dv@x*RZKP+#7U za3*!7cxt~(;!K5y;BW5r!X7Og4Gr}HJP9Szi}jn=i;K77;W;fD%=5)KxleykmnbZB z-_Sx8-KGWhxoJpUC;hK&--SUsfwn26A@N8<6WN2w@-s!x$c0b52f{mWq|~hn;QnjA)f%nHcA?ltGk^ zA-JlaeN9VYK`z9R?^QrQONaJ3vCGzXyytOc`ooB{{aT)T9Br-45!QAQArWr~G&xO^ zBKV8i4^|+K;Bq1!+DajsaPrMYsQ+cf=LqD1?TB{7-ZV4+huXUr*qX)v|EPVGV}IC9 zIsY}g$*rDyg;UnWkY-%ac?&P1S{0WYDM+eH=#@oeGzqa-i2J-IFIR4gqyGX~Z>M4&8##&K z#VN8-(Epltdb3Kg)uQxEmH$jT`BBHOX`euo2HiqpRb(Ikqzkq!l&nn8?Y_t-)p57i zB+b_8C->l=G{G_M!`3_!-+1_p5U>E+Ba5b9@J?nR(hT zUSN6%nA!-F&k8bHGKwWRkt6@3C@>RH^^emNFh4=HBVI#JotD`g(!7O=Dc}4s84NUm zjqMRS9Z12KlgfE$5YVd)b6t}8V0cyK=uV3}KSQzMK(Pm5+V9z4s5PTc`kN-7zc~VU zJZ-qE{-iRQoMRv!=^A~*-*-p@wq@LlPAut3NKCZ?d=npv56;X7z^vC-2Zkv;dSF^w zM^RfYdJS9r%CrgQx`0BPyNjCoRh!MHX_3MgCk7J|#hPD#(B^R!)S48*V*-Wx!VR%V zlUqFeTp}YhP~b-)hTShZSq^>*psD|nosQ_Ah)?P_{|@;Z!^E4Xe>mmHKuq^E5|S-! z^nH!sx+HGQ+l4s@+WZB7!QtFuh}BGt{9ifumt*1kjx1WUW`c6|T0Sz}GJz@TeNW9- zMz4lxb=kPDKc8*I3sknR%Fw_kFoRMz-7Its=4PyBl-40&Q!DoPVy0vmxHa2?K{r0@ z=hfBGPKd0@T^c0_{*~?`vYQbn6ax6Nq(`URKm!5h5!9B{?T@Qf%gU1pcy}@B-;di_ z9d`ssw}`}+M4qD`0fBXbe^EppR-~D&Be^xM!Vx!b$fef=Vp~f{$)G*8m}F>5=pUEY zDT$Nqvt0UrALD?RKywghb^715LP%V*sM@z31|i2qT1WkJvZ9aW8}?({MtUDbx`(Xz zm>sedegx#6*`6=hW-?UW4od3wc`M!)!@Eck=gbu`4pfBQjm%*Rqr5VPkTz`-)H32t8zP@sC_o~im6!;+Ap7-Ka<;?G_CeTnuR;M zd*tgzZhxZqZwYiwUO`$z3&=9*JA%n38T+gGnEXN4MDZ{JLEYB2-*GNKd0<^AR83Tj zomue|o~JGmN2AaqFKd23k}4|46UmEewl9U0%&oJcHSxsNvC6P50+^43@m$Ab$>DOA zAX=FPr_+`@8=sidFQpti@5-~Orw+F6KFB9UX=;G6QG}ac?uTCNZ+#1JnUm3EdQG$_ zPypFt_jD6+GHBotOT9CqlB9({^;5e-5K2W1gyPtF{OlWBzOmStrn1T#zfwN$SIYlW zenQO+3z)`52Rr&YHzAIL?E+@ZKbdCs(Z%D5(W`k$KjqS2`7Lej9Q2+x>Y~w7FS_H3 zON|&$cb;-k9xOCwXp9B0Nwcv-S%bXrLOfnSNIAjXvg5NGiNa}x{Kzg-Y&?oUFIwC& zMtRFFcS)>21&l)tsQ(#(Gc(8;bAIGy!|pKy$!Ke z;WEY8yj!hOnh)fozEYuywbchfx2aJk3Q(Xx>?DLDAl@w!Feb_nS4BNig@tevS%Lc08lk@8_w^p#8_1 zkH2t8gfq>O_0K2MnG*a7quE!479f))a=s#LY+2J%s?`Kb-e3+zOXRmkh6PQ^h;lMo>FgM}hOiDr#p7U@JpOO1Eu2fm8nG7EW5D$ao1x}iK( zOh=<6(hV73aC1|TS}v!@1{hrGiqe0_&_B{z__#*>v82gq^Lr89h}V*l>|1^cwd}(x zb{LC^&Q`(fwT=lE%M!ckVPUyzc!~%m&cSA~PlnRzkUhG8vv}Ev^cZ1JatkXLI=bGh zE4bc)vrMNaUW%aA%nNMiV{khi%ZUKZ+!b@H0Ng40GlD4Hl}imB9cx8$oz?~AT>Ars zU*YBNDhh{7|Kr@LGjpd9SIt@YOWmKr73e9_@^zR!#Jl!Uz(ek?wy1Ckz>&$gmE9(f z+_GRD1s00qlDQnFjA67igLB#v^vsXilpp;)akwh7JMOy-ol`<_L@1uu`=-(;MbQGLRl+SFL$Sk{xYKJ>Thk#bNV;)(Fs z(|`?k;FY0kxyEy<#RKhk$HLK;tlh7z?fP<}q%8~+-#d(c2!ZIw>&B5nk@lz_M>dZW)Y;q8OoSvHxP4swQJTpySN)o4R-U0l zsc6AEe?!MnkS910#E@65K9FGpB905p%UMBEscU`sa;r3H7rG_h zf3GV9lzL!`mpj9ottCl76nDUnKkAuiPdtBj^98#?j9u#22{XrM!MzFw1lji6Ujl`Y zGZy2%I5n5JWyFm{r^Oa9_YaqChbOQ6Jprr0#1pvS^n_z?-`UJ^L#~MEOhBt@DaC~% zz)Yu)V_&L}a*kEm>177!JO7QLW$-yk0W_LvY)glx*6`QZlDH-x(e-V4Qb*v#&RaQ@ zvIhdYMJb9nU9~Dk?mtK~C1RM$FZ>GkHWMOT$Ry9l)11Orvnw=-^ftx9-imI_FXJsf z0Rp(KT4z0{R>4o`RVof^dP@&V(5T(ZJgdm=25M}#+hR4XP1>srfPYpJ4pwt8Lmaps zSQ&8=_ZE#0Nstnt+HqJReO<*?`Zlb~$gqO*Y`J*CkhdLDo(RuOb_HldwD+k2KQ6`@ z`wvMCV%zDB{_EA?Re2?)x5spQ;o0L&W&Akb2E5KYvOAC?5a7yCs!EHgRS_Z}{T$H= zvDF@q8L=&O|AeJK&6Iq1w!cd;t=2owxlK#BZ|20V_TSH1AuOGApUO~H8`Ha<+Y7>M z-U`xog5?dS=|IqmO%tu`^?)NzWa1Do*}BBAF$oq25361$J(6P6+TVAoa(@m3DHCg< z$#$G^`T=$g5mqPC_^2Y;5Z>NB>{}jis8V_EMAQ^k2260XZM*lF&I583l0(}!8Jy6# z@G<%uE2D@WjSdB2sL|RYxC*M)W5g0(MVt$brV+};zoU{KVnZhqAG_L~Phd;e6)Vqf zD<2Yy1e;|GP?%q2o1iVTm%`+=Y?tKWjEWOiuG379*Iqb?))i)0jWnm-X-BrHu2?4- zsb6v;xhx{;wDh5Exhps^g~x_@aLMWZb|1mOXFQ06|E5xGWVa0bl)Xd%f| zjmPI$#VbfV5kbd|!TII3)!H(HP7GoCx22tj~wA4~$@L8+I=uN?e?)EFEnoQn=n(;q7Mk`F=TEt7IKtIQWm6C#Le+#TTB0mX`if za~G;i38{FF!>RRUA?U&+d^}1m{D+=$6 zbg`?~0tMXlgy9Z}=Ak-?g(x(X(r%$4-ut5dNmD{>l!5L@BVMuv)st= zQ&`TLfekv)nz1w?-g_x{yUiMSe>b_Uq8$9M0rFuaW*Y-st=a|-!@Z{1MIj;KO(8+~ zpet!bZM}7r$DTRe`2mX*BDu=HM${bSi=}Mkc8U?E%eAEY%m4M*3+xG~(5=O^&N;Ny zwN&Z^Z)Iagm~iQ8Yiln?rKqa9cIYw&CF(phsAWm*=$JI{%axs0tibpNu52Atiu8`F zO2-Bx9FIHf^%GF)loz(!i^V%f3A+$P+gy|KF7%NVMa9p-c>fyn74z{Cm(zry0tbU> z=1FfiU@Jf8$bPKtCCjK|nKVFDfd^M1Xu{#CPMY-AV`921r+>uWssd_1eN1u_fq_o^ znOILlk1S*;;8)y&F&gT@7$-yxIZyO=<;mD7aHK-$m79z?AWvM>4}0)3!q_wM)vh@> zyl-crc=3O@u%W|dx2kzc8R=USttcngKrvx_s-FKI=<&Ji60NmZt;bta0$(TC-A@Qy z$PY~k3WWzYDJ}N{NoQlb**~t_&wO2f1Hr5^XW2z&Z{Z9l>_g)HypNLQ0*RO8E;}nW z@9enzSRQ-^j7vrI1kenZBIVOmPGMg@15QS9-PJ#dE&nATZR>G{8s&b0a*BL@jvvjt zA|;zo#7vM1Zy7$XMnzTq73N466IZ2!SJ_vt!$$Esi#WsGg-2QUSv9$(?9NcDae-x$8mpF zNFRQ@KBS|6>~HQ^cfMwRUTa_7(S8U=S1ptZNevcuMS67I&YJ-6`^-{lB|bH}WyiN_ zMhBLUUA%E`r(6BUFxo&^H97WNgP_rC+rhCwDcMfzwzeY$tDmmXykJOacd&VQ-6<^e zf8y$RvKwEPQwOME-c3Up&J(zD63q?zIzWrj>CD##@KxSiQw@-VLmp#^g_Q}$MH{jl zi~#vb7h6|lb%H`)gEAFG@Pe!y{#qvkK(;|)1;PMEhT;3pY@G`96aLiLLUJw1J(ICx zLsXL^DiM-Ny#aQsc4@Ie7!_mq3R^BP@n9XlSWZ{%1J+)bReBtnZVvmtbWrmz1sPz| zEa(LyEC!smC{-y^FEPZ^LOSRLcVTxM>F(0-bx2*Qb(PG62Wz#3$0EZ4>K{++LRiu+ ztv=h{()YsDvt|};%Krs0fJMkeHJ|3rrG-=*a<@lh6@~Bi5h6j7ig*l6K&Tid=Ocy6 zrkPUD0EI@ZM-FwCbG}$=OSJajFtc68S6S`O>K#>#;gHUP=+-H z$I14`7-RQod&Jr{0`f-+$%iCRolYRGtilh?v?&lm%xRL5wmLY@bT@8*^@ND&Fy6pJ zr|4l0Wz&)=Yhg;9ECCAp<>W81xHC|Q8*3Q0M)074!1D17Pa>Oi1g4wWM3iBCDSJao z8~wQG*kc*Yo}QeB9k4sixDLL$hcV3DL>pm~!|2oIeM==NImap|GQa^rlo z6CRo>ZN|6`Z4IBfP@6oMJveA+V?neOlYahZ)LQ6xJSnFEKiir|2H|XcEFx|Li8SNH zhqL*~<%hFcE`&;yD@%*yy5(lks)o#iFI8i;SJT{;p%ll~Qf|pufs8liDRHgLU8MMy zxZKHbz-{JvLNKZ7h*xIM>KW65ar>1feoI!} zxWD~^$1z<~ZdBx2SL+b{S|n+=B^>BMV8ACBnBLz~^t zy*eFcC}efamTsJRZMR1|t523= zK5MF;jHI?2CC>l4Y-?Y3LYx_zNsgLa8Oj}^yv#*j+)>}_`OLGoXBo~nigxSzGsf?t z?&}|vOE5MgznMTMr+0Uo1+Wh8Wf;J{uD8B%%&D0eTLlVhzX0doS31y*Z0w-;(utS` z!dgR!Nr*OE$QH}scK}%wWBv?82G2k(yHZp&+h3D?fVcKQ&95Eqc3|11O1W}<- zdQU|4R!VBI+JP6`Eq(?*l!)&o1;xY9L;~-A?8D>wmH2I#6$x#s>WL9M7U{vi{;3=u zS5ednHlcy)N5B`hGP$+t6kV+0i zg`z_LOn66w(hxwQ78{N9y2bYFz!{zmC93WoGq7-aCCJzy2)^PO062cvqc$hg_r2l; zPNEz98nd2Q1&y4zLrf9wSX-ZIU$N@>y6jUKOcivhT;FZvG zK4r3ZD6-Gc0bK~_+g9@2qDo09+=R2MV&Owcm`^ZY-|ON{(S~@Mu_aO;4GvcL&}q_? zB8%dgbC}H&Z`E!=+9c6G69y#N6d40DuTwlfqOMjM+1= zlo<}njiX<=9Ch_9@01}+F3pOA<8B$LsxRn9!rkp28=}`n45TtU!(C}ayr0pR52Bo$ zom1&we|IiwukV&r1zFF(_glU0*r;!0BE>m&IN0MkckZ%LWfYETNhcXL-x4?Ic?75p z>)^FLH%SmY--AtdV2uuEL#aCl(gBDxey?B}6=pKg*l>7HfB8qLu&!~?iwD>(UJ2TC zZZD_>tV5gVW6iGKswt;A^S0B6U2trp&%-wcRBr(uRx=!A#eemo`rX&6)%9P9Q}orh9}PGySdvwe|HknX`i0=-jt?} zAunu9Go5GuxS#T2vhSIVYn)k~SauH<6 zaLKAC7SE`&6^dcgs@#`4BK)Y3>#n z8>ZCL)YdVdij%#+d#+`Ai!LKiwo-w_SSWjwSIt?R^;H)jgg`-z({tnZ}#On;%c(rSc zZ5Akez`snwsl}lYq=4C^9{Pd&kLGnb9I$QFjV={4gtK<1Wc;Uy#3d067 zMr2+G&mCwc!J{vYHpL?$_mK2s6w%cTqFmawm)W?0_Y)}1`*@^Pmy)h5zECKsl91)^ zX%a$F!+988*33g>7GJ{RE!yF9CenR7gByf-h*9eAswCz{Tx*!6kt^<>@pX?=VtZ0y z2=NlACXXY-dzBApo$v5cJdE3a%<8P?+RE?gy` zlz8F-kHatL&&k^Fi@-E|SrJ^`6Yw5dt*8~}n{5Hr+4F2l4NM^Id|J<@MsyXdH!?&1 zo$jR4O8RyC2i40)z1dBaXFquK-(Td+yk|eTa*x{vooP{bJSFRX?^po}X7b#$Pwy zjW1U>7eBgp3t>O*T^sgb;-vz~eus5Cdy4 zKz|tQW387HeQmx(!HEIhL^%v@+>*5ZJo0TOlp)Mes#g;oRF;h}1UiXTA1?IN3IpYN zBa=UJ%NW_HN&N0r(JKv27Zj1hvr9`RCL{nVeki@dnzj$%&9HlO^Yaa{A8m(IHK^Jk zz$vrndw}=wWTO70$_bW2jk{prEO)`EzJUyXIeLci#xOb($RXL?E}N8zM}ywlo9w3* zdgZL~rnLW(?A^`r!u5r(L-Cf~vI~>|5ex^fdGe6ggW2LkW0f|}_8X`}N8?kRMwb~y@{?!Z8+Qv6y z4oYonf0|Y#39xXLzRFnuEdEt$*L}p_2Vy79x}*$uuc;vX%OUY_sOWv+59BMI$0sLf zw|0r+z>G|T1Sn?C{jLK;B?PGkFcs3}5(H6DLk(auZRMV}S6yflVr)T=sc$}Ai>H`Kdt&t@|H*8ctNirl`V4B-h zG(&Q>(E&)slC6Z!^jWwch>$(KoUHT>-46QG_RBb?%knY);6FO&gV^8Uc7wSkl@jyB z>|y%-e4CCruU6nhKVNeKJFXzGTZJtHP>Vt_O5B8d``Df=V8aE0+&pWd-bW)p5L>-d zPLAw#0;NeB7BUYy<8H$4K(O8)Z9;wuS{hX1#)GLwC|37CtPw6^_WD?&IS5Afd8t)d z8q~qIbYgZ9Vy`JG zb3g==>~7A}d4?FiuJ`cyagbCopmmALyY4eMc=%ye5nu#TtR z>!cNR#rft_nQG%}8hC`Ag<$t^5HyH}lkCIN>2eh0>_H^t6%CIvJyTp%UTK!bj?uI7 z-9k?_5&_d~r1)tNv`Ky|2u#p^TUImrK7QVZ0&81wuIh1rDS3+1B+3#1v(xQJ#}y=^ zM-P(g=6{2+@4`Lk8lklVMR#0~T)xC7zC$uXcAfyT`7p+Drdg=x) zI9hH<1K%oM8Ix_ZP)V@c&=W^6yYeRkXP|Z1W=w1p7D6DLm$yON8D%$FYglsHvR{i6 zP=L}?g6G%GK?<`-cC&S{;nxNoIPm%2HnVxM9J1+cHwyG{t9jtvxSk|L*TTO*a<|j@ z5bg`=&LiNBfk<&D{C8a)3(?wAptUMf)LYH_g*2KmJtK;t%Zoh4 zn@z2P5dz-Fz!n%tX#RnYP@9@3r{t*U=nTNy*}}ibtmM%)dKb zz-|HPT`Rg#q%|ls+926)v0<^URKo_XCtGg7TBVtPE0jg)#m$ygvR4HfBOn)-)6HsC z7vn{~GK_?I6Bc9s!@p>vEVj)fzjt0lto)rvIdDOJGZ1!A(grIR@kE?){~oji9+41) zxo6llU|MU<>oLg@io|iIHIT>_O-KYq&<^DP*ZJ6PGtjttr*wyKva1*~$*<~m=~aza zPW_YnEd%FW z9+Zkp34Nd>6wosmTW?A$7nX2)+bFUgB0?3r+3iMAFhY&WICEZt-#U9nq7mLYyx`oQ zOPPNbT?t-@Y8))=N@#5j?^Gx>qR67jv)y{ZP=(pmjH<{2GZe&Hf+kzdR;_-?iNba< z3s=P>vnBWlnOv#S;CN6x4{}C@A^;fmu3|k+!Uq6-rUAvkw?zaE2!x@LolqM_S003C za=Beo5BJt{EL;t7e_`!IOuP!UUsT$(M-*HrMh9K#qp&1bxS*St{P$Y}-pH5LTb0!_ zykAiMt_w8-6xmwZTvt#KGQSLIhEKv-Psb}1&pi{Jg_XQk$|^lz>@YmR*IbVC>9$uu zHZ;s!0T>}5C?fdnl#^z=O*V_bMdxRxN!ufw_b`X#@S3y=vMbM!z4}Zcc>42s@d!tg zP9nG;#4F3SoC%XG-?E$cJJkteV>QW?z}GSF&PBz)9R?J(>E#xbtXmYair@-9G;N3~ zGqtX!D4#_(k5IiVOVJ&c<@|(bu!ydb>#EeoteWtcQWXz?Rg?LQG{$dx9zib=4Inek zye?ISwI^jRxg1?8PFug8F_#Kx{YIn?@5c`cJv5I+1W|A8KF(?pN0v1|UiHS$7JSO2 zlCVFFTHlku>pssGR1i(et%H1Bt`w`0yP;($^TjuH;ST_+6VTCKc$r@l)Dh-&PZ%Ni z82rXp;+LXM2-9c(vc2jUJ`AuIH>@#tHFR7|j|oOeoY{9~?iFm!mQ6ISd1flvKZUMw zU-2vhmk(tisCjh}yV|gjBAJc;5n^(?RB}t3rf!iQ@H~L&0%ZInxWh)AyPSR7cJI(W z5f3^|i~16l%Vc^D`+lyO%fVDrCKx<;ve`mF$fHhngc)^NSR&XT*xCV|GB)Ep?1~MQsZ(Xv1nw)De)o#ka(y1?un(m~P2r9Q4=}xMK zBQd*K5{^hPJy!9zBp*Y2ySjM??KDg|l#{{sw7v1Sl@uIt6wjk=nW!T8q7)_Q2}x(V z$p}wP@+3G$QqAc&WBQ>Wzu?wa`rU0ale?NG0&eg1mNW~WA94H`G0kiyGZexH@tgpR zDZ3fSb74;_AOA*n18d>~zua+$+Dom~xkj|_dpFk|obm?%tz~1<36RdA_Nc`Ni1z$qbM$TFZ+savWt!RX85f$rUODq0M8cB+h(Skr z<^JQicKKSD&0-Q~!%$39UI6(3eF^(>N#$jr-Eg+C|4b983?wUvUV{)0XQl@wMWUYC zOtVxL3tj7qKNup3rG1S_Q_ADWt?IRq-mBuuN%#y=@R<`ps$ZL8AcfE2&<0+~Iw0{0 z4%NaSQ!iI*br(Q@%o*{sK!v-ca=JRe+T5dFH3_*EF6{M5etBZ$@AONuT4m) z)GeB@N$rBFKX&0N&{PuE-gp-82Y~L1v&aOijrT3pDV#UU69~;%i2Uq*g{@QA94a-o zJqK;rJB)Th=%8*di=vK#mzeb^h$Af5hIJ_f-Jo=b?Ys@Y=sJzVI{&?Y-b=v8T9Ds0 z0Q$q%X~*8{H<^;&sxVz5@&KHN3&NRFm!pSZV5|B&3)N_^u%55U$#9o!SeHVz6SzlT zCe4t4N%NKNUGflAqZj-}LA!p@1Q^3ZDO!i?(Bx`k6#zH^gLOkk=NVZsE{v;)1kGq% zGNVcZ4P+3V2+fkx?0yG?Wq;wLXAT-XYO2$f^DbHGXozyYSGX#v$^_nA!A_!iz_qH!BJS6 zAf^-E8q(kWi40Jb@96(Y6QxE+D<}G_#;cPb6Qb!6G%*)01S6(Hp+JdRr22DBD>1_{|dqF(KlppzXte>mt9I1-8T21hJECrfle&W9Yq zz}O@Bf_AkL^|XQDzX4AK9Nx0fo7=G1 zBkxpnD>qM?t%5(l@Lzktv$oy$-HO2wtRRgJ^YQDS-8_%&jlhgPu{%G(|A_od7T zr7`K*<_Yd!T4CV}SfS1CX2keq_@~ZF3LZdEODnAzBaoIrp%id&qYa{>eI5GTx_!52 zvqBd&8=j(Sm6OhX(BXvIgk9knU4m3%=I(sSNAPn1r}cPsvx=^d&ws=y_0(glh0^$z zD?y6!jbucVPlXngw~3;$(ksb13ram96;9sIyL?6#UKrA}HXN4K9M2w@jIcJ0eEBXE zHaaACi!7!`{al!{jra3RjUKn(i>OR5TB)oI#e;XEbmQubV5K%){8%{FygS1MzH9EQ{Mn0OchN!Wp`nJI6JQ7#3Cz%_(W&Jq7$KF-z;i*=4|}O^86yO9rDr zg`>y-M9(z*QzOxT)l3TTs~YL7?ypG{NnqH7IZ*700w1CJ*Bs}$P;l1PlYHX^GX&^j zqzNGMkJ#mbh~}vVJVahRM$^qlu)!{YVKTwU*W7BTLkyXY;A6U=A12n9H}kU3|7#0u zGQg9|4s3^vkVNc`NSxMwtU&#V1JZWqU>|Np8 zK+wN9CGPb6!j{PF7gezS_b+8@OLCi=y8&V~vCoTZV$2wV?X=i#++hszA4ZM2kn!FE z-U9qKw{ZhMXsVg^Sh*FluNW7GBMSM*_r7E9;D>qGn2}|5I5Ukcd`FdXG~_bhI2GQW z4~raB=(YR1u2CbNSP~WMF(IRu>P3s{Ci2&@zNWRcv0K=v+E^2aNEZlqW$*bZyp^e@ z#$ZYg)caFSLu?INZAH&Z>MDb(z=M{uwy-s8Fis22W?ocPySmTY{9~>VO1j$~9s|#sOL9R_ex-*z}~^EGI4fa*A-%^ePQ> zQ+oCL<;pgf^3Bo^mU_-HieVQI=4)2zKpE+aQ}qAZ0)y6o7d*<8@Mm9X8M(JD#=2{l z5Ec%wIzHjU)$tFl2DP~W1}sBeHGI6gPL_;x6N*{K%{tP)Ul01Fjpf?xF1-=gn`JDS zemO*=v*VxBru0P&O-r?MC#=R=d@tgVzh~Un&1tM0*3AVnX0tleV=cO;xXQGVz5)DC zLFr8#6~Pnqh-Jttu>Hjyl4@A`32-gS>zfNRbeGR~>N?vnoK~h>l5C^7-~LENjU?>$ z^XQrVp$@kYetzGd`m)j;aO+WfzonS_Qk}W`c%rRT-Sv;MY22%Won5J#({9|*>xP@% zyKIrw0L%l%5!{{d28sHuG_=(}vd@CawocRlmntM{e~7F8G^ z9a-kFrNBHiuAxW6bnkLATr9s^*mQk2G5!#16kdMVOi;fHB{nLoD(f|Hn&~3O1&Yj3 z{`Dy-BT{#v^6hV-3{&ioD;IgY^GsRwTb-;{V z`Bi2bVn2^m;&-`Glwh%xCRl@%_dnydJ!W)u?*PV9*uDjo(+<^q|hf!5}g1()In}4-Z z%~Xm0t9?kJRUi7%m4HZNj!3*6%|dz9b)~O4;}Xxd5T^3oA-t5 z?Jd2ISi`g`h0ON|R1rs;zAT1YQ4r_gW=f1HrHhRs?~rvBUJQtn4l7;Mu~vN^h`nap zKfYZbx~`Cv^l4um5L{0@&lw49nR(_Ls5dFwo>}FtzSuS9 z;?o=&it}7}=^1!`lV-uPkYD^85MwWingG#7TB8D*2H#J$Ap+QtmKbT-U3waz>YPA@ zLUH0p6Tz1GTFG*!!(*Fx70&z#9cw3tpkgDncA4CkJMi94^FfD!1e5j>{^Y%q6O;!41_ZHZ&Iiv@jqqjEUy+o_Qb&lsCeK(@9m4mr`) z8f|3FU%n{~^IQqF?6myadpH?y%+q&*z>VD@s@>`0;Naor=8@LvcJ%GA#KRL!=2|fa0kujj8scO=zB4s3 zQF%fPkHQBS1#xrg2*JE-bP}RCt)RuuoW)u|tntLkl68}4 zxp$V${&3;7N|iJ4(Bqk{`DEk$5j0+>%Xq!KJCaE5e_INSTDdk&N$X}zBQoJ}dD=*SVQqwX)SWsKESl}} zLy*?CCt_=MYzlqd8*%6Z!B*aYf5?z}>eIm&A1FY4llJ5z1zH|4mH+CGdD|+3B(?Tr zd_zA88O)H5_2WqxWVO~PiA5WNPR1bD!qB!wan%8J2?9;QT7fRwD(Y3Lov!IKwv2qv zE8}&~spmt3VnJebm8dNSP7fcN=Xh4>=`-R&Pkml9Py<07Ib(_o%8n&>o88wUINs$; z%(N|6qvy^?C8f8;YLuX=JD~Xlvz-}zLAA2U=o0Vnd^aYdtT|njE}VW2lmAIPxz3fu zmA|Ic2QwwACm?=XnaE_Qh02;ofy(qGfJpVGMeUdR<0zdl|J(nLLhZ2Z$y^K_nH3=$Ajr~G zS>tFj9P9H8^KB8TwYIgkZf?(A%~c(h{5r28SH)nY#L(E<>$@_1Bk2Q9TuxNBVTv`= zbg#tk1HtD|Ok{01cn*5rXmM6<{dr_Yx3%}NsGq#TsHht!jNUFl==A&nh# zNP$a&$N!@m1jBFLRoMO;m5XB&H+70LvI|l)tm~Mcf4Bho3k<=mhX_hB7#{X=g}$IH z6K=BLWbmX{V}J=j>#rDMswL%S>5&EKM}`_gy=lGm@?X@!!5+g0>SH20dxQ4p*u0@@ z{bQU}B~x2np1HE6+Hi|SNjE*G&F(kqP|^VX8+E9e7!{JdNnVO*WQa3xJ2q8kv5+0c z8u9a-s>4BvZ@}y^ay|@3Iue|K~n8X{AW10$Hn>Qq7 zGdiUvdOZkS|v;FaYck_n(jm%4uJ6OT>_f2_39ZgLN2_FW?KJf4?h|M}zuzmlcn8eyI zT75!guoO>9wxsZqg_7G#8lr-H6P)MV=i+H^19$6u$Gn@<>wBU8!@Bip|L|x$GFPW< z=S73|?+-~YuT6Fi7q8FT^4EK_*m=|?R9Xv!qp~>@wh^%tH2Y8|%;i9~7PLDaNkdOAr&nzIC}4HNW(nW$k?po(*iiZ5(ZUGwe+4@ zl;+c*EGah#j&5D2q`{r|S?%tpg-q>oN%RfKvb^V(9Cbk3+f}hSHOP3dS!(^o=w#58 z_Vlg!Pnu~x>Z?Cd7wP$fgRkcYfvy(K>_<(&Rat;F*+maZ2CkkVse*#dX1Mh3HPo?F zic>dpA^9;F?i+>s2k=`oXPG>elTe?;S3x)}-+pcJ5RbPfGyi&U&M9$(Iv6_6USA4o z>R!-3&E$q=CP{wa!ldep^3KEI?GBf*bXxwD`Q#`L60L}@iCd^>WGeEk1439>YZTD$ z1VgBY-9ko2ucy{}jK7xLLq>8PjtxD->JV(ys5=OgP1udyX208DUER-5gKIHBt9_yr zY165aL<)l|nu;zl13%o`NhkBijP#nLxY7WT9 z^Z(FwPvL=e+q$S@+fK!{?WE$0?Nn^rwr$(CZQHhulljlN)_%@D^IZ44aW(qaT7N(O z1YrdymM15gchg;l9Ei{KE%9pXRy|76S*hL*y1DfaGm2iQWeRRHwo(k@eIpKALl663 zU0KMJ@#L>4^^?{C-y-MZg8|4iW9;e~^JuguASs1El~8q#R!3{xCrSd1%unFwMoO~X z-@3(+-A(}6f+f^$m-ffU^EI=L;Ngo9w3*CPev?yR#G~;FBxN4^4QQiXj zfAK3lc|4_KlI7X{Xb$tbe*gf$ea{x=>HkEZBwQ=F-RaeW$Sp;^XCf;jGx8JIpT9BX zSpWVLKQW*}wL=@T5^Ep6ZI>hTD@ohMo5!ZJ9`RqA!_oyBL-Qay2HI<0waKx!Vs5e3 zJaw`5E;GX&flC3Q^e+8TPM3V-bLBO>-yfrw^8G}ad+)- zL1FA4eunUqGe7rL9@;w**3bvnaHk336R5W?;QHn!ekPEG6rkITdhkux49K`sAqKvB zO&jv1K;XQ>0!d2kO&EflLzDXG_0?_{-Q;iDm@)E>?uGKq$eyF;fRWUb6<(+cVY#F| z>!-kZEmLMfO8y9%I=l3GYKp1`G? zjgy(Dfdlj4ni$?e7euk!lO^NJ>cePO|FGk!M$l}-Ju8lS{1DVmlevotH9SRWai>aC zp$go7)lN8yRYB~kf_1IlI<}qRA|~0u@Zgq~P~sk_2#bC!8q7AP$JBzQb#_oEYgpcM z@AexIcFUG?yzbuCHsmyNy7Ky`_cD{7fe}?^#=mKY;(yT&n@>On2>+%X+Ww&(ju&yE z7j#Hq{SZ|Oal$J}eKD*1H*hrd;Y`FnFo-T-f9G4~j9=uF@+*S_Ul$K!{m z8#Z)se)~}(u7O8Ie>ktVd3~3DZ!CYA|4zWm0C_=v^?vSJuUzxS_rBkB?q2u)M&*N_ z{BDQb2exY^y*SU-XM_(9DTJ`@fJAm4GfJMjw<5{VxBBU= zI`u!KZ?r&{Gn+|=xp4N3>LFt_|KS~;YN24B9a9VMcS*1_Ij(VolP#F!va3&00O>Q)FxSB=rLOm*l<6q4V=()=EVUtxz_W z2;oV(;Mf2c4F$_bEfg{wZ`0gOab{Auk*K>rXE3yrS?T02=ic^iT1GitN?d|OK-rJ) zP?Nx)2u-HrGHaqp`r|wBGLBVL!L;@B1UO+nQ|C$0p z0G$uip;)}`BaGA>Z#87%?G7LQT@*@cok24_e#jBb&9q5`29t5BGHAj9$ttGxcYsIk zL8H_}=?cZ#maKcY4?TLxzfIGerH z7r258zn{*c@IEOWF@`iNt$O~DShLC?41OH5B=x9*&;CdXAX2#3tZ^k@7!8NRgUd3S zOx(DK4$q+w!PI=3;-W79udFt&`=XMV@APf30PxCRwID@0*o6S)R|~Had_>GD^82Uj z>S%DmPV|#c&$&KtS^E@}ndW2A@fM2#lg7qVFv9~#zWqoI71 zwjp4^1Sg-i$GEi@xCbqo!>Ck4^wS&KUFtHJH?0|p0dN5u!GXec;HFW*^X{TJcftat zG-u9SOS^^L>jvpl<$C6dYq~ycQ4pAXa@3g9Hibv{%Cq{6CAl1$^s0j)gHY_hh%}Il zqJgmKvKvUkva8TkZfomvHIPhPjH|6asmB}LR^WtV9=CH%#Lp(QR%fWe%+CQ6wElUB ztkQ+?-Ebcwk3#u((_-MF8UpOF`CMsC<+k_Krq|VUeiqn9#)Zq`?2~GWgG5A+CHhzrgt{GvM)+x#dR++^ z&<#j3V-(R=r6{{DaDX{Lzjh5E0cHnOWSw}W>%Ksy?sZZJ-uM<>wlhZGkk4F) z8$=v%tXCrOW23klaaH_*?rjlbP!Qn~V}+pznh?`jL5h#LCCXIn;>68j*g}|nakx!V zwYo|&0TCO~nq1%U*#GVnr9{K6JtT9dAl?hN^m}JVtVw5Eor-z+R|lcpYj`$Trh8li z7Mi?1h>dZC%>tdZk^#pM&gnD7U5)!3mLwK{p_|tKd3djihJ4yIm_^>|#~;bQFa4Z9 z7$QVQ#}_^9`m6Uf$x9wYk(2)=So7vFa$=|4JR&7;IW)?H;w@qNFg6+N%8SI!N%&Cr zJIP}N)AZohcjCAQ(oZpz+jC`HqiFN4bW4S>IA)|>h3|@m)l-rF31KbOCh_;9jfI$W zRR$;aN;F4U8-ZYA+C1##?1#=|pCqu+Ec~EhK>7{nE*m!g_?WZqSebeKXQUZn_M{vu zby5zh2pn<{=3EC!J~Ae!Q5DK+%m$!U9PEjO97E&Hsz8>-iyup*O7`+u@b&xa9UGEc z(_rOb0+L0auWY!V2ul<(#~i{OHryMk;2#DM`#fv_*bN2l?-gN6q?|4v7SqaxVcvb< zur%g9Gu11J%~mE@oDlRIVZrJ<1TbcRI^dn4QgnWn$UmGRCJOiRz8*a3z9JVbbD+v- zmIx-q+^B?|DS$u{Z3l=wH1rm6VbT~#+hR#MHA@{#lwj=fvO*?_@`r}bOm<4SEoevy zY!l3Q&cP)?nsHp;MMIq0mAr1`5D%*PkCqWK)7OpqhpvhV184oyZL4w==f~jPt!gH$ zmfWItZy6R@yGtuXX47r0Y=OMGO;sV`3Z!tvBF6gxGCF=-b05@J<~^GM3=t1dgo$g# zt4K-{y4^|>S#wfPeD@c;Mp<)C4BaQuo4Ga#iTG%PFd6Nh8yDkU_wy*c1+0|{UQU}r zvYn!r4k(OOJ|%BRu3ErsmOGmPfZ|J%6xre>_)|ZPI;2@4*&JukwLqGw8S5@UHgAOg zk|9tFx5q~#eP*UZcepkJsR*x+JiPetkc2T|TDD5jMn*rXq=K8JN)uSBDRG-saRk%H zC8B!@0=@Q3ll8={Yq=3+(R^O4OsXA{BLoH{;5yv|7mJBe)La}w_=Mj1{eq;qslAhJ z%ry?B?fR4+sq>(361ZwTbD(1aUOulb;+@hvFY{!rgjic!;;OVD{Z{X(1i*bvS*f5) zS<4rhu~vCv>Zek6rHK3qtb(a+c|s6{vK2)`GG$q7i(CDe!FG8qqn@IS8!)f)DYZ^J zIO?JXkDr6oJM~o+dRV;4%V8U5Hw&bt^P-CrZg}j5pgd~R5TqSVCtpQov-^;M#<>Nw zQjW~yLu+(Bi5&Ga(S)}tT3f?j!9#KX>_lW1vxYi$6fTan!2{dV-6<88@FBApjCE?)mi`UO($ae-36NPz12ZQxyAIAe>mSfFX z)jc*=S|Xh6tiFR6l7PL-E);-VQv=J&Ahv#4d3Yf6Rv5;?UV-3yxeMM~5Zl7p-N9qqRB8x!QLtdR(D{VkK zU-u?~ICBeQ(}=NKkm=FA??AhE>e^)DZ_#O+8rN%a=48Q0nEryK?tX=U`4xhupFNA1 zIjt3$c>8xST>IIa3M^Gsv04t5Wm&+!JC$JIiKQ>?AC-1fY2pjZqhM@eC#xKd zYciZL+ldx99v=nAGq@mS%fp=$Riy@TB~BH0cfgY_-Z5_ZF&v7|J`7TO0WnK*|F*Cg zU#?z#xm(P#-<_@cL34?STAwfoPLu7)F2wkX4Mlr)x2Xvo+Oz6Kp19gaZljlc5!Kvz z8X-;xHQpI-KEKetU7!!$qd9Jg?Zk44g1|c}4+T51+{e^*6Ps(3T)OoJpzh`XVZ$iW$smLQBjK9r8jp@0_#!F*9)oOUk? zT3uAH(c7-3Y78cl**H+wiarr894iSE9*oOO90-l3%!OFdk67zj$?xIHL>{zhaX4O_ zwW9@>RBZ3V$1EHTual{0*vg1lLen%C=~cu6rIMf@C)}JW>;J2iT8_h*uE^<>6^}0O zmOCMce~S@nH%g&6_T5XF6X3Mq(Egk)Gx|k0yY>})Zr1&F^Eoc&h`1@#9cz*_hNiRa z$AMDOw(eCFvriNKeO|bn&)#Qt$XcGK0?f>1xmmJ!wi9SePN-o{etV5D{f#W59xrTe z*Gl;(TK4t~xzUOM`GCCe_kJa(pQ2&~^Ta+=>(g_k5ku|i_O-UedQ?drYdb(VcpD@h zJA*e=sE_3zRkEOTU!t~4&RfE(w=dWFgb77#onl5M1Wzir!9LM`y`!q66lexE?ev^u z(Hwq9Qk~~Gk!Hr7MQ|9?R9>{mk0Lf@hJ}uoVuGQwpa?B?DD{k#tzY5cJzTJ2)1s?^iXMm!gHswXa%*hd1lStq{aC}k08)fW4h^gQd(uy1Wm%nT7C(Pb8_Z^zN}2rA%eGBaxVN?I zaoh%c!fF`A4<;uA;#dfR3X^=(ri&@S62HQIRg_=Xc1?*t9O|fE2Q9zFLWcz88jK~x zo6g|r$Ax0r*_;t`O3zCa@wsT}6 zcSchc)KyS9W+8(#f(Uga>km}f4o-SKIZ8w^BXUe5D4IHq6o2rp=T8gQvZRqj*4s&# zOT2ntoly6)xgOJVYGy3H?W1^IwAucGl60B!{}CwCq<;j8o+jy-K0NtsL}18EQfIUH zidBPh4VjkUn6)0$53DXMqo{qo<(X4j3D+ua8QMY1%{5p8+2^=hf-f_sp7*|BsOP9- z(WY7iy2fKE_k0BF8mOtkRbMuG4Y{rs^gRjrSq5 zF>r7ejJm4Lm47J|KK;M-2Qlv!{-aPN921M)C}JIfJsM|941W}gIS>l>|6he7STxkLACkE3X}wfr7LYtkJhHyT)PGr4lPL}! zmfhvQC=`?1e%PT`%bfIW>$hO#G8!HJp)2Dz2{pP68hhjkaNIBQ7a~{5PLsk`tRx&w zCt&)S2RuG*{0PQ^lWxE6 zauxvlBIWRp?;UDKJQA!}UZh}+cPI7wkQWP0<@~un2EER{pb}_?nOEs!AmZEiJj%c( z4-Cq;5{?XLEJo$-d9fO|n;XARhtis=+@@1ar{9GYx>>S4(rX5ul_Jd$Hy*G+zBjGE zmrFF#p?8Lkv2s$Pg|Gu*R`~Y&LZ1ko#V{(daTu6;r=Yjo4rjLgES4uU>t+plX-w^= z>mmQnC>zWU7O=~bO)6`aLi!*|GwUJyz3zyrn`Gq8opz3k*oy3ORamtHH!31i=mT2d zkP8#L{B?o5;x)R^+|*)DEV&M)GVPJ8wRgfJe;F!Qsr>_fH8>=n^xJd z49~JSey|3!vXIeQbl&uSE~|bSe4MG%p*GogV=(xs)M{;Eh2IX$DV~Ob}$N zQff@~6MImFB!R>mJ8?eV|IEs^ZZez;gRerep}2(!F0h?iDdG-$s-Cw#)y<5TtY?nc zt>~GZ4crZ+xlEJIZDk}zC0rlQPHkxj3g4d}Wv!#Kzj<7r&ZO@iUNYOi-wqDpH4jc+ zcTYS)#aD(2I{|9V9B+6C0S-uW8$AcR&TOD4zp<&cDpAF+Gd|FukqG8$}^&j_Dr`xoD0IpW)Nns_PIYocamq@DlyuRHL2Y0U5Mm@5j6oA_Mh6zx&O5^q>ZMTMv*o zwOUbTZ4I39nwprYuhsQSPq|zy>(cDn76IM>hqFkw1YBX){tsiH?y2QAd#VjVcq)wB zx(RQ3=bDnj_0<%dEp|qARTZtN=y-WKmr@#9c)Low%jCGeEu*J`9#fMPnWArUzBo5wTBZIGkA&3Z6Vk4*!`H7e;M|56 zU?yD3MQo%UOFME3rj}gQ-)no~I}0x)7uIC4a{1ePJBJ=?dg8W%5qD#aN2zVo^Njd- zy%A?iQRer)Tdr;&2gUe)hCqa7^f?(MR*+ta7WAIE7IZ&+L-yf6d;_q6{{it@lf`80 zC;@_NOw8Sy;kleJub5%iRZi7J3pg|J!&DD&ad(pQmGd(`&YM>MrlF>Tle;jKFBO2? zDSo~OTtu!p5fi}%bm=&czIrSp}IJO8^NltJn2@Yv;F>~*_uCi#E~*1{#5(m#c+ia7{VE|spfNZq8WhYB}ZidnCsJM(hC zDsTZ*m$C~Mpj-Xb4Gr*VXszQRs!K9E@DO3J6%Yd0Ag$ya!w}N+(AOsZtUs=Y2C`tG zv)X$iN128n2_W2yO;bjKXkzDiFwBh)fUKGaxYM=&B?kxte13KzW6-5@uPos1w$~KZ zssYvD**AG=$nkn;xJZPqV9xI`#mTX2gHMVzd^I@APA12?ba%a<8YsnJT8;~N+u|&*{Wm#ke`F9=SNIPTU70Mj< zPYQBvOK0_t*7xV{3zMImNDTpH)18oCCj>b$wEqrd}{(h6)mi)a= z-u~#sie)q*+AQlJmtRp2D6N;DY(c*o*zPY+V~ zv05^ArqXwmRTF94OUqf;a3t&*5%I(OuYI2rcT45lMbNfVoJ#Rg;&jM8NgosAmI+RY zl*pSk(jJ)&y(UC8bZ^ckw5x`!sXqWQ9S8OJAu3^{f{X}P?jjJz0ztgQPe}5Hl2Z|2 z%$DIPksMVeTk2`1A_gto+`<3$g~Nv@gN|JH3x>}SdSsdeGbRD40@#UR?m0m$_9 zv(3Fn^4ZM`ef67sm)D-3UEZmiPJWo>q_o7|SMB>>vDmRbAFG7kBTLY|xRmoObnbv+{Z?>K?9#1QO4Y0o zAjT&~-&JQNZrc+0_x^Y^MfV+%TtYavQjoLQUZweA7U{OR4OxkiQ6aTow2vE5D+F5}4UG=X&& z48jdRJQ1(qoZw_`OiaAd9&w%Opd)oWK9Zs{6TPcEYrS;u`&8d5bIRJ?irqrCyT>< zpUy`T9bWO_rYVE?u?88L-7#0!ecx#A$D^TI5SMox*Qq5QK(VI}St4Dy@ zFalfKQ;RgF-3fZy7+=giF@96Ui>_PIZ?74YL>}uoa*h*z-e+S6BwRz4;g7sh$mf`C z@q?ywlfbFvBw)!yRjHuivbZ|;Xdb~Hz+2MTsFX9iORHbkiHCDAESuJgf_@Xs(UYl_ zM;$E$m6g(c_b3b=>P1E?7FA~*;#r~KNC9y%NQ6ZHMp=KM3SY# zxO$@7vnka(C%RPL&t?txo%OK`U&i^@uQZ?6Az7{;KmE#-Mpiaz3oc5h%k%!ZH+~;q zMjI~5i`!#f`s=+rek$yLRf*PRSINoQ&;O_rxx@Nw+{6X(UftVOW52eCGj%xe%|h2X zm$mQ=oX^+b>w${+SYewZ9SB<~TlxTviIyu+W9Z^cF8)C!lp!bv{s)ynVEhM_=qQa% z5O&BR;*CE~(3fpcxk6ill7Wq`7rb-wnZS+c6J+I&J?7!O72I(*4!|mV;|E+`5~2&` zq8OuQ)yi30VRljKnZ^WMq~DwrM8mR zHn@G7m@|sEEqBMaF*r{%Lcw2BB5AybGjvt!;fjuwTD=D{qa}N6*roidu2Ult3f5bh z5Wvp&GHE4wx`V?Smjhm0rVNZg0@?s#K{#6Dn5las$6&0b7xOv3!7?y1PtBeF})C?_$Rzx<05q{v@9_Ru+9!(S^5$etqc0H}v zPSrMh(S88p8y=K;Z~(00$Sk$iZVF(`ynd3&HXElO`eYt7xsyr9DzEy!2eKrG3?2G6 zxaJJ~qe$WiDTF{eQUmtsR&WOys~OQu)iSFjh1Ge~RR^DWnnmpNJtT9_!+*cs7DE_T zq)qONtfOxBK^7QY6GYj8pw4s}=Ytot#Y&d9X2RQVd%letH1N-Fc7B?g?!Pu&61Kg+ z8u_vZytVkQygTo`@w}U*JGKu65q#m@hTT4r-&Z$TUaEQeye~cL-?_fdb#C{AoQGkr zx2~bTzq9$Cb-tG|S<|+0zF#NVbiALnK)+j`U)Hymzq=2PeP5;>)%K`n#)}57@7AT0 zyi$z!-;aH(jU2xnu$<>sU5A1?ST2-6spChW*vxm8Mwh$;Y`AU~3y6jmg;y(jOa^H} zDLJ|<%l=U_;#M6_TE>R>bi#)&-YMlXNP-i9xS0kxCwzul)CAKgrez0;g|%#iO{C{0 z&9kA{d#F_$(%T`Q7FRRh(l)t<5A?h2;(hA!5Prw&yBpp65p~XRrhHHIr;%S!cK<4a zvVupHVQeXfSLT6A?41=elgB39pC6dMLRlt$A7*sM7d7tJ*E~PgU z4%e|FhK~@e`B$u=NkjJPpWa5#Exb~vHcTJnemkl_L5Bv|?JgesWcb4SaNUMpUR-OT zUy>AOt#;;yxX(pe;*CdtQ3ZU@?r$@=yfS7gR16ZA6W1S5z`rrnr|D9h6M)(B>ibBdPKCbV}OoD7k;4YjMm5IF9cOV;qV$hhMAbCd8wx9Bu5Kq!hw|{yrc|tJF zgbZ?(p*Q^(nPJlte1}7FD(!|I05KjDlP)pVu2J%ERF@La@~O{V6ubA_**S4#_`9oT z+%+-{y^b$rD_9ee)EVETDurtL|28u&L~U&uq@}MR3P%4iGlsMe2v$%2$IKY@puUih zpg5ANHPx(cz+V9@gw0hSB?%^=ENU8s>61=G6rwynBs40N_j@)YoKbR(NA%w`x-$m8 zveiH3=E>d=Uz*leOn`C#d%;yh_=UlbBnj{uJ|0L6mT8P`bqB@~;VNO*cge=>C(Ijy2U{mYM9edFl%1M3T?|Ryji8<4vUp3ma%6`cgHG9CVj=oaPKgKTY z6eshMrL{0pQB&H~+s7+~Qdr%kKj|!3B=5_rK;_CmnG->D7FcDojA%5k9Nt;3m~qGa zfIueee3wqYd^7z=K1uJ4KqMFScUiA57EhJKtkb%n)cS4!)hRs_==OO3Cw&{Wtphwn zt3$3#3at3POr;R;M|iK8@2bFu|MANApL%Q!2J80eGYxz8{)rzsqolRzFS?eDy*fcB zu?7qi8>GA`lPmG&Gi?}j&v0PUGZ|KV4534!ZhLmXnUM)}uEh9+Xo`B(iFoiC&)s|K49k-Fgdw?&L8TmW=a) zpqfha8iz#gNt^2IYKz*}^B(;3a0$R8tf*E}o5UrWqS=R57S^o387uo$dMgLGqJj1eM_bQpdlAg=W^o85+%FX8 zd_s^;Pmu%o(&_TpF;&=3dH{o215~|UTxa-eC zR$Y`|QdYy*zJ%$fS^qE*K|68NV5hU*e`pFj}NNZleD-O|(fP6U$?3 z(Zv9^BTIj@m=*v9QhI`LG9K2rfvOv-L-UJuAWTznW> z94aqWu!OM7nia`z3?M|r6u~+n-rq8ajY+cY$}T;4w*^POv5u+lr{K)bXizQ&ko@}x z0`w)aRS!P;!!qj~$8wofsiup@<_+z0bRXAmbU9|QQVoF6h=YSI{`ol)?9ot zAUJ7NRu@099F^se%R*;J={KIZ9XEsoY_JfST=`}KE(u~~7l^az`GYFCaA22m4MIFC zdq6%EXMMmC(*V3O>IBCDg332Bi_lXoIm3@{XXDUz&9}00(#w((`-h9)QLsrh@k~%( zT#iv@y-HJLvSIcdY&1SsT`bbXb`WgOepc~1M|)~XVbhGGT|-H*;?3rMk>_4lIN{Ix zN>)t&YxHq&456sWzJFFS_&tLdRE^1Lxi}r#f?Bz#k?o4ZaM);!^inRMRqO!T==K3*zqeL}Ui! zS`=C1*7b!Tz0;TCnveu`t-fOtE|6~mTV|eo5?w*t0UsdZKN&eQ!kcv6b}U%>JLd#k z(hj}FXedpp%avY^(1W46MFPG^EcNf9WC`H~ZyZ$FOoo(C@gjii`srnp7l>~;khwf8hCPe;+0S3)&Z%UGWWIEB@(%)vk{j&azN zURncWhH=o>-HiY9T*+Yd!O)HyMq?lfLuin+0$me&6Klk+mXsWVn1?e~$3Vwe3otF7 z>^PiwS^>OzE*Ku zT3lzeQ;rbvXIerg8R9TXu*}#-BrS5_!J#2W*Sah&GCz9Nbei-xQxh&A@q@S1ca{+} zU6ln|46sIFva!kzWN_|uO%-cFJA4%oZ=2J5o}}Cd$1`Xjd;Aswac(O; z_=3NV@vX4&LLXz{09pfKD8T6x>Wuu0+v|IfD0VfQI zD4Ob9{7jKo{52=kM#_K0iKeT6i4zb0ei{iQWkbKjMT?{6W~j(g7TCzhqGM zLyPf-_TrB?!E^n;;sgTCk2qoImJl9OO7gObPQViL==0tX6lQ)BW4x%U-ySALz}EIJ zazci6l9wtV%r-&mm>=jdMlJd>%Erz4eKg+BjvBL_mBz7{SUNQ&^d&|Vv~$q#oKdY- zK7E(Yw^l{fY{u9_Z4=ycn+nw%Z3el{mQq^?tO~5-&w4|hjh!;x8~nA{g0ih#VH!e$ zBmp__|DqE%AwTHEC?%Fxxc0#H$KE?#o1rD27*^nJ+-L8++^-XVHo1SiiTsezRryKM zpdC2IL@K+ofm)P!1o!qgA&>bnCChlH#|3@mIa`-D{whdboEKrLGmx9=(`I#R2p4?} zK%uJ8Pvx7ivDpsRfGafktH>JQw_g8yt)S>$&Qh-{pg{n{dK9{ho5d$}0wq)$ zr)S0POVS~}%>KZh(%*{@WHgEOo{lW2dRZ}HVc%xJdR!s6S-F}-|6F$VL zT5t=pX4=1=YT|3XI`)cS!k-}$^N~Xt<04)PlqK@OU&*C;FW5{vPGaFZ#@|LbvT==&t26^EFqXsIBc3e5;4DLX zED|RuGG-a;u}AV)pb-@+(w%2)B>G$A zG`M@@JO>Uwrg%|dy$2sV{Ad^b%#ox`n3*ihA@&%kDhLI&aWReKQ;F0YTyij?ak006sE)#^%SBY*u=> zcKipNh&bV$d#51={uLPf15Qvc{u`XwKl=|j@%hK0K$YpgfD<|qD?wQQ2b|D41V9~7 z9aX;iH#p%vzj3?```^F`CY2v>VzAL)xJO0&VC}zx6IuoWgrn%iPqX{UBY#KjtW>di zaO?pxoea^^D6g|*YX%6LKq09=AzpP%Ig|BILMmtU-7MOw9x{sRSfrZH z>yN>*Gz_S%+-&F7%ol5yv9Dch(l=Wh6>RSrLyMa@sNj!QU9u9Bi&7W;pNqS4T94a0 zVk!8d`257d0j!>(7z9QvY&)d1UqJ8XqHapfS>L6PHzxeQCVilu%j7SR@nCG8Gvoi_6+6Dja{0bjy1@n) zb)>9l#OMkP#L3mDxHOhhk16N=0=Xx`455~+vJN8RXb0S4H?>EDZ;|q-`8Pm4TU!@` z*|f@Cy|JO6f++vck!O_1a}rX_jhBm~?;iG!3{fIhyRLnCJNJXwgLn}P)^c^T^I&tH zDBVYMk{Cp8d;}e2WxWt#f$^PixHE@zq*w6K(R?a-YlQNI9C6H zj`x{uLn0_us%a@rm5Jh<$k9fz228>TFch~=4xim&dj6X*9W+v$}q>8(+y;OHEF4)@Yv6*v-~2TYN)*I`jez-B5{UWMM*_& zeKPMeLH)FCr=SAhoYFmN#Rl;f4Dt*SI)iMe)a-9WI&hpbN3-bfER{IHQZr}bF}*l$ zH+eM!)T3&p>7){F>=Z0)b_;B4wME*kl2B&iVRL2uw2BMu%`o0z_*bdzYh?lPpu~$f zQ@q{cw)G^n@nI=FAvwy*IMuY#GLi*y$t^cjA?n2Ug%MH&fYbIBnd+g>BGZ{tQ(T^W z%)qU`I6}Y2_!lKy%=xA^_-zL2sz>2Qg1w^~V3Af-#y4leI=#T=mk{`y`zj;mD<`KZ zWF2`}BsBlyO^o(%AhbXwtp9iu^!ESbO&mo1uQ!1!@sBs5yVI08WUjK}!h}!goa%Z~ zMg9RSNCvADLRos32r6#?lP~&sXsO(k7Ba|E*1sgV7L} z|D#PnTk7=jm;PVc1fsrGy`D?^vE9;0?5bsrw#l8(IJE1wolq6R{AF0%43ZA&Wl z`;Wz$uXM9mf47|#u!hOfz>@uVfHt=T-qUK@nZvYgZcvzH~A1p~~=;dcGa5=qntEkYiuXdTK}ufP~MDlft2K~L!l z-?tx!qt{SbAfzfNLcm_i+q<5$*+5(zE1SLa2JLN6=ZVW?-?Pre7-7Pm+v~{r%DT0r z!k@Lju3DoLwU%}sR4(djgL6aE_@~%;OOrEbfpCSvPqD_vtz=WNr5Y5+_v8I}L_bl- zPk%cx1+^^UAbpk%`}ZT|qMFv|lOsB5D_D)U5LoCnBv5)3AA#7;Aa8nwXc8ix)ei_( zB4dNQUUN7+3rk~nSs~xV5FN8X=ZRGRm{(8aEBO|C+ECx*Uc+81#6Pxc#f980p3@TvM9n;CPv$ zi>1a@=q5U;k~wkCeptmrd^0@pS^iJ6(SP+OCa7@;{dkGG{`3!9oIG_3LU;o&;x&3m zbbf0te(mH4G{WEd+rqQGW9|v!6@05510xIH^6h%mh+~GLiH=J0 z2dy$x^t$Q9OxvXl(R@ry^<~-g7H1zaF29LmDz6(H!vhT@ZI3x+KffXj$gcN>fPFSo z1wG+ez?Gsu2MhD+OaWuze_I4=bPSkr;xcz5oQJRTB7?4OoccG_WCTE9HuUcw2F%II zX|yn>vl0}n+BY>~TM^zK^vmMBGV`7y6-y77D zP6Bd|-%W7agL8k>ehn`hxws&>N2Q|X$0<5%&5LtI@%$3gaLA- zjP=5A``HOtnTqGS5V(<)^2nJysYm9J~m^U>L~7@(JC$7RnA{OD%_-$OgT7V6asxHgQ7xTRMqqAfUd!GT+R7b_*d# zT)}|#F0fjW3(@5;@)Z3+;>5?b&b7xg*Y|t(!SGFM^`7l?HKUQoGm)ow_ws|M} zNBYNCi=*4!$IGF{^Z7ENCKDs1?i}gFdOn~Hg7qKhgN@6l3~1*S`h(Jy!Xp)pjIsLT z(;dB?U+=!rkv&^`We>iA{1?bN3ff)>j8?vHhJ~&Xy=lj1>WFn2%oySt>4JFZ&1b>c zGHzk0UApjz0n_nW+P+7NABvUI*m2Myq>8Vdl_)lm^Su$&hL#X^7Kb z4Ac5FA%LSgvJ1n9Ur$dWT`ihfKeM%UInec)YEK$wzMdf|kI;=49WCXIUU6OOO-5d91&ETTBYrjx z=GU$!IiSuWA2u4({3Q=47Cv^;bW-kS3c@~H2B)Y}_!_z&5XV!FWqmI+DZL?$Bw$-t1+_7yt9d>Nnwr$%^{yguuj%kbqDsfNC9|t{r)rvDqMVWGQn~vf9(JzdTKZ`EVPV z{(e#E4yFo)qxUDSoG4_HX>Y`-1emCqa0F*|oN6*-`&VlCQfl}jnMRU90J}0V-N{S} z`Hx*Or<$|7#)GM{ub-Z8Jy?N#@_cQ_9-MXA54Tf{We2o?EOt?l?*Kdg_0=}dVWD)r zyyF!bu*7+Pf360J3Mq#iavp9SlgkU53_9+^XhsZOKU0hjk!$$GX{TJ0V`{rbDD%oU z$cTR|?FV6#xt;Eqk@bpw*i^>ezn@-&-FO^0 zbZFH7MTB3qYkE3#L7p#JZ_52QG^|-oK6b=_i!=MR^kl}6`19Z$bm z0Yk9RPz&O|hKlTSSR9ULgh+cShM^UqwuV1; z#c14rc7@OA!li9?ODCIzSM%%I8wme04_l(X<<_>-GzyT~@`vy69?*|nkyO1bmc3Iv zEvF!+Zr5xDKE$BWzjpXFcN$tS_ZC85&W-x7TLPP-yPUd)OqSkG(lQSgkFdYUuQ;~KT? z>cEzIg$XG&7-L_=e^1Z96ew!jWIfOGEHeo9MT>7a2M;(k-v;3L} z`?n`|CyG@73ZF3`+Qd{V0z4w)J^MV1@cM(d=|*?uOM#X8D`S7R+x+SNUhuuL`+kgz z#g_ni!}^-Ov~w$a+7^#>bMtNf{zB(RIQ-u5y9L&XL25saERW%;L$t-}(dWb)#Oehw zpfK>Ew=C=kJTtXN*R4_jrY6IvilLbWB?)MU!x0pa6hOBMfhr<7Epp<#Pvs+Php8EO zrc5$W_odmmn6J^yf~*;vaw<>4{sE`M+=gIcnB63DqENz{@cSAT$^5Ryy)3q-^Strh zC+k2fw>c*N?EZ!{C74GeTuw^bNyi38Zj#e_%|Lemg8YFiQW@l!Mbp@D@rM0p=iETW zbd7tYTi%TE*1K3bJDZy3)%8VAmFQU2qp4?#!G2Qaq;JQz}4kkCKh?lL7?s6WvGLJA8>df>2 zf8w0!5UNm=tw4?ySdO4z@bUA<^p9aLw=V}yNDZalGe(qsq6hJZ61h-3G2^`W`bNbg zcld`81^Q99$zTaAPs#8&-rt@dZ?BnMZ@{$67(-yY6ytNXS}cCxZ*3;`!VW;cSCo!E zx3}@(z+tC}(zWmEzH^QkWO8k$Y0wQ$gZ78jh|9+{ltm&N|2Po#&6)Fd)=>Wqc32fy zV%tdj8^}=Wy-=CD5Y$|KeMXrv&eAC{WFz20FTA?+dq9MMQp$>9(c(|7Ti=% z5MlCAce+tlj_D)YNBK=v;BE0!6v+>mw2xGu_qOdyWRu^uAF!Fe zq@a$S zG~J0YWlW-jn_s6}1(eCxTGBIl`B+2H!~N)Z$QDb=1tRLSGsmT-6P9;l z?;F-DVXSdJMU-d;3Qq#Jh`!5LlV{o(iA|@c*?BJ1hm`K*14m-Bn2&v+yI56?go!WR zo!Kw5uE{k$JYGDvTld#MmHYpOol1Bz&#dvYW^X27CIqGZ!X5K;{-N$n{(FlN=D}5> zQW*7_*Oq*C8+tzpK|~La%a$3m_uAK2@EDa>DtpA6{#)72+pwU5eSGqOR=u&i8~Gne zk#jiRBy7s{X_8cluU+ov@ix+grlO6@BNo%ox(2e;^3kh@a*fmZ?@}M# z^?)#u_V)Fh-krWw4g3}Sw>Qrzn|E96dDD{6w?dBJDX=<^lI_vkUdQjEyOvN{2G zx+RM%Ez8SERU{C0quBxocN;C%WtAn0t(o4u(9DNqX28tTn3v! zZ}G?8#L&);{YGs*R%6EMm(z2K=AmMF#~9?GD>4B>C0?Bw!9*I!5eRbwIYnEE@4};p zKb{9xT0yC%1^EPbr(o>6jlFh0uGHtV@F8VYX+!6#DOu5yTvMq%7hrkRnQGzG?p8%BZuSPHc0>gi#)NyHS14F8uKBteO3jmw2T87*3z@`T9G zIIA60jWW#{V8MeCKfnFg1i|A`J6%Mid)7mD4PLBO)GT)OF$Z}?^IFAXV=}1->oT*B z=}S#q+O;L|TyA-Z>Y5okx~5IYL<! z6RtnOT>5J1QCIjF7e^BW~DWyE+dE?h5x8rmJ% zv(fKx4P*5WZR7#32q8r?*T36eI+Nmw%yej$#+QKR9*W~4%z=NUbjT^nT~VdVj!=?t zghQ)?+X4?J$7G^D7{8A|_ExZ7Cq)o_*(S)9gU3)ryxV~}Y5%Q3N5)}~G9_>g#Z7D> zb^DTqTkX>FzKNT+>YLBDG15oinvXz}R_O<<$-k7FiWgO66MP(*ZvK`0zC-;r{%)q2 z#0#T+smc6osu0NwN7v(-93BW)-|XYX7$_#_?>Gi*%tE>m&2f^VE7)V=$)X()!O7JK z$E%hx3XHtS%@qUED=;PkW17Ocp($9-72X}bTojYZ+hq$c=|TopQ`la}dDBl6Gj!tCU>X!02zj95k-ak+dR?SJBQYQP z3ngVJ2_}rHUxYcFBuD@`#zz6oCS83llS=@6I%2CW7JQpU~k)}w3W57%#4l8(T| z{SfRK&_Jvf2wtN~?*aB@+r&;+zoOG#-DH0$LKp!<=}V9qpYM#M{0;JP1!CwDN=TS8 zwsugDk1VzpUX`NqPqh}g(=sD)|SeaB_o^$MTw=CD9jnq*p7i3weX9F zv|=5bq(+((x|?l<4wU|S8wNkDiKYh8YNeV}?qKCfbF&12{8{C%mG_FNT{cA;JFddk zhueXnGmk_|UlT{5^Wbz+bbUQ|(?sruAL7Es_<$C@LAN>~Lo01D1aY*pzye;Z&QCP# zvF~cBUf=Ts9&Dw!{Ky81mzVe6MeyR5hVibym1@>UY->9%`^jji1|+5{W?rw1{HT}} zkv3ptq&{|_p-aItV;KdEmSNPg39OniRZ`Qt$d4*CNV*u^uE?BXd)hi~RLdisu1&zY zB-tS+0X?A&5vvY6fTs%<{>m+eo@(vx}F9S<&+6T!g;_ z`oj4s$XL$Kj%jBWoWvBNfl=V5O~%O~aXuz&bGr)z+qZUF=Y@MQ7$1;xf)uY1&UxHM zq|a4?RlQZtw*XwDE=*g(bPSopxjrCqBY9IkU$W!4cU-*T_uB|Pl`x40uUkWw&jF(; zo6G8#B=s>&crY?x9vF`!0ZRbCs(y6t!sJ_{_$Hmp%L2=mtc!PZmAl`^pE;U3R%Zp* z>mlSUyv#2GMkNt*iD&u!^UM@22tmo%EAP0|>Vt0>12IT`+YJ5IT7$}0%{%rppWerS z!%p$o8w~$7N90DqtjLR6*$LeP!W5}KH-4bA8=tFXn%N(lnhHHbirhaK|Eq)+qUn!3 zhfhuaw7r~Y!=CC~m3kClmqqdCeGrmioRURnvTUxE|-)RnL`dzXbF{fk)GwB*fWdJ$-|D!~Ks%LVRSzwbi6 zc<~WeS*5I|LZ2HwLLHfcZ93S|ac}{Ag#ZqGfipgKSlWp&ofd}mQnB&()UuxyeO{G0 zZw`UH8oG{$%#cb(i%}gje_;Kv{L?QyMm`s=%aIEz503CQsd_bT@UBEF{&N=PY`c}` z%+xu;@SSJiPEGLqOh4U(`8-nKZzZ*7Po+glpFFm%82p#>+Acj$$;jxd{x#uF1J0-ra6ktKgY`Uq>=kUY))K?Kwhct-5y^O&6--eu~a8N zanl>V)R>hS{=WyBhw8vd_wvY;tGX)8Z%DY++n)sP!7Sdk^Z{PG7v|oEjlQ%su4HnC zukYgLlu*Hw^mu>KHz7#+FrVmzw9{psME^BAB$Mv2t|&PV|0oldwP})wVWZlyST^BW z6q&JCoQ|-~q3Ajb3TH9QMooi0;A#_|FN<^Q&K)|1$vYt2Tt0o8!I;7j>bLQyyC5E4V)zth{YW%cdJN62mc*Mducxgqx-#^}Hp z=g~KsO(qT+2v$I`JdU2axGe0};^_;di2Pi>Yj?QrA+RF_o*5+eT$=gw?Ky&lwc^L6J*)V`lKIfTEWWtav>5wx)p?%e?=X zi7X=A-l-pEg6|OeE)dL`0*gKc4zZrk`z%NMhnX<*5D8->bVM@_=Z*;5O%8P_4x}vE zupaV9JF>YUC&&f03RwoqjWfWZUQM?|J-NRy)GP!Uk+O$la-wX6H#5(POD2>yJ=#4n zu1inZGsZG-LJtnu9Nz*nw($=}f47)1a3`1)Vw<1;n^VHqM!Zot!Z+SM+}QH+J~7o} zx8jo&rD!vPK3{0LSiC$c+#Kis=dxmz!yl1c=Pe5iH_J%yq?d@ba~{QO5}>&0xWQXE zz==8ATw~32hl0>v%=e@?X84CO7pB?8sU+R4&84y(ED{dma)(c)hM5+(lz{wG%X7-g zE-oKRrAA05&>gfO+IZrL*I+~QR-eutPfRQ^J`4~cF?Ls!+MN-$h_3ue67383in#Pg zj%)CL$V7=kkIKjN+Q7f((y(PBwf;NT+BFiKS$PSNqCTSmLi=m(aO%9NGgN~=?X{j! z2_s#l;Yy1Aptx>*hfh7cz++CRq6n~hML)>Ig`50_>)ws`AHHxZ$(ri-l1cO?W;JN} zy7H(ShuuhB^L!#%LM{ssNKUG2(|zfmSP1s{_Ay7yy{k_2K|gT|zRr2!0@CIkFl3$g z$A$bIAk?YCA`C)8!Nn7>I-+^jFyPi?pq$ca}I5qtCX787OPL zl2-`!)JEoJ5XC>PYEihm8?$faXRUx3j?G>Kcm$y&t*H{rnJ7M&Gg%A1rM@&=mg~fl zA8van*REoDsp&ZjaLE~&WK;Tju#T$bqPO@jC10{yP7fm2F*dICx89AXGmwnlMEyBhb6JMK~{gan5deItR~EnY6XK`mMoW8N!CCbP0d z31y=^;_}MrW~GBd%X|Xb>|yJWxI3TFQmuK?U#koXl@Y`9kPwKp(3=P337zDs(G5eE z?98)|3(K)jr*{g}MOFKe8ue^sq+09ncBho)SHbIA&8n2=r-E{)Ocfl4S`wq0^`@)u zr)K%5`@;Kb#-a=izba54^)qkgIz_E+mpFE2=wulMJ;F+_PEk%}OBl-plLj)Z&+_@= zbhj+h=swc56v8GFe`-vS&9zx=ZELR$7K7->MW$w_vP(5hR(swVee@8f6T<_6>8rzbmFp7 z!U#&HKkDRt)F^q1RG|PcPB#76cacRm(<}SKs;zitG69GZ-1vovUaH>uhH*=oHqJ~n zZ>Mw*xj8y<{L{cE45V@61&PfIIaW=h`Czt^=UJ_H#O3$ma25kpuBXx|-g<)+qQhaW zU4iVKG>RcjNZ1jY(8Eh`=YS0RL8W$sF4)i7)xk=cWD{efc=_ruH4$MR3vzoBbfUPe zF!nVV6eu6m5rW>2@GGVr{jZ3`IL?sv&Z#Ih3vjz&JV?3ChBC5%FcJTZfH5sLyCID| z1Sk8CdcQ>kX;$KUG*x#FGfv_@%-_ES0T|+OZG(}WQns$5(nj-|gOBQ0%e7e_ zudMBq*Y5vywzU-d=o~P``m5CN+23e$aGW;p?%!s&-kr zlBS8ur@~}jF5O9S=bS?($&3lsiv2hfohKC7Sh9Efh@1a86I;g?qeCGlV*_hUbCV5` z#j1$-zy+Y8K^hp@X5%bEXtQK2;S@myiPM$h;eV5LN!l`|2$H~muU`4;7cvD~f*dbE zm@P4YphR%afy3+-4$%wRaluDnJA^7@*K5X-4Kfl5(WoVeuHliHu<-?9Emq*oA9;7) zU!0uA(q|b9RUF$(WPzGO`JhxXf29356R%u9&cwebc=36l;{l0=->Vs*iGky{6htPC zqf=Ty_@eq*M|o8vDephdgk0!;;g2(M6w^-MBvtdi|NW@0zV955g1a{J~nQ?UWd6)}h` z)Tq+5D##2i(TF*T%&`UTh2Q0dtP-eyOyu7O!KuZPb~gCKOdx=i%R9TYE~*qB@*L|Z zL$i`7Lkx$;Nfiys_~!At9=bmp-pd8}j`&5HJkLMw#!113o_p#vJ#Pz>yZC;{i>i4N zz8rUZr+lBb569-J-0=TM#~vTtU&nU0_W~dC@;gplg-5lTetfb&V`i=3dpJt=u$RRi z|2Y#>ksoh5WvuPxvc|{jza+3S2Kn@`iJX2lB{l1S9eA{1d)@m|!Pk-V6U)B>}Na@C08C3+X7i*7zu2ehu9_tF(}2;?1eCSO#QE z$|KSV3^yOcr$w}Ppk~rGr1;WO9m5|m%sQrQO{Ejgwi)c5BzuO*=VCER68*IcuPGrk zA5Et(BTkMJ@g1A+@@o^7V_5&ya-Ro4+9nKN#1c*jJdU7t^yzmr04t<-ZoSQhtDd~_ z>cpsoEp2NnxDsr8hW~0`zm}Nsr&-!(f*TTI#0ig)90ai9q^F+!RU=o7ZtvB8BE5He~$_QqK zHh^-~EH3RDTvlHv9oMZu=F%~&NyKO85i5U%Bmovp| zO<-0Eu9l%omi9Ob@w46D*f&chOcz_RrPf~%j5{-DYG||OK{uM3-JqMw*UA?i%^0v? zJZM`AOT^;V3bKE%u)sljkN=Wo$0n}D zyWchcn{7uvee?3#yQ@fgqUKy|!DSu*IH+vA4$Lzq z_yRD?=tOmzx&BGJN%DZYZ2FT(Yi)@O%zUS#qvG7{G@bnnf~kjZWw}>-$x%HB@{kVG zWOKg=$A96VG8(fX?#T94j%h562lxT~I1}c90up-83Mu0>2ajYjqMSvG0SslJV%eQC z9uHJ_3I<8GY2IT0=S&<`$H4b6diW14!Q1oY{4O^3$MluKh|85`(m5tm6AkDA4J8_G zJ$1dEWz0!2Z?=QhXLCt(%ra@vus$r%^UulQb5H0);1<~y?~7(B)> z@w;n{R`|$nh%30mLyPPJCyV*)N`p(deb?5#z0mcFn|aM3%EMuHr$6jb2{Moz;)OGf zlQK;A-4kN%1_{w^6KcY#uy}qtyY1MkCFnyOjao)RlUC$F*AuNGkgd7GY$-%%+wl;; zSAqw|;$@$cI_$#U$tv^w7QJwa0L`Cy4_f&aip?dfx=(Q10eT8uT#TL0R%bfjZz;4v zYoC_*eCXhi|7MpQIoc)nBiaA5NiLGShC&?X&E&Hle>~cPTEPzEcOpfmk4r ztPux}1X5qU3dAOv0tISkWVQw)hMt;il!$Ho9KGATAyD3)*yc`9z~xs{mTMV8G1=EK zaIpS-{@O(gR?J}TlA+X340c1dLBO4e-VW%#5N~e+FIo5Go`bao*BWego%%lmwxBthr-Fv=S#^_-AKV#zMglpujS@oUL!s*vSaSjOj zIyIXcmn*L@=8eVd(G=HO=F5hPis^T{nC}2V!9m6o-`i@KE`7C_@ept9)E`LZbs>Y8 zHW5ZKrP>B*URcDgqGd?*0uqF~L9f(VPk*eSH7s@M`_24nX{%e)ZU+F2rS9T9k}c?_&J*fc z@4I9JWjUC5+;r}_S6{=G=|$1`a<0T4aja+8^OOW(>Z;Xz5x&MTT_n%qm zOy4^|iTW}bL|gy!v(|sYgqh8d2Hj5>jiO(Z zE7QY(-e(*mHsS7yG?#qv=(cv_HRig5$&u2N`%lW%RPKSCV`gi_*8~Q_yy1bWuRdF> zyuu}iNK6&)8FDbhr;ze1IHz8n!!QN`YzXoQLPmbwu`CW5B;E*&rx?YopsU9OeMW{o z{c5&|ZD!2U%=?<7ekpE*ZuY^4eZ7-T$W5U8ZwcE`EWCl7VhOY)F()|+r|8$J_i$Z zuO;c<2J4)iR|0Vg&R&JtS36FU0@ezT$cF&Xi_>42k1qf{J3`(pl_z2fcV)QUW=&t{ zKy)?rHIn>zdN0#`44`h{E74Jva`+zainDRCa)1%<;-i6zk5ap>q{m=#y=QF9pu$R+ z4^!imip+~aR6Dqd5s7wAvW7&hd1ojvJ2SX6P6G$z^%mX-?^{2Cii;E(dFz9| zKM&yZYjZnPK2{gE8z2A6{-%oHbJ$A2j%OwX(MafKkEide&_PC{g-A^@jA&Z14Q*mG=zKykqk(m zC*QXVS!lSyH&e~J={pGTKtWM%`|HEl_={mP#9T8(xuY&pP)RA&ZZO+F$OMAst~)mn z6_B`tKb*|LtDjs4;>!}&-;gp)#ev30hOj<4=zpQ6Fb!>wj2`9Ru)1IAB{liCh=WME zOYLQKP18D$05E?A6aTT{x$~jrMmTVBnv>82QT6&#P|gK#h>gfL_C(n zil=n_>Hk9}g3f=C3GZxSYdMF!N*6^Z7v7j6lO%z(2o~?5QX`#a zw9+$`wt&&>U)I#t)^gN{x5HGL7H5;~CGw&C564 zw{K!DJ=V7u7h}8M0Q&YmUim)%>GAs5o9~_b^YhE}_Q7z}Np90O1x-u$cg4qR!lQ5Y z-iz}!$IasT_vk)_d{_C%_prQc_ow&g_fL~X)VJ;+vK~~YEwNAPw(Z=3QGCvJE@ao( znGXWC+dUMIJRaOHaaBUv%pN&*%hUAPBR!oqx|^y5sNqHM0|9}7{S>fd+)XysggaH0 z{Xm1q5uL#yU+qXkpA~B4m4u-Iq#QtxPE_8A!#%1+8HWKdK8{N-k*HOoMd4HFFUSlt z>`hDCgu$Qy0NK(&$9Y^HUB$1|6n(Vc@`q7F3U_Vi)}2 z4&8tivTGya4mAt5geIl_9FKb{z0sLS02)8z_th_2^8E6NAKrnhCdm?{i6YA8R}Y0k z-D%SMo8=TC@`3$@bw%S*uP2f_T@a1f0)~*)BAFD_a4|ktT&gg$scfCU#mwKYd zDy}75nCG8xsKSq_O%6aNdg^EgOC#q|jgmqXDH>`uKG6ZHJMl)i{O8oymh-Hwv!TNR zPDC2Tr9A(Z*rC7v3^nAS0GwgIG#g zp$NK!*er%(4hu!c#0^fOKBfW1PYDkvnB*;;BjwQd_}tuiiQD%ry<#^eQoY^74zbQ3 z-XU!Z(i9>V8jisus?kC$eN1lt9=vSPE@BJyA!z(U;D>jZ?%0Zt6Px$k7Qg0rqIN