async def run(self, broker: str, listen: str, connect: str) -> None: p = urlparse(broker, scheme="mqtt") if p.scheme not in ("mqtt", "mqtts") or not p.hostname: raise ValueError tls_context = None if p.scheme == "mqtts": tls_context = ssl.create_default_context() will = None async with Client( p.hostname, port=p.port or p.scheme == "mqtt" and 1883 or 8883, username=p.username, password=p.password, logger=logger, tls_context=tls_context, will=will, ) as mqtt: xmlrpc_local = self._xmlrpc_listen_url(listen) xmlrpc_remote = self._xmlrpc_connect_url(connect) homematic = HMConnection( interface_id=HM_INTERFACE_ID, local=xmlrpc_local.hostname, localport=xmlrpc_local.port or 0, remotes={ HM_REMOTE: { "ip": xmlrpc_remote.hostname, "port": xmlrpc_remote.port, "path": xmlrpc_remote.path or "", "username": xmlrpc_remote.username or "Admin", "password": xmlrpc_remote.password or "", } }, eventcallback=partial(self._event_callback, mqtt), systemcallback=partial(self._system_callback, mqtt), ) try: homematic.start() except AttributeError: sys.exit(1) async with mqtt.unfiltered_messages() as messages: async for message in messages: await self._process_packet(message, homematic) homematic.stop()
def test_0_pyhomematic_noinit(self): LOG.info("TestPyhomematicBase.test_0_pyhomematic_noinit") client = HMConnection(interface_id=DEFAULT_INTERFACE_CLIENT, autostart=False, remotes={ DEFAULT_REMOTE: { "ip": DEFAULT_IP, "port": self.localport, "connect": False } }) client.start() time.sleep(STARTUP_DELAY) servicemessages = client.getServiceMessages(DEFAULT_REMOTE) self.assertEqual(len(servicemessages), 1) self.assertEqual(servicemessages[0][0], 'VCU0000001:1') client.stop()
class Test_2_PyhomematicDevices(unittest.TestCase): def setUp(self): LOG.debug("TestPyhomematicDevices.setUp") s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(("", 0)) self.localport = s.getsockname()[1] s.close() self.vccu = vccu.ServerThread(local=DEFAULT_IP, localport=self.localport) self.vccu.start() time.sleep(0.5) self.client = HMConnection(interface_id=DEFAULT_INTERFACE_CLIENT, autostart=False, remotes={ DEFAULT_REMOTE: { "ip": DEFAULT_IP, "port": self.localport, "connect": True } }) self.client.start() time.sleep(STARTUP_DELAY) def tearDown(self): LOG.debug("TestPyhomematicDevices.tearDown") self.client.stop() self.vccu.stop() def test_0_pyhomematic_classes(self): LOG.info("TestPyhomematicDevices.test_0_pyhomematic_classes") devices = self.client.devices.get(DEFAULT_REMOTE) for _, deviceobject in devices.items(): deviceclass = devicetypes.SUPPORTED.get(deviceobject.TYPE, None) devicedata = DEVICES.get(deviceobject.TYPE, {}) if deviceclass: self.assertIsInstance(deviceobject, deviceclass) else: if not devicedata.get("supported", True): LOG.info("Unsupported device: %s" % deviceobject.TYPE) else: LOG.warning("Device class missing for: %s" % deviceobject.TYPE)
def test_1_pyhomematic_init(self): LOG.info("TestPyhomematicBase.test_1_pyhomematic_init") client = HMConnection(interface_id=DEFAULT_INTERFACE_CLIENT, autostart=False, remotes={ DEFAULT_REMOTE: { "ip": DEFAULT_IP, "port": self.localport, "connect": True } }) client.start() time.sleep(STARTUP_DELAY) servicemessages = client.getServiceMessages(DEFAULT_REMOTE) self.assertEqual(len(servicemessages), 1) self.assertEqual(servicemessages[0][0], 'VCU0000001:1') self.assertIsInstance(client.devices, dict) devices = client.devices.get(DEFAULT_REMOTE) self.assertIsInstance(devices, dict) self.assertGreater(len(devices.keys()), 0) client.stop()
def cli(local, localport, remote, remoteport, address, channel, state, toggle, timer, debug, user, password, variable, data): # debug? if debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) try: # Connect to HM pyhomematic = HMConnection(interface_id="testpyhomatic", local=local, localport=localport, remote=remote, remoteport=remoteport, autostart=True, rpcusername=user, rpcpassword=password, systemcallback=systemcallback) except Exception: print("Can't init HMConnection!") sys.exit(1) sleepcounter = 0 while not pyhomematic.devices and sleepcounter < 20: print("Waiting for devices") sleepcounter += 1 time.sleep(1) print(pyhomematic.devices) # read system variables print("******************************") print("Read all: %s" % str(pyhomematic.getAllSystemVariables('default'))) if variable is not None: pyhomematic.setSystemVariable(variable, data) print("Read: %s" % str(pyhomematic.getSystemVariable(variable))) print("******************************") # need test a hm object? if address in pyhomematic.devices: device = pyhomematic.devices[address] print("******************************") print("* Show metadata from %s" % address) print("* Elements: %s / Childs: %i" % (device.ELEMENT, len(device.CHANNELS))) print("* Class: %s" % str(device.__class__)) print("* Base: %s" % str(device.__class__.__bases__)) print("* Sensor datapoint: %s" % str(device.SENSORNODE)) print("* Binary datapoint: %s" % str(device.BINARYNODE)) print("* Write datapoint: %s" % str(device.WRITENODE)) print("* Attribute datapoint: %s" % str(device.ATTRIBUTENODE)) print("* Event datapoint: %s" % str(device.EVENTNODE)) print("* Action datapoint: %s" % str(device.ACTIONNODE)) print("******************************") # WeatherSensor if isinstance(device, WeatherSensor): print(" / Temperature: %f" % device.get_temperature()) print(" / Humidity: %i" % device.get_humidity()) print(" / Rain Counter: %f" % device.get_rain_counter()) print(" / Wind Speed: %f" % device.get_wind_speed()) print(" / Wind Direction: %i" % device.get_wind_direction()) print(" / Wind Direction Range: %i" % device.get_wind_direction_range()) print(" / Sunshineduration: %i" % device.get_sunshineduration()) print(" / Brightness: %i" % device.get_brightness()) print(" / Is Raining: %s" % str(device.is_raining())) # AreaThermostat if isinstance(device, AreaThermostat): print(" / Temperature: %f" % device.get_temperature()) print(" / Humidity: %i" % device.get_humidity()) # ShutterContact if isinstance(device, ShutterContact): print(" / Contact open: %s" % str(device.is_open())) # Smoke if isinstance(device, Smoke): print(" / Smoke detect: %s" % str(device.is_smoke())) # Motion if isinstance(device, Motion): print(" / Motion detect: %s" % str(device.is_motion())) print(" / Brightness: %i" % device.get_brightness()) # Remote if isinstance(device, Remote): print(" / is a Remote") if toggle: print(" / Press short/long") device.press_long(channel) device.press_short(channel) # Switch if isinstance(device, GenericSwitch): print(" / Switch is on: %s" % str(device.is_on(channel))) if toggle: print(" / Changee state to: %s" % str(bool(state))) device.set_state(bool(state), channel) print(" / Switch is on: %s" % str(device.is_on(channel))) ########### Attribute ######### print(" / RSSI_DEVICE: %i" % device.get_rssi()) if isinstance(device, HelperLowBat): print(" / Low batter: %s" % str(device.low_batt())) if isinstance(device, HelperSabotage): print(" / Sabotage: %s" % str(device.sabotage())) if isinstance(device, HelperWorking): print(" / Working: %s" % str(device.is_working())) if isinstance(device, HelperValveState): print(" / Valve state: %i" % device.valve_state()) if isinstance(device, HelperBatteryState): print(" / Bettery state: %f" % device.battery_state()) # do nothing for show & debug events print("Now waiting for events/callback") time.sleep(timer) # end pyhomematic.stop()
pyhomematic.devices[DEVICE1].move_down() time.sleep(10) # Get level of rollershutter from 0.0 to 1.0 directly from channel. print(pyhomematic.devices_all[DEVICE1 + ':1'].getValue("LEVEL")) # Check if doorcontact is open by querying the device. print(pyhomematic.devices[DEVICE2].is_open()) # Check if doorcontact is open or closed by querying the device-channel. True or False, depending on state. print(pyhomematic.devices_all[DEVICE2 + ':1'].getValue("STATE")) # Get Actual Temperature print(pyhomematic.devices[DEVICE3].actual_temperature) # Get Set Temperature print(pyhomematic.devices[DEVICE3].set_temperature) # Get Battery State print(pyhomematic.devices[DEVICE3].battery_state) # Set an eventcallback for the doorcontact that should be called when events occur. pyhomematic.devices[DEVICE2].setEventCallback(eventcallback) time.sleep(10) # Now open / close doorcontact and watch the eventcallback being called. # Stop the server thread so Python can exit properly. pyhomematic.stop() sys.exit(0)
class Homematic(SmartPlugin): """ Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the items """ PLUGIN_VERSION = '1.5.0' # ALLOW_MULTIINSTANCE = False connected = False def __init__(self, sh, *args, **kwargs): """ Initalizes the plugin. The parameters descriptions for this method are pulled from the entry in plugin.yaml. :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for a reference to the sh object any more. The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are imlemented to support older plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values: use the SmartPlugin method get_parameter_value(parameter_name) instead. Anywhere within the Plugin you can get the configured (and checked) value for a parameter by calling self.get_parameter_value(parameter_name). It returns the value in the datatype that is defined in the metadata. """ self.logger = logging.getLogger(__name__) # get the parameters for the plugin (as defined in metadata plugin.yaml): # self.param1 = self.get_parameter_value('param1') # Initialization code goes here self.username = self.get_parameter_value('username') self.password = self.get_parameter_value('password') self.host = self.get_parameter_value('host') # self.port = self.get_parameter_value('port') # self.port_hmip = self.get_parameter_value('port_hmip') self.port = 2001 self.port_hmip = 2010 # build dict identifier for the homematic ccu of this plugin instance self.hm_id = 'rf' if self.get_instance_name() != '': self.hm_id += '_' + self.get_instance_name() self.log_instance_str = ' ('+self.get_instance_name()+')' else: self.log_instance_str = '' # create HomeMatic object try: self.hm = HMConnection(interface_id="myserver", autostart=False, eventcallback=self.eventcallback, systemcallback=self.systemcallback, remotes={self.hm_id:{"ip": self.host, "port": self.port}}) # remotes={self.hm_id:{"ip": self.host, "port": self.port}, self.hmip_id:{"ip": self.host, "port": self.port_hmip}}) except: self.logger.error("{}: Unable to create HomeMatic object".format(self.get_fullname())) self._init_complete = False return # build dict identifier for the homematicIP ccu of this plugin instance if self.port_hmip != 0: self.hmip_id = 'ip' if self.get_instance_name() != '': self.hmip_id += '_' + self.get_instance_name() # create HomeMaticIP object try: self.hmip = HMConnection(interface_id="myserver_ip", autostart=False, eventcallback=self.eventcallback, systemcallback=self.systemcallback, remotes={self.hmip_id:{"ip": self.host, "port": self.port_hmip}}) except: self.logger.error("{}: Unable to create HomeMaticIP object".format(self.get_fullname())) # self._init_complete = False # return # set the name of the thread that got created by pyhomematic to something meaningfull self.hm._server.name = self.get_fullname() # start communication with HomeMatic ccu try: self.hm.start() self.connected = True except: self.logger.error("{}: Unable to start HomeMatic object - SmartHomeNG will be unable to terminate the thread vor this plugin (instance)".format(self.get_fullname())) self.connected = False # self._init_complete = False # stop the thread that got created by initializing pyhomematic # self.hm.stop() # return # start communication with HomeMatic ccu try: self.hmip.start() except: self.logger.error("{}: Unable to start HomeMaticIP object".format(self.get_fullname())) if self.connected: # TO DO: sleep besser lösen! sleep(20) # self.logger.warning("Plugin '{}': self.hm.devices".format(self.hm.devices)) if self.hm.devices.get(self.hm_id,{}) == {}: self.logger.error("{}: Connection to ccu failed".format(self.get_fullname())) # self._init_complete = False # stop the thread that got created by initializing pyhomematic # self.hm.stop() # return self.hm_items = [] if not self.init_webinterface(): # self._init_complete = False pass return def run(self): """ Run method for the plugin """ self.logger.debug("Plugin '{}': run method called".format(self.get_fullname())) self.alive = True # if you want to create child threads, do not make them daemon = True! # They will not shutdown properly. (It's a python bug) def stop(self): """ Stop method for the plugin """ self.logger.debug("Plugin '{}': stop method called".format(self.get_fullname())) self.alive = False self.hm.stop() self.hmip.stop() def parse_item(self, item): """ Default plugin parse_item method. Is called when the plugin is initialized. The plugin can, corresponding to its attribute keywords, decide what to do with the item in future, like adding it to an internal array for future reference :param item: The item to process. :return: If the plugin needs to be informed of an items change you should return a call back function like the function update_item down below. An example when this is needed is the knx plugin where parse_item returns the update_item function when the attribute knx_send is found. This means that when the items value is about to be updated, the call back function is called with the item, caller, source and dest as arguments and in case of the knx plugin the value can be sent to the knx with a knx write function within the knx plugin. """ if self.has_iattr(item.conf, 'hm_address'): init_error = False # self.logger.debug("parse_item{}: {}".format(self.log_instance_str, item)) dev_id = self.get_iattr_value(item.conf, 'hm_address') dev_type = self.get_iattr_value(item.conf, 'hm_type') dev_type = '?' dev = self.hm.devices[self.hm_id].get(dev_id) if dev is None: dev = self.hmip.devices[self.hmip_id].get(dev_id) if dev is not None: dev_type = 'hmIP' else: dev_type = 'hm' hm_address = self.get_iattr_value(item.conf, 'hm_address') hm_channel = self.get_iattr_value(item.conf, 'hm_channel') hm_function = self.get_iattr_value(item.conf, 'hm_function') hm_node = '' if dev is None: self.logger.error("parse_item{}: No HomeMatic device found with address '{}' for {}".format(self.log_instance_str, dev_id, item)) # return else: hm_devicetype = self.get_hmdevicetype( dev_id ) # self.logger.warning("{}, parse_item {}: type='{}', hm_address='{}', hm_channel='{}', hm_function='{}', hm_devicetype='{}'".format(self.get_fullname(), item, item.type(), hm_address, hm_channel, hm_function, hm_devicetype)) # Lookup hm_node and hm_channel for the configured hm_function if hm_function is None: hm_function = 'STATE' hm_channel, hm_node = self.get_hmchannelforfunction(hm_function, hm_channel, dev.ACTIONNODE, 'AC', item) if hm_node == '': hm_channel, hm_node = self.get_hmchannelforfunction(hm_function, hm_channel, dev.ATTRIBUTENODE, 'AT', item) if hm_node == '': hm_channel, hm_node = self.get_hmchannelforfunction(hm_function, hm_channel, dev.BINARYNODE, 'BI', item) if hm_node == '': hm_channel, hm_node = self.get_hmchannelforfunction(hm_function, hm_channel, dev.EVENTNODE, 'EV', item) if hm_node == '': hm_channel, hm_node = self.get_hmchannelforfunction(hm_function, hm_channel, dev.SENSORNODE, 'SE', item) if hm_node == '': hm_channel, hm_node = self.get_hmchannelforfunction(hm_function, hm_channel, dev.WRITENODE, 'WR', item) # self.logger.warning("{}, parse_item {}: dev.ELEMENT='{}'".format(self.get_fullname(), item, dev.ELEMENT)) self.logger.debug("parse_item{}: {}, type='{}', address={}:{}, function='{}', devicetype='{}'".format(self.log_instance_str, item, item.type(), hm_address, hm_channel, hm_function, hm_devicetype)) if hm_node == '': hm_node = None # store item and device information for plugin instance self.hm_items.append( [str(item), item, hm_address, hm_channel, hm_function, hm_node, dev_type] ) # Initialize item from HomeMatic if dev is not None: value = None if hm_node == 'AC': pass # actionNodeData can not be read for initialization init_error = True elif hm_node == 'AT': value = dev.getAttributeData(hm_function) elif hm_node == 'BI': value = dev.getBinaryData(hm_function) elif hm_node == 'EV': value = dev.event(hm_function) elif hm_node == 'SE': value = dev.getSensorData(hm_function) elif hm_node == 'WR': value = dev.getWriteData(hm_function) else: init_error = True self.logger.error("parse_item{}: Not initializing {}: Unknown hm_node='{}' for address={}:{}, function={}".format(self.log_instance_str, item, hm_node, hm_address, hm_channel, hm_function)) if value is not None: self.logger.info("parse_item{}: Initializing {} with '{}' from address={}:{}, function={}".format(self.log_instance_str, item, value, hm_address, hm_channel, hm_function)) item(value, 'HomeMatic', 'Init') else: if not init_error: self.logger.error("parse_item{}: Not initializing {} from address={}:{}, function='{}'".format(self.log_instance_str, item, hm_node, hm_address, hm_channel, hm_function)) return self.update_item def parse_logic(self, logic): """ Default plugin parse_logic method """ if 'xxx' in logic.conf: # self.function(logic['name']) pass def update_item(self, item, caller=None, source=None, dest=None): """ Write items values :param item: item to be updated towards the plugin :param caller: if given it represents the callers name :param source: if given it represents the source :param dest: if given it represents the dest """ if caller != 'HomeMatic': if self.has_iattr(item.conf, 'hm_address'): # self.hm_items[] = [str(item), item, hm_address, hm_channel, hm_function, hm_node] myitem = None for i in self.hm_items: if item == i[1]: myitem = i self.logger.warning("update_item{}: Test: item='{}', caller='{}', hm_function={}, itemvalue='{}'".format(self.log_instance_str, item, caller, i[4], item())) self.logger.warning("update_item{}: Todo: Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(self.log_instance_str, item(), item, caller, source, dest)) dev_id = self.get_iattr_value(item.conf, 'hm_address') dev = self.hm.devices[self.hm_id].get(dev_id) # Write item value to HomeMatic device if dev is not None: hm_node = myitem[5] hm_channel = myitem[3] hm_function = myitem[4] dev.CHANNELS[int(hm_channel)].setValue(hm_function, item()) self.logger.warning("{}, update_item (hm): Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(self.get_fullname(), item(), item, caller, source, dest)) else: dev = self.hmip.devices[self.hmip_id].get(dev_id) # Write item value to HomeMaticIP device if dev is not None: hm_node = myitem[5] hm_channel = myitem[3] hm_function = myitem[4] dev.CHANNELS[int(hm_channel)].setValue(hm_function, item()) self.logger.warning("{}, update_item (hmIP): Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(self.get_fullname(), item(), item, caller, source, dest)) # ACTIONNODE: PRESS_LONG (action), PRESS_SHORT (action), [LEVEL (float 0.0-1.0)] # LEVEL (float: 0.0-1.0), STOP (action), INHIBIT (bool), INSTALL_TEST (action), # OLD_LEVEL (action), RAMP_TIME (float 0.0-85825945.6 s), RAMP_STOP (action) # # Heizkörperthermostat (HM-CC-RT-DN): # SET_TEMPERATURE (float -10.0-50.0), AUTO_MODE (action), MANU_MODE (float 4.5-30.5), BOOST_MODE (action), COMFORT_MODE (action), LOWERING_MODE (action), # PARTY_MODE_SUBMIT (string), PARTY_TEMPERATURE (float 5.0-30.0), PARTY_START_TIME (int 0-1410), PARTY_START_DAY (int 0-31), PARTY_START_MONTH (int 1-12), PARTY_START_YEAR (int 0-99), # PARTY_STOP_TIME (int), PARTY_STOP_DAY (int), PARTY_STOP_MONTH (int), PARTY_STOP_YEAR (int) # # Heizkörperthermostat (HM-CC-RT-DN-BoM): # CLEAR_WINDOW_OPEN_SYMBOL (int 0-1), SET_SYMBOL_FOR_HEATING_PHASE (int 0-1), ... # # Funk- Wandthermostat ab V2.0 (CLIMATECONTROL_REGULATOR) # SETPOINT (float 6.0-30.0) # # KeyMatic: # RELOCK_DELAY (float 0.0-65535.0) # # Statusanzeige 16Kanal LED # LED_STATUS (option 0=OFF, 1=RED, 2=GREEN, 3=ORANGE), ALL_LEDS (string), LED_SLEEP_MODE (option 0=OFF, 1=ON) # # Funk- Fernbedienung 19 Tasten mit Display # TEXT (string), BULB (action), SWITCH (action), WINDOW (action), DOOR (action), BLIND (action), SCENE (action), PHONE (action), # BELL (action), CLOCK (action), ARROW_UP (action), ARROW_DOWN (action), UNIT (option 0=NONE, 1=PERCENT, 2=WATT, 3=CELSIUS, 4=FAHRENHEIT), # BEEP (option 0=NONE, 1-3=TONE1-3), BACKLIGHT (option 0=OFF, 1=ON, 2=BLINK_SLOW, 3=BLINK_FAST), # SUBMIT (action), ALARM_COUNT (int 0-255), SERVICE_COUNT (int 0-255) # # ON_TIME (float 0.0-85825945.6 s), SUBMIT (string) # STATE, LEVEL, STOP (action) def init_webinterface(self): """" Initialize the web interface for this plugin This method is only needed if the plugin is implementing a web interface """ try: self.mod_http = Modules.get_instance().get_module('http') # try/except to handle running in a core version that does not support modules except: self.mod_http = None if self.mod_http == None: self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) return False import sys if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) return False # set application configuration for cherrypy webif_dir = self.path_join(self.get_plugin_dir(), 'webif') config = { '/': { 'tools.staticdir.root': webif_dir, }, '/static': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'static' } } # Register the web interface as a cherrypy app self.mod_http.register_webif(WebInterface(webif_dir, self), self.get_shortname(), config, self.get_classname(), self.get_instance_name(), description='') return True # --------------------------------------------------------- # Methods of the plugin class for the external device # --------------------------------------------------------- def get_hmdevicetype(self, dev_id): """ get the devicetype for the given device id :param dev_id: HomeMatic device id :param type: str :return: device type :rtype: str """ dev = self.hm.devices[self.hm_id].get(dev_id) if dev is not None: d_type = str(dev.__class__).replace("<class '"+dev.__module__+'.', '').replace("'>",'') return d_type dev = self.hmip.devices[self.hmip_id].get(dev_id) if dev is not None: d_type = str(dev.__class__).replace("<class '"+dev.__module__+'.', '').replace("'>",'') return d_type return '' def get_hmchannelforfunction(self, hm_function, hm_channel, node, hm_node, item): """ Returns the HomeMatic Channel of the deivce for the wanted function :param hm_function: Configured function (or STATE) :param hm_channel: Preconfigured channel or None :param node: the node attribute of the Homematic device (e.g. dev.BINARYNODE) :param hm_node: short string for the nodename (AT, AC, BI, EV, SE, WR) """ if hm_function in node.keys(): if hm_channel is None: hm_channel = node[hm_function][0] else: if not int(hm_channel) in node[hm_function]: hm_node = '' self.logger.error("get_hmchannelforfunction{}: Invalid channel '{}' specified for {}".format(self.log_instance_str, hm_channel, item)) else: hm_node = '' return hm_channel, hm_node def systemcallback(self, src, *args): self.logger.info("systemcallback{}: src = '{}', args = '{}'".format(self.log_instance_str, src, args)) def eventcallback(self, interface_id, address, value_key, value): """ Callback method for HomeMatic events This method is called whenever the HomeMatic ccu processs an event """ defined = False for i in self.hm_items: if address == i[2]+':'+str(i[3]): if value_key == i[4]: self.logger.info("eventcallback{}: address={}, {}='{}' -> {}".format(self.log_instance_str, address, value_key, value, i[0])) # i[1](value, 'HomeMatic', address) i[1](value, 'HomeMatic') defined = True if not defined: self.logger.debug("eventcallback{}: Ohne item Zuordnung: interface_id = '{}', address = '{}', {} = '{}'".format(self.log_instance_str, interface_id, address, value_key, value))
def cli(local, localport, remote, remoteport, address, channel, state, toggle, timer, debug, user, password, variable, data): # debug? if debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) try: # Connect to HM pyhomematic = HMConnection(interface_id="test-pyhomatic", local=local, localport=localport, remote=remote, remoteport=remoteport, autostart=True, rpcusername=user, rpcpassword=password, systemcallback=systemcallback) except: print("Can't init HMConnection!") sys.exit(1) sleepcounter = 0 while not pyhomematic.devices and sleepcounter < 20: print("Waiting for devices") sleepcounter += 1 time.sleep(1) print(pyhomematic.devices) # read system variables print("******************************") print("Read all: %s" % str(pyhomematic.getAllSystemVariables())) if variable is not None: pyhomematic.setSystemVariable(variable, data) print("Read: %s" % str(pyhomematic.getSystemVariable(variable))) print("******************************") # need test a hm object? if address in pyhomematic.devices: device = pyhomematic.devices[address] print("******************************") print("* Show metadata from %s" % address) print("* Elements: %s / Childs: %i" % (device.ELEMENT, len(device.CHANNELS))) print("* Class: %s" % str(device.__class__)) print("* Base: %s" % str(device.__class__.__bases__)) print("* Sensor datapoint: %s" % str(device.SENSORNODE)) print("* Binary datapoint: %s" % str(device.BINARYNODE)) print("* Write datapoint: %s" % str(device.WRITENODE)) print("* Attribute datapoint: %s" % str(device.ATTRIBUTENODE)) print("* Event datapoint: %s" % str(device.EVENTNODE)) print("* Action datapoint: %s" % str(device.ACTIONNODE)) print("******************************") # WeatherSensor if isinstance(device, WeatherSensor): print(" / Temperature: %f" % device.get_temperature()) print(" / Humidity: %i" % device.get_humidity()) print(" / Rain Counter: %f" % device.get_rain_counter()) print(" / Wind Speed: %f" % device.get_wind_speed()) print(" / Wind Direction: %i" % device.get_wind_direction()) print(" / Wind Direction Range: %i" % device.get_wind_direction_range()) print(" / Sunshineduration: %i" % device.get_sunshineduration()) print(" / Brightness: %i" % device.get_brightness()) print(" / Is Raining: %s" % str(device.is_raining())) # AreaThermostat if isinstance(device, AreaThermostat): print(" / Temperature: %f" % device.get_temperature()) print(" / Humidity: %i" % device.get_humidity()) # ShutterContact if isinstance(device, ShutterContact): print(" / Contact open: %s" % str(device.is_open())) # Smoke if isinstance(device, Smoke): print(" / Smoke detect: %s" % str(device.is_smoke())) # Motion if isinstance(device, Motion): print(" / Motion detect: %s" % str(device.is_motion())) print(" / Brightness: %i" % device.get_brightness()) # Remote if isinstance(device, Remote): print(" / is a Remote") if toggle: print(" / Press short/long") device.press_long(channel) device.press_short(channel) # Switch if isinstance(device, GenericSwitch): print(" / Switch is on: %s" % str(device.is_on(channel))) if toggle: print(" / Changee state to: %s" % str(bool(state))) device.set_state(bool(state), channel) print(" / Switch is on: %s" % str(device.is_on(channel))) ########### Attribute ######### print(" / RSSI_DEVICE: %i" % device.get_rssi()) if isinstance(device, HelperLowBat): print(" / Low batter: %s" % str(device.low_batt())) if isinstance(device, HelperSabotage): print(" / Sabotage: %s" % str(device.sabotage())) if isinstance(device, HelperWorking): print(" / Working: %s" % str(device.is_working())) if isinstance(device, HelperValveState): print(" / Valve state: %i" % device.valve_state()) if isinstance(device, HelperBatteryState): print(" / Bettery state: %f" % device.battery_state()) # do nothing for show & debug events print("Now waiting for events/callback") time.sleep(timer) # end pyhomematic.stop()