def __handleDeviceParametersRequest(self, msg): args = msg.argument(0).toNative() device = self.device(args.get('id', 0)) if not device: return reply = LiveMessage('device-datareport') data = { 'id': args['id'] } if args.get('parameters', 0) == 1: parameters = json.dumps( device.allParameters(), separators=(',', ':'), sort_keys=True ) data['parameters'] = parameters data['parametersHash'] = hashlib.sha1(parameters).hexdigest() if args.get('metadata', 0) == 1: metadata = json.dumps( device.metadata(), separators=(',', ':'), sort_keys=True ) data['metadata'] = metadata data['metadataHash'] = hashlib.sha1(metadata).hexdigest() reply.append(data) self.live.send(reply)
def sensorValueUpdated(self, device, valueType, value, scale): """ Called every time a sensors value is updated. """ if device.isSensor() == False: return self.observers.sensorValueUpdated(device, valueType, value, scale) if not self.live.registered or device.ignored(): # don't send if ignored return msg = LiveMessage("SensorEvent") sensor = { 'name': device.name(), 'protocol': device.protocol(), 'model': device.model(), 'sensor_id': device.id(), } battery = device.battery() if battery is not None: sensor['battery'] = battery msg.append(sensor) values = device.sensorValues() valueList = [] for valueType in values: for value in values[valueType]: valueList.append({ 'type': valueType, 'lastUp': str(int(time.time())), 'value': str(value['value']), 'scale': value['scale'] }) msg.append(valueList) self.live.send(msg)
def __sendSensorReport(self, forceIgnored=False): if not self.live.registered: return l = [] for d in self.devices: if d.isSensor() == False or (d.ignored() and not forceIgnored): continue sensorFrame = [] sensor = { 'name': d.name(), 'protocol': d.protocol(), 'model': d.model(), 'sensor_id': d.id(), } battery = d.battery() if battery is not None: sensor['battery'] = battery sensorFrame.append(sensor) valueList = [] # TODO(micke): Add current values sensorFrame.append(valueList) l.append(sensorFrame) msg = LiveMessage("SensorsReport") msg.append(l) self.live.send(msg)
def __sendSensorReport(self): if not self.live.registered: return l = [] for d in self.devices: if d.isSensor() == False: continue sensorFrame = [] sensor = { 'name': d.name(), 'protocol': d.protocol(), 'model': d.model(), 'sensor_id': d.id(), } battery = d.battery() if battery is not None: sensor['battery'] = battery sensorFrame.append(sensor) valueList = [] values = d.sensorValues() for valueType in values: for value in values[valueType]: valueList.append({ 'type': valueType, 'lastUp': str(value['lastUpdated']), 'value': str(value['value']), 'scale': value['scale'] }) #d.lastUpdatedLive[valueType] = int(time.time()) # Telldus Live! does not aknowledge sensorreportupdates yet, so don't count this yet (wait for Cassandra only) sensorFrame.append(valueList) l.append(sensorFrame) msg = LiveMessage("SensorsReport") msg.append(l) self.live.send(msg)
def __sendDeviceReport(self): if not self.live.registered: return l = [] for d in self.devices: if not d.isDevice(): continue (state, stateValue) = d.state() device = { 'id': d.id(), 'name': d.name(), 'methods': d.methods(), 'state': state, 'stateValue': stateValue, 'protocol': d.protocol(), 'model': d.model(), 'transport': d.typeString(), 'ignored': d.ignored() } battery = d.battery() if battery is not None: device['battery'] = battery l.append(device) msg = LiveMessage("DevicesReport") msg.append(l) self.live.send(msg)
def sensorValuesUpdated(self, device, values): """ Called every time a sensor value is updated. :param device: The device/sensor being updated :param values: A list with all values updated """ if device.isSensor() is False: return shouldUpdateLive = False for valueElement in values: valueType = valueElement['type'] value = valueElement['value'] scale = valueElement['scale'] self.observers.sensorValueUpdated(device, valueType, value, scale) self.sensorValueUpdated(device, valueType, value, scale) if valueType not in device.lastUpdatedLive \ or valueType not in device.valueChangedTime \ or device.valueChangedTime[valueType] > device.lastUpdatedLive[valueType] \ or device.lastUpdatedLive[valueType] < (int(time.time()) - 300): shouldUpdateLive = True break if not self.live.registered or device.ignored() or not shouldUpdateLive: # don't send if not connected to live, sensor is ignored or if # values haven't changed and five minutes hasn't passed yet return msg = LiveMessage("SensorEvent") # pcc = packageCountChecked - already checked package count, # just accept it server side directly sensor = { 'name': device.name(), 'protocol': device.protocol(), 'model': device.model(), 'sensor_id': device.id(), 'pcc': 1, } battery = device.battery() if battery is not None: sensor['battery'] = battery msg.append(sensor) # small clarification: valueType etc that is sent in here is only used for sending # information about what have changed on to observers, below is instead all the values # of the sensor picked up and sent in a sensor event-message (the sensor values # have already been updated in other words) values = device.sensorValues() valueList = [] for valueType in values: device.lastUpdatedLive[valueType] = int(time.time()) for value in values[valueType]: valueList.append({ 'type': valueType, 'lastUp': str(value['lastUpdated']), 'value': str(value['value']), 'scale': value['scale'] }) msg.append(valueList) self.live.send(msg)
def execute(self, triggerInfo=None): triggerInfo = triggerInfo or {} msg = LiveMessage('event-executeaction') msg.append({ 'action': self.id, 'triggerInfo': triggerInfo }) self.event.manager.live.send(msg)
def validate(self, success, failure): self.outstandingRequests.append({ 'started': time.time(), 'success': success, 'failure': failure, }) msg = LiveMessage('event-validatecondition') msg.append({'condition': self.id}) self.event.manager.live.send(msg)
def addDevice(self, device): """ Call this function to register a new device to the device manager. .. note:: The :func:`Device.localId() <telldus.Device.localId>` function in the device must return a unique id for the transport type returned by :func:`Device.typeString() <telldus.Device.localId>` """ cachedDevice = None for i, delDevice in enumerate(self.devices): # Delete the cached device from loaded devices, since it is replaced # by a confirmed/specialised one if delDevice.localId() == device.localId() \ and device.typeString() == delDevice.typeString() \ and not delDevice.confirmed(): cachedDevice = delDevice del self.devices[i] break self.devices.append(device) device.setManager(self) if not cachedDevice: # New device, not stored in local cache self.nextId = self.nextId + 1 device.setId(self.nextId) else: # Transfer parameters from the loaded one device.loadCached(cachedDevice) self.save() if not cachedDevice: self.__deviceAdded(device) if self.live.registered and device.isDevice(): (state, stateValue) = device.state() parameters = json.dumps( device.allParameters(), separators=(',', ':'), sort_keys=True ) deviceDict = { 'id': device.id(), 'name': device.name(), 'methods': device.methods(), 'state': state, 'stateValue': stateValue, 'stateValues': device.stateValues(), 'protocol': device.protocol(), 'model': device.model(), 'parameters': parameters, 'parametersHash': hashlib.sha1(parameters).hexdigest(), 'transport': device.typeString() } msg = LiveMessage("DeviceAdded") msg.append(deviceDict) self.live.send(msg) else: # Previously cached device is now confirmed, TODO notify Live! about this too? self.observers.deviceConfirmed(device)
def rf433RawData(self, data, *__args, **__kwargs): if 'data' in data: data['data'] = int(data['data'], 16) msg = LiveMessage("RawData") msg.append(data) try: self.listener.sendto(msg.toByteArray(), self.clientAddress) except Exception as __error: # for example if listener isn't set pass
def fail(reason): # We failed to set status for some reason, nack the server if 'ACK' in args: msg = LiveMessage('NACK') msg.append({ 'ackid': args['ACK'], 'reason': reason, }) self.live.send(msg) # Abort the DeviceEvent this triggered raise DeviceAbortException()
def sendVersion(self): if self.zwave is None or not self.zwave.controller.version(): return # nothing or not finished yet if not self.listener: return # No listener registered msg = LiveMessage("zwaveinfo") msg.append({'version': self.zwave.controller.version()}) try: self.listener.sendto(msg.toByteArray(), self.clientAddress) except: # for example if listener isn't set pass
def reportRooms(self, rooms, removedRooms=None): report = {} if not rooms and not self.roomlistEmpty and not removedRooms: # only allow empty room reports if we know it has been # explicitly emptied return if rooms or self.roomlistEmpty: report['rooms'] = rooms if removedRooms: report['removedRooms'] = removedRooms msg = LiveMessage('RoomReport') msg.append(report) TelldusLive(self.context).send(msg)
def stateUpdated(self, device, ackId=None, origin=None): if device.isDevice() is False: return extras = {'stateValues': device.stateValues()} if ackId: extras['ACK'] = ackId if origin: extras['origin'] = origin else: extras['origin'] = 'Incoming signal' (state, stateValue) = device.state() if isinstance(stateValue, dict): stateValue = json.dumps(stateValue) else: stateValue = str(stateValue) self.__deviceStateChanged(device, state, stateValue, extras['origin']) self.save() if not self.live.registered: return msg = LiveMessage("DeviceEvent") msg.append(device.id()) msg.append(state) msg.append(str(stateValue)) msg.append(extras) self.live.send(msg)
def sensorValueUpdated(self, device, valueType, value, scale): """ Called every time a sensors value is updated. """ if device.isSensor() is False: return self.observers.sensorValueUpdated(device, valueType, value, scale) if not self.live.registered or device.ignored(): # don't send if not connected to live or sensor is ignored return if valueType in device.lastUpdatedLive \ and (valueType in device.valueChangedTime \ and device.valueChangedTime[valueType] < device.lastUpdatedLive[valueType]) \ and device.lastUpdatedLive[valueType] > (int(time.time()) - 300): # no values have changed since the last live-update, and the last # time this sensor was sent to live was less than 5 minutes ago return msg = LiveMessage("SensorEvent") # pcc = packageCountChecked - already checked package count, # just accept it server side directly sensor = { 'name': device.name(), 'protocol': device.protocol(), 'model': device.model(), 'sensor_id': device.id(), 'pcc': 1, } battery = device.battery() if battery is not None: sensor['battery'] = battery msg.append(sensor) # small clarification: valueType etc that is sent in here is only used for sending # information about what have changed on to observers, below is instead all the values # of the sensor picked up and sent in a sensor event-message (the sensor values # have already been updated in other words) values = device.sensorValues() valueList = [] for valueType in values: for value in values[valueType]: valueList.append({ 'type': valueType, 'lastUp': str(value['lastUpdated']), 'value': str(value['value']), 'scale': value['scale'] }) msg.append(valueList) device.lastUpdatedLive[valueType] = int(time.time()) self.live.send(msg)
def fail(reason): # We failed to set status for some reason, nack the server if not reason: # reason 0 will count as success in device log history reason = Device.FAILED_STATUS_UNKNOWN if 'ACK' in args: msg = LiveMessage('NACK') msg.append({ 'ackid': args['ACK'], 'reason': reason, }) self.live.send(msg) # Abort the DeviceEvent this triggered raise DeviceAbortException()
def __sendDeviceParameterReport(self, device, sendParameters, sendMetadata): reply = LiveMessage('device-datareport') data = {'id': device.id()} if sendParameters: parameters = json.dumps(device.allParameters(), separators=(',', ':'), sort_keys=True) data['parameters'] = parameters data['parametersHash'] = hashlib.sha1(parameters).hexdigest() if sendMetadata: metadata = json.dumps(device.metadata(), separators=(',', ':'), sort_keys=True) data['metadata'] = metadata data['metadataHash'] = hashlib.sha1(metadata).hexdigest() reply.append(data) self.live.send(reply)
def removeDevice(self, deviceId): """Removes a device. .. warning:: This function may only be called by the module supplying the device since removing of a device may be transport specific. """ isDevice = True for i, device in enumerate(self.devices): if device.id() == deviceId: self.__deviceRemoved(deviceId) isDevice = self.devices[i].isDevice() del self.devices[i] break self.save() if self.live.registered and isDevice: msg = LiveMessage("DeviceRemoved") msg.append({'id': deviceId}) self.live.send(msg)
def __sendDeviceReport(self): logging.warning("Send Devices Report") if not self.live.registered: return lst = [] for device in self.devices: if not device.isDevice(): continue (state, stateValue) = device.state() if isinstance(stateValue, dict): stateValue = json.dumps(stateValue) else: stateValue = str(stateValue) parametersHash = hashlib.sha1( json.dumps(device.allParameters(), separators=(',', ':'), sort_keys=True)) metadataHash = hashlib.sha1( json.dumps(device.metadata(), separators=(',', ':'), sort_keys=True)) dev = { 'id': device.id(), 'uuid': device.uuidAsString(), 'name': device.name(), 'methods': device.methods(), 'state': state, 'stateValue': stateValue, 'stateValues': device.stateValues(), 'protocol': device.protocol(), 'model': device.model(), 'parametersHash': parametersHash.hexdigest(), 'metadataHash': metadataHash.hexdigest(), 'transport': device.typeString(), 'ignored': device.ignored() } battery = device.battery() if battery is not None: dev['battery'] = battery lst.append(dev) msg = LiveMessage("DevicesReport") msg.append(lst) self.live.send(msg)
def execute(self, triggerInfo=None): del triggerInfo if self.objectType == 'room': room = self.roomManager.rooms.get(self.objectId, None) if room and room.get('responsible', '') == TelldusLive( self.roomManager.context).uuid: self.roomManager.setMode(self.objectId, self.modeId, self.setAlways) else: msg = LiveMessage('RequestRoomModeSet') msg.append({ 'id': self.objectId, 'mode': self.modeId, 'setAlways': self.setAlways }) TelldusLive(self.roomManager.context).send(msg) else: logging.error('Cannot handle mode change for type %s', self.objectType)
def setMode(self, roomId, mode, setAlways=1): """ Set a room to a new mode """ room = self.rooms.get(roomId, None) if not room: return setAlways = int(setAlways) if setAlways or room['mode'] != mode: if room['mode'] != mode: room['mode'] = mode self.settings['rooms'] = self.rooms live = TelldusLive(self.context) if live.registered and room.get('responsible', '') == live.uuid: # Notify live if we are the owner msg = LiveMessage('RoomModeSet') msg.append({'id': roomId, 'mode': mode}) live.send(msg) self.__modeChanged(roomId, mode, 'room', room.get('name', ''))
def __sendSensorReport(self): if not self.live.registered: return lst = [] for device in self.devices: if device.isSensor() is False: continue sensorFrame = [] sensor = { 'name': device.name(), 'protocol': device.protocol(), 'model': device.model(), 'sensor_id': device.id(), } if device.params() and 'sensorId' in device.params(): sensor['channelId'] = device.params()['sensorId'] battery = device.battery() if battery is not None: sensor['battery'] = battery if hasattr(device, 'declaredDead') and device.declaredDead: # Sensor shouldn't be removed for a while, but don't update it on server side sensor['declaredDead'] = 1 sensorFrame.append(sensor) valueList = [] values = device.sensorValues() for valueType in values: for value in values[valueType]: valueList.append({ 'type': valueType, 'lastUp': str(value['lastUpdated']), 'value': str(value['value']), 'scale': value['scale'] }) # Telldus Live! does not aknowledge sensorreportupdates yet, # so don't count this yet (wait for Cassandra only) # device.lastUpdatedLive[valueType] = int(time.time()) sensorFrame.append(valueList) lst.append(sensorFrame) msg = LiveMessage("SensorsReport") msg.append(lst) self.live.send(msg)
def stateUpdatedFail(self, device, state, stateValue, reason, origin): if not self.live.registered: return if device.isDevice() is False: return if not reason: reason = Device.FAILED_STATUS_UNKNOWN extras = { 'reason': reason, } if origin: extras['origin'] = origin else: extras['origin'] = 'Unknown' msg = LiveMessage('DeviceFailEvent') msg.append(device.id()) msg.append(state) msg.append(stateValue) msg.append(extras) self.live.send(msg)
def stateUpdatedFail(self, device, state, stateValue, reason, origin): if not self.live.registered: return if device.isDevice() == False: return extras = { 'reason': reason, } if origin: extras['origin'] = origin else: extras['origin'] = 'Unknown' (state, stateValue) = device.state() self.__deviceStateChanged(device, state, stateValue) msg = LiveMessage('DeviceFailEvent') msg.append(device.id()) msg.append(state) msg.append(stateValue) msg.append(extras) self.live.send(msg)
def stateUpdated(self, device, ackId=None, origin=None): if device.isDevice() == False: return extras = {} if ackId: extras['ACK'] = ackId if origin: extras['origin'] = origin else: extras['origin'] = 'Incoming signal' (state, stateValue) = device.state() self.__deviceStateChanged(device, state, stateValue) self.save() if not self.live.registered: return msg = LiveMessage("DeviceEvent") msg.append(device.id()) msg.append(state) msg.append(str(stateValue)) msg.append(extras) self.live.send(msg)
def stateUpdated(self, device, ackId=None, origin=None, executedState=None, executedStateValue=None): if device.isDevice() is False: return (state, stateValue) = device.state() extras = {'deviceState': state, 'stateValues': device.stateValues()} if ackId: extras['ACK'] = ackId if origin: extras['origin'] = origin else: extras['origin'] = 'Incoming signal' if executedStateValue: stateValue = executedStateValue elif executedState and executedState != state: # "state" is the current state of the device, but not # what was actually executed stateValue = device.stateValue(executedState) self.__deviceStateChanged(device, executedState, stateValue, extras['origin']) if isinstance(stateValue, dict): stateValue = json.dumps(stateValue) else: stateValue = str(stateValue) self.save() if not self.live.registered: return msg = LiveMessage("DeviceEvent") msg.append(device.id()) msg.append(executedState) msg.append(str(stateValue)) msg.append(extras) self.live.send(msg)
def __sendSensorChange(self, sensorid, valueType, value): msg = LiveMessage("SensorChange") device = None for d in self.devices: if d.id() == sensorid: device = d break if not device: return sensor = { 'protocol': device.typeString(), 'model': device.model(), 'sensor_id': device.id(), } msg.append(sensor) msg.append(valueType) msg.append(value) self.live.send(msg)
def __handleRoom(self, msg): data = msg.argument(0).toNative() if 'name' in data: if isinstance(data['name'], int): data['name'] = str(data['name']) else: data['name'] = data['name'].decode('UTF-8') live = TelldusLive(self.context) if data['action'] == 'set': oldResponsible = '' if data['id'] in self.rooms: # existing room room = self.rooms[data['id']] oldResponsible = room['responsible'] validKeys = ['name', 'color', 'content', 'icon', 'responsible'] for key in validKeys: if key in data: room[key] = data.get(key, '') if 'mode' in data and room['mode'] != data.get('mode', ''): room['mode'] = data.get('mode', '') self.__modeChanged(data['id'], room['mode'], 'room', room['name']) self.rooms[data['id']] = room else: # new room self.rooms[data['id']] = { 'name': data.get('name', ''), 'parent': data.get('parent', ''), 'color': data.get('color', ''), 'content': data.get('content', ''), 'icon': data.get('icon', ''), 'responsible': data['responsible'], 'mode': data.get('mode', ''), } if live.registered and \ (data['responsible'] == live.uuid or oldResponsible == live.uuid): room = self.rooms[data['id']] msg = LiveMessage('RoomSet') msg.append({ # No need to call get() on room here since we know every value has at least a # default value above 'id': data['id'], 'name': room['name'], 'parent': room['parent'], 'color': room['color'], 'content': room['content'], 'icon': room['icon'], 'responsible': room['responsible'], 'mode': room['mode'], }) live.send(msg) self.settings['rooms'] = self.rooms return if data['action'] == 'remove': room = self.rooms.pop(data['id'], None) if room is None: return if live.registered and room['responsible'] == live.uuid: msg = LiveMessage('RoomRemoved') msg.append({'id': data['id']}) live.send(msg) if len(self.getResponsibleRooms()) == 0: self.settings['roomlistEmpty'] = True self.roomlistEmpty = True self.settings['rooms'] = self.rooms return if data['action'] == 'setMode': self.setMode(data.get('id', None), data.get('mode', ''), data.get('setAlways', 1)) return if data['action'] == 'sync': rooms = data['rooms'] responsibleRooms = self.getResponsibleRooms() if not rooms and responsibleRooms: # list from server was completely empty but we have rooms locally, # this might be an error in the fetching, or we have added rooms locally # when offline. In any case, don't sync this time, just post our rooms # for next time self.reportRooms(responsibleRooms) return changedRooms = {} newRooms = {} removedRooms = [] for roomUUID in rooms: room = rooms[roomUUID] if room['responsible'] == live.uuid: # we are responsible for this room if roomUUID not in self.rooms: # this room does not exist locally anymore removedRooms.append(roomUUID) continue localRoom = self.rooms[roomUUID] if self.roomChanged(room, localRoom): changedRooms[roomUUID] = localRoom else: newRooms[roomUUID] = room newRooms.update(responsibleRooms) self.rooms = newRooms self.reportRooms(changedRooms, removedRooms) self.settings['rooms'] = self.rooms
def execute(self): msg = LiveMessage('event-executeaction') msg.append({'action': self.id}) self.event.manager.live.send(msg)