def _process_supervised(self): for service, method in self._supervised.items(): # Do an async call. If the owner of the service does not answer, we do not want to wait for # the timeout here. method.call_async(error_handler=lambda x: exit_on_error( self._supervise_failed, service, x)) return True
def set_sources(self, dbusmonitor, settings, dbusservice): SystemCalcDelegate.set_sources(self, dbusmonitor, settings, dbusservice) self._buzzer_on = False self._timer = None # Find GPIO buzzer gpio_paths = sc_utils.gpio_paths(BuzzerControl.GPIO_BUZZER_PATH) self._gpio_path = None if len(gpio_paths) > 0: self._gpio_path = os.path.join(gpio_paths[0], 'value') logging.info('GPIO buzzer found: {}'.format(self._gpio_path)) # Find PWM buzzer self._pwm_frequency = None try: pwm_frequency = sc_utils.gpio_paths(BuzzerControl.PWM_BUZZER_PATH) if len(pwm_frequency) > 0: self._pwm_frequency = int(pwm_frequency[0]) logging.info('PWM buzzer found @ frequency: {}'.format(self._pwm_frequency)) except ValueError: logging.error('Parsing of PWM buzzer settings at %s failed', BuzzerControl.PWM_BUZZER_PATH) if self._gpio_path == None and self._pwm_frequency == None: logging.info('No buzzer found') return self._dbusservice.add_path('/Buzzer/State', value=0, writeable=True, onchangecallback=lambda p,v: exit_on_error(self._on_buzzer_state_changed, v)) # Reset the buzzer so the buzzer state equals the D-Bus value. It will also silence the buzzer after # a restart of the service/system. self._set_buzzer(False)
def set_sources(self, dbusmonitor, settings, dbusservice): SystemCalcDelegate.set_sources(self, dbusmonitor, settings, dbusservice) # Find GPIO buzzer gpio_paths = sc_utils.gpio_paths(BuzzerControl.GPIO_BUZZER_PATH) if len(gpio_paths) > 0: self._gpio_path = os.path.join(gpio_paths[0], 'value') logging.info('GPIO buzzer found: {}'.format(self._gpio_path)) # Find PWM buzzer self._pwm_frequency = None try: pwm_frequency = sc_utils.gpio_paths(BuzzerControl.PWM_BUZZER_PATH) if len(pwm_frequency) > 0: self._pwm_frequency = int(pwm_frequency[0]) logging.info('PWM buzzer found @ frequency: {}'.format(self._pwm_frequency)) except ValueError: logging.error('Parsing of PWM buzzer settings at %s failed', BuzzerControl.PWM_BUZZER_PATH) if self._gpio_path is None and self._pwm_frequency is None: logging.info('No buzzer found') return self._dbusservice.add_path('/Buzzer/State', value=0, writeable=True, onchangecallback=lambda p, v: exit_on_error(self._on_buzzer_state_changed, v)) # Reset the buzzer so the buzzer state equals the D-Bus value. It will also silence the buzzer after # a restart of the service/system. self._set_buzzer(False)
def _on_socket_in(self, src, condition): exit_on_error(self._client.loop_read) return True
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)