Esempio n. 1
0
	def __init__(self,mqqthost,nodeid,service,base_topic='emonhub'):
		self.d = DbusMonitor(datalist.vrmtree, self._value_changed_on_dbus)

		"""
		self.ttl = 300    # seconds to keep sending the updates.  If no keepAlive received in this
						  # time - stop sending

		self.lastKeepAliveRcd = int(time.time()) - self.ttl   # initialised to when this code launches
		"""

		self.ttm = 0      # seconds to gather data before sending, 0 - send immediate, NN - gather
						  # for NN seconds
		self._last_publish = int(time.time() - 60)  # Just an initialisation value, so the first
											   # ttm timeout is _now_
		self._gathered_data_timer = None
		self._gathered_data = {}

		self._mqtt = mqtt.Client(client_id=get_vrm_portal_id(), clean_session=True, userdata=None)
		self._mqtt.loop_start()  # creates new thread and runs Mqtt.loop_forever() in it.
		self._mqtt.on_connect = self._on_connect
		self._mqtt.on_message = self._on_message
		self._mqtt.connect_async(mqqthost, port=1883, keepalive=60, bind_address="")


		self._service_name = service

		self._nodeid = nodeid #node ide expected by emonhub . need to modigy emonhub.conf accordingly
		self._topic = base_topic
		message = '{basetopic}/tx/{nodeid}/values'
		self._publishPath = message.format(basetopic=self._topic,nodeid=self._nodeid)
Esempio n. 2
0
    def __init__(self,
                 mqtt_server=None,
                 ca_cert=None,
                 user=None,
                 passwd=None,
                 dbus_address=None,
                 keep_alive_interval=None,
                 init_broker=False,
                 debug=False):
        self._dbus_address = dbus_address
        self._dbus_conn = (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) \
         if dbus_address is None \
         else dbus.bus.BusConnection(dbus_address)
        self._dbus_conn.add_signal_receiver(self._dbus_name_owner_changed,
                                            signal_name='NameOwnerChanged')
        self._connected_to_cloud = False

        # @todo EV Get portal ID from com.victronenergy.system?
        self._system_id = get_vrm_portal_id()
        # Key: D-BUS Service + path, value: topic
        self._topics = {}
        # Key: topic, value: last value seen on D-Bus
        self._values = {}
        # Key: service_type/device_instance, value: D-Bus service name
        self._services = {}
        # Key: short D-Bus service name (eg. 1:31), value: full D-Bus service name (eg. com.victronenergy.settings)
        self._service_ids = {}
        # A queue of value changes, so that we may rate-limit this somewhat
        self.queue = OrderedDict()
        gobject.timeout_add(1000, self._timer_service_queue)
        self._last_queue_run = 0

        if init_broker:
            self._registrator = MosquittoBridgeRegistrator(self._system_id)
            self._registrator.register()
        else:
            self._registrator = None

        self._dbus_conn.add_signal_receiver(
            self._on_dbus_value_changed,
            dbus_interface='com.victronenergy.BusItem',
            signal_name='PropertiesChanged',
            path_keyword='path',
            sender_keyword='service_id')
        services = self._dbus_conn.list_names()
        for service in services:
            if service.startswith('com.victronenergy.'):
                self._service_ids[self._dbus_conn.get_name_owner(
                    service)] = service
                self._scan_dbus_service(service, publish=False)

        # Bus scan may take a log time, so start keep alive after scan
        self._keep_alive_interval = keep_alive_interval
        self._keep_alive_timer = None

        MqttGObjectBridge.__init__(self, mqtt_server, "ve-dbus-mqtt-py",
                                   ca_cert, user, passwd, debug)
	def __init__(self, dbusmonitor_gen=None, dbusservice_gen=None, settings_device_gen=None):
		self.STATE_IDLE = 0
		self.STATE_CHARGING = 1
		self.STATE_DISCHARGING = 2

		self.BATSERVICE_DEFAULT = 'default'
		self.BATSERVICE_NOBATTERY = 'nobattery'

		# Why this dummy? Because DbusMonitor expects these values to be there, even though we don't
		# need them. So just add some dummy data. This can go away when DbusMonitor is more generic.
		dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None}
		dbus_tree = {
			'com.victronenergy.solarcharger': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/0/Current': dummy},
			'com.victronenergy.pvinverter': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Ac/L1/Power': dummy,
				'/Ac/L2/Power': dummy,
				'/Ac/L3/Power': dummy,
				'/Position': dummy,
				'/ProductId': dummy},
			'com.victronenergy.battery': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/0/Current': dummy,
				'/Dc/0/Power': dummy,
				'/Soc': dummy,
				'/TimeToGo': dummy,
				'/ConsumedAmphours': dummy},
			'com.victronenergy.vebus' : {
				'/Ac/ActiveIn/ActiveInput': dummy,
				'/Ac/ActiveIn/L1/P': dummy,
				'/Ac/ActiveIn/L2/P': dummy,
				'/Ac/ActiveIn/L3/P': dummy,
				'/Ac/Out/L1/P': dummy,
				'/Ac/Out/L2/P': dummy,
				'/Ac/Out/L3/P': dummy,
				'/Hub4/AcPowerSetpoint': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/0/Current': dummy,
				'/Dc/0/Power': dummy,
				'/Soc': dummy},
			'com.victronenergy.charger': {
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/0/Current': dummy},
			'com.victronenergy.grid' : {
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/ProductId' : dummy,
				'/DeviceType' : dummy,
				'/Ac/L1/Power': dummy,
				'/Ac/L2/Power': dummy,
				'/Ac/L3/Power': dummy},
			'com.victronenergy.genset' : {
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/ProductId' : dummy,
				'/DeviceType' : dummy,
				'/Ac/L1/Power': dummy,
				'/Ac/L2/Power': dummy,
				'/Ac/L3/Power': dummy},
			'com.victronenergy.settings' : {
				'/Settings/SystemSetup/AcInput1' : dummy,
				'/Settings/SystemSetup/AcInput2' : dummy}
		}

		if dbusmonitor_gen is None:
			self._dbusmonitor = DbusMonitor(dbus_tree, self._dbus_value_changed, self._device_added, self._device_removed)
		else:
			self._dbusmonitor = dbusmonitor_gen(dbus_tree)

		# Connect to localsettings
		supported_settings = {
			'batteryservice': ['/Settings/SystemSetup/BatteryService', self.BATSERVICE_DEFAULT, 0, 0],
			'hasdcsystem': ['/Settings/SystemSetup/HasDcSystem', 0, 0, 1],
			'writevebussoc': ['/Settings/SystemSetup/WriteVebusSoc', 0, 0, 1]}

		if settings_device_gen is None:
			self._settings = SettingsDevice(
				bus=dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus(),
				supportedSettings=supported_settings,
				eventCallback=self._handlechangedsetting)
		else:
			self._settings = settings_device_gen(supported_settings, self._handlechangedsetting)

		# put ourselves on the dbus
		if dbusservice_gen is None:
			self._dbusservice = VeDbusService('com.victronenergy.system')
		else:
			self._dbusservice = dbusservice_gen('com.victronenergy.system')

		self._dbusservice.add_mandatory_paths(
			processname=__file__,
			processversion=softwareVersion,
			connection='data from other dbus processes',
			deviceinstance=0,
			productid=None,
			productname=None,
			firmwareversion=None,
			hardwareversion=None,
			connected=1)

		# At this moment, VRM portal ID is the MAC address of the CCGX. Anyhow, it should be string uniquely
		# identifying the CCGX.
		self._dbusservice.add_path('/Serial', value=get_vrm_portal_id())

		self._dbusservice.add_path(
			'/AvailableBatteryServices', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/AvailableBatteryMeasurements', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/AutoSelectedBatteryService', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/AutoSelectedBatteryMeasurement', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/ActiveBatteryService', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/PvInvertersProductIds', value=None)
		self._summeditems = {
			'/Ac/Grid/L1/Power': {'gettext': '%.0F W'},
			'/Ac/Grid/L2/Power': {'gettext': '%.0F W'},
			'/Ac/Grid/L3/Power': {'gettext': '%.0F W'},
			'/Ac/Grid/Total/Power': {'gettext': '%.0F W'},
			'/Ac/Grid/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/Grid/ProductId': {'gettext': '%s'},
			'/Ac/Grid/DeviceType': {'gettext': '%s'},
			'/Ac/Genset/L1/Power': {'gettext': '%.0F W'},
			'/Ac/Genset/L2/Power': {'gettext': '%.0F W'},
			'/Ac/Genset/L3/Power': {'gettext': '%.0F W'},
			'/Ac/Genset/Total/Power': {'gettext': '%.0F W'},
			'/Ac/Genset/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/Genset/ProductId': {'gettext': '%s'},
			'/Ac/Genset/DeviceType': {'gettext': '%s'},
			'/Ac/Consumption/L1/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/L2/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/L3/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/Total/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/L1/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/L2/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/L3/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/Total/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/L1/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/L2/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/L3/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/Total/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/L1/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/L2/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/L3/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/NumberOfPhases': {'gettext': '%d'},
			'/Ac/PvOnGenset/Total/Power': {'gettext': '%.0F W'},
			'/Dc/Pv/Power': {'gettext': '%.0F W'},
			'/Dc/Pv/Current': {'gettext': '%.1F A'},
			'/Dc/Battery/Voltage': {'gettext': '%.2F V'},
			'/Dc/Battery/Current': {'gettext': '%.1F A'},
			'/Dc/Battery/Power': {'gettext': '%.0F W'},
			'/Dc/Battery/Soc': {'gettext': '%.0F %%'},
			'/Dc/Battery/State': {'gettext': '%s'},
			'/Dc/Battery/TimeToGo': {'gettext': '%.0F s'},
			'/Dc/Battery/ConsumedAmphours': {'gettext': '%.1F Ah'},
			'/Dc/Charger/Power': {'gettext': '%.0F %%'},
			'/Dc/Vebus/Current': {'gettext': '%.1F A'},
			'/Dc/Vebus/Power': {'gettext': '%.0F W'},
			'/Dc/System/Power': {'gettext': '%.0F W'},
			'/Hub': {'gettext': '%s'},
			'/Ac/ActiveIn/Source': {'gettext': '%s'},
			'/VebusService': {'gettext': '%s'}
		}

		for path in self._summeditems.keys():
			self._dbusservice.add_path(path, value=None, gettextcallback=self._gettext)

		self._batteryservice = None
		self._determinebatteryservice()

		if self._batteryservice is None:
			logger.info("Battery service initialized to None (setting == %s)" %
				self._settings['batteryservice'])

		self._changed = True
		for service, instance in self._dbusmonitor.get_service_list().items():
			self._device_added(service, instance, do_service_change=False)

		self._handleservicechange()
		self._updatevalues()

		self._writeVebusSocCounter = 9
		gobject.timeout_add(1000, exit_on_error, self._handletimertick)
	def __init__(self):
		self.STATE_IDLE = 0
		self.STATE_CHARGING = 1
		self.STATE_DISCHARGING = 2

		self.BATSERVICE_DEFAULT = 'default'
		self.BATSERVICE_NOBATTERY = 'nobattery'

		# Why this dummy? Because DbusMonitor expects these values to be there, even though we don't
		# need them. So just add some dummy data. This can go away when DbusMonitor is more generic.
		dummy = {'code': None, 'whenToLog': 'configChange', 'accessLevel': None}
		dbus_tree = {
			'com.victronenergy.solarcharger': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/0/Current': dummy,
				'/Dc/0/Temperature': dummy,
				'/FirmwareVersion': dummy},
			'com.victronenergy.pvinverter': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Ac/L1/Power': dummy,
				'/Ac/L2/Power': dummy,
				'/Ac/L3/Power': dummy,
				'/Position': dummy,
				'/ProductId': dummy},
			'com.victronenergy.battery': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/DeviceInstance': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/1/Voltage': dummy,
				'/Dc/0/Current': dummy,
				'/Dc/0/Power': dummy,
				'/Dc/0/Temperature': dummy,
				'/Soc': dummy,
				'/TimeToGo': dummy,
				'/ConsumedAmphours': dummy,
				'/ProductId': dummy,
				'/CustomName': dummy},
			'com.victronenergy.vebus' : {
				'/Ac/ActiveIn/ActiveInput': dummy,
				'/Ac/ActiveIn/L1/P': dummy,
				'/Ac/ActiveIn/L2/P': dummy,
				'/Ac/ActiveIn/L3/P': dummy,
				'/Ac/Out/L1/P': dummy,
				'/Ac/Out/L2/P': dummy,
				'/Ac/Out/L3/P': dummy,
				'/Connected': dummy,
				'/ProductId': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Mode': dummy,
				'/State': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/0/Current': dummy,
				'/Dc/0/Power': dummy,
				'/Dc/0/Temperature': dummy,
				'/Soc': dummy},
			'com.victronenergy.charger': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Dc/0/Voltage': dummy,
				'/Dc/0/Current': dummy,
				'/Dc/1/Voltage': dummy,
				'/Dc/1/Current': dummy,
				'/Dc/2/Voltage': dummy,
				'/Dc/2/Current': dummy},
			'com.victronenergy.grid' : {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/ProductId' : dummy,
				'/DeviceType' : dummy,
				'/Ac/L1/Power': dummy,
				'/Ac/L2/Power': dummy,
				'/Ac/L3/Power': dummy},
			'com.victronenergy.genset' : {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/ProductId' : dummy,
				'/DeviceType' : dummy,
				'/Ac/L1/Power': dummy,
				'/Ac/L2/Power': dummy,
				'/Ac/L3/Power': dummy},
			'com.victronenergy.settings' : {
				'/Settings/SystemSetup/AcInput1' : dummy,
				'/Settings/SystemSetup/AcInput2' : dummy,
				'/Settings/CGwacs/RunWithoutGridMeter' : dummy,
				'/Settings/System/TimeZone' : dummy},
			'com.victronenergy.temperature': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Temperature': dummy,
				'/TemperatureType': dummy},
			'com.victronenergy.inverter': {
				'/Connected': dummy,
				'/ProductName': dummy,
				'/Mgmt/Connection': dummy,
				'/Dc/0/Voltage': dummy,
				'/Ac/Out/L1/P': dummy,
				'/Ac/Out/L1/V': dummy,
				'/Ac/Out/L1/I': dummy,
			}
		}

		self._modules = [
			delegates.HubTypeSelect(),
			delegates.VebusSocWriter(),
			delegates.ServiceMapper(),
			delegates.RelayState(),
			delegates.BuzzerControl(),
			delegates.LgCircuitBreakerDetect(),
			delegates.Dvcc(),
			delegates.BatterySense(),
			delegates.SystemState(),
			delegates.BatteryLife(),
			delegates.ScheduledCharging(),
			delegates.SourceTimers(),
			delegates.BatteryData()]

		for m in self._modules:
			for service, paths in m.get_input():
				s = dbus_tree.setdefault(service, {})
				for path in paths:
					s[path] = dummy

		self._dbusmonitor = self._create_dbus_monitor(dbus_tree, valueChangedCallback=self._dbus_value_changed,
			deviceAddedCallback=self._device_added, deviceRemovedCallback=self._device_removed)

		# Connect to localsettings
		supported_settings = {
			'batteryservice': ['/Settings/SystemSetup/BatteryService', self.BATSERVICE_DEFAULT, 0, 0],
			'hasdcsystem': ['/Settings/SystemSetup/HasDcSystem', 0, 0, 1],
			'useacout': ['/Settings/SystemSetup/HasAcOutSystem', 1, 0, 1]}

		for m in self._modules:
			for setting in m.get_settings():
				supported_settings[setting[0]] = list(setting[1:])

		self._settings = self._create_settings(supported_settings, self._handlechangedsetting)

		self._dbusservice = self._create_dbus_service()

		for m in self._modules:
			m.set_sources(self._dbusmonitor, self._settings, self._dbusservice)

		# At this moment, VRM portal ID is the MAC address of the CCGX. Anyhow, it should be string uniquely
		# identifying the CCGX.
		self._dbusservice.add_path('/Serial', value=get_vrm_portal_id())
		self._dbusservice.add_path(
			'/AvailableBatteryServices', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/AvailableBatteryMeasurements', value=None)
		self._dbusservice.add_path(
			'/AutoSelectedBatteryService', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/AutoSelectedBatteryMeasurement', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/ActiveBatteryService', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/AutoSelectedTemperatureService', value=None, gettextcallback=self._gettext)
		self._dbusservice.add_path(
			'/PvInvertersProductIds', value=None)
		self._summeditems = {
			'/Ac/Grid/L1/Power': {'gettext': '%.0F W'},
			'/Ac/Grid/L2/Power': {'gettext': '%.0F W'},
			'/Ac/Grid/L3/Power': {'gettext': '%.0F W'},
			'/Ac/Grid/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/Grid/ProductId': {'gettext': '%s'},
			'/Ac/Grid/DeviceType': {'gettext': '%s'},
			'/Ac/Genset/L1/Power': {'gettext': '%.0F W'},
			'/Ac/Genset/L2/Power': {'gettext': '%.0F W'},
			'/Ac/Genset/L3/Power': {'gettext': '%.0F W'},
			'/Ac/Genset/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/Genset/ProductId': {'gettext': '%s'},
			'/Ac/Genset/DeviceType': {'gettext': '%s'},
			'/Ac/ConsumptionOnOutput/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/ConsumptionOnOutput/L1/Power': {'gettext': '%.0F W'},
			'/Ac/ConsumptionOnOutput/L2/Power': {'gettext': '%.0F W'},
			'/Ac/ConsumptionOnOutput/L3/Power': {'gettext': '%.0F W'},
			'/Ac/ConsumptionOnInput/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/ConsumptionOnInput/L1/Power': {'gettext': '%.0F W'},
			'/Ac/ConsumptionOnInput/L2/Power': {'gettext': '%.0F W'},
			'/Ac/ConsumptionOnInput/L3/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/Consumption/L1/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/L2/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/L3/Power': {'gettext': '%.0F W'},
			'/Ac/Consumption/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/L1/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/L2/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/L3/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnOutput/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/L1/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/L2/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/L3/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGrid/NumberOfPhases': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/L1/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/L2/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/L3/Power': {'gettext': '%.0F W'},
			'/Ac/PvOnGenset/NumberOfPhases': {'gettext': '%d'},
			'/Dc/Pv/Power': {'gettext': '%.0F W'},
			'/Dc/Pv/Current': {'gettext': '%.1F A'},
			'/Dc/Battery/Voltage': {'gettext': '%.2F V'},
			'/Dc/Battery/Temperature': {'gettext': '%.1F C'},
			'/Dc/Battery/VoltageService': {'gettext': '%s'},
			'/Dc/Battery/TemperatureService': {'gettext': '%s'},
			'/Dc/Battery/Current': {'gettext': '%.1F A'},
			'/Dc/Battery/Power': {'gettext': '%.0F W'},
			'/Dc/Battery/Soc': {'gettext': '%.0F %%'},
			'/Dc/Battery/State': {'gettext': '%s'},
			'/Dc/Battery/TimeToGo': {'gettext': '%.0F s'},
			'/Dc/Battery/ConsumedAmphours': {'gettext': '%.1F Ah'},
			'/Dc/Charger/Power': {'gettext': '%.0F %%'},
			'/Dc/Vebus/Current': {'gettext': '%.1F A'},
			'/Dc/Vebus/Power': {'gettext': '%.0F W'},
			'/Dc/System/Power': {'gettext': '%.0F W'},
			'/Ac/ActiveIn/Source': {'gettext': '%s'},
			'/VebusService': {'gettext': '%s'}
		}

		for m in self._modules:
			self._summeditems.update(m.get_output())

		for path in self._summeditems.keys():
			self._dbusservice.add_path(path, value=None, gettextcallback=self._gettext)

		self._batteryservice = None
		self._determinebatteryservice()

		if self._batteryservice is None:
			logger.info("Battery service initialized to None (setting == %s)" %
				self._settings['batteryservice'])

		self._changed = True
		for service, instance in self._dbusmonitor.get_service_list().items():
			self._device_added(service, instance, do_service_change=False)

		self._handleservicechange()
		self._updatevalues()

		gobject.timeout_add(1000, exit_on_error, self._handletimertick)
    def __init__(self):
        self.STATE_IDLE = 0
        self.STATE_CHARGING = 1
        self.STATE_DISCHARGING = 2

        self.BATSERVICE_DEFAULT = 'default'
        self.BATSERVICE_NOBATTERY = 'nobattery'

        # Why this dummy? Because DbusMonitor expects these values to be there, even though we don't
        # need them. So just add some dummy data. This can go away when DbusMonitor is more generic.
        dummy = {
            'code': None,
            'whenToLog': 'configChange',
            'accessLevel': None
        }
        dbus_tree = {
            'com.victronenergy.solarcharger': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy
            },
            'com.victronenergy.pvinverter': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Ac/L1/Power': dummy,
                '/Ac/L2/Power': dummy,
                '/Ac/L3/Power': dummy,
                '/Position': dummy,
                '/ProductId': dummy
            },
            'com.victronenergy.battery': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy,
                '/Dc/0/Power': dummy,
                '/Soc': dummy,
                '/TimeToGo': dummy,
                '/ConsumedAmphours': dummy,
                '/ProductId': dummy
            },
            'com.victronenergy.vebus': {
                '/Ac/ActiveIn/ActiveInput': dummy,
                '/Ac/ActiveIn/L1/P': dummy,
                '/Ac/ActiveIn/L2/P': dummy,
                '/Ac/ActiveIn/L3/P': dummy,
                '/Ac/Out/L1/P': dummy,
                '/Ac/Out/L2/P': dummy,
                '/Ac/Out/L3/P': dummy,
                '/Connected': dummy,
                '/ProductId': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Mode': dummy,
                '/State': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy,
                '/Dc/0/Power': dummy,
                '/Soc': dummy
            },
            'com.victronenergy.charger': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy
            },
            'com.victronenergy.grid': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/ProductId': dummy,
                '/DeviceType': dummy,
                '/Ac/L1/Power': dummy,
                '/Ac/L2/Power': dummy,
                '/Ac/L3/Power': dummy
            },
            'com.victronenergy.genset': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/ProductId': dummy,
                '/DeviceType': dummy,
                '/Ac/L1/Power': dummy,
                '/Ac/L2/Power': dummy,
                '/Ac/L3/Power': dummy
            },
            'com.victronenergy.settings': {
                '/Settings/SystemSetup/AcInput1': dummy,
                '/Settings/SystemSetup/AcInput2': dummy,
                '/Settings/CGwacs/RunWithoutGridMeter': dummy
            }
        }

        service_supervisor = delegates.ServiceSupervisor()
        self._modules = [
            delegates.HubTypeSelect(),
            delegates.VebusSocWriter(),
            delegates.ServiceMapper(), service_supervisor,
            delegates.RelayState(),
            delegates.BuzzerControl(),
            delegates.LgCircuitBreakerDetect(),
            delegates.Hub1Bridge(service_supervisor)
        ]

        for m in self._modules:
            for service, paths in m.get_input():
                s = dbus_tree.setdefault(service, {})
                for path in paths:
                    s[path] = dummy

        self._dbusmonitor = self._create_dbus_monitor(
            dbus_tree,
            valueChangedCallback=self._dbus_value_changed,
            deviceAddedCallback=self._device_added,
            deviceRemovedCallback=self._device_removed)

        # Connect to localsettings
        supported_settings = {
            'batteryservice': [
                '/Settings/SystemSetup/BatteryService',
                self.BATSERVICE_DEFAULT, 0, 0
            ],
            'hasdcsystem': ['/Settings/SystemSetup/HasDcSystem', 0, 0, 1],
            'useacout': ['/Settings/SystemSetup/HasAcOutSystem', 1, 0, 1]
        }

        for m in self._modules:
            for setting in m.get_settings():
                supported_settings[setting[0]] = list(setting[1:])

        self._settings = self._create_settings(supported_settings,
                                               self._handlechangedsetting)

        self._dbusservice = self._create_dbus_service()

        for m in self._modules:
            m.set_sources(self._dbusmonitor, self._settings, self._dbusservice)

        # At this moment, VRM portal ID is the MAC address of the CCGX. Anyhow, it should be string uniquely
        # identifying the CCGX.
        self._dbusservice.add_path('/Serial', value=get_vrm_portal_id())
        self._dbusservice.add_path('/AvailableBatteryServices',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/AvailableBatteryMeasurements', value=None)
        self._dbusservice.add_path('/AutoSelectedBatteryService',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/AutoSelectedBatteryMeasurement',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/ActiveBatteryService',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/PvInvertersProductIds', value=None)
        self._summeditems = {
            '/Ac/Grid/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/ProductId': {
                'gettext': '%s'
            },
            '/Ac/Grid/DeviceType': {
                'gettext': '%s'
            },
            '/Ac/Genset/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/ProductId': {
                'gettext': '%s'
            },
            '/Ac/Genset/DeviceType': {
                'gettext': '%s'
            },
            '/Ac/ConsumptionOnOutput/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/ConsumptionOnOutput/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/ConsumptionOnOutput/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/ConsumptionOnOutput/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/ConsumptionOnInput/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/ConsumptionOnInput/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/ConsumptionOnInput/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/ConsumptionOnInput/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/NumberOfPhases': {
                'gettext': '%d'
            },
            '/Dc/Pv/Power': {
                'gettext': '%.0F W'
            },
            '/Dc/Pv/Current': {
                'gettext': '%.1F A'
            },
            '/Dc/Battery/Voltage': {
                'gettext': '%.2F V'
            },
            '/Dc/Battery/Current': {
                'gettext': '%.1F A'
            },
            '/Dc/Battery/Power': {
                'gettext': '%.0F W'
            },
            '/Dc/Battery/Soc': {
                'gettext': '%.0F %%'
            },
            '/Dc/Battery/State': {
                'gettext': '%s'
            },
            '/Dc/Battery/TimeToGo': {
                'gettext': '%.0F s'
            },
            '/Dc/Battery/ConsumedAmphours': {
                'gettext': '%.1F Ah'
            },
            '/Dc/Charger/Power': {
                'gettext': '%.0F %%'
            },
            '/Dc/Vebus/Current': {
                'gettext': '%.1F A'
            },
            '/Dc/Vebus/Power': {
                'gettext': '%.0F W'
            },
            '/Dc/System/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/ActiveIn/Source': {
                'gettext': '%s'
            },
            '/VebusService': {
                'gettext': '%s'
            }
        }

        for m in self._modules:
            self._summeditems.update(m.get_output())

        for path in self._summeditems.keys():
            self._dbusservice.add_path(path,
                                       value=None,
                                       gettextcallback=self._gettext)

        self._batteryservice = None
        self._determinebatteryservice()

        if self._batteryservice is None:
            logger.info("Battery service initialized to None (setting == %s)" %
                        self._settings['batteryservice'])

        self._changed = True
        for service, instance in self._dbusmonitor.get_service_list().items():
            self._device_added(service, instance, do_service_change=False)

        self._handleservicechange()
        self._updatevalues()

        gobject.timeout_add(1000, exit_on_error, self._handletimertick)
Esempio n. 6
0
    def __init__(self,
                 mqtt_server=None,
                 ca_cert=None,
                 user=None,
                 passwd=None,
                 dbus_address=None,
                 keep_alive_interval=None,
                 init_broker=False):
        self._ca_cert = ca_cert
        self._mqtt_user = user
        self._mqtt_passwd = passwd
        self._mqtt_server = mqtt_server or '127.0.0.1'
        self._dbus_address = dbus_address
        self._dbus_conn = (dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS' in os.environ else dbus.SystemBus()) \
         if dbus_address == None \
         else dbus.bus.BusConnection(dbus_address)
        self._dbus_conn.add_signal_receiver(self._dbus_name_owner_changed,
                                            signal_name='NameOwnerChanged')

        # @todo EV Get portal ID from com.victronenergy.system?
        self._system_id = get_vrm_portal_id()
        # Key: D-BUS Service + path, value: topic
        self._topics = {}
        # Key: topic, value: last value seen on D-Bus
        self._values = {}
        # Key: service_type/device_instance, value: D-Bus service name
        self._services = {}
        # Key: short D-Bus service name (eg. 1:31), value: full D-Bus service name (eg. com.victronenergy.settings)
        self._service_ids = {}

        if init_broker and self._init_broker():
            gobject.timeout_add_seconds(60, exit_on_error, self._init_broker)

        self._dbus_conn.add_signal_receiver(
            self._on_dbus_value_changed,
            dbus_interface='com.victronenergy.BusItem',
            signal_name='PropertiesChanged',
            path_keyword='path',
            sender_keyword='service_id')
        services = self._dbus_conn.list_names()
        for service in services:
            if service.startswith('com.victronenergy.'):
                self._service_ids[self._dbus_conn.get_name_owner(
                    service)] = service
                self._scan_dbus_service(service, publish=False)

        # Bus scan may take a log time, so start keep alive after scan
        self._keep_alive_interval = keep_alive_interval
        if self._keep_alive_interval != None:
            self._keep_alive_timer = gobject.timeout_add_seconds(
                self._keep_alive_interval, exit_on_error,
                self._on_keep_alive_timeout)

        self._client = paho.mqtt.client.Client(client_id="ve/dbus-mqtt-py")
        self._client.on_connect = self._on_connect
        self._client.on_message = self._on_message
        self._client.on_disconnect = self._on_disconnect
        self._socket_watch = None
        self._socket_timer = None
        if self._init_mqtt():
            gobject.timeout_add_seconds(5, exit_on_error, self._init_mqtt)
Esempio n. 7
0
    def __init__(self,
                 dbusmonitor_gen=None,
                 dbusservice_gen=None,
                 settings_device_gen=None):
        self.STATE_IDLE = 0
        self.STATE_CHARGING = 1
        self.STATE_DISCHARGING = 2

        self.BATSERVICE_DEFAULT = 'default'
        self.BATSERVICE_NOBATTERY = 'nobattery'

        # Why this dummy? Because DbusMonitor expects these values to be there, even though we don't
        # need them. So just add some dummy data. This can go away when DbusMonitor is more generic.
        dummy = {
            'code': None,
            'whenToLog': 'configChange',
            'accessLevel': None
        }
        dbus_tree = {
            'com.victronenergy.solarcharger': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy
            },
            'com.victronenergy.pvinverter': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Ac/L1/Power': dummy,
                '/Ac/L2/Power': dummy,
                '/Ac/L3/Power': dummy,
                '/Position': dummy,
                '/ProductId': dummy
            },
            'com.victronenergy.battery': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy,
                '/Dc/0/Power': dummy,
                '/Soc': dummy,
                '/TimeToGo': dummy,
                '/ConsumedAmphours': dummy,
                '/ProductId': dummy
            },
            'com.victronenergy.vebus': {
                '/Ac/ActiveIn/ActiveInput': dummy,
                '/Ac/ActiveIn/L1/P': dummy,
                '/Ac/ActiveIn/L2/P': dummy,
                '/Ac/ActiveIn/L3/P': dummy,
                '/Ac/Out/L1/P': dummy,
                '/Ac/Out/L2/P': dummy,
                '/Ac/Out/L3/P': dummy,
                '/Connected': dummy,
                '/Hub4/AcPowerSetpoint': dummy,
                '/ProductId': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Mode': dummy,
                '/State': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy,
                '/Dc/0/Power': dummy,
                '/Soc': dummy
            },
            'com.victronenergy.charger': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/Dc/0/Voltage': dummy,
                '/Dc/0/Current': dummy
            },
            'com.victronenergy.grid': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/ProductId': dummy,
                '/DeviceType': dummy,
                '/Ac/L1/Power': dummy,
                '/Ac/L2/Power': dummy,
                '/Ac/L3/Power': dummy
            },
            'com.victronenergy.genset': {
                '/Connected': dummy,
                '/ProductName': dummy,
                '/Mgmt/Connection': dummy,
                '/ProductId': dummy,
                '/DeviceType': dummy,
                '/Ac/L1/Power': dummy,
                '/Ac/L2/Power': dummy,
                '/Ac/L3/Power': dummy
            },
            'com.victronenergy.settings': {
                '/Settings/SystemSetup/AcInput1': dummy,
                '/Settings/SystemSetup/AcInput2': dummy
            }
        }

        if dbusmonitor_gen is None:
            self._dbusmonitor = DbusMonitor(dbus_tree,
                                            self._dbus_value_changed,
                                            self._device_added,
                                            self._device_removed)
        else:
            self._dbusmonitor = dbusmonitor_gen(dbus_tree)

        # Connect to localsettings
        supported_settings = {
            'batteryservice': [
                '/Settings/SystemSetup/BatteryService',
                self.BATSERVICE_DEFAULT, 0, 0
            ],
            'hasdcsystem': ['/Settings/SystemSetup/HasDcSystem', 0, 0, 1],
            'writevebussoc': ['/Settings/SystemSetup/WriteVebusSoc', 0, 0, 1]
        }

        if settings_device_gen is None:
            self._settings = SettingsDevice(
                bus=dbus.SessionBus() if 'DBUS_SESSION_BUS_ADDRESS'
                in os.environ else dbus.SystemBus(),
                supportedSettings=supported_settings,
                eventCallback=self._handlechangedsetting)
        else:
            self._settings = settings_device_gen(supported_settings,
                                                 self._handlechangedsetting)

        # put ourselves on the dbus
        if dbusservice_gen is None:
            self._dbusservice = VeDbusService('com.victronenergy.system')
        else:
            self._dbusservice = dbusservice_gen('com.victronenergy.system')

        self._dbusservice.add_mandatory_paths(
            processname=__file__,
            processversion=softwareVersion,
            connection='data from other dbus processes',
            deviceinstance=0,
            productid=None,
            productname=None,
            firmwareversion=None,
            hardwareversion=None,
            connected=1)

        # At this moment, VRM portal ID is the MAC address of the CCGX. Anyhow, it should be string uniquely
        # identifying the CCGX.
        self._dbusservice.add_path('/Serial',
                                   value=get_vrm_portal_id(),
                                   gettextcallback=lambda x: str(x))
        self._dbusservice.add_path('/Relay/0/State',
                                   value=None,
                                   writeable=True,
                                   onchangecallback=lambda p, v: exit_on_error(
                                       self._on_relay_state_changed, p, v))

        self._dbusservice.add_path('/AvailableBatteryServices',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/AvailableBatteryMeasurements', value=None)
        self._dbusservice.add_path('/AutoSelectedBatteryService',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/AutoSelectedBatteryMeasurement',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/ActiveBatteryService',
                                   value=None,
                                   gettextcallback=self._gettext)
        self._dbusservice.add_path('/PvInvertersProductIds', value=None)
        self._dbusservice.add_path('/Dc/Battery/Alarms/CircuitBreakerTripped',
                                   value=None)
        self._summeditems = {
            '/Ac/Grid/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/Total/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/Grid/ProductId': {
                'gettext': '%s'
            },
            '/Ac/Grid/DeviceType': {
                'gettext': '%s'
            },
            '/Ac/Genset/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/Total/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/Genset/ProductId': {
                'gettext': '%s'
            },
            '/Ac/Genset/DeviceType': {
                'gettext': '%s'
            },
            '/Ac/Consumption/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/Total/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/Consumption/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/Total/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnOutput/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/Total/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGrid/NumberOfPhases': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/L1/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/L2/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/L3/Power': {
                'gettext': '%.0F W'
            },
            '/Ac/PvOnGenset/NumberOfPhases': {
                'gettext': '%d'
            },
            '/Ac/PvOnGenset/Total/Power': {
                'gettext': '%.0F W'
            },
            '/Dc/Pv/Power': {
                'gettext': '%.0F W'
            },
            '/Dc/Pv/Current': {
                'gettext': '%.1F A'
            },
            '/Dc/Battery/Voltage': {
                'gettext': '%.2F V'
            },
            '/Dc/Battery/Current': {
                'gettext': '%.1F A'
            },
            '/Dc/Battery/Power': {
                'gettext': '%.0F W'
            },
            '/Dc/Battery/Soc': {
                'gettext': '%.0F %%'
            },
            '/Dc/Battery/State': {
                'gettext': '%s'
            },
            '/Dc/Battery/TimeToGo': {
                'gettext': '%.0F s'
            },
            '/Dc/Battery/ConsumedAmphours': {
                'gettext': '%.1F Ah'
            },
            '/Dc/Charger/Power': {
                'gettext': '%.0F %%'
            },
            '/Dc/Vebus/Current': {
                'gettext': '%.1F A'
            },
            '/Dc/Vebus/Power': {
                'gettext': '%.0F W'
            },
            '/Dc/System/Power': {
                'gettext': '%.0F W'
            },
            '/Hub': {
                'gettext': '%s'
            },
            '/Ac/ActiveIn/Source': {
                'gettext': '%s'
            },
            '/VebusService': {
                'gettext': '%s'
            }
        }

        for path in self._summeditems.keys():
            self._dbusservice.add_path(path,
                                       value=None,
                                       gettextcallback=self._gettext)

        self._batteryservice = None
        self._determinebatteryservice()

        self._supervised = {}
        self._lg_battery = None

        if self._batteryservice is None:
            logger.info("Battery service initialized to None (setting == %s)" %
                        self._settings['batteryservice'])

        self._changed = True
        for service, instance in self._dbusmonitor.get_service_list().items():
            self._device_added(service, instance, do_service_change=False)

        self._handleservicechange()
        self._updatevalues()
        try:
            self._relay_file_read = open(relayGpioFile, 'rt')
            self._relay_file_write = open(relayGpioFile, 'wt')
            self._update_relay_state()
            gobject.timeout_add(5000, exit_on_error, self._update_relay_state)
        except IOError:
            self._relay_file_read = None
            self._relay_file_write = None
            logging.warn('Could not open %s (relay)' % relayGpioFile)

        self._writeVebusSocCounter = 9
        gobject.timeout_add(1000, exit_on_error, self._handletimertick)
        gobject.timeout_add(60000, exit_on_error, self._process_supervised)