예제 #1
0
 def __init__(self):
     self.devices = []
     self.s = Settings('telldus.devicemanager')
     self.nextId = self.s.get('nextId', 0)
     self.live = TelldusLive(self.context)
     self.registered = False
     self.__load()
예제 #2
0
	def __requestLocalKey(self, msg):
		args = msg.argument(0).toNative()
		live = TelldusLive(self.context)
		try:
			publicKey = serialization.load_pem_public_key(
				args.get('publicKey', ''),
				backend=default_backend(),
			)
			ttl = int(time.time()+2629743)  # One month
			accessToken = self.__generateToken({}, {
				'aud': args.get('app', 'Unknown'),
				'exp': ttl,
			})
			ciphertext = publicKey.encrypt(
				str(accessToken),
				padding.OAEP(
					mgf=padding.MGF1(algorithm=hashes.SHA256()),
					algorithm=hashes.SHA256(),
					label=None
				)
			)
		except Exception as error:
			live.pushToWeb('api', 'localkey', {
				'success': False,
				'error': str(error)
			})
			return
		live.pushToWeb('api', 'localkey', {
			'key': base64.b64encode(ciphertext),
			'ttl': ttl,
			'uuid': args.get('uuid', ''),
			'client': live.uuid,
		})
예제 #3
0
	def tunnelhandler(self, client, chan):
		sock = socket.socket()
		try:
			sock.connect(('localhost', 22))
		except Exception as e:
			logging.exception(e)
			return

		while True:
			r, w, x = select.select([sock, chan], [], [], 3)
			if sock in r:
				data = sock.recv(1024)
				if len(data) == 0:
					break
				chan.send(data)
			if chan in r:
				data = chan.recv(1024)
				if len(data) == 0:
					break
				sock.send(data)
		chan.close()
		sock.close()
		TelldusLive(self.context).pushToWeb('remotesupport', 'disconnected', None)
		client.close()
		client = None
예제 #4
0
    def __init__(self):
        self.version = 0
        self.hwVersion = None
        self.devices = []
        self.sensors = []
        self.rawEnabled = False
        self.rawEnabledAt = 0
        self.dev = Adapter(self, Board.rf433Port())
        deviceNode = DeviceNode(self.dev)
        self.deviceManager = DeviceManager(self.context)
        for d in self.deviceManager.retrieveDevices('433'):
            p = d.params()
            if 'type' not in p:
                continue
            if p['type'] == 'sensor':
                device = SensorNode()
                self.sensors.append(device)
            elif p['type'] == 'device':
                device = DeviceNode(self.dev)
                self.devices.append(device)
            else:
                continue
            device.setNodeId(d.id())
            device.setParams(p)
            self.deviceManager.addDevice(device)

        self.deviceManager.finishedLoading('433')
        self.dev.queue(
            RF433Msg('V', success=self.__version, failure=self.__noVersion))
        self.dev.queue(
            RF433Msg('H', success=self.__hwVersion,
                     failure=self.__noHWVersion))
        self.live = TelldusLive(self.context)
예제 #5
0
    def __init__(self):
        self.running = False
        #self.runningJobsLock = threading.Lock() #TODO needed?
        self.jobsLock = threading.Lock()
        self.maintenanceJobsLock = threading.Lock()
        self.maintenanceJobs = []
        self.lastMaintenanceJobId = 0
        self.runningJobs = {}  #id:s as keys
        self.settings = Settings('telldus.scheduler')
        Application().registerShutdown(self.stop)
        Application().registerMaintenanceJobHandler(
            self.addMaintenanceJobGeneric)
        self.timezone = self.settings.get('tz', 'UTC')
        self.latitude = self.settings.get('latitude', '55.699592')
        self.longitude = self.settings.get('longitude', '13.187836')
        self.jobs = []
        self.fetchLocalJobs()
        self.live = TelldusLive(self.context)
        self.deviceManager = DeviceManager(self.context)
        if self.live.isRegistered():
            #probably not practically possible to end up here
            self.requestJobsFromServer()

        self.thread = threading.Thread(target=self.run)
        self.thread.start()
예제 #6
0
	def waitForConnection(self, client, transport):
		chan = transport.accept(60)
		if chan is None:
			transport.close()
			TelldusLive(self.context).pushToWeb('remotesupport', 'disconnected', None)
			return
		thr = threading.Thread(target=self.tunnelhandler, args=(client, chan,))
		thr.setDaemon(True)
		thr.start()
예제 #7
0
 def __init__(self):
     self.events = {}
     self.settings = Settings('telldus.event')
     self.schedulersettings = Settings('telldus.scheduler')
     self.live = TelldusLive(self.context)
     self.timezone = self.schedulersettings.get('tz', 'UTC')
     self.latitude = self.schedulersettings.get('latitude', '55.699592')
     self.longitude = self.schedulersettings.get('longitude', '13.187836')
     self.loadLocalEvents()
예제 #8
0
 def getResponsibleRooms(self, responsible=None):
     if not responsible:
         live = TelldusLive(self.context)
         responsible = live.uuid
     rooms = {}
     for roomUUID in self.rooms:
         room = self.rooms[roomUUID]
         if room['responsible'] == responsible:
             rooms[roomUUID] = room
     return rooms
예제 #9
0
 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)
class WebRequestHandler(Plugin):
    implements(IWebRequestHandler, IWebRequestAuthenticationHandler)

    def __init__(self):
        self.store = memstore.MemoryStore()

    def getTemplatesDirs(self):
        return [resource_filename('tellduslive', 'web/templates')]

    def isUrlAuthorized(self, request):
        return request.session('loggedIn', False)

    def handleAuthenticationForUrl(self, request):
        return False

    def handleRequest(self, plugin, path, params, request, **kwargs):
        if plugin != 'tellduslive':
            return None
        oidconsumer = consumer.Consumer({}, self.store)
        if path == 'login':
            try:
                authrequest = oidconsumer.begin('http://login.telldus.com')
            except consumer.DiscoveryFailure, exc:
                logging.error(str(exc[0]))
                return None  # TODO(micke): Error
            sregRequest = sreg.SRegRequest(required=['fullname', 'email'])
            authrequest.addExtension(sregRequest)
            trustRoot = request.base()
            returnTo = '%s/tellduslive/authorize' % request.base()
            url = authrequest.redirectURL(trustRoot, returnTo)
            return WebResponseRedirect(url)
        if path == 'authorize':
            url = '%s/tellduslive/authorize' % request.base()
            info = oidconsumer.complete(params, url)
            displayIdentifier = info.getDisplayIdentifier()
            if info.status == consumer.FAILURE and displayIdentifier:
                return None  # TODO(micke): Error
            elif info.status == consumer.SUCCESS:
                sregResp = sreg.SRegResponse.fromSuccessResponse(info)
                data = dict(sregResp.items())
                if 'email' not in data:
                    return None  # TODO(micke): Error
                tellduslive = TelldusLive(self.context)
                if data['email'] != tellduslive.email:
                    return 'loginFailed.html', {
                        'reason': 1,
                        'loginEmail': data['email'],
                        'registeredEmail': tellduslive.email
                    }
                request.setSession('loggedIn', True)
                return request.loggedIn()
            else:
                return None  # TODO(micke): Error
        return None
예제 #11
0
	def __init__(self):
		self.devices = []
		self.deviceManager = DeviceManager(self.context)
		for d in self.deviceManager.retrieveDevices('group'):
			p = d.params()
			device = GroupDevice()
			self.devices.append(device)
			device.setNodeId(d.id())
			device.setParams(p)
			self.deviceManager.addDevice(device)
		self.deviceManager.finishedLoading('group')
		self.live = TelldusLive(self.context)
예제 #12
0
	def __init__(self):
		self.devices = []
		self.deviceManager = DeviceManager(self.context)  # pylint: disable=too-many-function-args
		for oldDevice in self.deviceManager.retrieveDevices('group'):
			params = oldDevice.params()
			device = GroupDevice()
			self.devices.append(device)
			device.setNodeId(oldDevice.id())
			device.setParams(params)
			self.deviceManager.addDevice(device)
		self.deviceManager.finishedLoading('group')
		self.live = TelldusLive(self.context)  # pylint: disable=too-many-function-args
예제 #13
0
	def handle(self):
		sock = self.request[1]
		product = ''.join(x.capitalize() for x in Board.product().split('-'))
		live = TelldusLive(Application.defaultContext())
		msg = '%s:%s:%s:%s:%s' % (
			product,
			AutoDiscoveryHandler.getMacAddr(Board.networkInterface()),
			Board.secret(),
			Board.firmwareVersion(),
			live.uuid,
		)
		sock.sendto(msg, self.client_address)
예제 #14
0
 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)
예제 #15
0
	def start(self, server, username):
		client = paramiko.SSHClient()
		client.load_system_host_keys()
		client.set_missing_host_key_policy(paramiko.WarningPolicy())
		try:
			client.connect(server, 22, username=username, key_filename=resource_filename('remotesupport', 'id_rsa'))
		except Exception as e:
			logging.exception(e)
			return
		transport = client.get_transport()
		port = transport.request_port_forward('', 0)
		TelldusLive(self.context).pushToWeb('remotesupport', 'connected', port)
		thr = threading.Thread(target=self.waitForConnection, args=(client,transport,))
		thr.setDaemon(True)
		thr.start()
예제 #16
0
 def handleRequest(self, plugin, path, params, request, **kwargs):
     if plugin != 'tellduslive':
         return None
     oidconsumer = consumer.Consumer({}, self.store)
     if path == 'login':
         try:
             authrequest = oidconsumer.begin('http://login.telldus.com')
         except consumer.DiscoveryFailure as exc:
             logging.error(str(exc[0]))
             return None  # TODO(micke): Error
         sregRequest = sreg.SRegRequest(required=['fullname', 'email'])
         authrequest.addExtension(sregRequest)
         trustRoot = request.base()
         returnTo = '%s/tellduslive/authorize' % request.base()
         url = authrequest.redirectURL(trustRoot, returnTo)
         return WebResponseRedirect(url)
     if path == 'authorize':
         url = '%s/tellduslive/authorize' % request.base()
         info = oidconsumer.complete(params, url)
         displayIdentifier = info.getDisplayIdentifier()
         if info.status == consumer.FAILURE and displayIdentifier:
             return None  # TODO(micke): Error
         elif info.status == consumer.SUCCESS:
             sregResp = sreg.SRegResponse.fromSuccessResponse(info)
             data = dict(list(sregResp.items()))
             if 'email' not in data:
                 return None  # TODO(micke): Error
             tellduslive = TelldusLive(self.context)
             if not tellduslive.registered or tellduslive.email == '':
                 return 'loginFailed.html', {
                     'reason': 1,
                     'loginEmail': data['email']
                 }
             if data['email'] != tellduslive.email:
                 return 'loginFailed.html', {
                     'reason': 2,
                     'loginEmail': data['email'],
                     'registeredEmail': tellduslive.email
                 }
             request.setSession('loggedIn', True)
             return request.loggedIn()
         else:
             return None  # TODO(micke): Error
     return None
예제 #17
0
    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', ''))
예제 #18
0
    def __init__(self):
        self.version = 0
        self.hwVersion = None
        self.devices = []
        self.sensors = []
        self.rawEnabled = False
        self.rawEnabledAt = 0
        self.dev = Adapter(self, Board.rf433Port())
        self.deviceManager = DeviceManager(self.context)
        self.registerSensorCleanup()
        for dev in self.deviceManager.retrieveDevices('433'):
            params = dev.params()
            if 'type' not in params:
                continue
            if params['type'] == 'sensor':
                device = SensorNode()
                self.sensors.append(device)
            elif params['type'] == 'device':
                device = DeviceNode(self.dev)  # pylint: disable=R0204
                self.devices.append(device)
            else:
                continue
            device.setNodeId(dev.id())
            device.setParams(params)
            if params['type'] == 'sensor':
                # already loaded, keep it that way!
                device._packageCount = 7  # pylint: disable=W0212
                device._sensorValues = dev._sensorValues  # pylint: disable=W0212
                device.batteryLevel = dev.batteryLevel
                if hasattr(dev, 'declaredDead'):
                    device.declaredDead = dev.declaredDead

            self.deviceManager.addDevice(device)

        self.deviceManager.finishedLoading('433')
        self.dev.queue(
            RF433Msg('V', success=self.__version, failure=self.__noVersion))
        self.dev.queue(
            RF433Msg('H', success=self.__hwVersion,
                     failure=self.__noHWVersion))
        self.live = TelldusLive(self.context)
예제 #19
0
    def __webMessage(self, msg):
        live = TelldusLive(self.context)  # pylint: disable=too-many-function-args
        data = msg.argument(0).toNative()
        print("Store", data)
        loader = Loader(self.context)
        if data['action'] == 'getState':
            live.pushToWeb(
                'plugins', 'state', {
                    'plugins':
                    [plugin.infoObject() for plugin in loader.plugins],
                    'suggested': list(loader.suggestedPlugins),
                })
            return

        if data['action'] == 'getStorePlugins':
            live.pushToWeb('plugins', 'storePlugins', self.storePlugins())
            return

        if data['action'] == 'install':
            live.pushToWeb('plugins', 'installStatus',
                           self.installStorePlugin(data.get('plugin')))
            return
예제 #20
0
    def __init__(self):
        Application().registerShutdown(self.onShutdown)
        self.live = TelldusLive(self.context)  # pylint: disable=too-many-function-args

        self.discovered_flag = False

        self.mqtt_connected_flag = False
        self.client = mqtt.Client()
        self.client.on_disconnect = self.onMqttDisconnect
        self.client.on_connect = self.onMqttConnect
        self.client.on_message = self.onMqttMessage

        username = self.config('username')
        password = self.config('password')
        # if username setup mqtt login
        if username != '':
            self.client.username_pw_set(username, password)

        useConfigUrl = self.config('useConfigUrl')
        configUrl = 'https://live.telldus.se' if self.config(
            'configUrl') == 'live' else ('http://%s' % getIpAddr())

        self.hub = devs.HaHub(self.config('device_name'), self._buildTopic,
                              configUrl if useConfigUrl else None)
        self._debug('Hub: %s' % json.dumps(self._getDeviceConfig(self.hub)))

        self.staticDevices = [
            self.hub,
            devs.HaLiveConnection(self.hub, self.live, self._buildTopic),
            devs.HaIpAddr(self.hub, self._buildTopic),
            devs.HaCpu(self.hub, self._buildTopic),
            devs.HaRamFree(self.hub, self._buildTopic),
            devs.HaNetIORecv(self.hub, self._buildTopic),
            devs.HaNetIOSent(self.hub, self._buildTopic)
        ]
        self.devices = self.staticDevices + []
        Application().queue(self.discoverAndConnect)
        Application().registerScheduledTask(self._updateTimedSensors,
                                            seconds=30)
예제 #21
0
    def __handleCommand(self, msg):
        data = msg.argument(0).toNative()
        action = data['action']
        if action == 'addScene':
            self.addDevice(data['name'], data['devices'])

        elif action == 'editScene':
            deviceId = data['device']
            for sceneId in self.scenes:
                device = self.scenes[sceneId]
                if device.id() == deviceId:
                    device.setParams({
                        'devices': data['devices'],
                    })
                    device.paramUpdated('')
                    break

        elif action == 'sceneInfo':
            deviceId = data['device']
            for sceneId in self.scenes:
                device = self.scenes[sceneId]
                if device.id() == deviceId:
                    params = device.params()
                    params['deviceId'] = deviceId
                    live = TelldusLive(self.context)
                    live.pushToWeb('scene', 'sceneInfo', params)
                    return

        elif action == 'remove':
            deviceId = data['device']
            for sceneId in self.scenes:
                device = self.scenes[sceneId]
                if device.id() == deviceId:
                    self.deviceManager.removeDevice(deviceId)
                    del self.scenes[sceneId]
                    return
예제 #22
0
    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
예제 #23
0
 def __notifyFrontend(self, action, data):
     # pylint: disable=too-many-function-args
     Server(self.context).webSocketSend('plugins', action, data)
     TelldusLive(self.context).pushToWeb('plugins', action, data)
예제 #24
0
 def syncRoom(self):
     TelldusLive(self.context).send(LiveMessage("roomsync-request"))
예제 #25
0
 def __init__(self):
     self.gpio = Gpio(self.context)
     self.live = TelldusLive(self.context)
     self.gpio.initPin('status:red')
     self.gpio.initPin('status:green')
     self.setNetworkLed()