def main(): if config is None: print("COULD NOT DETECT CONFIG FILE") return home = Home() home.set_auth_token(config.auth_token) home.init(config.access_point) print("Downloading configuration") home.get_current_state() if not os.path.exists("./img/"): os.makedirs("./img/") print("Generating QRCodes") for d in home.devices: img = qrcode.make(d.id) img.save("./img/{}.png".format(d.id)) print("Creating website") templatePath = os.path.join(os.path.dirname(__file__), 'qrcodes_template.html') template = None tableText = "" with open(templatePath, "r") as t: template = t.read() for g in home.groups: if not isinstance(g, MetaGroup): continue; for d in g.devices: tableText = tableText + "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td><img src=\"img/{}.png\"></td></tr>\n".format(g.label, d.label, d.id, d.modelType, d.id) result = template.replace("##QRROWS##", tableText) with codecs.open("qrcodes.html", "w", "UTF-8") as f: f.write(result) print("Finished")
class HomematicIpSource(Source): """ Collects sensor data from homematic IP. Requires pip install homematicip. See https://homematicip-rest-api.readthedocs.io/en/latest/gettingstarted.html#installation for more details """ def __init__(self, config): super().__init__(config) self._auth_token = config['authToken'] self._access_point = config['accessPoint'] self._home = None def setup(self, global_conf): super().setup(global_conf) self._home = Home() self._home.set_auth_token(self._auth_token) self._home.init(self._access_point) def _probe(self) -> Optional[ValueSet] or List[ValueSet]: values = ValueSet(labels=['room']) self._home.get_current_state() for group in self._home.groups: if group.groupType != 'META': continue room_name = self._escape_labels(group.label) for device in group.devices: if isinstance(device, TemperatureHumiditySensorDisplay): # device.lastStatusUpdate temp_target = device.setPointTemperature temp = device.actualTemperature humidity = device.humidity values.add( Value(temp_target, label_values=[room_name], name='temperature_target')) values.add( Value(temp, label_values=[room_name], name='temperature')) values.add( Value(humidity, label_values=[room_name], name='humidity')) return values @staticmethod def _escape_labels(label: str) -> str: label = label.lower().replace('ä', 'ae') \ .replace('ü', 'ue') \ .replace('ö', 'oe') \ .replace(' ', '_') return label
def setup(hass, config): """Set up the HomematicIP component.""" # pylint: disable=import-error, no-name-in-module from homematicip.home import Home hass.data.setdefault(DOMAIN, {}) homes = hass.data[DOMAIN] accesspoints = config.get(DOMAIN, []) def _update_event(events): """Handle incoming HomeMaticIP events.""" for event in events: etype = event['eventType'] edata = event['data'] if etype == 'DEVICE_CHANGED': dispatcher_send(hass, EVENT_DEVICE_CHANGED, edata.id) elif etype == 'GROUP_CHANGED': dispatcher_send(hass, EVENT_GROUP_CHANGED, edata.id) elif etype == 'HOME_CHANGED': dispatcher_send(hass, EVENT_HOME_CHANGED, edata.id) elif etype == 'JOURNAL_CHANGED': dispatcher_send(hass, EVENT_SECURITY_CHANGED, edata.id) return True for device in accesspoints: name = device.get(CONF_NAME) accesspoint = device.get(CONF_ACCESSPOINT) authtoken = device.get(CONF_AUTHTOKEN) home = Home() if name.lower() == 'none': name = '' home.label = name try: home.set_auth_token(authtoken) home.init(accesspoint) if home.get_current_state(): _LOGGER.info("Connection to HMIP established") else: _LOGGER.warning("Connection to HMIP could not be established") return False except timeout: _LOGGER.warning("Connection to HMIP could not be established") return False homes[home.id] = home home.onEvent += _update_event home.enable_events() _LOGGER.info('HUB name: %s, id: %s', home.label, home.id) for component in ['sensor']: load_platform(hass, component, DOMAIN, {'homeid': home.id}, config) return True
def main(): if config is None: print("COULD NOT DETECT CONFIG FILE") return home = Home() home.set_auth_token(config.auth_token) home.init(config.access_point) home.get_current_state() print("current AP Version: {}".format(home.currentAPVersion))
def fake_home(fake_cloud): home = Home() with no_ssl_verification(): lookup_url = "{}/getHost".format(fake_cloud.url) # home.download_configuration = fake_home_download_configuration home._connection = Connection() home._fake_cloud = fake_cloud home.set_auth_token( "8A45BAA53BE37E3FCA58E9976EFA4C497DAFE55DB997DB9FD685236E5E63ED7DE" ) home._connection.init(accesspoint_id="3014F711A000000BAD0C0DED", lookup_url=lookup_url) home.get_current_state() return home
def init(c=[]): global config global metrics global h config = c h = Home() h.set_auth_token(config["authtoken"]) h.init(config["accesspointid"]) metrics = {} metrics['heating'] = {} metrics['heating']['setPointTemperature'] = Gauge( 'homematicip_heating_setpointtemperature_celsius', 'Homematic IP setpoint temperature of a room', ['id', 'room']) metrics['heating']['actualTemperature'] = Gauge( 'homematicip_heating_actualtemperature_celsius', 'Homematic IP actual temperature of a room', ['id', 'room']) metrics['heating']['boostmode'] = Gauge( 'homematicip_heating_boostmode', 'Homematic IP wether boost mode is on or off', ['id', 'room']) metrics['heating']['ecomode'] = Gauge( 'homematicip_heating_ecomode', 'Homematic IP wether eco mode is on or off', ['id', 'room']) metrics['heating']['partymode'] = Gauge( 'homematicip_heating_partymode', 'Homematic IP wether party mode is on or off', ['id', 'room']) metrics['heating']['humidity'] = Gauge( 'homematicip_heating_humidity_percent', 'Homematic IP current relative humidity in percent', ['id', 'room']) metrics['heating']['lowbattery'] = Gauge( 'homematicip_heating_lowbattery', 'Homematic IP wether the battery is low or not', ['id', 'name', 'room', 'devicetype', 'modeltype']) metrics['heating']['reachable'] = Gauge( 'homematicip_heating_reachable', 'Homematic IP wether the device is reachable or not', ['id', 'name', 'room', 'devicetype', 'modeltype']) metrics['heating']['valveposition'] = Gauge( 'homematicip_heating_valveposition', 'Homematic IP position of the valve', ['id', 'name', 'room', 'modeltype']) metrics['heating']['windowState'] = Gauge( 'homematicip_heating_windowstate', 'Homematic IP wether the window is open or closed', ['id', 'name', 'room', 'modeltype'])
def main(): config = homematicip.find_and_load_config_file() home = Home() home.set_auth_token(config.auth_token) home.init(config.access_point) c = lambda: None c.__dict__ = config.raw_config['TB'] tb = ThingsboardConnection(c) home.get_current_state() for g in home.groups: if g.groupType == "META": for d in g.devices: try: x = tb.getOrCreateDevice(g, d) x.updateTelemetryFromHmIP(g, d) except: print("Error updating telemetry from '%s' (%s)" % (d.label, d.id))
def main(): if config is None: print("COULD NOT DETECT CONFIG FILE") return home = Home() home.set_auth_token(config.auth_token) home.init(config.access_point) if not home.get_current_state(): return for ip in SCANABLE_DEVICES: try: res = ping3.ping(ip) if res != None: if DEACTIVATE_ON_PRESENCE: for g in home.groups: if isinstance(g, homematicip.group.SecurityZoneGroup ) and g.active: print( "someone is at home. Deactivating security zones" ) home.set_security_zones_activation(False, False) return print( "someone is at home and security zones are deactivated -> do nothing" ) else: print("someone is at home -> do nothing") return except gaierror: print("could not resolve {}. Marking it as \"not at home\"".format( ip)) print("Noone is home -> activating security zones") home.set_security_zones_activation(ACTIVATE_INTERNAL_ZONE, ACTIVATE_EXTERNAL_ZONE)
class Exporter(object): """ Prometheus Exporter for Homematic IP devices """ def __init__(self, args): """ initializes the exporter :param args: the argparse.Args """ self.__home_client = None self.__metric_port = int(args.metric_port) self.__collect_interval_seconds = args.collect_interval_seconds self.__log_level = int(args.log_level) logging.info( "using config file '{}' and exposing metrics on port '{}'".format( args.config_file, self.__metric_port)) self.__init_client(args.config_file, args.auth_token, args.access_point, args.enable_event_metrics) self.__init_metrics() self.__collect_homematicip_info() try: prometheus_client.start_http_server(self.__metric_port) except Exception as e: logging.fatal( "starting the http server on port '{}' failed with: {}".format( self.__metric_port, str(e))) sys.exit(1) def __init_client(self, config_file, auth_token, access_point, enable_event_metrics): if auth_token and access_point: config = homematicip.HmipConfig( auth_token=auth_token, access_point=access_point, log_level=self.__log_level, log_file='hmip.log', raw_config=None, ) else: config = homematicip.load_config_file(config_file=config_file) try: self.__home_client = Home() self.__home_client.set_auth_token(config.auth_token) self.__home_client.init(config.access_point) # metrics on events if enable_event_metrics: self.__home_client.onEvent += self.__collect_event_metrics self.__home_client.enable_events() except Exception as e: logging.fatal( "Initializing HomematicIP client failed with: {}".format( str(e))) sys.exit(1) def __init_metrics(self): namespace = 'homematicip' labelnames = ['room', 'device_label'] detail_labelnames = [ 'device_type', 'firmware_version', 'permanently_reachable' ] event_device_labelnames = ['device_label'] event_group_labelnames = ['group_label'] event_labelnames = ['type', 'window_state', 'sabotage'] self.version_info = prometheus_client.Gauge( name='version_info', documentation='HomematicIP info', labelnames=['api_version'], namespace=namespace) self.metric_temperature_actual = prometheus_client.Gauge( name='temperature_actual', documentation='Actual temperature', labelnames=labelnames, namespace=namespace) self.metric_temperature_setpoint = prometheus_client.Gauge( name='temperature_setpoint', documentation='Set point temperature', labelnames=labelnames, namespace=namespace) self.metric_valve_adaption_needed = prometheus_client.Gauge( name='valve_adaption_needed', documentation='must the adaption re-run?', labelnames=labelnames, namespace=namespace) self.metric_temperature_offset = prometheus_client.Gauge( name='temperature_offset', documentation='the offset temperature for the thermostat', labelnames=labelnames, namespace=namespace) self.metric_valve_position = prometheus_client.Gauge( name='valve_position', documentation= 'the current position of the valve 0.0 = closed, 1.0 max opened', labelnames=labelnames, namespace=namespace) self.metric_humidity_actual = prometheus_client.Gauge( name='humidity_actual', documentation='Actual Humidity', labelnames=labelnames, namespace=namespace) self.metric_last_status_update = prometheus_client.Gauge( name='last_status_update', documentation="Device last status update", labelnames=labelnames, namespace=namespace) self.metric_device_info = prometheus_client.Gauge( name='device_info', documentation='Device information', labelnames=labelnames + detail_labelnames, namespace=namespace) self.metric_power_consumption = prometheus_client.Gauge( name='power_consumption', documentation='Power consumption', labelnames=labelnames, namespace=namespace) self.metric_device_event = prometheus_client.Counter( name='device_event', documentation='events triggered by a device', labelnames=event_device_labelnames + event_labelnames, namespace=namespace) self.metric_group_event = prometheus_client.Counter( name='group_event', documentation='events triggered by a group', labelnames=event_group_labelnames + event_labelnames, namespace=namespace, ) def __collect_homematicip_info(self): try: self.version_info.labels( api_version=self.__home_client.currentAPVersion).set(1) logging.debug("current homematic ip api version: '{}'".format( self.__home_client.currentAPVersion)) except Exception as e: logging.warning("collecting version info failed with: {}".format( str(e))) def __collect_thermostat_metrics(self, room, device): if device.actualTemperature: self.metric_temperature_actual.labels( room=room, device_label=device.label).set(device.actualTemperature) if device.setPointTemperature: self.metric_temperature_setpoint.labels( room=room, device_label=device.label).set(device.setPointTemperature) if device.humidity: self.metric_humidity_actual.labels(room=room, device_label=device.label).set( device.humidity) logging.info( "room: {}, label: {}, temperature_actual: {}, temperature_setpoint: {}, humidity_actual: {}" .format(room, device.label, device.actualTemperature, device.setPointTemperature, device.humidity)) def __collect_heating_metrics(self, room, device): # Do not check with if as 0 equals false self.metric_temperature_actual.labels( room=room, device_label=device.label).set(device.valveActualTemperature) self.metric_temperature_setpoint.labels(room=room, device_label=device.label).set( device.setPointTemperature) self.metric_valve_adaption_needed.labels( room=room, device_label=device.label).set(device.automaticValveAdaptionNeeded) self.metric_temperature_offset.labels(room=room, device_label=device.label).set( device.temperatureOffset) self.metric_valve_position.labels( room=room, device_label=device.label).set(device.valvePosition) logging.info( "room: {}, label: {}, temperature_actual: {}, temperature_setpoint: {}, valve_adaption_needed: {}, " "temperature_offset {}, valve_position: {}".format( room, device.label, device.valveActualTemperature, device.setPointTemperature, device.automaticValveAdaptionNeeded, device.temperatureOffset, device.valvePosition)) def __collect_device_info_metrics(self, room, device): logging.info( "found device: room: {}, label: {}, device_type: {}, firmware_version: {}, last_status_update: {}, permanently_reachable: {}" .format(room, device.label, device.deviceType.lower(), device.firmwareVersion, device.lastStatusUpdate, device.permanentlyReachable)) # general device info metric self.metric_device_info.labels( room=room, device_label=device.label, device_type=device.deviceType.lower(), firmware_version=device.firmwareVersion, permanently_reachable=device.permanentlyReachable).set(1) if device.lastStatusUpdate: # last status update metric self.metric_last_status_update.labels( room=room, device_label=device.label).set( device.lastStatusUpdate.timestamp()) def __collect_power_metrics(self, room, device): logging.info( "found device: room: {}, label: {}, device_type: {}, firmware_version: {}, last_status_update: {}, permanently_reachable: {}" .format(room, device.label, device.deviceType.lower(), device.firmwareVersion, device.lastStatusUpdate, device.permanentlyReachable)) # general device info metric logging.info(device.currentPowerConsumption) self.metric_power_consumption.labels( room=room, device_label=device.label).set(device.currentPowerConsumption) def __collect_event_metrics(self, eventList): for event in eventList: type = event["eventType"] data = event["data"] if type is EventType.DEVICE_CHANGED: _window_state = _sabotage = None if isinstance(data, ShutterContact): _window_state = str(data.windowState).lower() _sabotage = str(data.sabotage).lower() self.metric_device_event.labels(device_label=data.label, type=str(type).lower(), window_state=_window_state, sabotage=_sabotage).inc() logging.info( "got device event type: {}, label: {}, window_state: {}, sabotage: {}" .format(type, data.label, _window_state, _sabotage)) def collect(self): """ collect discovers all devices and generates metrics """ try: self.__home_client.get_current_state() for g in self.__home_client.groups: if g.groupType == "META": for d in g.devices: # collect general device metrics self.__collect_device_info_metrics(g.label, d) # collect temperature, humidity if isinstance(d, (WallMountedThermostatPro, TemperatureHumiditySensorDisplay, TemperatureHumiditySensorWithoutDisplay, TemperatureHumiditySensorOutdoor)): self.__collect_thermostat_metrics(g.label, d) elif isinstance(d, HeatingThermostat): logging.info("Device of type heating") self.__collect_heating_metrics(g.label, d) elif isinstance(d, PlugableSwitchMeasuring): logging.info( "Device of type PlugableSwitchMeasuring") self.__collect_power_metrics(g.label, d) except Exception as e: logging.warning( "collecting status from device(s) failed with: {1}".format( str(e))) finally: logging.info('waiting {}s before next collection cycle'.format( self.__collect_interval_seconds)) time.sleep(self.__collect_interval_seconds)
def main(): parser = ArgumentParser( description="a cli wrapper for the homematicip API") parser.add_argument( "--config_file", type=str, help= "the configuration file. If nothing is specified the script will search for it." ) parser.add_argument( "--debug-level", dest="debug_level", type=int, help="the debug level which should get used(Critical=50, DEBUG=10)") group = parser.add_argument_group("Display Configuration") group.add_argument("--dump-configuration", action="store_true", dest="dump_config", help="dumps the current configuration from the AP") group.add_argument("--list-devices", action="store_true", dest="list_devices", help="list all devices") group.add_argument("--list-groups", action="store_true", dest="list_groups", help="list all groups") group.add_argument("--list-group-ids", action="store_true", dest="list_group_ids", help="list all groups and their ids") group.add_argument("--list-firmware", action="store_true", dest="list_firmware", help="list the firmware of all devices") group.add_argument("--list-rssi", action="store_true", dest="list_rssi", help="list the reception quality of all devices") group.add_argument("--list-events", action="store_true", dest="list_events", help="prints all the events") group.add_argument("--list-last-status-update", action="store_true", dest="list_last_status_update", help="prints the last status update of all systems") parser.add_argument("--list-security-journal", action="store_true", dest="list_security_journal", help="display the security journal") parser.add_argument("--list-rules", action="store_true", dest="list_rules", help="display all automation rules") parser.add_argument( "-d", "--device", dest="device", action='append', help= "the device you want to modify (see \"Device Settings\").\nYou can use * to modify all devices or enter the parameter multiple times to modify more devices" ) parser.add_argument( "-g", "--group", dest="group", help="the group you want to modify (see \"Group Settings\")") group = parser.add_argument_group("Device Settings") group.add_argument("--turn-on", action="store_true", dest="device_switch_state", help="turn the switch on", default=None) group.add_argument("--set-dimmer", action="store", dest="set_dimmer", help="turn the switch on", default=None) group.add_argument("--turn-off", action="store_false", dest="device_switch_state", help="turn the switch off", default=None) group.add_argument("--set-shutter-level", action="store", dest="device_shutter_level", help="set shutter to level (0..1)") group.add_argument("--set-shutter-stop", action="store_true", dest="device_shutter_stop", help="stop shutter", default=None) group.add_argument("--set-label", dest="device_new_label", help="set a new label") group.add_argument("--set-display", dest="device_display", action="store", help="set the display mode", choices=["actual", "setpoint", "actual_humidity"]) group.add_argument("--enable-router-module", action="store_true", dest="device_enable_router_module", help="enables the router module of the device", default=None) group.add_argument("--disable-router-module", action="store_false", dest="device_enable_router_module", help="disables the router module of the device", default=None) group = parser.add_argument_group("Home Settings") group.add_argument("--set-protection-mode", dest="protectionmode", action="store", help="set the protection mode", choices=["presence", "absence", "disable"]) group.add_argument("--set-pin", dest="new_pin", action="store", help="set a new pin") group.add_argument("--delete-pin", dest="delete_pin", action="store_true", help="deletes the pin") group.add_argument( "--old-pin", dest="old_pin", action="store", help="the current pin. used together with --set-pin or --delete-pin", default=None) group.add_argument("--set-zones-device-assignment", dest="set_zones_device_assignment", action="store_true", help="sets the zones devices assignment") group.add_argument("--external-devices", dest="external_devices", nargs='+', help="sets the devices for the external zone") group.add_argument("--internal-devices", dest="internal_devices", nargs='+', help="sets the devices for the internal zone") group.add_argument("--activate-absence", dest="activate_absence", action="store", help="activates absence for provided amount of minutes", default=None, type=int) group.add_argument("--deactivate-absence", action="store_true", dest="deactivate_absence", help="deactivates absence") group = parser.add_argument_group("Group Settings") group.add_argument("--list-profiles", dest="group_list_profiles", action="store_true", help="displays all profiles for a group") group.add_argument( "--activate-profile", dest="group_activate_profile", help="activates a profile by using its index or its name") group.add_argument("--set-group-shutter-level", action="store", dest="group_shutter_level", help="set all shutters in group to level (0..1)") group.add_argument("--set-group-shutter-stop", action="store_true", dest="group_shutter_stop", help="stop all shutters in group", default=None) group.add_argument( "--set-point-temperature", action="store", dest="group_set_point_temperature", help= "sets the temperature for the given group. The group must be of the type \"HEATING\"", default=None, type=float) group.add_argument("--set-boost", action="store_true", dest="group_boost", help="activates the boost mode for a HEATING group", default=None) group.add_argument("--set-boost-stop", action="store_false", dest="group_boost", help="deactivates the boost mode for a HEATING group", default=None) if len(sys.argv) == 1: parser.print_help() return try: args = parser.parse_args() except: print('could not parse arguments') parser.print_help() return _config = None if args.config_file: try: _config = homematicip.load_config_file(args.config_file) except FileNotFoundError: print("##### CONFIG FILE NOT FOUND: {} #####".format( args.config_file)) return else: convert_config2ini() _config = homematicip.find_and_load_config_file() if _config is None: print("Could not find configuration file. Script will exit") return global logger logger = create_logger( args.debug_level if args.debug_level else _config.log_level, _config.log_file) home = Home() home.set_auth_token(_config.auth_token) home.init(_config.access_point) if not home.get_current_state(): return command_entered = False if args.dump_config: command_entered = True json_state = home.download_configuration() if "errorCode" in json_state: logger.error( "Could not get the current configuration. Error: {}".format( json_state["errorCode"])) else: print(json.dumps(json_state, indent=4, sort_keys=True)) if args.list_devices: command_entered = True sortedDevices = sorted(home.devices, key=attrgetter('deviceType', 'label')) for d in sortedDevices: print(u'{} {}'.format(d.id, str(d))) if args.list_groups: command_entered = True sortedGroups = sorted(home.groups, key=attrgetter('groupType', 'label')) for g in sortedGroups: print(str(g)) if args.list_last_status_update: command_entered = True print(u'Devices:') sortedDevices = sorted(home.devices, key=attrgetter('deviceType', 'label')) for d in sortedDevices: print(u'\t{}\t{}\t{}'.format(d.id, d.label, d.lastStatusUpdate)) print(u'Groups:') sortedGroups = sorted(home.groups, key=attrgetter('groupType', 'label')) for g in sortedGroups: print(u'\t{}\t{}\t{}'.format(g.groupType, g.label, g.lastStatusUpdate)) if args.list_group_ids: command_entered = True sortedGroups = sorted(home.groups, key=attrgetter('groupType', 'label')) for g in sortedGroups: print("Id: {} - Type: {} - Label: {}".format( g.id, g.groupType, g.label)) if args.protectionmode: command_entered = True if args.protectionmode == "presence": home.set_security_zones_activation(False, True) elif args.protectionmode == "absence": home.set_security_zones_activation(True, True) elif args.protectionmode == "disable": home.set_security_zones_activation(False, False) if args.new_pin: command_entered = True home.set_pin(args.new_pin, args.old_pin) if args.delete_pin: command_entered = True home.set_pin(None, args.old_pin) if args.list_security_journal: command_entered = True journal = home.get_security_journal() for entry in journal: print(str(entry)) if args.list_firmware: command_entered = True print( str("{:45s} - Firmware: {:6} - Available Firmware: {:6} UpdateState: {}" .format( "HmIP AccessPoint", home.currentAPVersion if home.currentAPVersion is not None else "None", home.availableAPVersion if home.availableAPVersion is not None else "None", home.updateState))) sortedDevices = sorted(home.devices, key=attrgetter('deviceType', 'label')) for d in sortedDevices: print( str("{:45s} - Firmware: {:6} - Available Firmware: {:6} UpdateState: {}" .format( d.label, d.firmwareVersion, d.availableFirmwareVersion if d.availableFirmwareVersion is not None else "None", d.updateState))) if args.list_rssi: command_entered = True print( str("{:45s} - Duty cycle: {:2}".format( "HmIP AccessPoint", home.dutyCycle if home.dutyCycle is not None else "None"))) sortedDevices = sorted(home.devices, key=attrgetter('deviceType', 'label')) for d in sortedDevices: print( str("{:45s} - RSSI: {:4} {} - Peer RSSI: {:4} - {} {}".format( d.label, d.rssiDeviceValue if d.rssiDeviceValue is not None else "None", getRssiBarString(d.rssiDeviceValue), d.rssiPeerValue if d.rssiPeerValue is not None else "None", getRssiBarString(d.rssiPeerValue), "Unreachable" if d.unreach else ""))) if args.list_rules: command_entered = True sortedRules = sorted(home.rules, key=attrgetter('ruleType', 'label')) for d in sortedRules: print(u'{} {}'.format(d.id, str(d))) if args.device: command_entered = False devices = [] for argdevice in args.device: if argdevice == '*': devices = home.devices break else: d = home.search_device_by_id(argdevice) if d == None: logger.error("Could not find device {}".format(argdevice)) else: devices.append(d) for device in devices: if args.device_new_label: device.set_label(args.device_new_label) command_entered = True if args.device_switch_state != None: if isinstance(device, PlugableSwitch): device.set_switch_state(args.device_switch_state) command_entered = True else: logger.error( "can't turn on/off device {} of type {}".format( device.id, device.deviceType)) if args.set_dimmer is not None: if isinstance(device, BrandDimmer): device.set_dim_level(args.set_dimmer) command_entered = True else: logger.error("can't set device {} of type {}".format( device.id, device.deviceType)) if args.device_shutter_level is not None: if isinstance(device, FullFlushShutter): device.set_shutter_level(args.device_shutter_level) command_entered = True else: logger.error( "can't set shutter level of device {} of type {}". format(device.id, device.deviceType)) if args.device_shutter_stop is not None: if isinstance(device, FullFlushShutter): device.set_shutter_stop() command_entered = True else: logger.error( "can't stop shutter of device {} of type {}".format( device.id, device.deviceType)) if args.device_display != None: if isinstance(device, TemperatureHumiditySensorDisplay): device.set_display(args.device_display.upper()) command_entered = True else: logger.error( "can't set display of device {} of type {}".format( device.id, device.deviceType)) if args.device_enable_router_module != None: if device.routerModuleSupported: device.set_router_module_enabled( args.device_enable_router_module) print("{} the router module for device {}".format( "Enabled" if args.device_enable_router_module else "Disabled", device.id)) command_entered = True else: logger.error( "the device {} doesn't support the router module". format(device.id)) if args.set_zones_device_assignment: internal = [] external = [] error = False command_entered = True for id in args.external_devices: d = home.search_device_by_id(id) if d == None: logger.error( "Device {} is not registered on this Access Point".format( id)) error = True else: external.append(d) for id in args.internal_devices: d = home.search_device_by_id(id) if d == None: logger.error( "Device {} is not registered on this Access Point".format( id)) error = True else: internal.append(d) if not error: home.set_zones_device_assignment(internal, external) if args.activate_absence: command_entered = True home.activate_absence_with_duration(args.activate_absence) if args.deactivate_absence: command_entered = True home.deactivate_absence() if args.group: command_entered = False group = None for g in home.groups: if g.id == args.group: group = g break if group == None: logger.error("Could not find group {}".format(args.group)) return if args.group_list_profiles: command_entered = True for p in group.profiles: isActive = p.id == group.activeProfile.id print("Index: {} - Id: {} - Name: {} - Active: {}".format( p.index, p.id, p.name, isActive)) if args.group_shutter_level: command_entered = True group.set_shutter_level(args.group_shutter_level) if args.group_shutter_stop: command_entered = True group.set_shutter_stop() if args.group_set_point_temperature: command_entered = True if isinstance(group, HeatingGroup): group.set_point_temperature(args.group_set_point_temperature) else: logger.error("Group {} isn't a HEATING group".format(g.id)) if args.group_activate_profile: command_entered = True if isinstance(group, HeatingGroup): index = args.group_activate_profile for p in group.profiles: if p.name == args.group_activate_profile: index = p.index break group.set_active_profile(index) else: logger.error("Group {} isn't a HEATING group".format(g.id)) if args.group_boost is not None: command_entered = True if isinstance(group, HeatingGroup): group.set_boost(args.group_boost) else: logger.error("Group {} isn't a HEATING group".format(g.id)) if args.list_events: command_entered = True home.onEvent += printEvents home.enable_events() try: while True: time.sleep(1) except KeyboardInterrupt: return if not command_entered: parser.print_help()
def main(): _config = homematicip.find_and_load_config_file() if _config is None: print("Could not find configuration file. Script will exit") return global logger logger = create_logger(_config.log_level, _config.log_file) home = Home() home.set_auth_token(_config.auth_token) home.init(_config.access_point) locale.setlocale(locale.LC_ALL, '') if not home.get_current_state(): print("home.get_current_state()={}".format(home.get_current_state())) return sortedGroups = sorted(home.groups, key=attrgetter("groupType", "label")) for g in sortedGroups: # print(type(g).__name__ +" "+g.label+":") if (isinstance(g, HeatingGroup)): # first print Sensor print("HeatingGroup " + g.label + ":") sensorDevices = [] heatingThermostats = [] plugableSwitchMeasurings = [] for d in g.devices: if isinstance(d, TemperatureHumiditySensorWithoutDisplay): # https://homematicip-rest-api.readthedocs.io/en/latest/homematicip.html#homematicip.device.TemperatureHumiditySensorWithoutDisplay sensorDevices.append(d) elif isinstance(d, HeatingThermostat): heatingThermostats.append(d) elif isinstance(d, PlugableSwitchMeasuring): plugableSwitchMeasurings.append(d) if (len(heatingThermostats) > 0 or len(plugableSwitchMeasurings) > 0): fileName = g.label + ".csv" if os.path.isfile(fileName): f = open(fileName, "a+") else: f = open(fileName, "a+") f.write("date\tactual\thumidity") for d in heatingThermostats: f.write("\tset\tvalve") for d in plugableSwitchMeasurings: f.write("\tsum\tcurrent") f.write("\n") for d in sorted(sensorDevices): print(" humidity {} {} {}".format( d.label, locale.str(d.actualTemperature), locale.str(d.humidity))) f.write("{}\t{}\t{}".format( datetime.now(), locale.str(d.actualTemperature), locale.str(d.humidity))) # Then all HeatingThermostat for d in sorted(heatingThermostats): print(" valvePosition {} {} {}".format( d.label, locale.str(d.setPointTemperature), locale.str(d.valvePosition * 100))) f.write("\t{}\t{}".format( locale.str(d.setPointTemperature), locale.str(d.valvePosition * 100))) # Then all PlugableSwitchMeasuring for d in sorted(plugableSwitchMeasurings): if (d.energyCounter is None or d.currentPowerConsumption is None): print(d) else: print(" energy {} {} {}".format( d.label, locale.str(d.energyCounter), locale.str(d.currentPowerConsumption))) f.write("\t{}\t{}".format( locale.str(d.energyCounter), locale.str(d.currentPowerConsumption))) f.write("\n") f.close() # print all valve positions in one file sortedDevices = sorted(home.devices, key=attrgetter("deviceType", "label")) fileName = "valvePositions.csv" if os.path.isfile(fileName): f = open(fileName, "a+") else: f = open(fileName, "a+") f.write("date") for d in sortedDevices: if isinstance(d, HeatingThermostat): f.write("\t{}".format(d.label)) f.write("\n") f.write("{}".format(datetime.now())) for d in sortedDevices: if isinstance(d, HeatingThermostat): f.write("\t{}".format(locale.str(d.valvePosition * 100))) f.write("\n") f.close() # print all temperatures in one file sortedDevices = sorted(home.devices, key=attrgetter("deviceType", "label")) fileName = "temperatures.csv" if os.path.isfile(fileName): f = open(fileName, "a+") else: f = open(fileName, "a+") f.write("date") for d in sortedDevices: if isinstance(d, TemperatureHumiditySensorWithoutDisplay): f.write("\t{}\t".format(d.label)) f.write("\n") f.write("{}".format(datetime.now())) for d in sortedDevices: if isinstance(d, TemperatureHumiditySensorWithoutDisplay): f.write("\t{}\t{}".format(locale.str(d.actualTemperature), locale.str(d.humidity))) f.write("\n") f.close()
class HmipClient: def __init__(self): LOGGER.info("HmipClient initializing...") self.readConfig() self.setup() LOGGER.info("HmipClient initialized.") def readConfig(self): config = configparser.ConfigParser() config.read('config.ini') self.hmip_authtoken = config['HMIP_AUTH']['authtoken'] self.hmip_accesspoint = config['HMIP_AUTH']['accesspoint'] def on_update_handler(self, data, event_type, obj): if obj: data['api_name'] = obj.__class__.__name__ now = time.time() data['timestamp'] = now LOGGER.debug(datetime.fromtimestamp(now).strftime('%Y-%m-%d_%H-%M-%S')) LOGGER.debug(pprint.pformat(data)) label = data['label'].replace(" ", "_") obj_type = '' if obj: obj_type = obj.__class__.__name__ # sid = data['id']; self.publishHandler.handle(event_type, obj_type, label, data) # save the data. #_file_name = '{}_{}.json'.format(obj.__class__.__name__, # datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')) #_full_path = os.path.join('tests/json_data', _file_name) #with open(_full_path, 'w') as fl: # json.dump(data, fl, indent=4) async def get_async_home(self): LOGGER.info("get_async_home") self.async_home = AsyncHome(self.loop) LOGGER.debug("AuthToken=" + self.hmip_authtoken) LOGGER.debug("AccessPoint=" + self.hmip_accesspoint) self.async_home.set_auth_token(self.hmip_authtoken) await self.async_home.init(self.hmip_accesspoint) return self.async_home def get_home(self): self.home = Home() self.home.set_auth_token(self.hmip_authtoken) self.home.init(self.hmip_accesspoint) async def update_state(self): LOGGER.info("update_state " + str(self.async_home)) await self.async_home.get_current_state() LOGGER.info("update_start success") for d in self.async_home.devices: LOGGER.debug('{} {} {}'.format(d.id, d.label, str(d))) for g in self.async_home.groups: LOGGER.debug('{} {} {}'.format(g.id, g.label, str(g))) async def wait_for_ws_incoming(self): await self.async_home.get_current_state() for d in self.async_home.devices: d.on_update(self.on_update_handler) for d in self.async_home.groups: d.on_update(self.on_update_handler) reader = await self.async_home.enable_events() await reader def readConfiguration(self): self.home.get_current_state() LOGGER.debug("Devices:") for d in self.home.devices: LOGGER.debug(' {} {} {}'.format(d.id, d.label, str(d))) LOGGER.debug("Groups:") for g in self.home.groups: LOGGER.debug(' {} {} {}'.format(g.id, g.label, str(g))) LOGGER.debug("Profiles:") for g in self.home.groups: if hasattr(g, 'profiles'): LOGGER.debug(" Profiles for Group {}".format(g.label)) for p in g.profiles: p.get_details() LOGGER.debug( " name={} id={} groupId={} homeId={}".format( p.name, p.id, p.groupId, p.homeId)) for day in p.profileDays: for period in p.profileDays[day].periods: if isinstance(period, HeatingCoolingPeriod): LOGGER.debug( " HeatingCoolingPeriod: Day={} start={} end={} value={}" .format(day, period.starttime, period.endtime, period.value)) elif isinstance(period, TimeProfilePeriod): LOGGER.debug( " TimeProfilePeriod: Day={} hour={} minute={} dimLevel={}" .format(day, period.hour, period.minute, period.dimLevel)) # self.weekdays = [] # self.hour = 0 # self.minute = 0 # self.astroOffset = 0 # self.astroLimitationType = "NO_LIMITATION" # NOT_EARLIER_THAN_TIME, NOT_LATER_THAN_TIME # self.switchTimeMode = "REGULAR_SWITCH_TIME" # ASTRO_SUNRISE_SWITCH_TIME, ASTRO_SUNSET_SWITCH_TIME # self.dimLevel = 1.0 # self.rampTime = 0 else: LOGGER.debug( " Unknown: Day={} period={}".format( day, period)) # self.jsonConf = self.async_home.download_configuration() # LOGGER.debug("Configuration: \n{}".format(self.jsonConf)) def setup(self): self.loop = asyncio.get_event_loop() self.get_home() self.readConfiguration() self.async_home = None try: self.async_home = self.loop.run_until_complete( self.get_async_home()) # self.loop.run_until_complete(self.readConfiguration()) except HmipConnectionError: LOGGER.error("Problem connecting [get home]") if self.async_home: try: self.loop.run_until_complete(self.update_state()) except HmipConnectionError: LOGGER.error("Problem connecting [update state]") # loop.close() # self.doLoop(None) def doLoop(self, mqttClient): self.mqtt_client = mqttClient self.publishHandler = HmipPublishHandler(mqttClient) LOGGER.info("HomematicIp Loop Start") try: self.loop.run_until_complete(self.wait_for_ws_incoming()) except HmipConnectionError: LOGGER.error("Problem connecting [incoming]") except KeyboardInterrupt: self.loop.run_until_complete( self.async_home.close_websocket_connection()) print("HomematicIp Loop End")
# coding=utf-8 import os.path import config import homematicip from homematicip.home import Home home = Home() home.init(config.ACCESS_POINT) home.set_auth_token(config.AUTH_TOKEN) home.get_current_state() def write_shutter(device): if not os.path.isfile("shutter.csv"): with open("shutter.csv", "w", encoding='utf-8') as csv: csv.write("name;timestamp;open/close\n") with open("shutter.csv", "a", encoding='utf-8') as csv: csv.write("{};{};{}\n".format(device.id, str(device.lastStatusUpdate), d.windowState)) def write_heatingthermostat(device): if not os.path.isfile("heatingthermostat.csv"): with open("heatingthermostat.csv", "w", encoding='utf-8') as csv: csv.write("name;timestamp;valveposition\n") with open("heatingthermostat.csv", "a", encoding='utf-8') as csv: csv.write("{};{};{}\n".format(device.id, str(device.lastStatusUpdate), d.valvePosition))
import json import homematicip from flask import Flask from homematicip.home import Home config = homematicip.find_and_load_config_file() home = Home() home.set_auth_token(config.auth_token) home.init(config.access_point) app = Flask(__name__) def get_heating_thermostat_as_json(device): return device._rawJSONData @app.route('/homematic/devices') def homematic_devices(): home.get_current_state() response = [] for group in home.groups: room = {"room": group.label, "devices": []} if group.groupType == "META": for device in group.devices: room["devices"].append(get_heating_thermostat_as_json(device)) response.append(room) response = app.response_class(response=json.dumps(response),
def main(): pd.set_option('display.width', 200) parser = ArgumentParser( description="a cli wrapper for the homematicip API") parser.add_argument( "--config_file", type=str, help= "the configuration file. If nothing is specified the script will search for it.", ) parser.add_argument( "--interval", type=int, help= "the interval between two subsequent server requests for temperature data.", ) try: args = parser.parse_args() except SystemExit: return except: print("could not parse arguments") parser.print_help() return _config = None if args.config_file: try: _config = homematicip.load_config_file(args.config_file) except FileNotFoundError: print("##### CONFIG FILE NOT FOUND: {} #####".format( args.config_file)) return else: _config = homematicip.find_and_load_config_file() if _config is None: print("Could not find configuration file. Script will exit") return _interval = 10 if args.interval: _interval = args.interval print("Using the interval: " + str(_interval)) else: print("Using the default interval: " + str(_interval)) home = Home() home.set_auth_token(_config.auth_token) home.init(_config.access_point) if not home.get_current_state(): print("homematicip cannot get its current state.") return print("\n=== Homematicip Initialized ===\n") rooms_history = {} data = [] i = 0 # Check if the log file already exist if os.path.isfile(log_file): df = pd.read_csv(log_file) data = df.values.tolist() print(str(len(data)) + " rows have been loaded from " + log_file) print("") while True: sortedGroups = [ str(g) for g in sorted(home.groups, key=attrgetter("groupType", "label")) ] # Regex to extract (room name, target temperature, current temperature) regex = re.compile( r'HEATING (.*) window.*setPointTemperature\((\d+\.+\d*)\).*actualTemperature\((\d+\.+\d*)\)' ) rooms = list(filter(regex.search, sortedGroups)) # Add new measurement into the dictionary t = datetime.now().strftime("%Y-%m-%d %H:%M:%S") for r in rooms: data.append([ t, regex.search(r).group(1), regex.search(r).group(2), regex.search(r).group(3) ]) # Pandas Dataframe data_frame = pd.DataFrame(data, columns=[ "time", "room", "target_temperature", "current_temperature" ]) data_frame.to_csv(log_file, index=False) print("Temperature measurement index: " + str(i)) i = i + 1 # Read temperature data every _interval seconds time.sleep(_interval)
def main(): parser = ArgumentParser( description="a cli wrapper for the homematicip API") parser.add_argument( "--config_file", type=str, help= "the configuration file. If nothing is specified the script will search for it.", ) parser.add_argument( "--server-config", type=str, dest="server_config", help= "the server configuration file. e.g. output from --dump-configuration.", ) parser.add_argument( "--debug-level", dest="debug_level", type=int, help="the debug level which should get used(Critical=50, DEBUG=10)", ) parser.add_argument( "--version", action="version", version="%(prog)s {}".format(homematicip.__version__), ) group = parser.add_argument_group("Display Configuration") group.add_argument( "--dump-configuration", action="store_true", dest="dump_config", help="dumps the current configuration from the AP", ) group.add_argument( "--anonymize", action="store_true", dest="anonymize", help="used together with --dump-configuration to anonymize the output", ) group.add_argument( "--list-devices", action="store_true", dest="list_devices", help="list all devices", ) group.add_argument("--list-groups", action="store_true", dest="list_groups", help="list all groups") group.add_argument( "--list-group-ids", action="store_true", dest="list_group_ids", help="list all groups and their ids", ) group.add_argument( "--list-firmware", action="store_true", dest="list_firmware", help="list the firmware of all devices", ) group.add_argument( "--list-rssi", action="store_true", dest="list_rssi", help="list the reception quality of all devices", ) group.add_argument( "--list-events", action="store_true", dest="list_events", help="prints all the events", ) group.add_argument( "--list-last-status-update", action="store_true", dest="list_last_status_update", help="prints the last status update of all systems", ) parser.add_argument( "--list-security-journal", action="store_true", dest="list_security_journal", help="display the security journal", ) parser.add_argument( "--list-rules", action="store_true", dest="list_rules", help="display all automation rules", ) parser.add_argument( "-d", "--device", dest="device", action="append", help= 'the device you want to modify (see "Device Settings").\nYou can use * to modify all devices or enter the parameter multiple times to modify more devices', ) parser.add_argument( "-g", "--group", dest="group", help='the group you want to modify (see "Group Settings")', ) parser.add_argument( "-r", "--rule", dest="rules", action="append", help= 'the automation you want to modify (see "Automation Rule Settings").\nYou can use * to modify all automations or enter the parameter multiple times to modify more automations', ) group = parser.add_argument_group("Device Settings") group.add_argument( "--turn-on", action="store_true", dest="device_switch_state", help="turn the switch on", default=None, ) group.add_argument( "--turn-off", action="store_false", dest="device_switch_state", help="turn the switch off", default=None, ) group.add_argument( "--set-dim-level", action="store", dest="device_dim_level", help="set dimmer to level (0..1)", default=None, ) group.add_argument( "--set-shutter-level", action="store", dest="device_shutter_level", help="set shutter to level (0..1)", ) group.add_argument( "--set-shutter-stop", action="store_true", dest="device_shutter_stop", help="stop shutter", default=None, ) group.add_argument("--set-label", dest="device_new_label", help="set a new label") group.add_argument( "--set-display", dest="device_display", action="store", help="set the display mode", choices=["actual", "setpoint", "actual_humidity"], ) group.add_argument( "--enable-router-module", action="store_true", dest="device_enable_router_module", help="enables the router module of the device", default=None, ) group.add_argument( "--disable-router-module", action="store_false", dest="device_enable_router_module", help="disables the router module of the device", default=None, ) group.add_argument( "--reset-energy-counter", action="store_true", dest="reset_energy_counter", help="resets the energy counter", ) group = parser.add_argument_group("Home Settings") group.add_argument( "--set-protection-mode", dest="protectionmode", action="store", help="set the protection mode", choices=["presence", "absence", "disable"], ) group.add_argument("--set-pin", dest="new_pin", action="store", help="set a new pin") group.add_argument("--delete-pin", dest="delete_pin", action="store_true", help="deletes the pin") group.add_argument( "--old-pin", dest="old_pin", action="store", help="the current pin. used together with --set-pin or --delete-pin", default=None, ) group.add_argument( "--set-zones-device-assignment", dest="set_zones_device_assignment", action="store_true", help="sets the zones devices assignment", ) group.add_argument( "--external-devices", dest="external_devices", nargs="+", help="sets the devices for the external zone", ) group.add_argument( "--internal-devices", dest="internal_devices", nargs="+", help="sets the devices for the internal zone", ) group.add_argument( "--activate-absence", dest="activate_absence", action="store", help="activates absence for provided amount of minutes", default=None, type=int, ) group.add_argument( "--deactivate-absence", action="store_true", dest="deactivate_absence", help="deactivates absence", ) group.add_argument( "--start-inclusion", action="store", dest="inclusion_device_id", help="start inclusion for device with given id", ) group = parser.add_argument_group("Group Settings") group.add_argument( "--list-profiles", dest="group_list_profiles", action="store_true", help="displays all profiles for a group", ) group.add_argument( "--activate-profile", dest="group_activate_profile", help="activates a profile by using its index or its name", ) group.add_argument( "--set-group-shutter-level", action="store", dest="group_shutter_level", help="set all shutters in group to level (0..1)", ) group.add_argument( "--set-group-shutter-stop", action="store_true", dest="group_shutter_stop", help="stop all shutters in group", default=None, ) group.add_argument( "--set-point-temperature", action="store", dest="group_set_point_temperature", help= 'sets the temperature for the given group. The group must be of the type "HEATING"', default=None, type=float, ) group.add_argument( "--set-boost", action="store_true", dest="group_boost", help="activates the boost mode for a HEATING group", default=None, ) group.add_argument( "--set-boost-stop", action="store_false", dest="group_boost", help="deactivates the boost mode for a HEATING group", default=None, ) group.add_argument( "--set-boost-duration", dest="group_boost_duration", action="store", help="sets the boost duration for a HEATING group in minutes", default=None, type=int, ) group = parser.add_argument_group("Automation Rule Settings") group.add_argument( "--enable-rule", action="store_true", dest="rule_activation", help="activates the automation rules", default=None, ) group.add_argument( "--disable-rule", action="store_false", dest="rule_activation", help="deactivates the automation rules", default=None, ) if len(sys.argv) == 1: parser.print_help() return try: args = parser.parse_args() except SystemExit: return except: print("could not parse arguments") parser.print_help() return _config = None if args.config_file: try: _config = homematicip.load_config_file(args.config_file) except FileNotFoundError: print("##### CONFIG FILE NOT FOUND: {} #####".format( args.config_file)) return else: _config = homematicip.find_and_load_config_file() if _config is None: print("Could not find configuration file. Script will exit") return global logger logger = create_logger( args.debug_level if args.debug_level else _config.log_level, _config.log_file) home = Home() home.set_auth_token(_config.auth_token) home.init(_config.access_point) command_entered = False if args.server_config: global server_config server_config = args.server_config home.download_configuration = fake_download_configuration if args.dump_config: command_entered = True json_state = home.download_configuration() output = handle_config(json_state, args.anonymize) if output: print(output) if not home.get_current_state(): return if args.list_devices: command_entered = True sortedDevices = sorted(home.devices, key=attrgetter("deviceType", "label")) for d in sortedDevices: print("{} {}".format(d.id, str(d))) if args.list_groups: command_entered = True sortedGroups = sorted(home.groups, key=attrgetter("groupType", "label")) for g in sortedGroups: print(g) if args.list_last_status_update: command_entered = True print("Devices:") sortedDevices = sorted(home.devices, key=attrgetter("deviceType", "label")) for d in sortedDevices: print("\t{}\t{}\t{}".format(d.id, d.label, d.lastStatusUpdate)) print("Groups:") sortedGroups = sorted(home.groups, key=attrgetter("groupType", "label")) for g in sortedGroups: print("\t{}\t{}\t{}".format(g.groupType, g.label, g.lastStatusUpdate)) if args.list_group_ids: command_entered = True sortedGroups = sorted(home.groups, key=attrgetter("groupType", "label")) for g in sortedGroups: print("Id: {} - Type: {} - Label: {}".format( g.id, g.groupType, g.label)) if args.protectionmode: command_entered = True if args.protectionmode == "presence": home.set_security_zones_activation(False, True) elif args.protectionmode == "absence": home.set_security_zones_activation(True, True) elif args.protectionmode == "disable": home.set_security_zones_activation(False, False) if args.new_pin: command_entered = True home.set_pin(args.new_pin, args.old_pin) if args.delete_pin: command_entered = True home.set_pin(None, args.old_pin) if args.list_security_journal: command_entered = True journal = home.get_security_journal() for entry in journal: print(entry) if args.list_firmware: command_entered = True print( "{:45s} - Firmware: {:6} - Available Firmware: {:6} UpdateState: {}" .format( "HmIP AccessPoint", home.currentAPVersion if home.currentAPVersion is not None else "None", home.availableAPVersion if home.availableAPVersion is not None else "None", home.updateState, )) sortedDevices = sorted(home.devices, key=attrgetter("deviceType", "label")) for d in sortedDevices: print( "{:45s} - Firmware: {:6} - Available Firmware: {:6} UpdateState: {} LiveUpdateState: {}" .format( d.label, d.firmwareVersion, d.availableFirmwareVersion if d.availableFirmwareVersion is not None else "None", d.updateState, d.liveUpdateState, )) if args.list_rssi: command_entered = True print("{:45s} - Duty cycle: {:2}".format( "HmIP AccessPoint", home.dutyCycle if home.dutyCycle is not None else "None", )) sortedDevices = sorted(home.devices, key=attrgetter("deviceType", "label")) for d in sortedDevices: print( "{:45s} - RSSI: {:4} {} - Peer RSSI: {:4} - {} {} permanentlyReachable: {}" .format( d.label, d.rssiDeviceValue if d.rssiDeviceValue is not None else "None", getRssiBarString(d.rssiDeviceValue), d.rssiPeerValue if d.rssiPeerValue is not None else "None", getRssiBarString(d.rssiPeerValue), "Unreachable" if d.unreach else "", d.permanentlyReachable, )) if args.list_rules: command_entered = True sortedRules = sorted(home.rules, key=attrgetter("ruleType", "label")) for d in sortedRules: print("{} {}".format(d.id, str(d))) if args.device: command_entered = False devices = [] for argdevice in args.device: if argdevice == "*": devices = home.devices break else: d = home.search_device_by_id(argdevice) if d == None: logger.error("Could not find device %s", argdevice) else: devices.append(d) for device in devices: if args.device_new_label: device.set_label(args.device_new_label) command_entered = True if args.device_switch_state is not None: if isinstance(device, Switch): device.set_switch_state(args.device_switch_state) else: logger.error( "can't turn on/off device %s of type %s", device.id, device.deviceType, ) command_entered = True if args.device_dim_level is not None: if isinstance(device, Dimmer): device.set_dim_level(args.device_dim_level) else: logger.error( "can't set dim level of device %s of type %s", device.id, device.deviceType, ) command_entered = True if args.device_shutter_level is not None: if isinstance(device, FullFlushShutter): device.set_shutter_level(args.device_shutter_level) else: logger.error( "can't set shutter level of device %s of type %s", device.id, device.deviceType, ) command_entered = True if args.device_shutter_stop is not None: if isinstance(device, FullFlushShutter): device.set_shutter_stop() else: logger.error( "can't stop shutter of device %s of type %s", device.id, device.deviceType, ) command_entered = True if args.device_display is not None: if isinstance(device, TemperatureHumiditySensorDisplay): device.set_display( ClimateControlDisplay(args.device_display.upper())) else: logger.error( "can't set display of device %s of type %s", device.id, device.deviceType, ) command_entered = True if args.device_enable_router_module is not None: if device.routerModuleSupported: device.set_router_module_enabled( args.device_enable_router_module) print("{} the router module for device {}".format( "Enabled" if args.device_enable_router_module else "Disabled", device.id, )) else: logger.error( "the device %s doesn't support the router module", device.id) command_entered = True if args.reset_energy_counter: if isinstance(device, SwitchMeasuring): device.reset_energy_counter() print("reset energycounter {}".format(device.id)) else: logger.error( "can't reset energy counter for device %s of type %s", device.id, device.deviceType, ) command_entered = True if args.set_zones_device_assignment: internal = [] external = [] error = False command_entered = True for id in args.external_devices: d = home.search_device_by_id(id) if d == None: logger.error( "Device %s is not registered on this Access Point", id) error = True else: external.append(d) for id in args.internal_devices: d = home.search_device_by_id(id) if d == None: logger.error( "Device %s is not registered on this Access Point", id) error = True else: internal.append(d) if not error: home.set_zones_device_assignment(internal, external) if args.activate_absence: command_entered = True home.activate_absence_with_duration(args.activate_absence) if args.deactivate_absence: command_entered = True home.deactivate_absence() if args.inclusion_device_id: command_entered = True home.start_inclusion(args.inclusion_device_id) if args.group: command_entered = False group = None for g in home.groups: if g.id == args.group: group = g break if group == None: logger.error("Could not find group %s", args.group) return if args.group_list_profiles: command_entered = True for p in group.profiles: isActive = p.id == group.activeProfile.id print("Index: {} - Id: {} - Name: {} - Active: {}".format( p.index, p.id, p.name, isActive)) if args.group_shutter_level: command_entered = True group.set_shutter_level(args.group_shutter_level) if args.group_shutter_stop: command_entered = True group.set_shutter_stop() if args.group_set_point_temperature: command_entered = True if isinstance(group, HeatingGroup): group.set_point_temperature(args.group_set_point_temperature) else: logger.error("Group %s isn't a HEATING group", g.id) if args.group_activate_profile: command_entered = True if isinstance(group, HeatingGroup): index = args.group_activate_profile for p in group.profiles: if p.name == args.group_activate_profile: index = p.index break group.set_active_profile(index) else: logger.error("Group %s isn't a HEATING group", g.id) if args.group_boost is not None: command_entered = True if isinstance(group, HeatingGroup): group.set_boost(args.group_boost) else: logger.error("Group %s isn't a HEATING group", g.id) if args.group_boost_duration is not None: command_entered = True if isinstance(group, HeatingGroup): group.set_boost_duration(args.group_boost_duration) else: logger.error("Group %s isn't a HEATING group", g.id) if args.rules: command_entered = False rules = [] for argrule in args.rules: if argrule == "*": rules = home.rules break else: r = home.search_rule_by_id(argrule) if r == None: logger.error("Could not find automation rule %s", argrule) else: rules.append(r) for rule in rules: if args.rule_activation is not None: if isinstance(rule, SimpleRule): rule.set_rule_enabled_state(args.rule_activation) command_entered = True else: logger.error( "can't enable/disable rule %s of type %s", rule.id, rule.ruleType, ) if args.list_events: command_entered = True home.onEvent += printEvents home.enable_events() try: while True: time.sleep(1) except KeyboardInterrupt: return if not command_entered: parser.print_help()
class HmIP(object): def __init__(self): self.config = homematicip.load_config_file( config_file=path.join(app.instance_path, 'config.ini')) self.home = Home() self.home.set_auth_token(self.config.auth_token) self.home.init(self.config.access_point) def fetch_metrics(self): if not self.home.get_current_state(): self.home.init(self.config.access_point) self.home.get_current_state() for group in self.home.groups: if group.groupType == 'META': for device in group.devices: if isinstance(device, WallMountedThermostatPro): self.__collect_thermostat_metrics(group.label, device) elif isinstance(device, ShutterContact): self.__collect_shutter_metrics(group.label, device) elif isinstance(device, TemperatureHumiditySensorOutdoor): self.__collect_thermostat_outdoor_metrics( group.label, device) def __collect_shutter_metrics(self, room, device): rrd = path.join(app.instance_path, 'rrds', room, f'{device.label}.rrd') if not path.exists(rrd): makedirs(path.join(app.instance_path, 'rrds', room), mode=0o0750, exist_ok=True) rrdtool.create(rrd, '--start', 'now', '--step', '180', 'DS:state:GAUGE:540:0:1', 'RRA:AVERAGE:0.5:1:360000') app.logger.debug('room: {}, label: {}, windowState: {}'.format( room, device.label, device.windowState)) try: rrdtool.update( path.join(app.instance_path, 'rrds', room, f'{device.label}.rrd'), f'N: {self.__window_state(device.windowState)}') except rrdtool.OperationalError: app.logger.error('room: {}, label: {}, windowState: {}'.format( room, device.label, device.windowState)) @staticmethod def __collect_thermostat_metrics(room, device): rrd = path.join(app.instance_path, 'rrds', room, f'{device.label}.rrd') if not path.exists(rrd): makedirs(path.join(app.instance_path, 'rrds', room), mode=0o0750, exist_ok=True) rrdtool.create(rrd, '--start', 'now', '--step', '180', 'DS:actualtemperature:GAUGE:540:0:50', 'DS:settemperature:GAUGE:540:0:40', 'DS:humidity:GAUGE:540:0:100', 'DS:vapor:GAUGE:540:0:100', 'RRA:AVERAGE:0.5:1:360000') app.logger.debug( f'room: {room}, label: {device.label}, temperature_actual: {device.actualTemperature}, temperature_setpoint: ' f'{device.setPointTemperature}, humidity_actual: {device.humidity} vaporAmount: {device.vaporAmount}' ) try: rrdtool.update( path.join(app.instance_path, 'rrds', room, f'{device.label}.rrd'), f'N: {device.actualTemperature}:' f'{device.setPointTemperature}:' f'{device.humidity}:{device.vaporAmount}') except rrdtool.OperationalError: app.logger.error( f'room: {room}, label: {device.label}, temperature_actual: {device.actualTemperature}, temperature_setpoint: ' f'{device.setPointTemperature}, humidity_actual: {device.humidity} vaporAmount: {device.vaporAmount}' ) @staticmethod def __collect_thermostat_outdoor_metrics(room, device): rrd = path.join(app.instance_path, 'rrds', room, f'{device.label}.rrd') if not path.exists(rrd): makedirs(path.join(app.instance_path, 'rrds', room), mode=0o0750, exist_ok=True) rrdtool.create(rrd, '--start', 'now', '--step', '180', 'DS:actualtemperature:GAUGE:540:-20:55', 'DS:humidity:GAUGE:540:0:100', 'DS:vapor:GAUGE:540:0:100', 'RRA:AVERAGE:0.5:1:360000') app.logger.debug( f'room: {room}, label: {device.label}, temperature_actual: {device.actualTemperature}, humidity_actual: {device.humidity} ' f'vaporAmount: {device.vaporAmount}') try: rrdtool.update( path.join(app.instance_path, 'rrds', room, f'{device.label}.rrd'), f'N: {device.actualTemperature}:' f'{device.humidity}:{device.vaporAmount}') except rrdtool.OperationalError: app.logger.error( f'room: {room}, label: {device.label}, temperature_actual: {device.actualTemperature}, humidity_actual: {device.humidity} ' f'vaporAmount: {device.vaporAmount}') @staticmethod def __window_state(state): return 1 if state == 'OPEN' else 0 def convert_to_time_ms(self, timestamp): return 1000 * self.convert_to_time_s(timestamp) @staticmethod def convert_to_time_s(timestamp): return timegm( datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%fZ').timetuple()) def get_metric_names(self): ret = set() for group in self.home.groups: if group.groupType == 'META': for device in group.devices: if isinstance(device, WallMountedThermostatPro): ret.add('actualtemperature') ret.add('settemperature') ret.add('humidity') ret.add('vapor') elif isinstance(device, ShutterContact): ret.add('state') elif isinstance(device, TemperatureHumiditySensorOutdoor): ret.add('actualtemperature') ret.add('humidity') ret.add('vapor') return ret def get_metrics(self, start, end, resolution, metrics): ret = [] for root, dirs, files in walk(path.join(app.instance_path, 'rrds')): for file in files: if file.endswith('.rrd'): rrd = path.join(root, file) app.logger.debug(f'open rrd: {rrd}') fetch = rrdtool.fetch(rrd, 'AVERAGE', '--resolution', resolution, '--start', str(self.convert_to_time_s(start)), '--end', str(self.convert_to_time_s(end))) for num, name in enumerate(fetch[1]): if name in metrics: datapoints = [] ts = fetch[0][0] for dp in fetch[2]: datapoints.append([dp[num], ts * 1000]) ts += fetch[0][2] ret.append({ 'target': file.split('.')[0], 'datapoints': datapoints }) return ret