annotate velib_python/dbusmonitor.py @ 13:4450cf739263

Add link to protocol document.
author Daniel O'Connor <darius@dons.net.au>
date Mon, 06 Dec 2021 11:25:51 +1030
parents 9c0435a617db
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
1 #!/usr/bin/env python3
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
3
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
4 ## @package dbus_vrm
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
5 # This code takes care of the D-Bus interface (not all of below is implemented yet):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
6 # - on startup it scans the dbus for services we know. For each known service found, it searches for
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
7 # objects/paths we know. Everything we find is stored in items{}, and an event is registered: if a
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
8 # value changes weĺl be notified and can pass that on to our owner. For example the vrmLogger.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
9 # we know.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
10 # - after startup, it continues to monitor the dbus:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
11 # 1) when services are added we do the same check on that
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
12 # 2) when services are removed, we remove any items that we had that referred to that service
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
13 # 3) if an existing services adds paths we update ourselves as well: on init, we make a
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
14 # VeDbusItemImport for a non-, or not yet existing objectpaths as well1
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
15 #
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
16 # Code is used by the vrmLogger, and also the pubsub code. Both are other modules in the dbus_vrm repo.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
17
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
18 from dbus.mainloop.glib import DBusGMainLoop
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
19 from gi.repository import GLib
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
20 import dbus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
21 import dbus.service
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
22 import inspect
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
23 import logging
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
24 import argparse
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
25 import pprint
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
26 import traceback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
27 import os
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
28 from collections import defaultdict
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
29 from functools import partial
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
30
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
31 # our own packages
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
32 from ve_utils import exit_on_error, wrap_dbus_value, unwrap_dbus_value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
33 notfound = object() # For lookups where None is a valid result
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
34
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
35 logger = logging.getLogger(__name__)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
36 logger.setLevel(logging.INFO)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
37 class SystemBus(dbus.bus.BusConnection):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
38 def __new__(cls):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
39 return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SYSTEM)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
40
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
41 class SessionBus(dbus.bus.BusConnection):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
42 def __new__(cls):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
43 return dbus.bus.BusConnection.__new__(cls, dbus.bus.BusConnection.TYPE_SESSION)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
44
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
45 class MonitoredValue(object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
46 def __init__(self, value, text, options):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
47 super(MonitoredValue, self).__init__()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
48 self.value = value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
49 self.text = text
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
50 self.options = options
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
51
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
52 # For legacy code, allow treating this as a tuple/list
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
53 def __iter__(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
54 return iter((self.value, self.text, self.options))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
55
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
56 class Service(object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
57 whentologoptions = ['configChange', 'onIntervalAlwaysAndOnEvent',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
58 'onIntervalOnlyWhenChanged', 'onIntervalAlways', 'never']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
59 def __init__(self, id, serviceName, deviceInstance):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
60 super(Service, self).__init__()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
61 self.id = id
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
62 self.name = serviceName
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
63 self.paths = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
64 self._seen = set()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
65 self.deviceInstance = deviceInstance
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
66
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
67 self.configChange = []
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
68 self.onIntervalAlwaysAndOnEvent = []
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
69 self.onIntervalOnlyWhenChanged = []
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
70 self.onIntervalAlways = []
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
71 self.never = []
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
72
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
73 # For legacy code, attributes can still be accessed as if keys from a
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
74 # dictionary.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
75 def __setitem__(self, key, value):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
76 self.__dict__[key] = value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
77 def __getitem__(self, key):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
78 return self.__dict__[key]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
79
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
80 def set_seen(self, path):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
81 self._seen.add(path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
82
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
83 def seen(self, path):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
84 return path in self._seen
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
85
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
86 @property
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
87 def service_class(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
88 return '.'.join(self.name.split('.')[:3])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
89
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
90 class DbusMonitor(object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
91 ## Constructor
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
92 def __init__(self, dbusTree, valueChangedCallback=None, deviceAddedCallback=None,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
93 deviceRemovedCallback=None, vebusDeviceInstance0=False):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
94 # valueChangedCallback is the callback that we call when something has changed.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
95 # def value_changed_on_dbus(dbusServiceName, dbusPath, options, changes, deviceInstance):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
96 # in which changes is a tuple with GetText() and GetValue()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
97 self.valueChangedCallback = valueChangedCallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
98 self.deviceAddedCallback = deviceAddedCallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
99 self.deviceRemovedCallback = deviceRemovedCallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
100 self.dbusTree = dbusTree
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
101 self.vebusDeviceInstance0 = vebusDeviceInstance0
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
102
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
103 # Lists all tracked services. Stores name, id, device instance, value per path, and whenToLog info
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
104 # indexed by service name (eg. com.victronenergy.settings).
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
105 self.servicesByName = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
106
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
107 # Same values as self.servicesByName, but indexed by service id (eg. :1.30)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
108 self.servicesById = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
109
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
110 # Keep track of services by class to speed up calls to get_service_list
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
111 self.servicesByClass = defaultdict(list)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
112
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
113 # Keep track of any additional watches placed on items
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
114 self.serviceWatches = defaultdict(list)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
115
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
116 # For a PC, connect to the SessionBus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
117 # For a CCGX, connect to the SystemBus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
118 self.dbusConn = SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else SystemBus()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
119
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
120 # subscribe to NameOwnerChange for bus connect / disconnect events.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
121 (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ \
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
122 else dbus.SystemBus()).add_signal_receiver(
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
123 self.dbus_name_owner_changed,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
124 signal_name='NameOwnerChanged')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
125
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
126 # Subscribe to PropertiesChanged for all services
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
127 self.dbusConn.add_signal_receiver(self.handler_value_changes,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
128 dbus_interface='com.victronenergy.BusItem',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
129 signal_name='PropertiesChanged', path_keyword='path',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
130 sender_keyword='senderId')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
131
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
132 # Subscribe to ItemsChanged for all services
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
133 self.dbusConn.add_signal_receiver(self.handler_item_changes,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
134 dbus_interface='com.victronenergy.BusItem',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
135 signal_name='ItemsChanged', path='/',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
136 sender_keyword='senderId')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
137
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
138 logger.info('===== Search on dbus for services that we will monitor starting... =====')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
139 serviceNames = self.dbusConn.list_names()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
140 for serviceName in serviceNames:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
141 self.scan_dbus_service(serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
142
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
143 logger.info('===== Search on dbus for services that we will monitor finished =====')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
144
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
145 def dbus_name_owner_changed(self, name, oldowner, newowner):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
146 if not name.startswith("com.victronenergy."):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
147 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
148
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
149 #decouple, and process in main loop
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
150 GLib.idle_add(exit_on_error, self._process_name_owner_changed, name, oldowner, newowner)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
151
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
152 def _process_name_owner_changed(self, name, oldowner, newowner):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
153 if newowner != '':
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
154 # so we found some new service. Check if we can do something with it.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
155 newdeviceadded = self.scan_dbus_service(name)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
156 if newdeviceadded and self.deviceAddedCallback is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
157 self.deviceAddedCallback(name, self.get_device_instance(name))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
158
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
159 elif name in self.servicesByName:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
160 # it disappeared, we need to remove it.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
161 logger.info("%s disappeared from the dbus. Removing it from our lists" % name)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
162 service = self.servicesByName[name]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
163 deviceInstance = service['deviceInstance']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
164 del self.servicesById[service.id]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
165 del self.servicesByName[name]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
166 for watch in self.serviceWatches[name]:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
167 watch.remove()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
168 del self.serviceWatches[name]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
169 self.servicesByClass[service.service_class].remove(service)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
170 if self.deviceRemovedCallback is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
171 self.deviceRemovedCallback(name, deviceInstance)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
172
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
173 def scan_dbus_service(self, serviceName):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
174 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
175 return self.scan_dbus_service_inner(serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
176 except:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
177 logger.error("Ignoring %s because of error while scanning:" % (serviceName))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
178 traceback.print_exc()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
179 return False
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
180
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
181 # Errors 'org.freedesktop.DBus.Error.ServiceUnknown' and
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
182 # 'org.freedesktop.DBus.Error.Disconnected' seem to happen when the service
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
183 # disappears while its being scanned. Which might happen, but is not really
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
184 # normal either, so letting them go into the logs.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
185
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
186 # Scans the given dbus service to see if it contains anything interesting for us. If it does, add
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
187 # it to our list of monitored D-Bus services.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
188 def scan_dbus_service_inner(self, serviceName):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
189
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
190 # make it a normal string instead of dbus string
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
191 serviceName = str(serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
192
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
193 paths = self.dbusTree.get('.'.join(serviceName.split('.')[0:3]), None)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
194 if paths is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
195 logger.debug("Ignoring service %s, not in the tree" % serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
196 return False
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
197
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
198 logger.info("Found: %s, scanning and storing items" % serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
199 serviceId = self.dbusConn.get_name_owner(serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
200
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
201 # we should never be notified to add a D-Bus service that we already have. If this assertion
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
202 # raises, check process_name_owner_changed, and D-Bus workings.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
203 assert serviceName not in self.servicesByName
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
204 assert serviceId not in self.servicesById
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
205
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
206 # for vebus.ttyO1, this is workaround, since VRM Portal expects the main vebus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
207 # devices at instance 0. Not sure how to fix this yet.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
208 if serviceName == 'com.victronenergy.vebus.ttyO1' and self.vebusDeviceInstance0:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
209 di = 0
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
210 elif serviceName == 'com.victronenergy.settings':
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
211 di = 0
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
212 elif serviceName.startswith('com.victronenergy.vecan.'):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
213 di = 0
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
214 else:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
215 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
216 di = self.dbusConn.call_blocking(serviceName,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
217 '/DeviceInstance', None, 'GetValue', '', [])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
218 except dbus.exceptions.DBusException:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
219 logger.info(" %s was skipped because it has no device instance" % serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
220 return False # Skip it
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
221 else:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
222 di = int(di)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
223
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
224 logger.info(" %s has device instance %s" % (serviceName, di))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
225 service = Service(serviceId, serviceName, di)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
226
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
227 # Let's try to fetch everything in one go
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
228 values = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
229 texts = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
230 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
231 values.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetValue', '', []))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
232 texts.update(self.dbusConn.call_blocking(serviceName, '/', None, 'GetText', '', []))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
233 except:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
234 pass
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
235
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
236 for path, options in paths.items():
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
237 # path will be the D-Bus path: '/Ac/ActiveIn/L1/V'
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
238 # options will be a dictionary: {'code': 'V', 'whenToLog': 'onIntervalAlways'}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
239 # check that the whenToLog setting is set to something we expect
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
240 assert options['whenToLog'] is None or options['whenToLog'] in Service.whentologoptions
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
241
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
242 # Try to obtain the value we want from our bulk fetch. If we
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
243 # cannot find it there, do an individual query.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
244 value = values.get(path[1:], notfound)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
245 if value != notfound:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
246 service.set_seen(path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
247 text = texts.get(path[1:], notfound)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
248 if value is notfound or text is notfound:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
249 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
250 value = self.dbusConn.call_blocking(serviceName, path, None, 'GetValue', '', [])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
251 service.set_seen(path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
252 text = self.dbusConn.call_blocking(serviceName, path, None, 'GetText', '', [])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
253 except dbus.exceptions.DBusException as e:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
254 if e.get_dbus_name() in (
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
255 'org.freedesktop.DBus.Error.ServiceUnknown',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
256 'org.freedesktop.DBus.Error.Disconnected'):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
257 raise # This exception will be handled below
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
258
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
259 # TODO org.freedesktop.DBus.Error.UnknownMethod really
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
260 # shouldn't happen but sometimes does.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
261 logger.debug("%s %s does not exist (yet)" % (serviceName, path))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
262 value = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
263 text = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
264
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
265 service.paths[path] = MonitoredValue(unwrap_dbus_value(value), unwrap_dbus_value(text), options)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
266
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
267 if options['whenToLog']:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
268 service[options['whenToLog']].append(path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
269
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
270
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
271 logger.debug("Finished scanning and storing items for %s" % serviceName)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
272
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
273 # Adjust self at the end of the scan, so we don't have an incomplete set of
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
274 # data if an exception occurs during the scan.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
275 self.servicesByName[serviceName] = service
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
276 self.servicesById[serviceId] = service
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
277 self.servicesByClass[service.service_class].append(service)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
278
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
279 return True
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
280
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
281 def handler_item_changes(self, items, senderId):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
282 if not isinstance(items, dict):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
283 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
284
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
285 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
286 service = self.servicesById[senderId]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
287 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
288 # senderId isn't there, which means it hasn't been scanned yet.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
289 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
290
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
291 for path, changes in items.items():
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
292 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
293 v = unwrap_dbus_value(changes['Value'])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
294 except (KeyError, TypeError):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
295 continue
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
296
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
297 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
298 t = changes['Text']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
299 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
300 t = str(v)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
301 self._handler_value_changes(service, path, v, t)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
302
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
303 def handler_value_changes(self, changes, path, senderId):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
304 # If this properyChange does not involve a value, our work is done.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
305 if 'Value' not in changes:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
306 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
307
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
308 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
309 service = self.servicesById[senderId]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
310 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
311 # senderId isn't there, which means it hasn't been scanned yet.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
312 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
313
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
314 v = unwrap_dbus_value(changes['Value'])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
315 # Some services don't send Text with their PropertiesChanged events.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
316 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
317 t = changes['Text']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
318 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
319 t = str(v)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
320 self._handler_value_changes(service, path, v, t)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
321
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
322 def _handler_value_changes(self, service, path, value, text):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
323 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
324 a = service.paths[path]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
325 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
326 # path isn't there, which means it hasn't been scanned yet.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
327 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
328
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
329 service.set_seen(path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
330
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
331 # First update our store to the new value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
332 if a.value == value:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
333 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
334
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
335 a.value = value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
336 a.text = text
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
337
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
338 # And do the rest of the processing in on the mainloop
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
339 if self.valueChangedCallback is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
340 GLib.idle_add(exit_on_error, self._execute_value_changes, service.name, path, {
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
341 'Value': value, 'Text': text}, a.options)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
342
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
343 def _execute_value_changes(self, serviceName, objectPath, changes, options):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
344 # double check that the service still exists, as it might have
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
345 # disappeared between scheduling-for and executing this function.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
346 if serviceName not in self.servicesByName:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
347 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
348
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
349 self.valueChangedCallback(serviceName, objectPath,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
350 options, changes, self.get_device_instance(serviceName))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
351
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
352 # Gets the value for a certain servicename and path
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
353 # The default_value is returned when:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
354 # 1. When the service doesn't exist.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
355 # 2. When the path asked for isn't being monitored.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
356 # 3. When the path exists, but has dbus-invalid, ie an empty byte array.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
357 # 4. When the path asked for is being monitored, but doesn't exist for that service.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
358 def get_value(self, serviceName, objectPath, default_value=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
359 service = self.servicesByName.get(serviceName, None)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
360 if service is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
361 return default_value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
362
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
363 value = service.paths.get(objectPath, None)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
364 if value is None or value.value is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
365 return default_value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
366
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
367 return value.value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
368
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
369 # returns if a dbus exists now, by doing a blocking dbus call.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
370 # Typically seen will be sufficient and doesn't need access to the dbus.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
371 def exists(self, serviceName, objectPath):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
372 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
373 self.dbusConn.call_blocking(serviceName, objectPath, None, 'GetValue', '', [])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
374 return True
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
375 except dbus.exceptions.DBusException as e:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
376 return False
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
377
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
378 # Returns if there ever was a successful GetValue or valueChanged event.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
379 # Unlike get_value this return True also if the actual value is invalid.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
380 #
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
381 # Note: the path might no longer exists anymore, but that doesn't happen in
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
382 # practice. If a service really wants to reconfigure itself typically it should
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
383 # reconnect to the dbus which causes it to be rescanned and seen will be updated.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
384 # If it is really needed to know if a path still exists, use exists.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
385 def seen(self, serviceName, objectPath):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
386 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
387 return self.servicesByName[serviceName].seen(objectPath)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
388 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
389 return False
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
390
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
391 # Sets the value for a certain servicename and path, returns the return value of the D-Bus SetValue
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
392 # method. If the underlying item does not exist (the service does not exist, or the objectPath was not
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
393 # registered) the function will return -1
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
394 def set_value(self, serviceName, objectPath, value):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
395 # Check if the D-Bus object referenced by serviceName and objectPath is registered. There is no
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
396 # necessity to do this, but it is in line with previous implementations which kept VeDbusItemImport
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
397 # objects for registers items only.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
398 service = self.servicesByName.get(serviceName, None)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
399 if service is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
400 return -1
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
401 if objectPath not in service.paths:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
402 return -1
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
403 # We do not catch D-Bus exceptions here, because the previous implementation did not do that either.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
404 return self.dbusConn.call_blocking(serviceName, objectPath,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
405 dbus_interface='com.victronenergy.BusItem',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
406 method='SetValue', signature=None,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
407 args=[wrap_dbus_value(value)])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
408
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
409 # Similar to set_value, but operates asynchronously
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
410 def set_value_async(self, serviceName, objectPath, value,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
411 reply_handler=None, error_handler=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
412 service = self.servicesByName.get(serviceName, None)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
413 if service is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
414 if objectPath in service.paths:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
415 self.dbusConn.call_async(serviceName, objectPath,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
416 dbus_interface='com.victronenergy.BusItem',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
417 method='SetValue', signature=None,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
418 args=[wrap_dbus_value(value)],
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
419 reply_handler=reply_handler, error_handler=error_handler)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
420 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
421
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
422 if error_handler is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
423 error_handler(TypeError('Service or path not found, '
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
424 'service=%s, path=%s' % (serviceName, objectPath)))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
425
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
426 # returns a dictionary, keys are the servicenames, value the instances
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
427 # optionally use the classfilter to get only a certain type of services, for
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
428 # example com.victronenergy.battery.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
429 def get_service_list(self, classfilter=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
430 if classfilter is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
431 return { servicename: service.deviceInstance \
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
432 for servicename, service in self.servicesByName.items() }
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
433
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
434 if classfilter not in self.servicesByClass:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
435 return {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
436
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
437 return { service.name: service.deviceInstance \
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
438 for service in self.servicesByClass[classfilter] }
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
439
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
440 def get_device_instance(self, serviceName):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
441 return self.servicesByName[serviceName].deviceInstance
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
442
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
443 # Parameter categoryfilter is to be a list, containing the categories you want (configChange,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
444 # onIntervalAlways, etc).
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
445 # Returns a dictionary, keys are codes + instance, in VRM querystring format. For example vvt[0]. And
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
446 # values are the value.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
447 def get_values(self, categoryfilter, converter=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
448
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
449 result = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
450
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
451 for serviceName in self.servicesByName:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
452 result.update(self.get_values_for_service(categoryfilter, serviceName, converter))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
453
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
454 return result
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
455
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
456 # same as get_values above, but then for one service only
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
457 def get_values_for_service(self, categoryfilter, servicename, converter=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
458 deviceInstance = self.get_device_instance(servicename)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
459 result = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
460
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
461 service = self.servicesByName[servicename]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
462
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
463 for category in categoryfilter:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
464
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
465 for path in service[category]:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
466
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
467 value, text, options = service.paths[path]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
468
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
469 if value is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
470
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
471 value = value if converter is None else converter.convert(path, options['code'], value, text)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
472
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
473 precision = options.get('precision')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
474 if precision:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
475 value = round(value, precision)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
476
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
477 result[options['code'] + "[" + str(deviceInstance) + "]"] = value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
478
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
479 return result
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
480
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
481 def track_value(self, serviceName, objectPath, callback, *args, **kwargs):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
482 """ A DbusMonitor can watch specific service/path combos for changes
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
483 so that it is not fully reliant on the global handler_value_changes
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
484 in this class. Additional watches are deleted automatically when
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
485 the service disappears from dbus. """
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
486 cb = partial(callback, *args, **kwargs)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
487
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
488 def root_tracker(items):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
489 # Check if objectPath in dict
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
490 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
491 v = items[objectPath]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
492 _v = unwrap_dbus_value(v['Value'])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
493 except (KeyError, TypeError):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
494 return # not in this dict
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
495
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
496 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
497 t = v['Text']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
498 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
499 cb({'Value': _v })
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
500 else:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
501 cb({'Value': _v, 'Text': t})
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
502
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
503 # Track changes on the path, and also on root
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
504 self.serviceWatches[serviceName].extend((
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
505 self.dbusConn.add_signal_receiver(cb,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
506 dbus_interface='com.victronenergy.BusItem',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
507 signal_name='PropertiesChanged',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
508 path=objectPath, bus_name=serviceName),
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
509 self.dbusConn.add_signal_receiver(root_tracker,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
510 dbus_interface='com.victronenergy.BusItem',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
511 signal_name='ItemsChanged',
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
512 path="/", bus_name=serviceName),
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
513 ))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
514
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
515
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
516 # ====== ALL CODE BELOW THIS LINE IS PURELY FOR DEVELOPING THIS CLASS ======
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
517
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
518 # Example function that can be used as a starting point to use this code
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
519 def value_changed_on_dbus(dbusServiceName, dbusPath, dict, changes, deviceInstance):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
520 logger.debug("0 ----------------")
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
521 logger.debug("1 %s%s changed" % (dbusServiceName, dbusPath))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
522 logger.debug("2 vrm dict : %s" % dict)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
523 logger.debug("3 changes-text: %s" % changes['Text'])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
524 logger.debug("4 changes-value: %s" % changes['Value'])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
525 logger.debug("5 deviceInstance: %s" % deviceInstance)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
526 logger.debug("6 - end")
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
527
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
528
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
529 def nameownerchange(a, b):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
530 # used to find memory leaks in dbusmonitor and VeDbusItemImport
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
531 import gc
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
532 gc.collect()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
533 objects = gc.get_objects()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
534 print (len([o for o in objects if type(o).__name__ == 'VeDbusItemImport']))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
535 print (len([o for o in objects if type(o).__name__ == 'SignalMatch']))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
536 print (len(objects))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
537
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
538
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
539 def print_values(dbusmonitor):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
540 a = dbusmonitor.get_value('wrongservice', '/DbusInvalid', default_value=1000)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
541 b = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NotInTheMonitorList', default_value=1000)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
542 c = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/DbusInvalid', default_value=1000)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
543 d = dbusmonitor.get_value('com.victronenergy.dummyservice.ttyO1', '/NonExistingButMonitored', default_value=1000)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
544
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
545 print ("All should be 1000: Wrong Service: %s, NotInTheMonitorList: %s, DbusInvalid: %s, NonExistingButMonitored: %s" % (a, b, c, d))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
546 return True
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
547
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
548 # We have a mainloop, but that is just for developing this code. Normally above class & code is used from
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
549 # some other class, such as vrmLogger or the pubsub Implementation.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
550 def main():
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
551 # Init logging
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
552 logging.basicConfig(level=logging.DEBUG)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
553 logger.info(__file__ + " is starting up")
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
554
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
555 # Have a mainloop, so we can send/receive asynchronous calls to and from dbus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
556 DBusGMainLoop(set_as_default=True)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
557
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
558 import os
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
559 import sys
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
560 sys.path.insert(1, os.path.join(os.path.dirname(__file__), '../../'))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
561
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
562 dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
563 monitorlist = {'com.victronenergy.dummyservice': {
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
564 '/Connected': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
565 '/ProductName': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
566 '/Mgmt/Connection': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
567 '/Dc/0/Voltage': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
568 '/Dc/0/Current': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
569 '/Dc/0/Temperature': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
570 '/Load/I': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
571 '/FirmwareVersion': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
572 '/DbusInvalid': dummy,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
573 '/NonExistingButMonitored': dummy}}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
574
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
575 d = DbusMonitor(monitorlist, value_changed_on_dbus,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
576 deviceAddedCallback=nameownerchange, deviceRemovedCallback=nameownerchange)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
577
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
578 # logger.info("==configchange values==")
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
579 # logger.info(pprint.pformat(d.get_values(['configChange'])))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
580
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
581 # logger.info("==onIntervalAlways and onIntervalOnlyWhenChanged==")
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
582 # logger.info(pprint.pformat(d.get_values(['onIntervalAlways', 'onIntervalAlwaysAndOnEvent'])))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
583
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
584 GLib.timeout_add(1000, print_values, d)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
585
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
586 # Start and run the mainloop
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
587 logger.info("Starting mainloop, responding on only events")
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
588 mainloop = GLib.MainLoop()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
589 mainloop.run()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
590
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
591 if __name__ == "__main__":
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
592 main()