def setDim(self, command): DEVICEID = "ebfc16d57ed374932cjqfk" DEVICEIP = "192.168.1.150" DEVICEKEY = "805217605357161b" DEVICEVERS = "us" # Check for environmental variables and always use those if available DDEVICEID = os.getenv("DEVICEID", DEVICEID) DEVICEIP = os.getenv("DEVICEIP", DEVICEIP) DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY) DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS) LOGGER.info("TreatLife - Smart Switch Test [%s]\n" % tinytuya.__version__) LOGGER.info('TESTING: Device %s at %s with key %s version %s' % (DEVICEID, DEVICEIP, DEVICEKEY, DEVICEVERS)) LOGGER.info('TESTING: Device %s' % (DEVICEIP)) d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY) d.set_version(3.3) d.set_socketPersistent(True) ivr_one = 'percent' percent = int(command.get('value')) def set_percent(self, command): percent = int(command.get('value') * 10) if percent < 0 or percent > 100: LOGGER.error('Invalid Level {}'.format(percent)) else: d.set_brightness_percentage( percent) #d.set_brightness_percentage(percent) self.setDriver('GV3', percent) LOGGER.info('Dimmer Setpoint = ' + str(percent) + 'Level')
def session_get (self,path,data): if path == 'authorize': # All calls before with have auth token, don't reformat with json return self.session.get(path,data) else: res = self.session.get(path,{ 'json': json.dumps(data) }, auth='{} {}'.format(self.tokenData['token_type'], self.tokenData['access_token']) ) if res is False: return res if res['data'] is False: return False self.l_debug('session_get', 0, 'res={}'.format(res)) if not 'status' in res['data']: return res res_st_code = int(res['data']['status']['code']) if res_st_code == 0: return res LOGGER.error('Checking Bad Status Code {} for {}'.format(res_st_code,res)) if res_st_code == 14: self.l_error('session_get', 'Token has expired, will refresh') # TODO: Should this be a loop instead ? if self._getRefresh() is True: return self.session.get(path,{ 'json': json.dumps(data) }, auth='{} {}'.format(self.tokenData['token_type'], self.tokenData['access_token'])) elif res_st_code == 16: self._reAuth("session_get: Token deauthorized by user: {}".format(res)) return False
def set_driver(self, mdrv, val, default=0, force=False, report=True): #LOGGER.debug(f'{self.lpfx} {mdrv},{val} default={default} force={force},report={report}') if val is None: # Restore from DB for existing nodes try: val = self.getDriver(mdrv) LOGGER.info(f'{self.lpfx} {val}') except: LOGGER.warning( f'{self.lpfx} getDriver({mdrv}) failed which can happen on new nodes, using {default}' ) val = default if val is None else int(val) try: if not mdrv in self.__my_drivers or val != self.__my_drivers[ mdrv] or force: self.setDriver(mdrv, val, report=report) info = '' if self.id in NODE_DEF_MAP and mdrv in NODE_DEF_MAP[self.id]: info += f"'{NODE_DEF_MAP[self.id][mdrv]['name']}' = " info += f"'{NODE_DEF_MAP[self.id][mdrv]['keys'][val]}'" if val in NODE_DEF_MAP[ self.id][mdrv]['keys'] else "'NOT IN NODE_DEF_MAP'" self.__my_drivers[mdrv] = val LOGGER.debug(f'{self.lpfx} set_driver({mdrv},{val}) {info}') #else: # LOGGER.debug(f'{self.lpfx} not necessary') except: LOGGER.error(f'{self.lpfx} set_driver({mdrv},{val}) failed') return None return val
def _checkTokens(self): if self.refreshingTokens: LOGGER.error('Waiting for token refresh to complete...') while self.refreshingTokens: time.sleep(.1) if 'access_token' in self.tokenData: exp_d = self._expire_delta() if exp_d is not False: # We allow for 10 long polls to refresh the token... if exp_d.total_seconds() < int(self.polyConfig['longPoll']) * 10: self.l_info('_checkTokens','Tokens {} expires {} will expire in {} seconds, so refreshing now...'.format(self.tokenData['refresh_token'],self.tokenData['expires'],exp_d.total_seconds())) return self._getRefresh() else: # Only print this ones, then once a minute at most... sd = True if 'ctdt' in self.msgi: md = datetime.now() - self.msgi['ctdt'] if md.total_seconds() < 60: sd = False if sd: self.l_debug('_checkTokens',0,'Tokens valid until: {} ({} seconds, longPoll={})'.format(self.tokenData['expires'],exp_d.seconds,int(self.polyConfig['longPoll']))) self.msgi['ctdt'] = datetime.now() self.set_auth_st(True) return True else: self.l_error('_checkTokens', 'No expires in tokenData:{}'.format(self.tokenData)) else: self.set_auth_st(False) self.l_error('_checkTokens','tokenData or access_token not available') # self.saveCustomDataWait({}) # this._getPin() return False
def _discover(self, *args, **kwargs): LOGGER.info('Discovering Ecobee Thermostats') if not 'access_token' in self.tokenData: return False self.revData = {} # Intialize in case we fail thermostats = self.getThermostats() if thermostats is False: LOGGER.error("Discover Failed, No thermostats returned! Will try again on next long poll") return False self.revData = deepcopy(thermostats) # # Build or update the profile first. # self.check_profile(thermostats) # # Now add our thermostats # for thermostatId, thermostat in thermostats.items(): address = self.thermostatIdToAddress(thermostatId) if not address in self.nodes: fullData = self.getThermostatFull(thermostatId) if fullData is not False: tstat = fullData['thermostatList'][0] useCelsius = True if tstat['settings']['useCelsius'] else False self.addNode(Thermostat(self, address, address, thermostatId, 'Ecobee - {}'.format(get_valid_node_name(thermostat['name'])), thermostat, fullData, useCelsius)) return True
def list_cameras(self): try: return self.camect.list_cameras() except Exception as err: LOGGER.error(f'list_cameras: {err}') self.camect = False return []
def RmProgramCtrl(url, access_token, command): #extract the zone number from the command string program = ''.join(filter(lambda i: i.isdigit(), command['address'])) if command['cmd'] == 'STOP': try: response = requests.post(url + 'api/4/program/' + str(program) + "/stop" + access_token, data=None, json=None, verify=False) LOGGER.debug(response) LOGGER.debug('Received Stop Command') except: LOGGER.error('Unable to stop program {} watering'.format(program)) elif command['cmd'] == 'RUN': #extract the run duration from the command string and convert it to minutes #zone_duration = '{"time":' + str(int(command['value'])*60) +'}' #LOGGER.debug(zone_duration) #'{"time":60}' try: response = requests.post(url + 'api/4/program/' + str(program) + "/start" + access_token, data=None, json=None, verify=False) LOGGER.debug('Received Run Command') LOGGER.debug(response.url) except: LOGGER.error('Unable to stop program {0}'.format(str(program)))
def set_debug_level(self, level=None): LOGGER.info(f"level={level}") mdrv = "GV2" if level is None: # Restore from DB for existing nodes level = self.get_driver(mdrv, 20) level = int(level) if level == 0: level = 20 LOGGER.info(f"Seting {mdrv} to {level}") self.setDriver(mdrv, level) # 0=All 10=Debug are the same because 0 (NOTSET) doesn't show everything. slevel = logging.WARNING if level <= 10: if level < 10: slevel = logging.DEBUG level = logging.DEBUG elif level == 20: level = logging.INFO elif level == 30: level = logging.WARNING elif level == 40: level = logging.ERROR elif level == 50: level = logging.CRITICAL else: LOGGER.error(f"Unknown level {level}") #LOG_HANDLER.set_basic_config(True,logging.DEBUG) self.set_all_logs(level, slevel)
def __russound_loop_tcp(self, processCommand): buf = bytearray(50) st = 0 while self.connected: try: data = self.sock.recv(4096) #LOGGER.debug(data) for b in data: if st == 0: # looking for start byte if b == 0xf0: buf[st] = b st += 1 else: # looking for end byte if b == 0xf7: buf[st] = b st = 0 LOGGER.debug('recv: ' + ' '.join('{:02x}'.format(x) for x in data)) msg = rnet_message.RNetMessage(buf) processCommand(msg) else: buf[st] = b st += 1 except BlockingIOError: LOGGER.info('waiting on data') pass except ConnectionResetError as msg: LOGGER.error('Connection error: ' + str(msg)) self.connected = False
def get_sensor_nodedef(self, sensor): # Given the ecobee sensor data, figure out the nodedef # {'id': 'rs:100', 'name': 'Test Sensor', 'type': 'ecobee3_remote_sensor', 'code': 'VRSP', 'inUse': False, 'capability': [{'id': '1', 'type': 'temperature', 'value': 'unknown'}, {'id': '2', 'type': 'occupancy', 'value': 'false'}]} # {'name': '', 'type': 'monitor_sensor', 'inUse': False, 'id': 'ei:0:1', 'capability': [{'type': 'dryContact', 'value': '0', 'id': ''}]} has_hum = False has_temp = False has_dry_contact = False has_occupancy = False if 'capability' in sensor: for cb in sensor['capability']: if cb['type'] == 'temperature': has_temp = True elif cb['type'] == 'humidity': has_hum = True elif cb['type'] == 'dryContact': has_dry_contact = True elif cb['type'] == 'occupancy': has_occupancy = True if sensor['type'] == 'monitor_sensor': if has_dry_contact: if has_hum or has_temp or has_occupancy: LOGGER.error( "Currently Unsupported sensor has_dry_contact={} has_temp={} has_hum={} has_occupancy={}" .format(has_dry_contact, has_temp, has_hum, has_occupancy)) return False else: return 'EcobeeSensorMSD' else: CorF = 'C' if self.useCelsius else 'F' HorN = 'H' if has_hum else '' return 'EcobeeSensor{}{}'.format(HorN, CorF)
def refresh(self, *args, **kwargs): LOGGER.info('') if self.isy_hue_emu is False: LOGGER.error('No Hue Emulator?') return self.isy_hue_emu.refresh() self.update_config_docs()
def set_debug_level(self, level): LOGGER.info(str(level)) if level is None: level = 20 level = int(level) if level == 0: level = 20 LOGGER.info('Set GV1 to {}'.format(level)) self.setDriver('GV1', level) # 0=All 10=Debug are the same because 0 (NOTSET) doesn't show everything. if level <= 10: l = logging.DEBUG elif level <= 20: l = logging.INFO elif level <= 30: l = logging.WARNING elif level <= 40: l = logging.ERROR elif level <= 50: l = logging.CRITICAL else: LOGGER.error("Unknown level {}".format(level)) return LOGGER.setLevel(l) logging.getLogger('hueUpnp').setLevel(l) logging.getLogger('ISYHueEmu').setLevel(l) # this is the best way to control logging for modules, so you can # still see warnings and errors if level < 10: self.set_module_logs(level) else: # Just warnigns for the modules unless in module debug mode self.set_module_logs(logging.WARNING)
def check_params(self): """ This is an example if using custom Params for user and password and an example with a Dictionary """ self.removeNoticesAll() self.addNotice('Hey there, my IP is {}'.format(self.poly.network_interface['addr']),'hello') self.addNotice('Hello Friends! (without key)') default_user = "******" default_password = "******" if 'user' in self.polyConfig['customParams']: self.user = self.polyConfig['customParams']['user'] else: self.user = default_user LOGGER.error('check_params: user not defined in customParams, please add it. Using {}'.format(self.user)) st = False if 'password' in self.polyConfig['customParams']: self.password = self.polyConfig['customParams']['password'] else: self.password = default_password LOGGER.error('check_params: password not defined in customParams, please add it. Using {}'.format(self.password)) st = False # Make sure they are in the params self.addCustomParam({'password': self.password, 'user': self.user, 'some_example': '{ "type": "TheType", "host": "host_or_IP", "port": "port_number" }'}) # Add a notice if they need to change the user/password from the default. if self.user == default_user or self.password == default_password: # This doesn't pass a key to test the old way. self.addNotice('Please set proper user and password in configuration page, and restart this nodeserver') # This one passes a key to test the new way. self.addNotice('This is a test','test')
def setDim(self, command): DEVICEID = self.DEVICEID DEVICEIP = self.DEVICEIP DEVICEKEY = self.DEVICEKEY DEVICEVERS = self.DEVICEVERS DEVICEID = os.getenv("DEVICEID", DEVICEID) DEVICEIP = os.getenv("DEVICEIP", DEVICEIP) DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY) DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS) d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY) d.set_version(3.3) d.set_socketPersistent(True) ivr_one = 'percent' percent = int(command.get('value')) def set_percent(self, command): percent = int(command.get('value') * 10) if percent < 0 or percent > 100: LOGGER.error('Invalid Level {}'.format(percent)) else: d.set_brightness_percentage( percent) #d.set_brightness_percentage(percent) self.setDriver('GV3', percent) LOGGER.info('Dimmer Setpoint = ' + str(percent) + 'Level')
def check_params(self): default_lutron_bridge_ip = None default_oauth_code = None if 'lutron_bridge_ip' in self.polyConfig['customParams']: self.lutron_bridge_ip = self.polyConfig['customParams']['lutron_bridge_ip'] else: self.lutron_bridge_ip = default_lutron_bridge_ip LOGGER.error('check_params: lutron_bridge_ip not defined in customParams, please add it. Using {}'.format(self.lutron_bridge_ip)) st = False if 'oauth_code' in self.polyConfig['customParams']: self.oauth_code = self.polyConfig['customParams']['oauth_code'] else: self.oauth_code = default_oauth_code LOGGER.error('check_params: oauth_code not defined.') st = False # Make sure they are in the params self.addCustomParam({'oauth_code': self.oauth_code, 'lutron_bridge_ip': self.lutron_bridge_ip}) # Add a notice if they need to change the user/password from the default. if self.lutron_bridge_ip == default_lutron_bridge_ip or self.oauth_code == default_oauth_code: # This doesn't pass a key to test the old way. self.addNotice('Please set proper lutron_bridge_ip and oauth_code in configuration page, and restart this nodeserver', 'addconfig') else: self.removeNotice('addconfig')
def update(self, sensor): LOGGER.debug("{}:update:".format(self.address)) LOGGER.debug("{}:update: sensor={}".format(self.address,sensor)) updates = { 'GV1': 2 # Default is N/A } # Cross reference from sensor capabilty to driver xref = { 'temperature': 'ST', 'humidity': 'CLIHUM', 'occupancy': 'GV1', 'responding': 'GV2', 'dryContact': 'GV3' } for item in sensor['capability']: if item['type'] in xref: val = item['value'] if val == "true": val = 1 elif val == "false": val = 0 if item['type'] == 'temperature': # temperature unknown seems to mean the sensor is not responding.s if val == 'unknown': updates[xref['responding']] = 0 else: updates[xref['responding']] = 1 val = self.parent.tempToDriver(val,True,False) if val is not False: updates[xref[item['type']]] = val else: LOGGER.error("{}:update: Unknown capabilty: {}".format(self.address,item)) LOGGER.debug("{}:update: updates={}".format(self.address,updates)) for key, value in updates.items(): self.setDriver(key, value)
def setDim(self, command): DEVICEID = "ebfd4f4263bb769d99zjkq" DEVICEIP = "192.168.1.149" DEVICEKEY = "ec0b2b581a246eab" DEVICEVERS = "us" # Check for environmental variables and always use those if available DDEVICEID = os.getenv("DEVICEID", DEVICEID) DEVICEIP = os.getenv("DEVICEIP", DEVICEIP) DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY) DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS) LOGGER.info("TreatLife - Smart Switch Test [%s]\n" % tinytuya.__version__) LOGGER.info('TESTING: Device %s at %s with key %s version %s' % (DEVICEID, DEVICEIP, DEVICEKEY, DEVICEVERS)) LOGGER.info('TESTING: Device %s' % (DEVICEIP)) d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY) d.set_version(3.3) d.set_socketPersistent(True) ivr_one = 'percent' percent = int(command.get('value')) def set_percent(self, command): percent = int(command.get('value') * 10) if percent < 0 or percent > 100: LOGGER.error('Invalid Level {}'.format(percent)) else: d.set_brightness_percentage(percent) self.setDriver('GV3', percent)
def discover(self): LOGGER.info(f'started') if self.hosts is not None: LOGGER.debug(f'saved_hosts={json.dumps(self.saved_hosts,indent=2)}') LOGGER.debug(f'saved_cameras={json.dumps(self.saved_cameras,indent=2)}') for host in self.hosts: # Would be better to do this conneciton inside the Host object # but addNode is async so we ned to get the address in this loop # before addNode is called :() camect_obj = self.connect_host(host['host']) if camect_obj is not False: camect_info = camect_obj.get_info() LOGGER.debug(f"saved_hosts={self.saved_hosts}") if camect_info['id'] in self.saved_hosts: # Use existing and don't re-discover new = False address = self.saved_hosts[camect_info['id']]['node_address'] else: # Need to discover new = True address = self.controller.get_host_address(camect_info) try: self.nodes_by_id[camect_info['id']] = self.addNode(Host(self, address, host['host'], camect_obj, new=new)) except: LOGGER.error('Failed to add camect host {host}',exc_info=True) return self.save_custom_data() if self.hosts is None: self.set_driver('GV2',0) else: self.set_driver('GV2',len(self.hosts)) self.set_mode_all() LOGGER.info('completed')
def discover(self, *args, **kwargs): """ Example Do discovery here. Does not have to be called discovery. Called from example controller start method and from DISCOVER command recieved from ISY as an exmaple. """ if not self.is_connected(): return False # self.addNode(LutronCasetaSmartBridge(self, self.address, 'smartbridgeaddr', 'Caseta Smart Bridge')) devices = self.sb.get_devices() scenes = self.sb.get_scenes() for device_id, device in devices.items(): """ '1': {'device_id': '1', 'name': 'Smart Bridge 2', 'type': 'SmartBridge', 'zone': None, 'current_state': -1}, '3': {'device_id': '3', 'name': 'Living Room_Left Window', 'type': 'SerenaHoneycombShade', 'zone': '2', 'current_state': -1} """ NodeType = None if device.get('type') == "SerenaHoneycombShade": NodeType = SerenaHoneycombShade elif device.get('type') == "QsWirelessShade": NodeType = QsWirelessShade if not NodeType: LOGGER.error("Unsupported Node Type: {}".format(device)) continue address = 'device' + str(device.get('device_id')) LOGGER.info("Adding node: '{}' {}".format(device.get('name'),address)) self.devices[device_id] = self.addNode( NodeType( self, self.address, address, device.get('name'), self.sb, device.get('device_id'), device.get('type'), device.get('zone'), device.get('current_state') ) ) for scene_id, scene in scenes.items(): """ '1': {'scene_id': '1', 'name': 'All Close'}, '2': {'scene_id': '2', 'name': 'All Open'}, '3': {'scene_id': '3', 'name': 'All Halfway'} """ self.addNode( Scene( self, self.address, 'scene' + str(scene.get('scene_id')), scene.get('name'), self.sb ) )
def _reAuth(self, reason): # Need to re-auth! LOGGER.error('_reAuth because: {}'.format(reason)) self.addNotice({'reauth': "Must Re-Authorize because {}".format(reason)}) cdata = deepcopy(self.polyConfig['customData']) if not 'tokenData' in cdata: LOGGER.error('No tokenData in customData: {}'.format(cdata)) self.saveCustomDataWait(cdata) self.authorize()
def shortPoll(self): self.set_isy_connected() self.update_config_docs() if self.thread is not None: if not self.thread.is_alive(): self.thread = None LOGGER.error("Thread is dead, restarting.") self.check_params() # Reload in case they changed. self.connect()
def callback(self,event): # {'type': 'alert', 'desc': 'Out Front Door just saw a person.', 'url': 'https://home.camect.com/home/...', # 'cam_id': '96f69defdef1d0b6602a', 'cam_name': 'Out Front Door', 'detected_obj': ['person']} LOGGER.debug(f"{self.lpfx} type={event['type']}") if event['type'] == 'alert': if 'detected_obj' in event: self.detected_obj(event['detected_obj']) else: LOGGER.error(f"Unknown alert, no detected_obj in {event}")
def setClimateType(self, val): if val is True: val = self.program['currentClimateRef'] if not is_int(val): if val in climateMap: val = climateMap[val] else: LOGGER.error("Unknown climate name {}".format(val)) return False self.set_driver('GV3', int(val))
def RmZoneProperties(url, access_token): try: response = requests.get(url + 'api/4/zone' + access_token, verify=False) #rm_zone_data = json.loads(response.content) rm_zone_data = response.json() return rm_zone_data except: LOGGER.error('Unable to get zone properties') return ""
def cmd_set_mode(self, command): LOGGER.debug(f'{self.lpfx}: {command}') #self.set_mode(int(command.get('value'))) # Don't set it, let the callback handle it. val = int(command.get('value')) for mname in HOST_MODE_MAP: if HOST_MODE_MAP[mname] == val: LOGGER.info(f"{self.lpfx}: Setting Camect Mode={mname}") self.camect.set_mode(mname) return LOGGER.error(f'{self.lpfx}: Unknown Mode Value {val}')
def getClimateIndex(self, name): if name in climateMap: climateIndex = climateMap[name] else: if not name in self._gcidx[name]: LOGGER.error( "Unknown climateType='{}' which is a known issue https://github.com/Einstein42/udi-ecobee-poly/issues/63" .format(name)) self._gcidx[name] = True climateIndex = climateMap['unknown'] return climateIndex
def update_config_docs(self): # '<style> table { cellpadding: 10px } </style>' if self.ucd_check is False: try: if self.poly.supports_feature('customParamsDoc'): self.ucd = True else: LOGGER.error( 'polyinterface customParamsDoc feature not supported') self.ucd = False except AttributeError: LOGGER.error('polyinterface supports feature failed?', True) self.ucd = False self.ucd_check = True if self.ucd is False: return self.config_info = [ '<h1>Spoken Device Table</h1>', 'This table is refreshed during short poll, so it may be out of date for a few seconds<br>', '<table border=1>', '<tr><th colspan=2><center>Hue<th rowspan=2><center>NSId<th colspan=2><center>Property Node/Scene<th colspan=3><center>Scene<th rowspan=2><center>Spoken<th rowspan=2><center>On<th rowspan=2><center>Bri</tr>', '<tr><th><center>Id<th><center>Type<th><center>Id<th><center>NodeDefId<th><center>Name<th><center>Scene<th><center>Name<th></tr>' ] if self.isy_hue_emu is not False: for i, device in enumerate(self.isy_hue_emu.pdevices): # Only used for debug if device is False: dtype = 'None' elif device.node.protocol == pyisy.constants.PROTO_GROUP: dtype = 'Scene' else: dtype = device.node.node_def_id if device is False: self.config_info.append( '<tr><td>{}<td colspan=9>empty</tr>'.format(i)) elif device.scene is False: self.config_info.append( '<tr><td>{}<td> {} <td> {} <td> {} <td> {} <td colspan=2> None <td> {} <td> {} <td> {} <td> {} </tr>' .format(i, device.type, device.id, device.node, dtype, device.node.name, device.name, device.on, device.bri)) else: self.config_info.append( '<tr><td> {} <td>{}<td> {} <td> {} <td> {} <td> {} <td> {} <td> {} <td> {} <td> {} <td> {} </tr>' .format(i, device.type, device.id, device.node, dtype, device.node.name, device.scene, device.scene.name, device.name, device.on, device.bri)) self.config_info.append('</table>') s = "\n" cstr = s.join(self.config_info) if self.sent_cstr != cstr: self.poly.add_custom_config_docs(cstr, True) self.sent_cstr = cstr
def set_value(self, device, value): LOGGER.info("Sending value to Smart Bridge for device {}: {}".format( device, value)) LOGGER.info("is_connected={}".format(self.controller.is_connected())) try: result = asyncio.run_coroutine_threadsafe( self.sb.set_value(device, value), self.controller.mainloop) except Exception as e: LOGGER.error('set_value {}'.format(e), exc_info=True) result = False LOGGER.info("set_value result: {}".format(result))
def setFanState(self, val): if is_int(val): dval = val else: if val in fanMap: dval = fanMap[val] else: LOGGER.error("{}:Fan: Unknown fanMap name {}".format( self.address, val)) return False LOGGER.debug('{}:setFanState: {}={}'.format(self.address, val, dval)) self.set_driver('CLIFRS', dval)
def setScheduleMode(self, val): LOGGER.debug('{}:setScheduleMode: {}'.format(self.address, val)) if not is_int(val): if val in transitionMap: val = transitionMap[val] else: LOGGER.error( "{}:setScheduleMode: Unknown transitionMap name {}".format( self.address, val)) return False self.set_driver('CLISMD', int(val)) self.clismd = int(val)