-
Notifications
You must be signed in to change notification settings - Fork 0
/
dbusdummyservice.py
122 lines (98 loc) · 4.2 KB
/
dbusdummyservice.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env python3
"""
A class to put a simple service on the dbus, according to victron standards, with constantly updating
paths. See example usage below. It is used to generate dummy data for other processes that rely on the
dbus. See files in dbus_vebus_to_pvinverter/test and dbus_vrm/test for other usage examples.
To change a value while testing, without stopping your dummy script and changing its initial value, write
to the dummy data via the dbus. See example.
https://github.com/victronenergy/dbus_vebus_to_pvinverter/tree/master/test
"""
from gi.repository import GLib
import platform
import logging
import sys
import os
# our own packages
sys.path.insert(1, os.path.join(os.path.dirname(__file__), "../ext/velib_python"))
from vedbus import VeDbusService
class DbusDummyService(object):
def __init__(
self,
servicename,
deviceinstance,
paths,
productname="Dummy product",
connection="Dummy service",
productid=0,
):
self._dbusservice = VeDbusService(servicename)
self._paths = paths
logging.debug("%s /DeviceInstance = %d" % (servicename, deviceinstance))
# Create the management objects, as specified in the ccgx dbus-api document
self._dbusservice.add_path("/Mgmt/ProcessName", __file__)
self._dbusservice.add_path(
"/Mgmt/ProcessVersion",
"Unkown version, and running on Python " + platform.python_version(),
)
self._dbusservice.add_path("/Mgmt/Connection", connection)
# Create the mandatory objects
self._dbusservice.add_path("/DeviceInstance", deviceinstance)
self._dbusservice.add_path("/ProductId", productid)
self._dbusservice.add_path("/ProductName", productname)
self._dbusservice.add_path("/FirmwareVersion", 0)
self._dbusservice.add_path("/HardwareVersion", 0)
self._dbusservice.add_path("/Connected", 1)
for path, settings in self._paths.items():
self._dbusservice.add_path(
path,
settings["initial"],
writeable=True,
onchangecallback=self._handlechangedvalue,
)
GLib.timeout_add(1000, self._update)
def _update(self):
with self._dbusservice as s:
for path, settings in self._paths.items():
if "update" in settings:
update = settings["update"]
if callable(update):
s[path] = update(path, s[path])
else:
s[path] += update
logging.debug("%s: %s" % (path, s[path]))
return True
def _handlechangedvalue(self, path, value):
logging.debug("someone else updated %s to %s" % (path, value))
return True # accept the change
# === All code below is to simply run it from the commandline for debugging purposes ===
# It will created a dbus service called com.victronenergy.pvinverter.output.
# To try this on commandline, start this program in one terminal, and try these commands
# from another terminal:
# dbus com.victronenergy.pvinverter.output
# dbus com.victronenergy.pvinverter.output /Ac/Energy/Forward GetValue
# dbus com.victronenergy.pvinverter.output /Ac/Energy/Forward SetValue %20
#
# Above examples use this dbus client: http://code.google.com/p/dbus-tools/wiki/DBusCli
# See their manual to explain the % in %20
def main():
logging.basicConfig(level=logging.DEBUG)
from dbus.mainloop.glib import DBusGMainLoop
# Have a mainloop, so we can send/receive asynchronous calls to and from dbus
DBusGMainLoop(set_as_default=True)
pvac_output = DbusDummyService(
servicename="com.victronenergy.dummyservice.ttyO1",
deviceinstance=0,
paths={
"/Ac/Energy/Forward": {"initial": 0, "update": 1},
"/Position": {"initial": 0, "update": 0},
"/Nonupdatingvalue/UseForTestingWritesForExample": {"initial": None},
"/DbusInvalid": {"initial": None},
},
)
logging.info(
"Connected to dbus, and switching over to GLib.MainLoop() (= event based)"
)
mainloop = GLib.MainLoop()
mainloop.run()
if __name__ == "__main__":
main()