Exemple #1
0
    def smarthome_sync(self, payload, token):
        """Handle action.devices.SYNC request.
        https://developers.google.com/actions/smarthome/create-app#actiondevicessync
        """
        devices = []
        states = {}
        aogDevs.clear()
        getDevices()  # sync all devices
        getSettings()
        enableReport = ReportState.enable_report_state()

        for state in aogDevs.values():

            entity = _GoogleEntity(state)
            serialized = entity.sync_serialize()

            if serialized is None:
                continue

            devices.append(serialized)
            if state.report_state:
                try:
                    states[entity.entity_id] = entity.query_serialize()
                except:
                    continue

        if enableReport:
            t = threading.Thread(target=self.delay_report_state,
                                 args=(states, token)).start()

        return {
            'agentUserId': token.get('userAgentId', None),
            'devices': devices,
        }
Exemple #2
0
    def smarthome_query(self, payload, token):
        """Handle action.devices.QUERY request.
        https://developers.google.com/actions/smarthome/create-app#actiondevicesquery
        """
        enableReport = ReportState.enable_report_state()
        response = {}
        devices = {}
        getDevices()
        
        for device in payload.get('devices', []):
            devid = device['id']
            #_GoogleEntity(aogDevs.get(devid, None)).async_update()
            state = aogDevs.get(devid, None)           
            if not state:
                # If we can't find a state, the device is offline
                devices[devid] = {'online': False}
                continue

            e = _GoogleEntity(state)
            devices[devid] = e.query_serialize()
                        
        response = {'devices': devices}
        logger.info("Response " + json.dumps(response, indent=2, sort_keys=True, ensure_ascii=False))
        
        if state.report_state == True and enableReport == True:
            self.report_state(devices, token)
               
        return {'devices': devices}
Exemple #3
0
    def forceDevicesSync(self):
        userAgent = self.getUserAgent()
        enableReport = ReportState.enable_report_state()
        if userAgent is None:
            return 500  # internal error

        data = {"agentUserId": userAgent}
        if enableReport:
            r = ReportState.call_homegraph_api(REQUEST_SYNC_BASE_URL, data)
        elif 'Homegraph_API_Key' in configuration and configuration['Homegraph_API_Key'] != 'ADD_YOUR HOMEGRAPH_API_KEY_HERE':
            r = ReportState.call_homegraph_api_key(REQUEST_SYNC_BASE_URL, data)
        else:
            logger.error("No configuration for request_sync available")

        return r
Exemple #4
0
    def sync_serialize(self):
        """Serialize entity for a SYNC response.
        https://developers.google.com/actions/smarthome/create-app#actiondevicessync
        """
        state = self.state
        enableReport = ReportState.enable_report_state()
        traits = self.traits()

        # Found no supported traits for this entity
        if not traits:
            return None

        if enableReport:
            reportState = state.report_state
        else:
            reportState = enableReport

        device = {
            'id': state.entity_id,
            'name': {
                'name': state.name
            },
            'attributes': {},
            'traits': [trait.name for trait in traits],
            'willReportState': reportState,
            'deviceInfo': {
                'manufacturer': "Domoticz",
                "model": state.hardware
            },
            'type': DOMOTICZ_TO_GOOGLE_TYPES[state.domain],
        }

        # use aliases
        aliases = state.nicknames
        if aliases:
            device['name']['nicknames'] = aliases

        # add room hint if annotated
        room = state.room
        if room:
            device['roomHint'] = room

        for trt in traits:
            device['attributes'].update(trt.sync_attributes())

        return device
Exemple #5
0
    def settings(self, s):
        user = self.getSessionUser()
        if user is None or user.get('uid', '') == '':
            s.redirect('login?redirect_uri={0}'.format('settings'))
            return

        enableReport = ReportState.enable_report_state()
        update = checkupdate()
        public_url = getTunnelUrl()
        message = ''
        meta = '<!-- <meta http-equiv="refresh" content="5"> -->'
        code = readFile(os.path.join(FILE_DIR, CONFIGFILE))

        templatepage = env.get_template('home.html')
        s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))
Exemple #6
0
    def smarthome_sync(self, payload, token):
        """Handle action.devices.SYNC request.
        https://developers.google.com/actions/smarthome/create-app#actiondevicessync
        """
        devices = []
        aogDevs.clear()
        getDevices()  # sync all devices
        getSettings()
        enableReport = ReportState.enable_report_state()
        agent_user_id = token.get('userAgentId', None)

        for state in aogDevs.values():

            entity = _GoogleEntity(state)
            serialized = entity.sync_serialize(agent_user_id)

            if serialized is None:
                continue

            devices.append(serialized)

        response = {'agentUserId': agent_user_id, 'devices': devices}
                
        return response
Exemple #7
0
    def smarthome_exec(self, payload, token):
        """Handle action.devices.EXECUTE request.
        https://developers.google.com/actions/smarthome/create-app#actiondevicesexecute
        """
        entities = {}
        results = {}
        states = {}
        enableReport = ReportState.enable_report_state()

        for command in payload['commands']:
            for device, execution in product(command['devices'],
                                             command['execution']):
                entity_id = device['id']
                new_state = execution.get('params')
                # Happens if error occurred. Skip entity for further processing
                if entity_id in results:
                    continue

                if entity_id not in entities:
                    if len(aogDevs) == 0:
                        getDevices()
                        getSettings()

                    state = aogDevs.get(entity_id, None)
                    if state is None:
                        results[entity_id] = {
                            'ids': [entity_id],
                            'status': 'ERROR',
                            'errorCode': ERR_DEVICE_OFFLINE
                        }
                        continue

                    entities[entity_id] = _GoogleEntity(state)

                try:
                    entities[entity_id].execute(
                        execution['command'], execution.get('params', {}),
                        execution.get('challenge', None))

                except SmartHomeError as err:
                    results[entity_id] = {
                        'ids': [entity_id],
                        'status': 'ERROR',
                        'errorCode': err.code
                    }
                    logger.error(err)
                except SmartHomeErrorNoChallenge as err:
                    results[entity_id] = {
                        'ids': [entity_id],
                        'status': 'ERROR',
                        'errorCode': err.code,
                        'challengeNeeded': {
                            'type': err.desc
                        }
                    }
                    logger.error(err)

        final_results = list(results.values())

        for entity in entities.values():
            if entity.entity_id in results:
                continue
            entity.async_update()
            # final_results.append({'ids': [entity.entity_id], 'status': 'SUCCESS', 'states': entity.query_serialize()})
            final_results.append({
                'ids': [entity.entity_id],
                'status': 'SUCCESS',
                'states': new_state
            })
            if state.report_state:
                try:
                    # states[entity.entity_id] = entity.query_serialize()
                    states[entity.entity_id] = new_state
                except:
                    continue

        if state.report_state == True and enableReport == True:
            self.report_state(states, token)

        return {'commands': final_results}
Exemple #8
0
    def settings_post(self, s):
        enableReport = ReportState.enable_report_state()
        update = checkupdate()
        confJSON = json.dumps(configuration)
        public_url = getTunnelUrl()
        logs = readFile(os.path.join(logfilepath, LOGFILE))
        code = readFile(os.path.join(FILE_DIR, CONFIGFILE))
        meta = '<!-- <meta http-equiv="refresh" content="5"> -->'

        if s.form.get("save"):
            textToSave = s.form.get("save", None)
            codeToSave = textToSave.replace("+", " ")
            saveFile(CONFIGFILE, codeToSave)
            message = 'Config saved'
            logger.info(message)
            logs = readFile(os.path.join(logfilepath, LOGFILE))
            code = readFile(os.path.join(FILE_DIR, CONFIGFILE))
            template = TEMPLATE.format(message=message,
                                       uptime=uptime(),
                                       list=deviceList,
                                       meta=meta,
                                       code=code,
                                       conf=confJSON,
                                       public_url=public_url,
                                       logs=logs,
                                       update=update)

            s.send_message(200, template)

        if s.form.get("backup"):
            codeToSave = readFile(os.path.join(FILE_DIR, CONFIGFILE))
            saveFile('config/config.yaml.bak', codeToSave)
            message = 'Backup saved'
            logger.info(message)
            logs = readFile(os.path.join(logfilepath, LOGFILE))
            template = TEMPLATE.format(message=message,
                                       uptime=uptime(),
                                       list=deviceList,
                                       meta=meta,
                                       code=code,
                                       conf=confJSON,
                                       public_url=public_url,
                                       logs=logs,
                                       update=update)

            s.send_message(200, template)

        if s.form.get("restart"):
            message = 'Restart Server, please wait a minute!'
            meta = '<meta http-equiv="refresh" content="20">'
            code = ''
            logs = ''

            template = TEMPLATE.format(message=message,
                                       uptime=uptime(),
                                       list=deviceList,
                                       meta=meta,
                                       code=code,
                                       conf=confJSON,
                                       public_url=public_url,
                                       logs=logs,
                                       update=update)

            s.send_message(200, template)
            restartServer()

        if s.form.get("sync"):
            if 'Homegraph_API_Key' in configuration and configuration[
                    'Homegraph_API_Key'] != 'ADD_YOUR HOMEGRAPH_API_KEY_HERE' or enableReport == True:
                r = self.forceDevicesSync()
                time.sleep(0.5)
                if r:
                    message = 'Devices syncronized'
                else:
                    message = 'Homegraph api key not valid!'
            else:
                message = 'Add Homegraph api key or a Homegraph Service Account json file to sync devices here!'
            logs = readFile(os.path.join(logfilepath, LOGFILE))
            template = TEMPLATE.format(message=message,
                                       uptime=uptime(),
                                       list=deviceList,
                                       meta=meta,
                                       code=code,
                                       conf=confJSON,
                                       public_url=public_url,
                                       logs=logs,
                                       update=update)
            s.send_message(200, template)

        if s.form.get("reload"):
            message = ''

            template = TEMPLATE.format(message=message,
                                       uptime=uptime(),
                                       list=deviceList,
                                       meta=meta,
                                       code=code,
                                       conf=confJSON,
                                       public_url=public_url,
                                       logs=logs,
                                       update=update)
            s.send_message(200, template)

        if s.form.get("deletelogs"):
            logfile = os.path.join(logfilepath, LOGFILE)
            if os.path.exists(logfile):
                f = open(logfile, 'w')
                f.close()
            logger.info('Logs removed by user')
            message = 'Logs removed'
            logs = readFile(os.path.join(logfilepath, LOGFILE))
            template = TEMPLATE.format(message=message,
                                       uptime=uptime(),
                                       list=deviceList,
                                       meta=meta,
                                       code=code,
                                       conf=confJSON,
                                       public_url=public_url,
                                       logs=logs,
                                       update=update)
            s.send_message(200, template)

        if s.form.get("update"):
            repo.git.reset('--hard')
            repo.remotes.origin.pull()
            message = 'Updating to latest ' + repo.active_branch.name + ', please wait a minute!'
            meta = '<meta http-equiv="refresh" content="20">'

            template = TEMPLATE.format(message=message,
                                       uptime=uptime(),
                                       list=deviceList,
                                       meta=meta,
                                       code=code,
                                       conf=confJSON,
                                       public_url=public_url,
                                       logs=logs,
                                       update=update)
            s.send_message(200, template)

            subprocess.call([
                'pip', 'install', '-r',
                os.path.join(FILE_DIR, 'requirements/pip-requirements.txt')
            ])
            restartServer()
Exemple #9
0
def getAog(device):
    domain = AogGetDomain(device)
    if domain is None:
        return None

    aog = AogState()
    aog.name = device["Name"]  # .encode('ascii', 'ignore')
    aog.domain = domain
    aog.id = device["idx"]
    aog.entity_id = domain + aog.id
    aog.state = device.get("Data", "Scene")
    aog.level = device.get("LevelInt", 0)
    aog.temp = device.get("Temp")
    aog.humidity = device.get("Humidity")
    aog.setpoint = device.get("SetPoint")
    aog.color = device.get("Color")
    aog.protected = device.get("Protected")
    aog.maxdimlevel = device.get("MaxDimLevel")
    aog.seccode = settings.get("SecPassword")
    aog.secondelay = settings.get("SecOnDelay")
    aog.tempunit = settings.get("TempUnit")
    aog.battery = device.get("BatteryLevel")
    aog.hardware = device.get("HardwareName")
    aog.selectorLevelName = device.get("LevelNames")
    aog.language = settings.get("Language")

    if lightDOMAIN == aog.domain and "Dimmer" == device["SwitchType"]:
        aog.attributes = ATTRS_BRIGHTNESS
    if outletDOMAIN == aog.domain and "Dimmer" == device["SwitchType"]:
        aog.attributes = ATTRS_BRIGHTNESS
    if colorDOMAIN == aog.domain and "Dimmer" == device["SwitchType"]:
        aog.attributes = ATTRS_BRIGHTNESS
    if colorDOMAIN == aog.domain and "RGBWW" == device["SubType"]:
        aog.attributes = ATTRS_COLOR_TEMP
    if climateDOMAIN == aog.domain and "Thermostat" == device["Type"]:
        aog.attributes = ATTRS_THERMSTATSETPOINT
    if blindsDOMAIN == aog.domain and "Blinds Percentage" == device[
            "SwitchType"]:
        aog.attributes = ATTRS_PERCENTAGE
    if blindsDOMAIN == aog.domain and "Blinds Percentage Inverted" == device[
            "SwitchType"]:
        aog.attributes = ATTRS_PERCENTAGE

    # Try to get device specific voice control configuration from Domoticz
    # Read it from the configuration file if not in Domoticz (for backward compatibility)
    desc = getDeviceConfig(device.get("Description"))
    if desc is None:
        desc = getDesc(aog)

    if desc is not None:
        n = desc.get('nicknames', None)
        if n is not None:
            aog.nicknames = n
        r = desc.get('room', None)
        if r is not None:
            aog.room = r
        ack = desc.get('ack', False)
        if ack:
            aog.ack = ack
        report_state = desc.get('report_state', True)
        if not ReportState.enable_report_state():
            aog.report_state = False
        if not report_state:
            aog.report_state = report_state
    if aog.domain == cameraDOMAIN:
        aog.report_state = False
    return aog
Exemple #10
0
        '/json.htm?type=command&param=addlogmessage&message=Connected to Google Assistant with DZGA v'
        + VERSION,
        auth=(configuration['Domoticz']['username'],
              configuration['Domoticz']['password']),
        timeout=(2, 5))
except Exception as e:
    logger.error('Connection to Domoticz refused with error: %s' % e)

try:
    import git
    repo = git.Repo(FILE_DIR)
except:
    repo = None

ReportState = ReportState()
if not ReportState.enable_report_state():
    logger.error("Service account key is not found.")
    logger.error("Report state will be unavailable")


def checkupdate():
    if 'CheckForUpdates' in configuration and configuration[
            'CheckForUpdates'] == True:
        try:
            r = requests.get(
                'https://raw.githubusercontent.com/DewGew/Domoticz-Google-Assistant/'
                + repo.active_branch.name + '/const.py')
            text = r.text
            if VERSION not in text:
                update = 1
                logger.info("========")
Exemple #11
0
    def settings_post(self, s):
        enableReport = ReportState.enable_report_state()
        update = checkupdate()
        public_url = getTunnelUrl()
        code = readFile(os.path.join(FILE_DIR, CONFIGFILE))
        meta = '<!-- <meta http-equiv="refresh" content="5"> -->'

        if s.form.get("save"):
            textToSave = s.form.get("save", None)
            codeToSave = textToSave.replace("+", " ")
            saveFile(CONFIGFILE, codeToSave)
            message = 'Configuration saved. Restart DZGA for the settings to take effect'
            logger.info(message)
            logs = readFile(os.path.join(logfilepath, LOGFILE))
            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))

        if s.form.get("backup"):
            codeToSave = readFile(os.path.join(FILE_DIR, CONFIGFILE))
            saveFile('config/config.yaml.bak', codeToSave)
            message = 'Backup saved'
            logger.info(message)
            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))

        if s.form.get("restart"):
            meta = '<meta http-equiv="refresh" content="10">'
            message = 'Restarts DZGA server'

            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))
            restartServer()

        if s.form.get("sync"):
            if 'Homegraph_API_Key' in configuration and configuration['Homegraph_API_Key'] != 'ADD_YOUR HOMEGRAPH_API_KEY_HERE' or enableReport == True:
                r = self.forceDevicesSync()
                time.sleep(0.5)
                if r:
                    message = 'Devices syncronized'
                else:
                    message = 'Homegraph api key not valid!'
            else:
                message = 'Add Homegraph api key or a Homegraph Service Account json file to sync devices in the UI! You can still sync by voice eg. "Hey Google, Sync my devices".'
            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))

        if s.form.get("reload"):
            message = ''

            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))

        if s.form.get("deletelogs"):
            logfile = os.path.join(logfilepath, LOGFILE)
            if os.path.exists(logfile):
                f = open(logfile, 'w')
                f.close()
            logger.info('Logs removed by user')
            message = 'Logs removed'
            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))

        if s.form.get("update"):
            repo.git.reset('--hard')
            repo.remotes.origin.pull()
            message = 'Updating to latest ' + branch + ', please wait a minute!'
            meta = '<meta http-equiv="refresh" content="20">'

            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))
            
            subprocess.call(['pip3', 'install','-r', os.path.join(FILE_DIR, 'requirements/pip-requirements.txt')])
            restartServer()
            
        if s.form.get("saveSettings"):
            savedSettings = json.loads(s.form.get("saveSettings", None))
            with open(os.path.join(FILE_DIR, CONFIGFILE), 'r') as conf_file:
                newsettings = yaml.safe_load(conf_file)
                newsettings.update(savedSettings)
                
            saveFile(CONFIGFILE, yaml.safe_dump(newsettings, allow_unicode=True))
            logger.info(yaml.dump(savedSettings))
            message = 'Settings saved. Restart DZGA for the settings to take effect'
            logger.info(message)
            logs = readFile(os.path.join(logfilepath, LOGFILE))
            templatepage = env.get_template('home.html')
            s.send_message(200, templatepage.render(message=message, uptime=uptime(), meta=meta, code=code,
                                       conf=configuration, public_url=public_url, update=update, keyfile=enableReport,
                                       branch=branch, dzversion=settings['dzversion'], dzgaversion=VERSION))
Exemple #12
0
def getAog(device):
    domain = AogGetDomain(device)
    if domain is None:
        return None

    aog = AogState()
    aog.name = device["Name"]  # .encode('ascii', 'ignore')
    aog.domain = domain
    aog.id = device["idx"]
    aog.entity_id = domain + aog.id
    aog.plan = device.get("PlanID")                               
    aog.state = device.get("Data", "Scene")
    aog.level = device.get("LevelInt", 0)
    aog.temp = device.get("Temp")
    aog.humidity = device.get("Humidity")
    aog.setpoint = device.get("SetPoint")
    if aog.domain is "Color":
        aog.color = device.get("Color")
    aog.protected = device.get("Protected")
    aog.maxdimlevel = device.get("MaxDimLevel")   
    aog.battery = device.get("BatteryLevel")
    aog.hardware = device.get("HardwareName")
    aog.selectorLevelName = device.get("LevelNames")
    aog.lastupdate = device.get("LastUpdate")
    
    aog.language = settings.get("Language")
    aog.tempunit = settings.get("TempUnit")
    if aog.domain is "Security":
        aog.seccode = settings.get("SecPassword")
        aog.secondelay = settings.get("SecOnDelay")


    # Try to get device specific voice control configuration from Domoticz
    # Read it from the configuration file if not in Domoticz (for backward compatibility)
    desc = getDeviceConfig(device.get("Description"))
    if desc is not None:
        logger.debug('<voicecontrol> tags found for idx %s in domoticz description.', aog.id)
        logger.debug('Device_Config for idx %s will be ignored in config.yaml!', aog.id)
    if desc is None:
        desc = getDesc(aog)

    if desc is not None:
        dt = desc.get('devicetype', None)
        if dt is not None:
            if aog.domain in [domains['blinds']]:
                if dt.lower() in ['window', 'gate', 'garage', 'door']:
                    aog.domain = domains[dt.lower()]
            if aog.domain in [domains['light'], domains['switch']]:
                if dt.lower() in ['window', 'door', 'gate', 'garage', 'light', 'ac_unit', 'bathtub', 'coffeemaker', 'dishwasher', 'dryer', 'fan', 'heater', 'kettle', 'media', 'microwave', 'outlet', 'oven', 'speaker', 'switch', 'vacuum', 'washer', 'waterheater']:
                    aog.domain = domains[dt.lower()]
            if aog.domain in [domains['door']]:
                if dt.lower() in ['window', 'gate', 'garage']:
                    aog.domain = domains[dt.lower()]    
            if aog.domain in [domains['selector']]:
                if dt.lower() in ['vacuum']:
                    aog.domain = domains[dt.lower()]
        pn = desc.get('name', None)
        if pn is not None:
            aog.name = pn
        n = desc.get('nicknames', None)
        if n is not None:
            aog.nicknames = n
        r = desc.get('room', None)
        if r is not None:
            aog.room = r
        ack = desc.get('ack', False)
        if ack:
            aog.ack = ack
        report_state = desc.get('report_state', True)
        if not ReportState.enable_report_state():
            aog.report_state = False
        if not report_state:
            aog.report_state = report_state            
        if domains['thermostat'] == aog.domain:
            at_idx = desc.get('actual_temp_idx', None)
            if at_idx is not None:
                aog.actual_temp_idx = at_idx
                try:
                    aog.state = str(aogDevs[domains['temperature'] + at_idx].temp)
                    aogDevs[domains['temperature'] + at_idx].domain = domains['merged'] + aog.id + ')'
                except:
                    logger.error('Merge Error, Cant find temperature device with idx %s', at_idx)
            modes_idx = desc.get('selector_modes_idx', None)
            if modes_idx is not None:
                aog.modes_idx = modes_idx
                try:
                    aog.level = aogDevs[domains['selector'] + modes_idx].level
                    aog.selectorLevelName = aogDevs[domains['selector'] + modes_idx].selectorLevelName
                    aogDevs[domains['selector'] + modes_idx].domain = domains['merged'] + aog.id + ')'
                except:
                    logger.error('Merge Error, Cant find selector device with idx %s', modes_idx)
        if aog.domain in [domains['heater'], domains['kettle'], domains['waterheater'], domains['oven']]:
            tc_idx = desc.get('merge_thermo_idx', None)
            if tc_idx is not None:
                aog.merge_thermo_idx = tc_idx
                try:
                    aog.temp = aogDevs[domains['thermostat'] + tc_idx].state
                    aog.setpoint = aogDevs[domains['thermostat'] + tc_idx].setpoint
                    aogDevs[domains['thermostat'] + tc_idx].domain = domains['merged'] + aog.id + ')'
                except:
                    logger.error('Merge Error, Cant find thermostat device with idx %s', tc_idx)
        hide = desc.get('hide', False)
        if hide:
            if aog.domain not in [domains['scene'], domains['group']]:
                aog.domain = domains['hidden']
            else:
                logger.error('Scenes and Groups does not support function "hide" yet')
            
    if aog.domain in [domains['camera']]:
        aog.report_state = False
        
    if domains['light'] == aog.domain and "Dimmer" == device["SwitchType"]:
        aog.attributes = ATTRS_BRIGHTNESS
    if domains['fan'] == aog.domain and "Selector" == device["SwitchType"]:
        aog.attributes = ATTRS_FANSPEED
    if domains['outlet'] == aog.domain and "Dimmer" == device["SwitchType"]:
        aog.attributes = ATTRS_BRIGHTNESS
    if domains['color'] == aog.domain and "Dimmer" == device["SwitchType"]:
        aog.attributes = ATTRS_BRIGHTNESS
    if domains['color'] == aog.domain and device["SubType"] in ["RGBWW", "White"]:
        aog.attributes = ATTRS_COLOR_TEMP
    if domains['thermostat'] == aog.domain and "Thermostat" == device["Type"]:
        aog.attributes = ATTRS_THERMSTATSETPOINT
    if domains['blinds'] == aog.domain and "Blinds Percentage" == device["SwitchType"]:
        aog.attributes = ATTRS_PERCENTAGE
    if domains['blindsinv'] == aog.domain and "Blinds Percentage Inverted" == device["SwitchType"]:
        aog.attributes = ATTRS_PERCENTAGE
    if domains['vacuum'] == aog.domain and "Selector" == device["SwitchType"]:
        aog.attributes = ATTRS_VACUUM_MODES
        
    if aog.room == None:
        if aog.domain not in [domains['scene'], domains['group']]:
            if aog.plan is not "0":
                aog.room = getPlans(aog.plan)
        
    return aog
              configuration['Domoticz']['password']))
except Exception as e:
    logger.error('Connection to Domoticz refused with error: %s' % (e))

try:
    import git
except ImportError:
    logger.info('Installing package GitPython')
    pip.main(['install', 'gitpython'])
    import git
try:
    repo = git.Repo(FILE_DIR)
except:
    repo = None
ReportState = ReportState()
if ReportState.enable_report_state() == False:
    logger.error("Service account key is not found.")
    logger.error("Report state will be unavailable")


def checkupdate():
    if 'CheckForUpdates' in configuration and configuration[
            'CheckForUpdates'] == True:
        try:
            r = requests.get(
                'https://raw.githubusercontent.com/DewGew/Domoticz-Google-Assistant/'
                + repo.active_branch.name + '/const.py')
            text = r.text
            if VERSION not in text:
                update = 1
                logger.info("========")