def list_sensors(): core = td.TelldusCore() sensors = core.sensors() print("Number of sensors: %d\n" % len(sensors)) print("{:<5} {:<15} {:<22} {:<8s} {:<8} {}".format("ID", "PROTOCOL", "MODEL", "TEMP", "HUMIDITY", "LAST UPDATED")) for sensor in sensors: temperature, humidity, timestamp = ["", "", ""] if sensor.has_value(const.TELLSTICK_TEMPERATURE): sensor_value = sensor.value(const.TELLSTICK_TEMPERATURE) temperature = sensor_value.value timestamp = sensor_value.timestamp if sensor.has_value(const.TELLSTICK_HUMIDITY): sensor_value = sensor.value(const.TELLSTICK_TEMPERATURE) humidity = sensor_value.value if not timestamp: timestamp = sensor_value.timestamp if not (temperature or humidity): continue timestamp_formatted = time.strftime("%F %T", time.localtime(timestamp)) output = "{:<5d} {:<15} {:<22} {:<9s}{:<9s}{}".format( sensor.id, sensor.protocol, sensor.model, temperature, humidity, timestamp_formatted) print(output)
def loop(self): loop = asyncio.get_event_loop() dispatcher = td.AsyncioCallbackDispatcher(loop) core = td.TelldusCore(callback_dispatcher=dispatcher) core.register_sensor_event(self.sensor_event) print("Starting loop") loop.run_forever()
def setup(hass, config): """Setup the Tellstick component.""" # pylint: disable=global-statement, import-error global TELLCORE_REGISTRY import tellcore.telldus as telldus import tellcore.constants as tellcore_constants from tellcore.library import DirectCallbackDispatcher core = telldus.TelldusCore(callback_dispatcher=DirectCallbackDispatcher()) TELLCORE_REGISTRY = TellstickRegistry(hass, core) devices = core.devices() # Register devices TELLCORE_REGISTRY.register_devices(devices) # Discover the switches _discover(hass, config, [ switch.id for switch in devices if not switch.methods(tellcore_constants.TELLSTICK_DIM) ], "switch") # Discover the lights _discover(hass, config, [ light.id for light in devices if light.methods(tellcore_constants.TELLSTICK_DIM) ], "light") return True
def setup_platform(hass, config, add_devices_callback, discovery_info=None): """ Find and return Tellstick lights. """ import tellcore.telldus as telldus from tellcore.library import DirectCallbackDispatcher import tellcore.constants as tellcore_constants core = telldus.TelldusCore(callback_dispatcher=DirectCallbackDispatcher()) signal_repetitions = config.get('signal_repetitions', SIGNAL_REPETITIONS) switches_and_lights = core.devices() lights = [] for switch in switches_and_lights: if switch.methods(tellcore_constants.TELLSTICK_DIM): lights.append(TellstickLight(switch, signal_repetitions)) def _device_event_callback(id_, method, data, cid): """ Called from the TelldusCore library to update one device """ for light_device in lights: if light_device.tellstick_device.id == id_: # Execute the update in another thread light_device.update_ha_state(True) break callback_id = core.register_device_event(_device_event_callback) def unload_telldus_lib(event): """ Un-register the callback bindings """ if callback_id is not None: core.unregister_callback(callback_id) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, unload_telldus_lib) add_devices_callback(lights)
def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the Tellstick sensors.""" from tellcore import telldus import tellcore.constants as tellcore_constants sensor_value_descriptions = { tellcore_constants.TELLSTICK_TEMPERATURE: DatatypeDescription('temperature', config.get(CONF_TEMPERATURE_SCALE)), tellcore_constants.TELLSTICK_HUMIDITY: DatatypeDescription('humidity', '%'), tellcore_constants.TELLSTICK_RAINRATE: DatatypeDescription('rain rate', ''), tellcore_constants.TELLSTICK_RAINTOTAL: DatatypeDescription('rain total', ''), tellcore_constants.TELLSTICK_WINDDIRECTION: DatatypeDescription('wind direction', ''), tellcore_constants.TELLSTICK_WINDAVERAGE: DatatypeDescription('wind average', ''), tellcore_constants.TELLSTICK_WINDGUST: DatatypeDescription('wind gust', '') } try: tellcore_lib = telldus.TelldusCore() except OSError: _LOGGER.exception('Could not initialize Tellstick') return sensors = [] datatype_mask = config.get(CONF_DATATYPE_MASK) if config[CONF_ONLY_NAMED]: named_sensors = { named_sensor[CONF_ID]: named_sensor[CONF_NAME] for named_sensor in config[CONF_ONLY_NAMED]} for tellcore_sensor in tellcore_lib.sensors(): if not config[CONF_ONLY_NAMED]: sensor_name = str(tellcore_sensor.id) else: if tellcore_sensor.id not in named_sensors: continue sensor_name = named_sensors[tellcore_sensor.id] for datatype in sensor_value_descriptions: if datatype & datatype_mask and \ tellcore_sensor.has_value(datatype): sensor_info = sensor_value_descriptions[datatype] sensors.append(TellstickSensor( sensor_name, tellcore_sensor, datatype, sensor_info)) add_entities(sensors)
def setup_platform(hass, config, add_devices, discovery_info=None): """ Sets up Tellstick sensors. """ sensor_value_descriptions = { tellcore_constants.TELLSTICK_TEMPERATURE: DatatypeDescription( 'temperature', config.get('temperature_scale', TEMP_CELCIUS)), tellcore_constants.TELLSTICK_HUMIDITY: DatatypeDescription('humidity', '%'), tellcore_constants.TELLSTICK_RAINRATE: DatatypeDescription('rain rate', ''), tellcore_constants.TELLSTICK_RAINTOTAL: DatatypeDescription('rain total', ''), tellcore_constants.TELLSTICK_WINDDIRECTION: DatatypeDescription('wind direction', ''), tellcore_constants.TELLSTICK_WINDAVERAGE: DatatypeDescription('wind average', ''), tellcore_constants.TELLSTICK_WINDGUST: DatatypeDescription('wind gust', '') } try: core = telldus.TelldusCore() except OSError: logging.getLogger(__name__).exception( 'Could not initialize Tellstick.') return sensors = [] datatype_mask = util.convert(config.get('datatype_mask'), int, 127) for ts_sensor in core.sensors(): try: sensor_name = config[ts_sensor.id] except KeyError: if 'only_named' in config: continue sensor_name = str(ts_sensor.id) for datatype in sensor_value_descriptions.keys(): if datatype & datatype_mask and ts_sensor.has_value(datatype): sensor_info = sensor_value_descriptions[datatype] sensors.append( TellstickSensor( sensor_name, ts_sensor, datatype, sensor_info)) add_devices(sensors)
def sensor_event_loop(sensor_event_handler): dispatcher = td.QueuedCallbackDispatcher() core = td.TelldusCore(callback_dispatcher=dispatcher) core.register_sensor_event(sensor_event_handler.handle_sensor_event) try: while True: core.callback_dispatcher.process_pending_callbacks() sensor_event_handler.handle_loop() time.sleep(0.5) except KeyboardInterrupt: sensor_event_handler.handle_exit()
def get_devices(hass, config): """ Find and return Tellstick switches. """ try: import tellcore.telldus as telldus except ImportError: logging.getLogger(__name__).exception("Failed to import tellcore") return [] core = telldus.TelldusCore() switches = core.devices() return [TellstickSwitch(switch) for switch in switches]
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Tellstick sensors.""" import tellcore.telldus as telldus import tellcore.constants as tellcore_constants sensor_value_descriptions = { tellcore_constants.TELLSTICK_TEMPERATURE: DatatypeDescription('temperature', config.get(CONF_TEMPERATURE_SCALE)), tellcore_constants.TELLSTICK_HUMIDITY: DatatypeDescription('humidity', '%'), tellcore_constants.TELLSTICK_RAINRATE: DatatypeDescription('rain rate', ''), tellcore_constants.TELLSTICK_RAINTOTAL: DatatypeDescription('rain total', ''), tellcore_constants.TELLSTICK_WINDDIRECTION: DatatypeDescription('wind direction', ''), tellcore_constants.TELLSTICK_WINDAVERAGE: DatatypeDescription('wind average', ''), tellcore_constants.TELLSTICK_WINDGUST: DatatypeDescription('wind gust', '') } try: core = telldus.TelldusCore() except OSError: logging.getLogger(__name__).exception('Could not initialize Tellstick') return sensors = [] datatype_mask = config.get(CONF_DATATYPE_MASK) for ts_sensor in core.sensors(): try: sensor_name = config[ts_sensor.id] except KeyError: if config.get(CONF_ONLY_NAMED): continue sensor_name = str(ts_sensor.id) for datatype in sensor_value_descriptions: if datatype & datatype_mask and ts_sensor.has_value(datatype): sensor_info = sensor_value_descriptions[datatype] sensors.append(TellstickSensor( sensor_name, ts_sensor, datatype, sensor_info)) add_devices(sensors)
def setup_platform(hass, config, add_devices_callback, discovery_info=None): """ Find and return Tellstick lights. """ try: import tellcore.telldus as telldus except ImportError: logging.getLogger(__name__).exception("Failed to import tellcore") return [] core = telldus.TelldusCore() switches_and_lights = core.devices() lights = [] for switch in switches_and_lights: if switch.methods(tellcore_constants.TELLSTICK_DIM): lights.append(TellstickLight(switch)) add_devices_callback(lights)
def setup_platform(hass, config, add_devices_callback, discovery_info=None): """ Find and return Tellstick switches. """ try: import tellcore.telldus as telldus except ImportError: logging.getLogger(__name__).exception("Failed to import tellcore") return signal_repetitions = config.get('signal_repetitions', SINGAL_REPETITIONS) core = telldus.TelldusCore() switches_and_lights = core.devices() switches = [] for switch in switches_and_lights: if not switch.methods(tellcore_constants.TELLSTICK_DIM): switches.append(TellstickSwitchDevice(switch, signal_repetitions)) add_devices_callback(switches)
def setup_platform(hass, config, add_devices_callback, discovery_info=None): """ Find and return Tellstick switches. """ try: import tellcore.telldus as telldus except ImportError: _LOGGER.exception("Failed to import tellcore") return core = telldus.TelldusCore(callback_dispatcher=DirectCallbackDispatcher()) signal_repetitions = config.get('signal_repetitions', SIGNAL_REPETITIONS) switches_and_lights = core.devices() switches = [] for switch in switches_and_lights: if not switch.methods(tellcore_constants.TELLSTICK_DIM): switches.append(TellstickSwitchDevice(switch, signal_repetitions)) def _device_event_callback(id_, method, data, cid): """ Called from the TelldusCore library to update one device """ for switch_device in switches: if switch_device.tellstick_device.id == id_: switch_device.update_ha_state() break callback_id = core.register_device_event(_device_event_callback) def unload_telldus_lib(event): """ Un-register the callback bindings """ if callback_id is not None: core.unregister_callback(callback_id) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, unload_telldus_lib) add_devices_callback(switches)
def setup_platform(hass, config, add_devices_callback, discovery_info=None): """ Find and return Tellstick lights. """ try: import tellcore.telldus as telldus except ImportError: logging.getLogger(__name__).exception("Failed to import tellcore") return [] core = telldus.TelldusCore(callback_dispatcher=DirectCallbackDispatcher()) switches_and_lights = core.devices() lights = [] for switch in switches_and_lights: if switch.methods(tellcore_constants.TELLSTICK_DIM): lights.append(TellstickLight(switch)) def _device_event_callback(id_, method, data, cid): """ Called from the TelldusCore library to update one device """ for light_device in lights: if light_device.tellstick_device.id == id_: # Execute the update in another thread light_device.update_ha_state(True) break callback_id = core.register_device_event(_device_event_callback) def unload_telldus_lib(event): """ Un-register the callback bindings """ if callback_id is not None: core.unregister_callback(callback_id) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, unload_telldus_lib) add_devices_callback(lights)
def setup(hass, config): """ Register services or listen for events that your component needs. """ logger = logging.getLogger(__name__) try: import tellcore.telldus as telldus import tellcore.constants as tellcore_constants except ImportError: logger.exception("Failed to import tellcore") return False core = telldus.TelldusCore() sensors = core.sensors() if len(sensors) == 0: logger.error("No Tellstick sensors found") return False sensor_value_descriptions = { tellcore_constants.TELLSTICK_TEMPERATURE: DatatypeDescription('temperature', config[DOMAIN]['temperature_scale']), tellcore_constants.TELLSTICK_HUMIDITY: DatatypeDescription('humidity', ' %'), tellcore_constants.TELLSTICK_RAINRATE: DatatypeDescription('rain rate', ''), tellcore_constants.TELLSTICK_RAINTOTAL: DatatypeDescription('rain total', ''), tellcore_constants.TELLSTICK_WINDDIRECTION: DatatypeDescription('wind direction', ''), tellcore_constants.TELLSTICK_WINDAVERAGE: DatatypeDescription('wind average', ''), tellcore_constants.TELLSTICK_WINDGUST: DatatypeDescription('wind gust', '') } def update_sensor_value_state(sensor_name, sensor_value): """ Update the state of a sensor value """ sensor_value_description = \ sensor_value_descriptions[sensor_value.datatype] sensor_value_name = '{} {}'.format(sensor_name, sensor_value_description.name) entity_id = ENTITY_ID_FORMAT.format(util.slugify(sensor_value_name)) state = sensor_value.value state_attr = { ATTR_FRIENDLY_NAME: sensor_value_name, ATTR_UNIT_OF_MEASUREMENT: sensor_value_description.unit } hass.states.set(entity_id, state, state_attr) sensor_value_datatypes = [ tellcore_constants.TELLSTICK_TEMPERATURE, tellcore_constants.TELLSTICK_HUMIDITY, tellcore_constants.TELLSTICK_RAINRATE, tellcore_constants.TELLSTICK_RAINTOTAL, tellcore_constants.TELLSTICK_WINDDIRECTION, tellcore_constants.TELLSTICK_WINDAVERAGE, tellcore_constants.TELLSTICK_WINDGUST ] def update_sensor_state(sensor): """ Updates all the sensor values from the sensor """ try: sensor_name = config[DOMAIN][str(sensor.id)] except KeyError: if 'only_named' in config[DOMAIN]: return sensor_name = str(sensor.id) for datatype in sensor_value_datatypes: if datatype & int(config[DOMAIN]['datatype_mask']) and \ sensor.has_value(datatype): update_sensor_value_state(sensor_name, sensor.value(datatype)) # pylint: disable=unused-argument def update_sensors_state(time): """ Update the state of all sensors """ for sensor in sensors: update_sensor_state(sensor) update_sensors_state(None) hass.track_time_change(update_sensors_state, second=[0, 30]) return True
now = datetime.datetime.now() metric_timestamp = sensor.value(tdconst.TELLSTICK_TEMPERATURE).datetime if (now - metric_timestamp).total_seconds() > 3600: #print "VALUE TOO OLD {}".format(my_sensors[sensor.id]["name"]) continue result.append({ "id": sensor.id, "idx": my_sensors[sensor.id]["idx"], "type": "Temp + Humidity", "temperature": sensor.value(tdconst.TELLSTICK_TEMPERATURE).value, "humidity": sensor.value(tdconst.TELLSTICK_HUMIDITY).value, "name": my_sensors[sensor.id]["name"], }) return result MY_SENSORS = parse_sensors(config) print json.dumps( get_sensor_values(td.TelldusCore().sensors(), MY_SENSORS, sys.argv[1] if len(sys.argv) > 1 else None))
class SchedulerAPI(object): core = td.TelldusCore() def __init__(self, api, config): self.config = config self.jobs = config['jobs'] api.add_route( 'scheduler', { 'joblist': { 'fn': self.joblist }, 'jobinfo': { 'fn': self.jobinfo, 'inputs': [{ 'name': 'id', 'type': 'string', 'description': 'Jobs unique identifier' }] }, 'setjob': { 'fn': self.setjob, 'inputs': [ { 'name': 'id', 'type': 'int', 'description': 'The job id, when updating an existing job' }, { 'name': 'deviceId', 'type': 'string', 'description': 'The device id to schedule. Only valid when creating a new job' }, { 'name': 'method', 'type': 'string', 'description': 'What to do when the schedule runs. This should be any of the method constants' }, { 'name': 'methodValue', 'type': 'int', 'description': 'Only required for methods that requires this.' }, { 'name': 'type', 'type': 'dropdown', 'description': 'This can be \'time\', \'sunrise\' or \'sunset\'', 'options': ['time', 'sunrise', 'sunset'] }, { 'name': 'hour', 'type': 'int', 'description': 'A value between 0-23' }, #, 'default': time.strftime("%H") }, { 'name': 'minute', 'type': 'int', 'description': 'A value between 0-59' }, { 'name': 'offset', 'type': 'int', 'description': 'A value between -1439-1439. This is only used when type is either \'sunrise\' or \'sunset\'' }, { 'name': 'randomInterval', 'type': 'int', 'description': 'Number of minutes after the specified time to randomize.' }, { 'name': 'retries', 'type': 'int', 'description': 'If the client is offline, this specifies the number of times to retry executing the job before consider the job as failed.' }, { 'name': 'retryInterval', 'type': 'int', 'description': 'The number of minutes between retries. Example: If retries is 3 and retryInterval is 5 the scheduler will try executing the job every five minutes for fifteen minutes.' }, { 'name': 'reps', 'type': 'int', 'description': 'Number of times to resend the job to the client, for better reliability' }, { 'name': 'active', 'type': 'dropdown', 'description': 'Is the job active or paused?', 'options': ['1|1 (active)', '0|0 (paused)'] }, { 'name': 'weekdays', 'type': 'dropdown-multiple', 'description': 'A comma separated list of weekdays. 1 is monday. Example: 2,3,4', 'options': [ '1|1 (Monday)', '2|2 (Tuesday)', '3|3 (Wednesday)', '4|4 (Thursday)', '5|5(Friday)', '6|6(Saturday)', '7|7(Sunday)' ] } ] }, 'removejob': { 'fn': self.removejob, 'inputs': [{ 'name': 'id', 'type': 'string', 'description': 'The job id' }] } }) def joblist(self, func): """Job list""" return {'job': [job for id, job in self.jobs.iteritems()]} def jobinfo(self, func, id): if id and id in self.jobs: return self.jobs[id] return {'error': 'The request job was not found'} def calcNextRunTime(self, job): hour = int(job['hour']) minute = int(job['minute']) weekdays = job['weekdays'] currentTime = dt.datetime.now().replace(second=0, microsecond=0) def calcRunTime(weekday): newDate = currentTime.replace(hour=hour, minute=minute, second=0) + timedelta(days=weekday) if newDate < currentTime: newDate += timedelta(days=7) return newDate # Convert days into 0 based integers daysToRun = map(lambda d: int(d) - 1, weekdays.split(',')) allDays = [calcRunTime(day) for day in daysToRun] allDays.sort() if not allDays: return None nextRunTime = allDays[0] return self.dateTimeToEpoch(nextRunTime) def dateTimeToEpoch(self, timeObj): return int(time.mktime(timeObj.timetuple())) def removejob(self, func, id): if id in self.jobs: del self.jobs[id] self.config.notifyKey('jobs') return {"status": "OK"} def setjob(self, func, id, deviceId, method, methodValue, type, hour, minute, offset, randomInterval, retries, retryInterval, reps, active, weekdays): # If no ID is provided, find the next available if id == 0: keys = self.jobs.keys() if len(keys) == 0: id = 1 else: id = max([int(k) for k in keys]) + 1 id = str(id) newJob = { 'id': id, 'deviceId': deviceId, 'method': method or 1, 'methodValue': methodValue or 0, 'type': type, 'hour': hour or 0, 'minute': minute or 0, 'offset': offset or 0, 'randomInterval': randomInterval, 'retries': retries or 3, 'retryInterval': retryInterval or 5, 'reps': reps or 1, 'active': active or '1', 'weekdays': weekdays } self.jobs[id] = newJob self.config.notifyKey('jobs') nextRunTime = self.jobs[id]['nextRunTime'] return {'id': id, 'nextRunTime': nextRunTime}
Requires: bottle tellcore-py Start with command: python3 http_api.py sensors.json """ import sys import tellcore.telldus as td from bottle import route, response, request, run from device.device import list_devices, turn_off, turn_on from sensor.sensor import TellstickSensor core = td.TelldusCore() # borrowed from https://ongspxm.github.io/blog/2017/02/bottlepy-cors/ def enable_cors(func): def wrapper(*args, **kwargs): response.set_header("Access-Control-Allow-Origin", "*") response.set_header("Content-Type", "application/json") response.set_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") response.set_header("Access-Control-Allow-Headers", "Access-Control-Allow-Origin, Content-Type") # skip the function if it is not needed if request.method == 'OPTIONS': return
class TellstickAPI(object): """ Mimick Telldus Live """ config = None core = td.TelldusCore() sensors = {} jobs = {} def __init__(self, api, config, version): self.config = config self.version = version self.load_devices() self.load_sensors() self.jobs['1'] = { "id": "335108", "deviceId": "2", "method": "16", "methodValue": "217", "nextRunTime": 0, "type": "time", "hour": "6", "minute": "25", "offset": 0, "randomInterval": 0, "retries": 3, "retryInterval": 5, "reps": 1, "active": "0", "weekdays": "1,2,3,4,5" } id = { 'name': 'id', 'type': 'int', 'description': 'The id of the device' } api.add_route( 'devices', { 'list': { 'fn': self.devices_list, 'inputs': { 'name': 'supportedMethods', 'type': 'int', 'description': '' } } }) api.add_route( 'device', { 'add': { 'fn': self.device_add, 'inputs': [{ 'name': 'clientId', 'type': 'int', 'description': 'The id of the client' }, { 'name': 'name', 'type': 'string', 'description': '' }, { 'name': 'protocol', 'type': 'string', 'description': '' }, { 'name': 'model', 'type': 'string', 'description': '' }] }, 'info': { 'fn': self.device_info, 'inputs': [ id, { 'name': 'supportedMethods', 'type': 'int', 'description': '' } ] }, 'setparameter': { 'fn': self.device_set_parameter, 'inputs': [ id, { 'name': 'parameter', 'type': 'string', 'description': '' }, { 'name': 'value', 'type': 'string', 'description': '' } ] }, 'setname': { 'fn': self.device_set_attr, 'description': 'Renames a device', 'inputs': [ id, { 'name': 'name', 'type': 'string', 'description': '' } ] }, 'setmodel': { 'fn': self.device_set_attr, 'description': 'Set device model', 'inputs': [ id, { 'name': 'model', 'type': 'string', 'description': '' } ] }, 'setprotocol': { 'fn': self.device_set_attr, 'description': 'Set device protocol', 'inputs': [ id, { 'name': 'protocol', 'type': 'string', 'description': '' } ] }, 'command': { 'fn': self.device_command, 'inputs': [ id, { 'name': 'value', 'type': 'int', 'description': '' }, { 'name': 'method', 'type': 'int', 'description': '' } ] }, 'remove': { 'fn': self.device_remove, 'inputs': id }, 'dim': { 'fn': self.device_command, 'inputs': [id, { 'name': 'level', 'type': 'int', 'description': '' }] }, 'bell': { 'fn': self.device_command, 'inputs': id }, 'down': { 'fn': self.device_command, 'inputs': id }, 'learn': { 'fn': self.device_command, 'inputs': id }, 'stop': { 'fn': self.device_command, 'inputs': id }, 'turnon': { 'fn': self.device_command, 'inputs': id }, 'turnoff': { 'fn': self.device_command, 'inputs': id }, 'up': { 'fn': self.device_command, 'inputs': id }, 'toggle': { 'fn': self.device_command, 'inputs': id }, 'execute': { 'fn': self.device_command, 'inputs': id } }) api.add_route( 'clients', { 'list': { 'fn': self.clients_list, 'inputs': { 'name': 'extras', 'type': 'string', 'description': 'Returns a list of all clients associated with the current user' } } }) api.add_route( 'client', { 'info': { 'fn': self.client_info, 'inputs': { 'name': 'id', 'type': 'int', 'description': 'The id of the client' } } }) api.add_route( 'sensors', { 'list': { 'fn': self.sensors_list, 'inputs': { 'name': 'includeignored', 'type': 'int', 'description': 'Set to 1 to include ignored sensors' } } }) api.add_route( 'sensor', { 'info': { 'fn': self.sensor_info, 'inputs': { 'name': 'id', 'type': 'int', 'description': '' } }, 'setignore': { 'fn': self.sensor_setignore, 'inputs': [{ 'name': 'id', 'type': 'int', 'description': '' }, { 'name': 'ignore', 'type': 'int', 'description': '' }] }, 'setname': { 'fn': self.sensor_setname, 'inputs': [{ 'name': 'id', 'type': 'int', 'description': '' }, { 'name': 'name', 'type': 'string', 'description': '' }] } }) api.add_route('group', {'remove': { 'fn': self.device_remove, 'inputs': id }}) def devices_list(self, func, supportedMethods): """Returns a list of all clients associated with the current user.""" # TODO is this necessary? self.load_devices() return { 'device': [ self.device_to_dict(device, supportedMethods, False) for device in self.devices.values() ] } @dec_response def device_add(self, func, clientid, name, protocol, model): """Adds a device""" if (self.config['editable'] is False): return "Client is not editable" if (clientid != self.config['client_id']): return "Client \"" + str(clientid) + "\" not found!" try: resp = self.core.add_device(name, protocol, model) if type(resp) is td.Device: return [TELLSTICK_SUCCESS, resp.id] except Exception as e: return e def device_info(self, func, id, supportedMethods): """Information about a device""" device = self.get_device(id) if not device: return map_response(TELLSTICK_ERROR_DEVICE_NOT_FOUND, id) return self.device_to_dict(device, supportedMethods, True) @dec_response def device_set_parameter(self, func, id, parameter, value): """Set device parameter""" device = self.get_device(id) if not device: return [TELLSTICK_ERROR_DEVICE_NOT_FOUND, id] try: device.set_parameter(parameter, value) except Exception as e: return e return TELLSTICK_SUCCESS @dec_response def device_set_attr(self, func, id, value): device = self.get_device(id) if not device: return [TELLSTICK_ERROR_DEVICE_NOT_FOUND, id] attr = func[3:].lower() if device.__setattr__(attr, value): return TELLSTICK_SUCCESS return TELLSTICK_ERROR_NOT_FOUND def get_device(self, id): self.load_devices() if (self.devices.has_key(id)): return self.devices[id] return None @dec_response def device_remove(self, func, id): device = self.get_device(id) if not device: return [TELLSTICK_ERROR_DEVICE_NOT_FOUND, id] try: device.remove() except Exception as e: return e return TELLSTICK_SUCCESS @dec_response def device_command(self, func, id, value=0, method=0): device = self.get_device(id) if not device: return [TELLSTICK_ERROR_DEVICE_NOT_FOUND, id] try: if (method == TELLSTICK_BELL or func == 'bell'): device.bell() elif (method == TELLSTICK_DIM or func == 'dim'): device.dim(value) elif (method == TELLSTICK_DOWN or func == 'down'): device.down() elif (method == TELLSTICK_LEARN or func == 'learn'): device.learn() elif (method == TELLSTICK_STOP or func == 'stop'): device.stop() elif (method == TELLSTICK_TURNON or func == 'turnon'): device.turn_on() elif (method == TELLSTICK_TURNOFF or func == 'turnoff'): device.turn_off() elif (method == TELLSTICK_UP or func == 'up'): device.up() elif (method == TELLSTICK_TOGGLE or func == 'toggle'): self.toggle_device(device) elif (method == TELLSTICK_EXECUTE or func == 'execute'): device.execute() else: return "Device " + str(id) + " does not support method " + str( method) except Exception as e: return e return TELLSTICK_SUCCESS def toggle_device(self, device): # TODO or last command was a dim with value > 0? if device.last_sent_command(TELLSTICK_TURNON + TELLSTICK_TURNOFF) == TELLSTICK_TURNON: device.turn_off() else: device.turn_on() def clients_list(self, func, extras): return {'client': [self.get_client_info()]} def client_info(self, func, id): if (id != self.config['client_id']): return {"error": "Client \"" + str(id) + "\" not found!"} return self.get_client_info() def sensors_list(self, func, includeIgnored): self.load_sensors() includeIgnored = True if includeIgnored == 1 else False return { 'sensor': [ self.sensor_to_dict(sensor, False) for id, sensor in self.sensors.iteritems() if includeIgnored or int(sensor.ignore) == 0 ] } def get_sensor(self, id): self.load_sensors() # The ID should be an integer, but we store them in the dictionary as # strings, so treat as such id = str(id) if (self.sensors.has_key(id)): return self.sensors[id] return None def sensor_info(self, func, id): sensor = self.get_sensor(id) if not sensor: return map_response("Sensor " + "\"" + str(id) + "\" not found!") return self.sensor_to_dict(sensor, True) @dec_response def sensor_setignore(self, func, id, ignore): sensor = self.get_sensor(id) if not sensor: return "Sensor " + "\"" + str(id) + "\" not found!" sensor.ignore = 1 if ignore == 1 else 0 return TELLSTICK_SUCCESS @dec_response def sensor_setname(self, func, id, name): sensor = self.get_sensor(id) if not sensor: return "Sensor " + "\"" + str(id) + "\" not found!" sensor.name = name return TELLSTICK_SUCCESS def load_devices(self): """ Read in all devices using tellcore-py library and convert into id keyed dictionary """ self.devices = {device.id: device for device in self.core.devices()} def load_sensors(self): """ Read in all sensors using tellcore-py library and convert into id keyed dictionary """ sensors = self.core.sensors() if (self.config['debug']): sensors.append( MSensor('prot1', 'model1', 9998, TELLSTICK_TEMPERATURE)) sensors.append( MSensor('prot2', 'model2', 9999, TELLSTICK_TEMPERATURE + TELLSTICK_HUMIDITY)) self.sensors = { str(rawsensor.id): TASensor(self.config, rawsensor) for rawsensor in sensors } def editable(self): return 1 if self.config['editable'] else 0 def client(self): return self.config['client_id'] or 1 def clientName(self): return self.config['client_name'] or '' def device_type_to_string(self, type): if (type == TELLSTICK_TYPE_DEVICE): return 'device' elif (type == TELLSTICK_TYPE_GROUP): return 'group' else: return 'scene' """ Converts a device into a dictionary ready for outputting to json/xml info is used to indicate whether it is used to output for info as per spec """ def device_to_dict(self, device, methods_supported, info): methods_supported = methods_supported or 0 # We support toggle ourselves, so add it to the supported list deviceMethods = device.methods(methods_supported) if methods_supported & TELLSTICK_TOGGLE == TELLSTICK_TOGGLE: deviceMethods |= TELLSTICK_TOGGLE dict = { 'id': device.id, 'name': device.name, 'state': device.last_sent_command(methods_supported), 'statevalue': device.last_sent_value(), 'methods': deviceMethods, 'type': self.device_type_to_string(device.type), 'online': 1, 'editable': self.editable() } if info: dict['protocol'] = device.protocol dict['model'] = device.model dict['parameter'] = device.parameters() else: dict['client'] = self.client() dict['clientName'] = self.clientName() dict = bh.set_attribute(dict) return dict def sensor_to_dict(self, sensor, info): # Set default value in case we get back nothing lastUpdated = -1 # Populate sensor data using calls to core library sensor_data = [] for type in [{ 'name': 'temp', 'key': TELLSTICK_TEMPERATURE }, { 'name': 'humidity', 'key': TELLSTICK_HUMIDITY }]: if sensor.raw.datatypes & type['key'] != 0: svalue = sensor.raw.value(type['key']) lastUpdated = svalue.timestamp sensor_data.append({ 'name': type['name'], 'value': svalue.value }) base_dict = { 'id': sensor.raw.id, 'name': sensor.name, 'lastUpdated': lastUpdated, 'ignored': int(sensor.ignore), 'online': 1, 'editable': self.editable(), 'client': self.client() } if info: extra_dict = { 'data': sensor_data, 'protocol': sensor.raw.protocol, 'sensorId': sensor.raw.id, 'timezoneoffset': 7200 } base_dict = dict(base_dict.items() + extra_dict.items()) else: base_dict['clientName'] = self.clientName() return base_dict def get_client_info(self): return { 'id': self.config['client_id'] or 1, 'uuid': '00000000-0000-0000-0000-000000000000', 'name': self.config['client_name'] or '', 'online': '1', 'editable': 1 if self.config['editable'] else 0, 'version': self.version, 'type': 'TellProx' }
def turn_on_device(id): core = td.TelldusCore() core.sensors() device = find_device(id, core.devices()) if device is not None: device.turn_on()
class TellstickAPI(object): """ Mimick Telldus Live """ config = None core = td.TelldusCore() sensors = {} def __init__(self, api, config): self.config = config self.load_devices() self.load_sensors() api.add_route('devices', self.route_devices) api.add_route('device', self.route_device) api.add_route('clients', self.route_clients) api.add_route('client', self.route_client) api.add_route('sensors', self.route_sensors) api.add_route('sensor', self.route_sensor) #api.add_route('group', 'not implemented yet' #api.add_route('scheduler', 'not implemented yet' def load_devices(self): """ Read in all devices using tellcore-py library and convert into id keyed dictionary """ self.devices = { device.id: device for device in self.core.devices() } def load_sensors(self): """ Read in all sensors using tellcore-py library and convert into id keyed dictionary """ sensors = self.core.sensors() if (self.config['debug']): sensors.append(MSensor('prot1', 'model1', 9998, TELLSTICK_TEMPERATURE)) sensors.append(MSensor('prot2', 'model2', 9999, TELLSTICK_TEMPERATURE + TELLSTICK_HUMIDITY)) self.sensors = { str(rawsensor.id) : TASensor(self.config, rawsensor) for rawsensor in sensors } def route_devices(self, func): if not func == 'list': bh.raise404() supportedMethods = self.get_supported_methods() self.load_devices() return { 'device': [ self.device_to_dict(device, supportedMethods, False) for k, device in self.devices.iteritems() ]} def route_device(self, func): if (func == 'add'): id = '' resp = self.add_device() if type(resp) is td.Device: id = resp.id resp = TELLSTICK_SUCCESS return self.map_response(resp, id) else: """ With the only function that does not require ID out of the way, determine the device we want to interact with """ id = bh.get_int('id') self.load_devices() if (self.devices.has_key(id)): device = self.devices[id] if (func == 'info'): return self.device_to_dict(device, self.get_supported_methods(), True) elif (func[:3] == 'set'): resp = self.device_set_parameter(device, func[3:]) elif (func == 'command'): resp = self.device_command(device, bh.get_int('method'), bh.get_int('value')) else: resp = self.device_command(device, func, bh.get_int('level')) if resp is None: bh.raise404() else: resp = "Device " + "\"" + str(id) + "\" not found!" return self.map_response(resp) def add_device(self): if (self.config['editable'] is False): return "Client is not editable" clientid = bh.get_int('id') if (clientid != self.config['client_id']): return "Client \"" + str(clientid) + "\" not found!" try: return self.core.add_device( bh.get_string('name'), bh.get_string('protocol'), bh.get_string('model')) except Exception as e: return e def device_command(self, device, func, value = ''): try: if (func == 'bell'): device.bell() elif (func == 'dim'): device.dim(value) elif (func == 'down'): device.down() elif (func == 'learn'): device.learn() elif (func == 'remove'): device.remove() elif (func == 'stop'): device.stop() elif (func == 'turnon'): device.turn_on() elif (func == 'turnoff'): device.turn_off() elif (func == 'up'): device.up() elif (func == 'toggle'): self.toggle_device(device) except Exception as e: return e return TELLSTICK_SUCCESS def toggle_device(self, device): if device.last_sent_command(TELLSTICK_TURNON + TELLSTICK_TURNOFF) == 1: device.turn_off() else: device.turn_on() def device_set_parameter(self, device, attr): if (attr == 'parameter'): resp = device.set_parameter(bh.get_string('parameter'), bh.get_string('value')) elif attr in ['name', 'model', 'protocol']: value = bh.get_string(attr) if value is None: return "Attribute \"" + attr + "\" not found" resp = device.__setattr__(attr, value) else: bh.raise404() if resp: return TELLSTICK_SUCCESS else: return TELLSTICK_ERROR_NOT_FOUND def route_clients(self, func): if not func == 'list': bh.raise404() return { 'client': [self.get_client_info()] } def route_client(self, func): if not func == 'info': bh.raise404() clientid = clientid = bh.get_int('id') if (clientid != self.config['client_id']): return { "error" : "Client \"" + str(clientid) + "\" not found!" } return self.get_client_info() def route_sensors(self, func): if not func == 'list': bh.raise404() self.load_sensors() includeIgnored = True if bh.get_int('includeignored') == 1 else False return { 'sensor': [ self.sensor_to_dict(sensor, False) for id, sensor in self.sensors.iteritems() if includeIgnored or int(sensor.ignore) == 0 ]} def route_sensor(self, func): # The ID should be an integer, but we store them in the dictionary as # strings, so treat as such id = str(bh.get_int('id')) self.load_sensors() resp = TELLSTICK_SUCCESS if (self.sensors.has_key(id)): sensor = self.sensors[id] if (func == 'info'): return self.sensor_to_dict(sensor, True) elif (func == 'setignore'): sensor.ignore = 1 if bh.get_int('ignore') == 1 else 0 elif (func == 'setname'): sensor.name = bh.get_string('name') if resp is None: bh.raise404() else: resp = "Sensor " + "\"" + str(id) + "\" not found!" return self.map_response(resp) def editable(self): return 1 if self.config['editable'] else 0 def client(self): return self.config['client_id'] or 1 def clientName(self): return self.config['client_name'] or '' def device_type_to_string(self, type): if (type == TELLSTICK_TYPE_DEVICE): return 'device' elif (type == TELLSTICK_TYPE_GROUP): return 'group' else: return 'scene' """ Converts a device into a dictionary ready for outputting to json/xml info is used to indicate whether it is used to output for info as per spec """ def device_to_dict(self, device, methods_supported, info): json = { 'id': device.id, 'name': device.name, 'state': device.last_sent_command(methods_supported), 'statevalue': device.last_sent_value(), 'methods': device.methods(methods_supported), 'type': self.device_type_to_string(device.type), 'online': 1, 'editable': self.editable() } if info: json['protocol'] = None # TODO json['model'] = None # TODO else: json['client'] = self.client() json['clientName'] = self.clientName() json = bh.set_attribute(json) return json def sensor_to_dict(self, sensor, info): # Set default value in case we get back nothing lastUpdated = -1 # Populate sensor data using calls to core library sensor_data = [] for type in [ {'name': 'temp', 'key': TELLSTICK_TEMPERATURE }, {'name': 'humidity', 'key': TELLSTICK_HUMIDITY } ]: if sensor.raw.datatypes & type['key'] != 0: svalue = sensor.raw.value(type['key']) lastUpdated = svalue.timestamp sensor_data.append({'name': type['name'], 'value': svalue.value}) json = { 'id' : sensor.raw.id, 'name' : sensor.name, 'lastUpdated': lastUpdated, 'ignored' : int(sensor.ignore), 'online' : 1, 'editable' : self.editable(), 'client' : self.client() } if info: extra_json = { 'data': sensor_data, 'protocol': sensor.raw.protocol, 'sensorId': sensor.raw.id, 'timezoneoffset': 7200 } json = dict(json.items() + extra_json.items()) else: json['clientName'] = self.clientName() return json def get_client_info(self): return { 'id': self.config['client_id'] or 1, 'uuid':'00000000-0000-0000-0000-000000000000', 'name':self.config['client_name'] or '', 'online': '1', 'editable': 1 if self.config['editable'] else 0, 'version':'0.24', 'type':'TellProx' } def map_response(self, cmdresp, id = '', method = ''): if (cmdresp == TELLSTICK_SUCCESS): resp = { "status" : "success" } if not id == '': resp['id'] = id return resp elif isinstance(cmdresp, int): id = str(id) if (cmdresp == TELLSTICK_ERROR_DEVICE_NOT_FOUND): msg = "Device " + "\"" + id + "\" not found!" elif (cmdresp == TELLSTICK_ERROR_BROKEN_PIPE): msg = "Broken pipe" elif (cmdresp == TELLSTICK_ERROR_COMMUNICATING_SERVICE): msg = "Communicating service" elif (cmdresp == TELLSTICK_ERROR_COMMUNICATION): msg = "Communication" elif (cmdresp == TELLSTICK_ERROR_CONNECTING_SERVICE): msg = "Cannot connect to service" elif (cmdresp == TELLSTICK_ERROR_METHOD_NOT_SUPPORTED): msg = "Device \"" + id + "\" does not support method \"" + str(method) + "\"" elif (cmdresp == TELLSTICK_ERROR_NOT_FOUND): msg = "Not found" elif (cmdresp == TELLSTICK_ERROR_PERMISSION_DENIED): msg = "Permission denied" elif (cmdresp == TELLSTICK_ERROR_SYNTAX): msg = "Syntax error" else: msg = "Unknown response" else: msg = str(cmdresp) return { "error" : msg } """ Helper Functions """ def get_supported_methods(self): return bh.get_int('supportedMethods') or 0
def setup_platform(opp, config, add_entities, discovery_info=None): """Set up the Tellstick sensors.""" sensor_value_descriptions = { tellcore_constants.TELLSTICK_TEMPERATURE: DatatypeDescription("temperature", config.get(CONF_TEMPERATURE_SCALE)), tellcore_constants.TELLSTICK_HUMIDITY: DatatypeDescription("humidity", PERCENTAGE), tellcore_constants.TELLSTICK_RAINRATE: DatatypeDescription("rain rate", ""), tellcore_constants.TELLSTICK_RAINTOTAL: DatatypeDescription("rain total", ""), tellcore_constants.TELLSTICK_WINDDIRECTION: DatatypeDescription("wind direction", ""), tellcore_constants.TELLSTICK_WINDAVERAGE: DatatypeDescription("wind average", ""), tellcore_constants.TELLSTICK_WINDGUST: DatatypeDescription("wind gust", ""), } try: tellcore_lib = telldus.TelldusCore() except OSError: _LOGGER.exception("Could not initialize Tellstick") return sensors = [] datatype_mask = config.get(CONF_DATATYPE_MASK) if config[CONF_ONLY_NAMED]: named_sensors = {} for named_sensor in config[CONF_ONLY_NAMED]: name = named_sensor[CONF_NAME] proto = named_sensor.get(CONF_PROTOCOL) model = named_sensor.get(CONF_MODEL) id_ = named_sensor[CONF_ID] if proto is not None: if model is not None: named_sensors[f"{proto}{model}{id_}"] = name else: named_sensors[f"{proto}{id_}"] = name else: named_sensors[id_] = name for tellcore_sensor in tellcore_lib.sensors(): if not config[CONF_ONLY_NAMED]: sensor_name = str(tellcore_sensor.id) else: proto_id = f"{tellcore_sensor.protocol}{tellcore_sensor.id}" proto_model_id = "{}{}{}".format(tellcore_sensor.protocol, tellcore_sensor.model, tellcore_sensor.id) if tellcore_sensor.id in named_sensors: sensor_name = named_sensors[tellcore_sensor.id] elif proto_id in named_sensors: sensor_name = named_sensors[proto_id] elif proto_model_id in named_sensors: sensor_name = named_sensors[proto_model_id] else: continue for datatype in sensor_value_descriptions: if datatype & datatype_mask and tellcore_sensor.has_value( datatype): sensor_info = sensor_value_descriptions[datatype] sensors.append( TellstickSensor(sensor_name, tellcore_sensor, datatype, sensor_info)) add_entities(sensors)
for device in core.devices(): if status == 'on': device.turn_on() else: device.turn_off() try: import asyncio loop = asyncio.get_event_loop() dispatcher = td.AsyncioCallbackDispatcher(loop) except ImportError: loop = None dispatcher = td.QueuedCallbackDispatcher() core = td.TelldusCore(callback_dispatcher=dispatcher) callbacks = [core.register_raw_device_event(raw_event)] for device in core.devices(): device.turn_on() for device in core.devices(): device.turn_off() try: if loop: loop.run_forever() else: import time while True: core.callback_dispatcher.process_pending_callbacks()
def turn_off_device(id): core = td.TelldusCore() device = find_device(id, core.devices()) if device is not None: device.turn_off()