def _get_light_gamut(bridge, light): gamut = "C" # default try: gamut = bridge.lights( )[light]['capabilities']['control']['colorgamuttype'] # xbmc.log("[script.service.hue] Light: {}, gamut: {}".format(l, gamut)) except QhueException as exc: xbmc.log( f"[script.service.hue] Can't get gamut for light, defaulting to Gamut C: {light}, error: {exc}" ) except KeyError: xbmc.log( f"[script.service.hue] Unknown gamut type, unsupported light: {light}" ) notification(_("Hue Service"), _("Unknown colour gamut for light:") + f" {light}") except requests.RequestException as exc: xbmc.log( f"[script.service.hue] Get Light Gamut RequestsException: {exc}" ) notification(header=_("Hue Service"), message=_(f"Connection Error"), icon=xbmcgui.NOTIFICATION_ERROR) if gamut == "A" or gamut == "B" or gamut == "C": return gamut return "C" # default to C if unknown gamut type
def _error_report_dialog(exc): response = xbmcgui.Dialog().yesnocustom(heading=_("Hue Service Error"), message=_("The following error occurred:") + f"\n[COLOR=red]{exc}[/COLOR]\n" + _("Automatically report this error?"), customlabel=_("Never report errors")) if response == 2: xbmc.log("[script.service.hue] Error Reporting disabled") ADDON.setSettingBool("error_reporting", False) return False return response
def home(**kwargs): profile_settings = load_profile(profile_id=1) if profile_settings['first_boot'] == 1: first_boot() folder = plugin.Folder() if len(profile_settings['pswd']) > 0 and len( profile_settings['devicekey']) > 0: folder.add_item(label=_(_.LIVE_TV, _bold=True), path=plugin.url_for(func_or_url=live_tv)) folder.add_item(label=_(_.CHANNELS, _bold=True), path=plugin.url_for(func_or_url=replaytv)) #if settings.getBool('showMoviesSeries'): # folder.add_item(label=_(_.SERIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='series', label=_.SERIES, start=0)) # folder.add_item(label=_(_.MOVIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='movies', label=_.MOVIES, start=0)) # folder.add_item(label=_(_.KIDS_SERIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='kidsseries', label=_.KIDS_SERIES, start=0)) # folder.add_item(label=_(_.KIDS_MOVIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='kidsmovies', label=_.KIDS_MOVIES, start=0)) folder.add_item(label=_(_.SEARCH, _bold=True), path=plugin.url_for(func_or_url=search_menu)) folder.add_item(label=_(_.LOGIN, _bold=True), path=plugin.url_for(func_or_url=login)) folder.add_item(label=_.SETTINGS, path=plugin.url_for(func_or_url=settings_menu)) return folder
def _update_hue_rgb(self, r, g, b, light, transition_time, bri): gamut = self.ambi_lights[light].get('gamut') prev_xy = self.ambi_lights[light].get('prev_xy') if gamut == "A": xy = self.converterA.rgb_to_xy(r, g, b) elif gamut == "B": xy = self.converterB.rgb_to_xy(r, g, b) else: xy = self.converterC.rgb_to_xy(r, g, b) xy = round(xy[0], 4), round(xy[1], 4) # Hue has a max precision of 4 decimal points distance = self.helper.get_distance_between_two_points( XYPoint(xy[0], xy[1]), XYPoint(prev_xy[0], prev_xy[1])) # only update hue if XY changed enough if distance > MINIMUM_COLOR_DISTANCE: try: self.bridge.lights[light].state( xy=xy, bri=bri, transitiontime=int(transition_time)) self.ambi_lights[light].update(prev_xy=xy) except QhueException as exc: if "201" in exc.type_id: # xbmc.log(f"[script.service.hue] QhueException {exc.type_id} {exc.message}") # 201 Param not modifiable because light is off error. pass elif "500" in exc.type_id or "901" in exc.type_id: # bridge internal error, usually occurs when there's too many Zigbee calls xbmc.log( f"[script.service.hue] Bridge internal error: {exc.type_id}: {exc.message} {traceback.format_exc()}" ) self._bridge_error500() elif "6" in exc.type_id: xbmc.log( f"[script.service.hue] Parameter unavailable error: {exc.type_id}: {exc.message} {traceback.format_exc()}" ) AMBI_RUNNING.clear() notification( header=_("Hue Service"), message=_( f"Error: Lights incompatible with Ambilight"), icon=xbmcgui.NOTIFICATION_ERROR) else: xbmc.log( f"[script.service.hue] Ambi: QhueException Hue call fail: {exc.type_id}: {exc.message} {traceback.format_exc()}" ) AMBI_RUNNING.clear() # shut it down reporting.process_exception(exc) except requests.RequestException as exc: xbmc.log(f"[script.service.hue] Requests exception: {exc}") notification(header=_("Hue Service"), message=_(f"Connection Error"), icon=xbmcgui.NOTIFICATION_ERROR) AMBI_RUNNING.clear() except KeyError: xbmc.log( "[script.service.hue] Ambi: KeyError, light not found")
def _bridgeError500(self): self.bridgeError500 = self.bridgeError500 + 1 # increment counter if self.bridgeError500 > 100 and settings_storage['show500Error']: stopShowingError = xbmcgui.Dialog().yesno(_("Hue Bridge over capacity"), _("The Hue Bridge is over capacity. Increase refresh rate or reduce the number of Ambilights."), yeslabel=_("Don't show again"), nolabel=_("Ok")) if stopShowingError: ADDON.setSettingBool("show500Error", False) self.bridgeError500 = 0
def _force_on(ambi_lights, bridge, saved_light_states): for L in ambi_lights: try: if not saved_light_states[L]['state']['on']: xbmc.log("[script.service.hue] Forcing lights on") bridge.lights[L].state(on=True, bri=1) except requests.RequestException as exc: xbmc.log(f"[script.service.hue] Requests exception: {exc}") notification(header=_("Hue Service"), message=_(f"Connection Error"), icon=xbmcgui.NOTIFICATION_ERROR)
def _validate_ambilight(): xbmc.log( f"[script.service.hue] Validate ambilight config. Enabled: {ADDON.getSettingBool('group3_enabled')}" ) if ADDON.getSettingBool("group3_enabled"): light_ids = ADDON.getSetting("group3_Lights") if light_ids == "-1": ADDON.setSettingBool("group3_enabled", False) xbmc.log("[script.service.hue] No ambilights selected") notification(_("Hue Service"), _("No lights selected for Ambilight."), icon=xbmcgui.NOTIFICATION_ERROR)
def _bridge_error500(self): self.bridge_error500 = self.bridge_error500 + 1 # increment counter if self.bridge_error500 > 50 and ADDON.getSettingBool("show500Error"): AMBI_RUNNING.clear() # shut it down stop_showing_error = xbmcgui.Dialog().yesno( _("Hue Bridge over capacity"), _("The Hue Bridge is over capacity. Increase refresh rate or reduce the number of Ambilights." ), yeslabel=_("Do not show again"), nolabel=_("Ok")) if stop_showing_error: ADDON.setSettingBool("show500Error", False) self.bridge_error500 = 0
def _validate_ambilight(): logger.debug("Validate ambilight config. Enabled: {}".format( settings_storage['ambiEnabled'])) if settings_storage['ambiEnabled']: light_ids = ADDON.getSetting("group3_Lights") if light_ids == "-1": logger.error("No ambilights selected") xbmcgui.Dialog().notification( _("Hue Service"), _("No lights selected for Ambilight."), icon=xbmcgui.NOTIFICATION_ERROR) ADDON.setSettingBool("group3_enabled", False) settings_storage['ambiEnabled'] = False
def _get_light_states(lights, bridge): states = {} for L in lights: try: states[L] = (bridge.lights[L]()) except QhueException as exc: xbmc.log( f"[script.service.hue] Hue call fail: {exc.type_id}: {exc.message} {traceback.format_exc()}" ) except requests.RequestException as exc: xbmc.log(f"[script.service.hue] Requests exception: {exc}") notification(header=_("Hue Service"), message=_(f"Connection Error"), icon=xbmcgui.NOTIFICATION_ERROR) return states
def _validate_schedule(): xbmc.log( f"[script.service.hue] Validate schedule. Schedule Enabled: {ADDON.getSettingBool('enableSchedule')}" ) if ADDON.getSettingBool("enableSchedule"): try: convert_time(ADDON.getSettingString("startTime")) convert_time(ADDON.getSettingString("endTime")) # xbmc.log("[script.service.hue] Time looks valid") except ValueError as e: ADDON.setSettingBool("EnableSchedule", False) xbmc.log(f"[script.service.hue] Invalid time settings: {e}") notification(_("Hue Service"), _("Invalid start or end time, schedule disabled"), icon=xbmcgui.NOTIFICATION_ERROR)
def replaytv_list(character, label='', start=0, **kwargs): start = int(start) folder = plugin.Folder(title=label) data = load_file(file='list_replay.json', isJSON=True) if not data: gui.ok(message=_.NO_REPLAY_TV_INFO, heading=_.NO_REPLAY_TV_INFO) return folder if not check_key(data, character): return folder processed = process_replaytv_list(data=data[character], start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'count') and len(data[character]) > processed['count']: folder.add_item( label=_(_.NEXT_PAGE, _bold=True), path=plugin.url_for(func_or_url=replaytv_list, character=character, label=label, start=processed['count']), ) return folder
def search_menu(**kwargs): folder = plugin.Folder(title=_.SEARCHMENU) label = _.NEWSEARCH folder.add_item( label = label, info = {'plot': _.NEWSEARCHDESC}, path = plugin.url_for(func_or_url=search), ) profile_settings = load_profile(profile_id=1) for x in range(1, 10): searchstr = profile_settings['search' + unicode(x)] if searchstr != '': label = searchstr folder.add_item( label = label, info = {'plot': _(_.SEARCH_FOR, query=searchstr)}, path = plugin.url_for(func_or_url=search, query=searchstr), ) return folder
def search_menu(**kwargs): folder = plugin.Folder(title=_.SEARCHMENU) label = _.NEWSEARCH folder.add_item( label = label, info = {'plot': _.NEWSEARCHDESC}, path = plugin.url_for(func_or_url=search), ) folder.add_item( label= label + " (Online)", path=plugin.url_for(func_or_url=online_search) ) for x in range(1, 10): searchstr = settings.get(key='_search' + unicode(x)) if searchstr != '': type = settings.get(key='_search_type' + unicode(x)) label = searchstr + type if type == " (Online)": path = plugin.url_for(func_or_url=online_search, query=searchstr) else: path = plugin.url_for(func_or_url=search, query=searchstr) folder.add_item( label = label, info = {'plot': _(_.SEARCH_FOR, query=searchstr)}, path = path, ) return folder
def search(query=None, **kwargs): items = [] if not query: query = gui.input(message=_.SEARCH, default='').strip() if not query: return for x in reversed(list(range(2, 10))): settings.set(key='_search' + unicode(x), value=settings.get(key='_search' + unicode(x - 1))) settings.set(key='_search1', value=query) folder = plugin.Folder(title=_(_.SEARCH_FOR, query=query)) data = load_file(file='list_replay.json', isJSON=True) processed = process_replaytv_search(data=data, start=0, search=query) items += processed['items'] items[:] = sorted(items, key=_sort_replay_items, reverse=True) items = items[:25] folder.add_items(items) return folder
def replaytv_content(label, day, station='', start=0, **kwargs): day = int(day) start = int(start) folder = plugin.Folder(title=label) data = load_file(file=station + "_replay.json", isJSON=True) if not data: gui.ok(_.DISABLE_ONLY_STANDARD, _.NO_REPLAY_TV_INFO) return folder totalrows = len(data) processed = process_replaytv_content(data=data, day=day, start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'count') and totalrows > processed['count']: folder.add_item( label=_(_.NEXT_PAGE, _bold=True), path=plugin.url_for(func_or_url=replaytv_content, label=label, day=day, station=station, start=processed['count']), ) return folder
def search(query=None, **kwargs): items = [] if not query: query = gui.input(message=_.SEARCH, default='').strip() if not query: return db_query = "UPDATE `vars` SET `search10`=`search9`, `search9`=`search8`, `search8`=`search7`, `search7`=`search6`, `search6`=`search5`, `search5`=`search4`, `search4`=`search3`, `search3`=`search2`, `search2`=`search1`, `search1`='{search1}' WHERE profile_id={profile_id}".format(search1=query, profile_id=1) query_settings(query=db_query, return_result=False, return_insert=False, commit=False) folder = plugin.Folder(title=_(_.SEARCH_FOR, query=query)) processed = process_replaytv_search(search=query) items += processed['items'] if settings.getBool('showMoviesSeries'): processed = process_vod_content(data='series', start=0, search=query, type=_.SERIES) items += processed['items'] processed = process_vod_content(data='film1', start=0, search=query, type=_.MOVIES) items += processed['items'] processed = process_vod_content(data='videoshop', start=0, search=query, type=_.VIDEOSHOP) items += processed['items'] items[:] = sorted(items, key=_sort_replay_items, reverse=True) items = items[:25] folder.add_items(items) return folder
def replaytv_item(ids=None, label=None, start=0, **kwargs): start = int(start) first = label[0] folder = plugin.Folder(title=label) if first.isalpha(): data = load_file(file=first + "_replay.json", isJSON=True) else: data = load_file(file='other_replay.json', isJSON=True) if not data: return folder processed = process_replaytv_list_content(data=data, ids=ids, start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'totalrows') and check_key( processed, 'count') and processed['totalrows'] > processed['count']: folder.add_item( label=_(_.NEXT_PAGE, _bold=True), path=plugin.url_for(func_or_url=replaytv_item, ids=ids, label=label, start=processed['count']), ) return folder
def online_search(query=None, **kwargs): if not query: query = gui.input(message=_.SEARCH, default='').strip() if not query: return for x in reversed(list(range(2, 10))): settings.set(key='_search' + unicode(x), value=settings.get(key='_search' + unicode(x - 1))) settings.set(key='_search_type' + unicode(x), value=settings.get(key='_search_type' + unicode(x - 1))) settings.set(key='_search1', value=query) settings.set(key='_search_type1', value=' (Online)') folder = plugin.Folder(title=_(_.SEARCH_FOR, query=query)) data = api.online_search(search=query, vod=settings.getBool('showMoviesSeries')) if data: processed = process_online_search(data=data) if processed: folder.add_items(processed) return folder
def _validate_schedule(): logger.debug("Validate schedule. Schedule Enabled: {}".format( settings_storage['enableSchedule'])) if settings_storage['enableSchedule']: try: convert_time(settings_storage['startTime']) convert_time(settings_storage['endTime']) logger.debug("Time looks valid") except ValueError as e: logger.error("Invalid time settings: {}".format(e)) xbmcgui.Dialog().notification( _("Hue Service"), _("Invalid start or end time, schedule disabled"), icon=xbmcgui.NOTIFICATION_ERROR) ADDON.setSettingBool("EnableSchedule", False) settings_storage['enableSchedule'] = False
def _perf_average(process_times): process_times = list(process_times) size = len(process_times) total = 0 if size > 0: for x in process_times: total += x average_process_time = int(total / size * 1000) return f"{average_process_time} ms" return _("Unknown")
def home(**kwargs): if settings.getBool(key='_first_boot') == True: first_boot() folder = plugin.Folder() if not plugin.logged_in: folder.add_item(label=_(_.LOGIN, _bold=True), path=plugin.url_for(func_or_url=login)) else: folder.add_item(label=_(_.LIVE_TV, _bold=True), path=plugin.url_for(func_or_url=live_tv)) folder.add_item(label=_(_.CHANNELS, _bold=True), path=plugin.url_for(func_or_url=replaytv)) folder.add_item(label=_(_.SEARCH, _bold=True), path=plugin.url_for(func_or_url=search_menu)) folder.add_item(label=_.SETTINGS, path=plugin.url_for(func_or_url=settings_menu)) return folder
def search(query=None, **kwargs): items = [] if not query: query = gui.input(message=_.SEARCH, default='').strip() if not query: return for x in reversed(list(range(2, 10))): settings.set(key='_search' + unicode(x), value=settings.get(key='_search' + unicode(x - 1))) settings.set(key='_search1', value=query) folder = plugin.Folder(title=_(_.SEARCH_FOR, query=query)) data = load_file(file='list_replay.json', isJSON=True) processed = process_replaytv_search(data=data, start=0, search=query) items += processed['items'] if settings.getBool('showMoviesSeries') == True: processed = process_vod_content(data=load_file(file='vod.json', isJSON=True)['series'], start=0, search=query, type=_.SERIES) items += processed['items'] processed = process_vod_content(data=load_file(file='vod.json', isJSON=True)['movies'], start=0, search=query, type=_.MOVIES) items += processed['items'] processed = process_vod_content(data=load_file( file='vod.json', isJSON=True)['kidsseries'], start=0, search=query, type=_.KIDS_SERIES) items += processed['items'] processed = process_vod_content(data=load_file( file='vod.json', isJSON=True)['kidsmovies'], start=0, search=query, type=_.KIDS_MOVIES) items += processed['items'] items[:] = sorted(items, key=_sort_replay_items, reverse=True) items = items[:25] folder.add_items(items) return folder
def vod(file, label, start=0, **kwargs): start = int(start) folder = plugin.Folder(title=label) processed = process_vod_content(data=file, start=start, type=label) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'total') and check_key(processed, 'count2') and processed['total'] > processed['count2']: folder.add_item( label = _(_.NEXT_PAGE, _bold=True), path = plugin.url_for(func_or_url=vod, file=file, label=label, start=processed['count2']), ) return folder
def replaytv_item(label=None, idtitle=None, start=0, **kwargs): start = int(start) folder = plugin.Folder(title=label) processed = process_replaytv_list_content(label=label, idtitle=idtitle, start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'total') and check_key(processed, 'count') and int(processed['total']) > int(processed['count']): folder.add_item( label = _(_.NEXT_PAGE, _bold=True), path = plugin.url_for(func_or_url=replaytv_item, label=label, idtitle=idtitle, start=start+processed['count']), ) return folder
def replaytv_list(character, label='', start=0, **kwargs): start = int(start) folder = plugin.Folder(title=label) processed = process_replaytv_list(character=character, start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'count') and check_key(processed, 'total') and processed['total'] > 50: folder.add_item( label = _(_.NEXT_PAGE, _bold=True), path = plugin.url_for(func_or_url=replaytv_list, character=character, label=label, start=start+processed['count']), ) return folder
def home(**kwargs): if settings.getBool(key='_first_boot') == True: first_boot() folder = plugin.Folder() if not plugin.logged_in: folder.add_item(label=_(_.LOGIN, _bold=True), path=plugin.url_for(func_or_url=login)) else: folder.add_item(label=_(_.LIVE_TV, _bold=True), path=plugin.url_for(func_or_url=live_tv)) folder.add_item(label=_(_.CHANNELS, _bold=True), path=plugin.url_for(func_or_url=replaytv)) if settings.getBool('showMoviesSeries') == True: folder.add_item(label=_(_.SERIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='series', label=_.SERIES, start=0)) folder.add_item(label=_(_.MOVIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='movies', label=_.MOVIES, start=0)) folder.add_item(label=_(_.KIDS_SERIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='kidsseries', label=_.KIDS_SERIES, start=0)) folder.add_item(label=_(_.KIDS_MOVIES, _bold=True), path=plugin.url_for(func_or_url=vod, file='kidsmovies', label=_.KIDS_MOVIES, start=0)) folder.add_item(label=_(_.SEARCH, _bold=True), path=plugin.url_for(func_or_url=search_menu)) folder.add_item(label=_.SETTINGS, path=plugin.url_for(func_or_url=settings_menu)) return folder
def replaytv_content(label, day, station='', start=0, **kwargs): day = int(day) start = int(start) folder = plugin.Folder(title=label) processed = process_replaytv_content(station=station, day=day, start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'total') and check_key(processed, 'count') and processed['total'] > processed['count']: folder.add_item( label = _(_.NEXT_PAGE, _bold=True), path = plugin.url_for(func_or_url=replaytv_content, label=label, day=day, station=station, start=processed['count']), ) return folder
def channel_picker(type, **kwargs): if type=='live': title = _.LIVE_TV rows = get_live_channels(addon=False, all=True) elif type=='replay': title = _.CHANNELS rows = get_replay_channels(all=True) else: title = _.SIMPLEIPTV rows = get_live_channels(addon=False, all=True) folder = plugin.Folder(title=title) prefs = load_prefs(profile_id=1) results = load_tests(profile_id=1) type = unicode(type) for row in rows: id = unicode(row['channel']) if not prefs or not check_key(prefs, id) or prefs[id][type] == 1: color = 'green' else: color = 'red' label = _(row['label'], _bold=True, _color=color) if results and check_key(results, id): if results[id][type] == 1: label += _(' (' + _.TEST_SUCCESS + ')', _bold=False, _color='green') else: label += _(' (' + _.TEST_FAILED + ')', _bold=False, _color='red') else: label += _(' (' + _.NOT_TESTED + ')', _bold=False, _color='orange') if not prefs or not check_key(prefs, id) or prefs[id][type + '_auto'] == 1: choice = _(' ,' + _.AUTO_CHOICE + '', _bold=False, _color='green') else: choice = _(' ,' + _.MANUAL_CHOICE + '', _bold=False, _color='orange') label += choice folder.add_item( label = label, art = {'thumb': row['image']}, path = plugin.url_for(func_or_url=change_channel, type=type, id=id, change=0), context = [ (_.AUTO_CHOICE_SET, 'Container.Update({context_url})'.format(context_url=plugin.url_for(func_or_url=change_channel, type=type, id=id, change=1)), ), #(_.TEST_CHANNEL, 'RunPlugin({context_url})'.format(context_url=plugin.url_for(func_or_url=test_channel, channel=id)), ), ], playable = False, ) return folder
def vod(file, label, kids=0, start=0, **kwargs): kids = int(kids) start = int(start) folder = plugin.Folder(title=label) data = load_file(file='vod.json', isJSON=True)[file] if not data: return folder processed = process_vod_content(data=data, start=start, series=kids, type=label) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'count') and len(data) > processed['count']: folder.add_item( label = _(_.NEXT_PAGE, _bold=True), path = plugin.url_for(func_or_url=vod, file=file, label=label, kids=kids, start=processed['count']), ) return folder