annotate velib_python/vedbus.py @ 14:60ead9b5fc1b

Mark temperature as invalid when <-20C as per spec. Shows up as -25C on the unit I have when the sensor is not connected.
author Daniel O'Connor <darius@dons.net.au>
date Mon, 06 Dec 2021 11:26:20 +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 import dbus.service
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
5 import logging
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
6 import traceback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
7 import os
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
8 import weakref
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
9 from collections import defaultdict
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
10 from ve_utils import wrap_dbus_value, unwrap_dbus_value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
11
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
12 # vedbus contains three classes:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
13 # VeDbusItemImport -> use this to read data from the dbus, ie import
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
14 # VeDbusItemExport -> use this to export data to the dbus (one value)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
15 # VeDbusService -> use that to create a service and export several values to the dbus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
16
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
17 # Code for VeDbusItemImport is copied from busitem.py and thereafter modified.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
18 # All projects that used busitem.py need to migrate to this package. And some
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
19 # projects used to define there own equivalent of VeDbusItemExport. Better to
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
20 # use VeDbusItemExport, or even better the VeDbusService class that does it all for you.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
21
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
22 # TODOS
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
23 # 1 check for datatypes, it works now, but not sure if all is compliant with
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
24 # com.victronenergy.BusItem interface definition. See also the files in
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
25 # tests_and_examples. And see 'if type(v) == dbus.Byte:' on line 102. Perhaps
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
26 # something similar should also be done in VeDbusBusItemExport?
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
27 # 2 Shouldn't VeDbusBusItemExport inherit dbus.service.Object?
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
28 # 7 Make hard rules for services exporting data to the D-Bus, in order to make tracking
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
29 # changes possible. Does everybody first invalidate its data before leaving the bus?
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
30 # And what about before taking one object away from the bus, instead of taking the
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
31 # whole service offline?
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
32 # They should! And after taking one value away, do we need to know that someone left
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
33 # the bus? Or we just keep that value in invalidated for ever? Result is that we can't
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
34 # see the difference anymore between an invalidated value and a value that was first on
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
35 # the bus and later not anymore. See comments above VeDbusItemImport as well.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
36 # 9 there are probably more todos in the code below.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
37
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
38 # Some thoughts with regards to the data types:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
39 #
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
40 # Text from: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
41 # ---
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
42 # Variants are represented by setting the variant_level keyword argument in the
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
43 # constructor of any D-Bus data type to a value greater than 0 (variant_level 1
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
44 # means a variant containing some other data type, variant_level 2 means a variant
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
45 # containing a variant containing some other data type, and so on). If a non-variant
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
46 # is passed as an argument but introspection indicates that a variant is expected,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
47 # it'll automatically be wrapped in a variant.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
48 # ---
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
49 #
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
50 # Also the different dbus datatypes, such as dbus.Int32, and dbus.UInt32 are a subclass
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
51 # of Python int. dbus.String is a subclass of Python standard class unicode, etcetera
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
52 #
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
53 # So all together that explains why we don't need to explicitly convert back and forth
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
54 # between the dbus datatypes and the standard python datatypes. Note that all datatypes
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
55 # in python are objects. Even an int is an object.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
56
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
57 # The signature of a variant is 'v'.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
58
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
59 # Export ourselves as a D-Bus service.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
60 class VeDbusService(object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
61 def __init__(self, servicename, bus=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
62 # dict containing the VeDbusItemExport objects, with their path as the key.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
63 self._dbusobjects = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
64 self._dbusnodes = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
65 self._ratelimiters = []
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
66 self._dbusname = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
67
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
68 # dict containing the onchange callbacks, for each object. Object path is the key
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
69 self._onchangecallbacks = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
70
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
71 # Connect to session bus whenever present, else use the system bus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
72 self._dbusconn = bus or (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus())
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
73
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
74 # make the dbus connection available to outside, could make this a true property instead, but ach..
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
75 self.dbusconn = self._dbusconn
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
76
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
77 # Register ourselves on the dbus, trigger an error if already in use (do_not_queue)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
78 self._dbusname = dbus.service.BusName(servicename, self._dbusconn, do_not_queue=True)
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 # Add the root item that will return all items as a tree
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
81 self._dbusnodes['/'] = VeDbusRootExport(self._dbusconn, '/', self)
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 logging.info("registered ourselves on D-Bus as %s" % servicename)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
84
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
85 # To force immediate deregistering of this dbus service and all its object paths, explicitly
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
86 # call __del__().
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
87 def __del__(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
88 for node in list(self._dbusnodes.values()):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
89 node.__del__()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
90 self._dbusnodes.clear()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
91 for item in list(self._dbusobjects.values()):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
92 item.__del__()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
93 self._dbusobjects.clear()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
94 if self._dbusname:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
95 self._dbusname.__del__() # Forces call to self._bus.release_name(self._name), see source code
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
96 self._dbusname = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
97
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
98 # @param callbackonchange function that will be called when this value is changed. First parameter will
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
99 # be the path of the object, second the new value. This callback should return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
100 # True to accept the change, False to reject it.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
101 def add_path(self, path, value, description="", writeable=False,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
102 onchangecallback=None, gettextcallback=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
103
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
104 if onchangecallback is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
105 self._onchangecallbacks[path] = onchangecallback
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 item = VeDbusItemExport(
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
108 self._dbusconn, path, value, description, writeable,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
109 self._value_changed, gettextcallback, deletecallback=self._item_deleted)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
110
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
111 spl = path.split('/')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
112 for i in range(2, len(spl)):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
113 subPath = '/'.join(spl[:i])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
114 if subPath not in self._dbusnodes and subPath not in self._dbusobjects:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
115 self._dbusnodes[subPath] = VeDbusTreeExport(self._dbusconn, subPath, self)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
116 self._dbusobjects[path] = item
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
117 logging.debug('added %s with start value %s. Writeable is %s' % (path, value, writeable))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
118
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
119 # Add the mandatory paths, as per victron dbus api doc
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
120 def add_mandatory_paths(self, processname, processversion, connection,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
121 deviceinstance, productid, productname, firmwareversion, hardwareversion, connected):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
122 self.add_path('/Mgmt/ProcessName', processname)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
123 self.add_path('/Mgmt/ProcessVersion', processversion)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
124 self.add_path('/Mgmt/Connection', connection)
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 # Create rest of the mandatory objects
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
127 self.add_path('/DeviceInstance', deviceinstance)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
128 self.add_path('/ProductId', productid)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
129 self.add_path('/ProductName', productname)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
130 self.add_path('/FirmwareVersion', firmwareversion)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
131 self.add_path('/HardwareVersion', hardwareversion)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
132 self.add_path('/Connected', connected)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
133
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
134 # Callback function that is called from the VeDbusItemExport objects when a value changes. This function
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
135 # maps the change-request to the onchangecallback given to us for this specific path.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
136 def _value_changed(self, path, newvalue):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
137 if path not in self._onchangecallbacks:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
138 return True
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
139
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
140 return self._onchangecallbacks[path](path, newvalue)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
141
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
142 def _item_deleted(self, path):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
143 self._dbusobjects.pop(path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
144 for np in list(self._dbusnodes.keys()):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
145 if np != '/':
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
146 for ip in self._dbusobjects:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
147 if ip.startswith(np + '/'):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
148 break
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
149 else:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
150 self._dbusnodes[np].__del__()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
151 self._dbusnodes.pop(np)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
152
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
153 def __getitem__(self, path):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
154 return self._dbusobjects[path].local_get_value()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
155
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
156 def __setitem__(self, path, newvalue):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
157 self._dbusobjects[path].local_set_value(newvalue)
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 def __delitem__(self, path):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
160 self._dbusobjects[path].__del__() # Invalidates and then removes the object path
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
161 assert path not in self._dbusobjects
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
162
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
163 def __contains__(self, path):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
164 return path in self._dbusobjects
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
165
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
166 def __enter__(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
167 l = ServiceContext(self)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
168 self._ratelimiters.append(l)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
169 return l
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
170
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
171 def __exit__(self, *exc):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
172 # pop off the top one and flush it. If with statements are nested
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
173 # then each exit flushes its own part.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
174 if self._ratelimiters:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
175 self._ratelimiters.pop().flush()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
176
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
177 class ServiceContext(object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
178 def __init__(self, parent):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
179 self.parent = parent
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
180 self.changes = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
181
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
182 def __getitem__(self, path):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
183 return self.parent[path]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
184
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
185 def __setitem__(self, path, newvalue):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
186 c = self.parent._dbusobjects[path]._local_set_value(newvalue)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
187 if c is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
188 self.changes[path] = c
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 def flush(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
191 if self.changes:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
192 self.parent._dbusnodes['/'].ItemsChanged(self.changes)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
193
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
194 class TrackerDict(defaultdict):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
195 """ Same as defaultdict, but passes the key to default_factory. """
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
196 def __missing__(self, key):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
197 self[key] = x = self.default_factory(key)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
198 return x
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
199
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
200 class VeDbusRootTracker(object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
201 """ This tracks the root of a dbus path and listens for PropertiesChanged
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
202 signals. When a signal arrives, parse it and unpack the key/value changes
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
203 into traditional events, then pass it to the original eventCallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
204 method. """
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
205 def __init__(self, bus, serviceName):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
206 self.importers = defaultdict(weakref.WeakSet)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
207 self.serviceName = serviceName
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
208 self._match = bus.get_object(serviceName, '/', introspect=False).connect_to_signal(
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
209 "ItemsChanged", weak_functor(self._items_changed_handler))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
210
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
211 def __del__(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
212 self._match.remove()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
213 self._match = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
214
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
215 def add(self, i):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
216 self.importers[i.path].add(i)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
217
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
218 def _items_changed_handler(self, items):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
219 if not isinstance(items, dict):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
220 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
221
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
222 for path, changes in items.items():
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
223 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
224 v = changes['Value']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
225 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
226 continue
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
227
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
228 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
229 t = changes['Text']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
230 except KeyError:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
231 t = str(unwrap_dbus_value(v))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
232
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
233 for i in self.importers.get(path, ()):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
234 i._properties_changed_handler({'Value': v, 'Text': t})
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 """
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
237 Importing basics:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
238 - If when we power up, the D-Bus service does not exist, or it does exist and the path does not
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
239 yet exist, still subscribe to a signal: as soon as it comes online it will send a signal with its
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
240 initial value, which VeDbusItemImport will receive and use to update local cache. And, when set,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
241 call the eventCallback.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
242 - If when we power up, save it
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
243 - When using get_value, know that there is no difference between services (or object paths) that don't
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
244 exist and paths that are invalid (= empty array, see above). Both will return None. In case you do
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
245 really want to know ifa path exists or not, use the exists property.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
246 - When a D-Bus service leaves the D-Bus, it will first invalidate all its values, and send signals
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
247 with that update, and only then leave the D-Bus. (or do we need to subscribe to the NameOwnerChanged-
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
248 signal!?!) To be discussed and make sure. Not really urgent, since all existing code that uses this
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
249 class already subscribes to the NameOwnerChanged signal, and subsequently removes instances of this
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
250 class.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
251
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
252 Read when using this class:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
253 Note that when a service leaves that D-Bus without invalidating all its exported objects first, for
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
254 example because it is killed, VeDbusItemImport doesn't have a clue. So when using VeDbusItemImport,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
255 make sure to also subscribe to the NamerOwnerChanged signal on bus-level. Or just use dbusmonitor,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
256 because that takes care of all of that for you.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
257 """
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
258 class VeDbusItemImport(object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
259 def __new__(cls, bus, serviceName, path, eventCallback=None, createsignal=True):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
260 instance = object.__new__(cls)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
261
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
262 # If signal tracking should be done, also add to root tracker
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
263 if createsignal:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
264 if "_roots" not in cls.__dict__:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
265 cls._roots = TrackerDict(lambda k: VeDbusRootTracker(bus, k))
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 return instance
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
268
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
269 ## Constructor
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
270 # @param bus the bus-object (SESSION or SYSTEM).
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
271 # @param serviceName the dbus-service-name (string), for example 'com.victronenergy.battery.ttyO1'
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
272 # @param path the object-path, for example '/Dc/V'
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
273 # @param eventCallback function that you want to be called on a value change
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
274 # @param createSignal only set this to False if you use this function to one time read a value. When
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
275 # leaving it to True, make sure to also subscribe to the NameOwnerChanged signal
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
276 # elsewhere. See also note some 15 lines up.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
277 def __init__(self, bus, serviceName, path, eventCallback=None, createsignal=True):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
278 # TODO: is it necessary to store _serviceName and _path? Isn't it
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
279 # stored in the bus_getobjectsomewhere?
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
280 self._serviceName = serviceName
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
281 self._path = path
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
282 self._match = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
283 # TODO: _proxy is being used in settingsdevice.py, make a getter for that
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
284 self._proxy = bus.get_object(serviceName, path, introspect=False)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
285 self.eventCallback = eventCallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
286
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
287 assert eventCallback is None or createsignal == True
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
288 if createsignal:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
289 self._match = self._proxy.connect_to_signal(
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
290 "PropertiesChanged", weak_functor(self._properties_changed_handler))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
291 self._roots[serviceName].add(self)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
292
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
293 # store the current value in _cachedvalue. When it doesn't exists set _cachedvalue to
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
294 # None, same as when a value is invalid
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
295 self._cachedvalue = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
296 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
297 v = self._proxy.GetValue()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
298 except dbus.exceptions.DBusException:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
299 pass
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
300 else:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
301 self._cachedvalue = unwrap_dbus_value(v)
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 __del__(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
304 if self._match is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
305 self._match.remove()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
306 self._match = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
307 self._proxy = None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
308
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
309 def _refreshcachedvalue(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
310 self._cachedvalue = unwrap_dbus_value(self._proxy.GetValue())
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
311
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
312 ## Returns the path as a string, for example '/AC/L1/V'
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
313 @property
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
314 def path(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
315 return self._path
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
316
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
317 ## Returns the dbus service name as a string, for example com.victronenergy.vebus.ttyO1
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
318 @property
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
319 def serviceName(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
320 return self._serviceName
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 ## Returns the value of the dbus-item.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
323 # the type will be a dbus variant, for example dbus.Int32(0, variant_level=1)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
324 # this is not a property to keep the name consistant with the com.victronenergy.busitem interface
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
325 # returns None when the property is invalid
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
326 def get_value(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
327 return self._cachedvalue
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 ## Writes a new value to the dbus-item
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
330 def set_value(self, newvalue):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
331 r = self._proxy.SetValue(wrap_dbus_value(newvalue))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
332
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
333 # instead of just saving the value, go to the dbus and get it. So we have the right type etc.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
334 if r == 0:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
335 self._refreshcachedvalue()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
336
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
337 return r
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
338
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
339 ## Resets the item to its default value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
340 def set_default(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
341 self._proxy.SetDefault()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
342 self._refreshcachedvalue()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
343
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
344 ## Returns the text representation of the value.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
345 # For example when the value is an enum/int GetText might return the string
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
346 # belonging to that enum value. Another example, for a voltage, GetValue
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
347 # would return a float, 12.0Volt, and GetText could return 12 VDC.
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 # Note that this depends on how the dbus-producer has implemented this.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
350 def get_text(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
351 return self._proxy.GetText()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
352
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
353 ## Returns true of object path exists, and false if it doesn't
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
354 @property
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
355 def exists(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
356 # TODO: do some real check instead of this crazy thing.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
357 r = False
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
358 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
359 r = self._proxy.GetValue()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
360 r = True
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
361 except dbus.exceptions.DBusException:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
362 pass
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
363
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
364 return r
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
365
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
366 ## callback for the trigger-event.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
367 # @param eventCallback the event-callback-function.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
368 @property
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
369 def eventCallback(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
370 return self._eventCallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
371
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
372 @eventCallback.setter
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
373 def eventCallback(self, eventCallback):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
374 self._eventCallback = eventCallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
375
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
376 ## Is called when the value of the imported bus-item changes.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
377 # Stores the new value in our local cache, and calls the eventCallback, if set.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
378 def _properties_changed_handler(self, changes):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
379 if "Value" in changes:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
380 changes['Value'] = unwrap_dbus_value(changes['Value'])
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
381 self._cachedvalue = changes['Value']
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
382 if self._eventCallback:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
383 # The reason behind this try/except is to prevent errors silently ending up the an error
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
384 # handler in the dbus code.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
385 try:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
386 self._eventCallback(self._serviceName, self._path, changes)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
387 except:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
388 traceback.print_exc()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
389 os._exit(1) # sys.exit() is not used, since that also throws an exception
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
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
392 class VeDbusTreeExport(dbus.service.Object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
393 def __init__(self, bus, objectPath, service):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
394 dbus.service.Object.__init__(self, bus, objectPath)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
395 self._service = service
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
396 logging.debug("VeDbusTreeExport %s has been created" % objectPath)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
397
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
398 def __del__(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
399 # self._get_path() will raise an exception when retrieved after the call to .remove_from_connection,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
400 # so we need a copy.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
401 path = self._get_path()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
402 if path is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
403 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
404 self.remove_from_connection()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
405 logging.debug("VeDbusTreeExport %s has been removed" % path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
406
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
407 def _get_path(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
408 if len(self._locations) == 0:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
409 return None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
410 return self._locations[0][1]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
411
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
412 def _get_value_handler(self, path, get_text=False):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
413 logging.debug("_get_value_handler called for %s" % path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
414 r = {}
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
415 px = path
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
416 if not px.endswith('/'):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
417 px += '/'
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
418 for p, item in self._service._dbusobjects.items():
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
419 if p.startswith(px):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
420 v = item.GetText() if get_text else wrap_dbus_value(item.local_get_value())
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
421 r[p[len(px):]] = v
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
422 logging.debug(r)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
423 return r
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
424
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
425 @dbus.service.method('com.victronenergy.BusItem', out_signature='v')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
426 def GetValue(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
427 value = self._get_value_handler(self._get_path())
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
428 return dbus.Dictionary(value, signature=dbus.Signature('sv'), variant_level=1)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
429
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
430 @dbus.service.method('com.victronenergy.BusItem', out_signature='v')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
431 def GetText(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
432 return self._get_value_handler(self._get_path(), True)
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 def local_get_value(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
435 return self._get_value_handler(self.path)
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 class VeDbusRootExport(VeDbusTreeExport):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
438 @dbus.service.signal('com.victronenergy.BusItem', signature='a{sa{sv}}')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
439 def ItemsChanged(self, changes):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
440 pass
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
441
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
442 @dbus.service.method('com.victronenergy.BusItem', out_signature='a{sa{sv}}')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
443 def GetItems(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
444 return {
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
445 path: {
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
446 'Value': wrap_dbus_value(item.local_get_value()),
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
447 'Text': item.GetText() }
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
448 for path, item in self._service._dbusobjects.items()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
449 }
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
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
452 class VeDbusItemExport(dbus.service.Object):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
453 ## Constructor of VeDbusItemExport
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
454 #
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
455 # Use this object to export (publish), values on the dbus
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
456 # Creates the dbus-object under the given dbus-service-name.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
457 # @param bus The dbus object.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
458 # @param objectPath The dbus-object-path.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
459 # @param value Value to initialize ourselves with, defaults to None which means Invalid
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
460 # @param description String containing a description. Can be called over the dbus with GetDescription()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
461 # @param writeable what would this do!? :).
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
462 # @param callback Function that will be called when someone else changes the value of this VeBusItem
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
463 # over the dbus. First parameter passed to callback will be our path, second the new
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
464 # value. This callback should return True to accept the change, False to reject it.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
465 def __init__(self, bus, objectPath, value=None, description=None, writeable=False,
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
466 onchangecallback=None, gettextcallback=None, deletecallback=None):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
467 dbus.service.Object.__init__(self, bus, objectPath)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
468 self._onchangecallback = onchangecallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
469 self._gettextcallback = gettextcallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
470 self._value = value
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
471 self._description = description
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
472 self._writeable = writeable
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
473 self._deletecallback = deletecallback
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
474
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
475 # To force immediate deregistering of this dbus object, explicitly call __del__().
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
476 def __del__(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
477 # self._get_path() will raise an exception when retrieved after the
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
478 # call to .remove_from_connection, so we need a copy.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
479 path = self._get_path()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
480 if path == None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
481 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
482 if self._deletecallback is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
483 self._deletecallback(path)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
484 self.local_set_value(None)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
485 self.remove_from_connection()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
486 logging.debug("VeDbusItemExport %s has been removed" % path)
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 _get_path(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
489 if len(self._locations) == 0:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
490 return None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
491 return self._locations[0][1]
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
492
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
493 ## Sets the value. And in case the value is different from what it was, a signal
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
494 # will be emitted to the dbus. This function is to be used in the python code that
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
495 # is using this class to export values to the dbus.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
496 # set value to None to indicate that it is Invalid
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
497 def local_set_value(self, newvalue):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
498 changes = self._local_set_value(newvalue)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
499 if changes is not None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
500 self.PropertiesChanged(changes)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
501
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
502 def _local_set_value(self, newvalue):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
503 if self._value == newvalue:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
504 return None
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
505
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
506 self._value = newvalue
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
507 return {
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
508 'Value': wrap_dbus_value(newvalue),
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
509 'Text': self.GetText()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
510 }
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
511
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
512 def local_get_value(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
513 return self._value
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 # ==== ALL FUNCTIONS BELOW THIS LINE WILL BE CALLED BY OTHER PROCESSES OVER THE DBUS ====
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
516
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
517 ## Dbus exported method SetValue
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
518 # Function is called over the D-Bus by other process. It will first check (via callback) if new
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
519 # value is accepted. And it is, stores it and emits a changed-signal.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
520 # @param value The new value.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
521 # @return completion-code When successful a 0 is return, and when not a -1 is returned.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
522 @dbus.service.method('com.victronenergy.BusItem', in_signature='v', out_signature='i')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
523 def SetValue(self, newvalue):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
524 if not self._writeable:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
525 return 1 # NOT OK
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
526
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
527 newvalue = unwrap_dbus_value(newvalue)
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 if newvalue == self._value:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
530 return 0 # OK
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
531
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
532 # call the callback given to us, and check if new value is OK.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
533 if (self._onchangecallback is None or
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
534 (self._onchangecallback is not None and self._onchangecallback(self.__dbus_object_path__, newvalue))):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
535
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
536 self.local_set_value(newvalue)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
537 return 0 # OK
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 return 2 # NOT OK
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
540
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
541 ## Dbus exported method GetDescription
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
542 #
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
543 # Returns the a description.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
544 # @param language A language code (e.g. ISO 639-1 en-US).
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
545 # @param length Lenght of the language string.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
546 # @return description
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
547 @dbus.service.method('com.victronenergy.BusItem', in_signature='si', out_signature='s')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
548 def GetDescription(self, language, length):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
549 return self._description if self._description is not None else 'No description given'
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
550
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
551 ## Dbus exported method GetValue
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
552 # Returns the value.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
553 # @return the value when valid, and otherwise an empty array
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
554 @dbus.service.method('com.victronenergy.BusItem', out_signature='v')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
555 def GetValue(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
556 return wrap_dbus_value(self._value)
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 ## Dbus exported method GetText
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
559 # Returns the value as string of the dbus-object-path.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
560 # @return text A text-value. '---' when local value is invalid
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
561 @dbus.service.method('com.victronenergy.BusItem', out_signature='s')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
562 def GetText(self):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
563 if self._value is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
564 return '---'
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
565
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
566 # Default conversion from dbus.Byte will get you a character (so 'T' instead of '84'), so we
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
567 # have to convert to int first. Note that if a dbus.Byte turns up here, it must have come from
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
568 # the application itself, as all data from the D-Bus should have been unwrapped by now.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
569 if self._gettextcallback is None and type(self._value) == dbus.Byte:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
570 return str(int(self._value))
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
571
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
572 if self._gettextcallback is None and self.__dbus_object_path__ == '/ProductId':
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
573 return "0x%X" % self._value
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 if self._gettextcallback is None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
576 return str(self._value)
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 return self._gettextcallback(self.__dbus_object_path__, self._value)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
579
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
580 ## The signal that indicates that the value has changed.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
581 # Other processes connected to this BusItem object will have subscribed to the
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
582 # event when they want to track our state.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
583 @dbus.service.signal('com.victronenergy.BusItem', signature='a{sv}')
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
584 def PropertiesChanged(self, changes):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
585 pass
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
586
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
587 ## This class behaves like a regular reference to a class method (eg. self.foo), but keeps a weak reference
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
588 ## to the object which method is to be called.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
589 ## Use this object to break circular references.
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
590 class weak_functor:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
591 def __init__(self, f):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
592 self._r = weakref.ref(f.__self__)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
593 self._f = weakref.ref(f.__func__)
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
594
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
595 def __call__(self, *args, **kargs):
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
596 r = self._r()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
597 f = self._f()
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
598 if r == None or f == None:
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
599 return
9c0435a617db Import velib_python
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
600 f(r, *args, **kargs)