From 8123a112876c54201b26155d5e402f9756a9d13a Mon Sep 17 00:00:00 2001
From: Hyperion-Bot <20935312+Hyperion-Bot@users.noreply.github.com>
Date: Sat, 23 Mar 2024 14:08:52 +0100
Subject: [PATCH 1/9] Update fr.json (POEditor.com)
---
assets/webconfig/i18n/fr.json | 47 ++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 12 deletions(-)
diff --git a/assets/webconfig/i18n/fr.json b/assets/webconfig/i18n/fr.json
index 55504413..7965ed38 100644
--- a/assets/webconfig/i18n/fr.json
+++ b/assets/webconfig/i18n/fr.json
@@ -52,7 +52,7 @@
"conf_helptable_option": "Option",
"conf_leds_config_error": "Erreur dans la configuration de la disposition",
"conf_leds_config_warning": "Verifiez la configuration de la disposition des LEDs",
- "conf_leds_contr_label_contrtype": "Type de contrôleur : ",
+ "conf_leds_contr_label_contrtype": "Type de contrôleur: ",
"conf_leds_device_info_log": "Si vos LED ne fonctionnent pas, vérifiez ici s'il y a des erreurs :",
"conf_leds_device_intro": "Hyperion prend en charge de nombreux contrôleurs pour transmettre des données à votre appareil cible. Sélectionnez un contrôleur LED dans la liste triée et configurez-le. Nous avons choisi les meilleurs paramètres par défaut pour chaque appareil.",
"conf_leds_error_get_properties_text": "Erreur lors de l'obtention des propriétés de l'appareil. Veuillez vérifier les éléments de configuration.",
@@ -82,6 +82,7 @@
"conf_leds_layout_cl_bottomright": "Bas droit (Coin)",
"conf_leds_layout_cl_cornergap": "Écart aux coins",
"conf_leds_layout_cl_edgegap": "Écart aux bords",
+ "conf_leds_layout_cl_entertainment": "Espace de divertissement",
"conf_leds_layout_cl_gaglength": "Taille de l'écart",
"conf_leds_layout_cl_gappos": "Position de l'écart",
"conf_leds_layout_cl_hleddepth": "Profondeur LED horizontale",
@@ -193,34 +194,34 @@
"dashboard_alert_message_disabled": "Cette instance est actuellement désactivée ! Pour l'utiliser à nouveau, activez-la dans le tableau de bord.",
"dashboard_alert_message_disabled_t": "Instance matérielle LED désactivée",
"dashboard_componentbox_label_comp": "Composant",
- "dashboard_componentbox_label_status": "Etat",
+ "dashboard_componentbox_label_status": "État",
"dashboard_componentbox_label_title": "Etat des composants",
- "dashboard_infobox_label_currenthyp": "Votre version d'Hyperion : ",
+ "dashboard_infobox_label_currenthyp": "Votre version Hyperion : ",
"dashboard_infobox_label_disableh": "Désactiver l'instance : $1",
"dashboard_infobox_label_enableh": "Activer l'instance : $1",
- "dashboard_infobox_label_instance": "Instance",
+ "dashboard_infobox_label_instance": "Instance:",
"dashboard_infobox_label_latesthyp": "Dernière version d'Hyperion : ",
- "dashboard_infobox_label_platform": "Plateforme",
+ "dashboard_infobox_label_platform": "Plateforme:",
"dashboard_infobox_label_port_boblight": "Serveur Boblight :",
"dashboard_infobox_label_port_flat": "Flatbuffer:",
"dashboard_infobox_label_port_json": "Server-JSON:",
"dashboard_infobox_label_port_proto": "Protobuffer:",
"dashboard_infobox_label_ports": "Ports",
"dashboard_infobox_label_ports_websocket": "WebSocket (ws|wss):",
- "dashboard_infobox_label_smartacc": "Accès simplifié",
- "dashboard_infobox_label_statush": "Statut d'Hyperion : ",
+ "dashboard_infobox_label_smartacc": "Accès Intelligent",
+ "dashboard_infobox_label_statush": "Statut Hyperion : ",
"dashboard_infobox_label_title": "Information",
"dashboard_infobox_label_watchedversionbranch": "Branche surveillée :",
"dashboard_infobox_message_updatesuccess": "Vous utilisez la dernière version d'Hyperion.",
"dashboard_infobox_message_updatewarning": "Une nouvelle version d'Hyperion est disponible ! ($1)",
- "dashboard_label_intro": "Ce dashboard vous donne une vue rapide sur l'état d'Hyperion.",
+ "dashboard_label_intro": "Ce dashboard vous donne une vue rapide sur l'état Hyperion",
"dashboard_message_default_password": "La WebUI utilise le mot de passe par défaut. Nous recommandons de le modifier.",
"dashboard_message_default_password_t": "Utilisation du mot de passe par défaut pour la WebUI",
"dashboard_message_do_not_show_again": "Ne plus afficher ce message",
"dashboard_message_global_setting": "Les réglages sur cette page sont indépendantes des instances. Tout changement sera global a toutes les instances.",
"dashboard_message_global_setting_t": "Réglage global",
"dashboard_newsbox_label_title": "Hyperion - Blog",
- "dashboard_newsbox_noconn": "Impossible d'accéder au blog d'Hyperion. Votre connexion internet fonctionne-t-elle ?",
+ "dashboard_newsbox_noconn": "Impossible d'accéder au blog Hyperion. Votre connexion internet est fonctionnel ?",
"dashboard_newsbox_readmore": "Lire plus",
"dashboard_newsbox_visitblog": "Visiter le Blog d'Hyperion",
"edt_append_degree": "°",
@@ -271,6 +272,7 @@
"edt_conf_bb_unknownFrameCnt_title": "image inconnu",
"edt_conf_bge_heading_title": "Effet/Couleur d'arrière-plan",
"edt_conf_bobls_heading_title": "Serveur Boblight",
+ "edt_conf_cec_event_title": "Évenement CEC",
"edt_conf_color_accuracyLevel_expl": "Niveau de précision de l'évaluation des couleurs dominantes. Un niveau plus élevé permet d'obtenir des résultats plus précis, mais nécessite également une plus grande puissance de traitement. Doit être combiné avec un traitement réduit des pixels.",
"edt_conf_color_accuracyLevel_title": "Niveau d'exactitude",
"edt_conf_color_backlightColored_expl": "Ajouter des couleurs à votre rétroéclairage",
@@ -333,6 +335,10 @@
"edt_conf_enum_PAL": "PAL",
"edt_conf_enum_SECAM": "SECAM",
"edt_conf_enum_VERTICAL": "Verticale",
+ "edt_conf_enum_action_idle": "Inactif",
+ "edt_conf_enum_action_restart": "Redémarrer",
+ "edt_conf_enum_action_resume": "Continuer",
+ "edt_conf_enum_action_suspend": "Suspendre",
"edt_conf_enum_automatic": "Automatique",
"edt_conf_enum_bbclassic": "Classique",
"edt_conf_enum_bbdefault": "Defaut",
@@ -341,6 +347,8 @@
"edt_conf_enum_bgr": "BGR",
"edt_conf_enum_bottom_up": "De bas en haut",
"edt_conf_enum_brg": "BRG",
+ "edt_conf_enum_cec_key_f1_blue": "Bouton bleu enfoncé",
+ "edt_conf_enum_cec_key_f2_red": "Bouton rouge enfoncé",
"edt_conf_enum_color": "Couleur",
"edt_conf_enum_custom": "Personnalisation",
"edt_conf_enum_decay": "Décroissance",
@@ -468,6 +476,8 @@
"edt_conf_net_localApiAuth_title": "Authentification de l'API locale",
"edt_conf_net_restirctedInternetAccessAPI_expl": "Vous pouvez limiter l'accès à l'API via l'internet à certaines IP.",
"edt_conf_net_restirctedInternetAccessAPI_title": "Limité aux IP",
+ "edt_conf_os_events_suspendEnable_expl": "Écoute les événements de suspension/reprise du système d'exploitation",
+ "edt_conf_os_events_suspendOnLockEnable_title": "Suspendre lorsqu'il est verrouillé",
"edt_conf_pbs_heading_title": "Serveur Protocol Buffers",
"edt_conf_pbs_timeout_expl": "Si aucune donnée n'est reçue dans la période de temps donnée, le composant sera désactivé.",
"edt_conf_pbs_timeout_title": "Temps écoulé",
@@ -488,6 +498,7 @@
"edt_conf_smooth_updateDelay_title": "Changer le retard",
"edt_conf_smooth_updateFrequency_expl": "Le vitesse de sortie pour le contrôleur led.",
"edt_conf_smooth_updateFrequency_title": "Charger la fréquence",
+ "edt_conf_time_event_title": "Temps",
"edt_conf_v4l2_blueSignalThreshold_expl": "Assombrie les valeurs bleues faibles (reconnues comme noires)",
"edt_conf_v4l2_blueSignalThreshold_title": "Seuil de signal bleu",
"edt_conf_v4l2_cecDetection_expl": "Si cette option est activée, la capture USB sera temporairement désactivée lorsque l'événement CEC standby sera reçu du bus HDMI.",
@@ -556,8 +567,11 @@
"edt_conf_webc_keyPassPhrase_title": "Mot de passe de clé",
"edt_conf_webc_keyPath_expl": "Chemin vers la clé (doit être au format PEM, chiffrée avec RSA)",
"edt_conf_webc_keyPath_title": "Chemin de clé privée",
+ "edt_conf_webc_port_title": "Port HTTP",
"edt_conf_webc_sslport_expl": "Port HTTPS du serveur web",
"edt_conf_webc_sslport_title": "Port HTTPS",
+ "edt_dev_auth_key_title": "Jeton Autorisation",
+ "edt_dev_auth_key_title_info": "Jeton d'autorisation requis pour avoir accès au matériel",
"edt_dev_enum_sub_min_cool_adjust": "Soustraire le blanc froid",
"edt_dev_enum_sub_min_warm_adjust": "Soustraire le blanc chaud",
"edt_dev_enum_subtract_minimum": "Soustraire le minimum",
@@ -675,6 +689,7 @@
"edt_dev_spec_transistionTime_title": "Temps de transition",
"edt_dev_spec_uid_title": "UID",
"edt_dev_spec_universe_title": "Univers",
+ "edt_dev_spec_useAPIv2_title": "Utliser API v2",
"edt_dev_spec_useEntertainmentAPI_title": "Utiliser l'API Hue Entertainment",
"edt_dev_spec_useOrbSmoothing_title": "Utiliser le lissage orb",
"edt_dev_spec_useRgbwProtocol_title": "Utiliser le protocole RGBW",
@@ -745,6 +760,7 @@
"edt_eff_ledlist": "Liste de LED",
"edt_eff_ledtest_header": "Test LED",
"edt_eff_ledtest_header_desc": "sortie tournante: rouge, verte, blanche, noire",
+ "edt_eff_ledtest_seq_header": "Séquence d'essais LED",
"edt_eff_length": "Longueur",
"edt_eff_lightclock_header": "Horloge lumineuse",
"edt_eff_lightclock_header_desc": "Une véritable horloge lumineuse ! Ajustez les couleurs des heures, des minutes et des secondes. Un marqueur 3/6/9/12 heures est également disponible. Si l'horloge est erronée, vous devez vérifier l'horloge de votre système.",
@@ -866,9 +882,9 @@
"general_btn_grantAccess": "Donner l'accès",
"general_btn_iswitch": "Basculer",
"general_btn_next": "Suivant",
- "general_btn_off": "Off",
+ "general_btn_off": "Désactivation",
"general_btn_ok": "OK",
- "general_btn_on": "On",
+ "general_btn_on": "Activation",
"general_btn_overwrite": "Remplacer",
"general_btn_rename": "Renommer",
"general_btn_restarthyperion": "Redémarrer Hyperion",
@@ -887,7 +903,7 @@
"general_comp_BLACKBORDER": "Détection des bandes noires",
"general_comp_BOBLIGHTSERVER": "Serveur Boblight",
"general_comp_FLATBUFSERVER": "Serveur Flatbuffers",
- "general_comp_FORWARDER": "Transfert",
+ "general_comp_FORWARDER": "Transition",
"general_comp_GRABBER": "Capture d'écran",
"general_comp_LEDDEVICE": "Périphérique LED",
"general_comp_PROTOSERVER": "Serveur Protocol Buffers",
@@ -912,6 +928,7 @@
"general_speech_en": "Anglais",
"general_speech_es": "Espagnol",
"general_speech_fr": "Français",
+ "general_speech_he": "Hébreu",
"general_speech_hu": "Hongrois",
"general_speech_it": "Italien",
"general_speech_ja": "Japonais",
@@ -970,6 +987,8 @@
"main_menu_dashboard_token": "Tableau de bord",
"main_menu_effect_conf_token": "Effets",
"main_menu_effectsconfigurator_token": "Configurateur d'effets",
+ "main_menu_event_services_token": "Services Évènements",
+ "main_menu_events": "Services Évènements",
"main_menu_general_conf_token": "Général",
"main_menu_grabber_conf_token": "Capture matérielle",
"main_menu_input_selection_token": "Sélection de l'entrée",
@@ -1082,6 +1101,7 @@
"wiz_cololight_noprops": "Récupération des propriétés du périphérique impossible. Définissez manuellement le nombre de LED physiques",
"wiz_cololight_title": "Assistant Cololight",
"wiz_guideyou": "Le $1 vous guidera à travers les réglages. Cliquez sur le bouton !",
+ "wiz_hue_blinkblue": "Laisse-le s'éclairer",
"wiz_hue_clientkey": "Clé Client :",
"wiz_hue_create_user": "Créer un nouvel utilisateur",
"wiz_hue_desc1": "Il recherche automatiquement un Hue Bridge, au cas où il n'en trouverait pas, vous devez fournir l'adresse IP et appuyer sur le bouton actualiser à droite. Maintenant, vous avez besoin d'un ID utilisateur, si vous n'en avez pas, créez-en un nouveau.",
@@ -1114,6 +1134,9 @@
"wiz_identify_tip": "Identifier le dispositif configuré en l'allumant",
"wiz_ids_disabled": "Désactivé",
"wiz_ids_entire": "Image entière",
+ "wiz_layout": "Générer une mise en page",
+ "wiz_nanoleaf_press_onoff_button": "Veuillez appuyer sur le bouton Marche/Arrêt de votre appareil Nanoleaf pendant 5 à 7 secondes.",
+ "wiz_nanoleaf_user_auth_intro": "L'assistant vous aide à générer un jeton d'autorisation utilisateur requis pour permettre à Hyperion d'accéder à l'appareil.",
"wiz_noLights": "Pas de $1 trouvé! Veuillez connecter les lumières au réseau ou configurez les manuellement.",
"wiz_pos": "Position/État",
"wiz_rgb_expl": "Le point coloré change de couleur (rouge, vert) toutes les x secondes, en même temps que vos LEDs passent à cette couleur. Répondez aux questions en bas pour vérifier/corriger votre ordre d'octets.",
From efda0714b3560368d1f24acc8c6e8eccfa75cf4f Mon Sep 17 00:00:00 2001
From: Hyperion-Bot <20935312+Hyperion-Bot@users.noreply.github.com>
Date: Sat, 23 Mar 2024 14:08:53 +0100
Subject: [PATCH 2/9] Update de.json (POEditor.com)
---
assets/webconfig/i18n/de.json | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/assets/webconfig/i18n/de.json b/assets/webconfig/i18n/de.json
index aa64787d..56848b0a 100644
--- a/assets/webconfig/i18n/de.json
+++ b/assets/webconfig/i18n/de.json
@@ -115,6 +115,10 @@
"conf_leds_layout_cl_topright": "Oben Rechts (Ecke)",
"conf_leds_layout_cl_vleddepth": "Vertikale LED-Tiefe",
"conf_leds_layout_frame": "Klassisches Layout (Rahmen)",
+ "conf_leds_layout_gapbottom": "Abstand von unten",
+ "conf_leds_layout_gapleft": "Abstand von links",
+ "conf_leds_layout_gapright": "Abstand von rechts",
+ "conf_leds_layout_gaptop": "Abstand von oben",
"conf_leds_layout_generatedconf": "Generierte/Aktuelle LED-Konfiguration",
"conf_leds_layout_generation_error": "LED Layout wurde nicht erzeugt",
"conf_leds_layout_generation_success": "LED-Layout erfolgreich erstellt",
@@ -969,7 +973,9 @@
"general_speech_en": "Englisch",
"general_speech_es": "Spanisch",
"general_speech_fr": "Französisch",
+ "general_speech_he": "Hebräisch",
"general_speech_hu": "Ungarisch",
+ "general_speech_id": "Indonesisch",
"general_speech_it": "Italienisch",
"general_speech_ja": "Japanisch",
"general_speech_nb": "Norwegisch (Bokmål)",
@@ -980,6 +986,7 @@
"general_speech_ru": "Russisch",
"general_speech_sv": "Schwedisch",
"general_speech_tr": "Türkisch",
+ "general_speech_uk": "Ukrainisch",
"general_speech_vi": "Vietnamesisch",
"general_speech_zh-CN": "Chinesisch (vereinfacht)",
"general_webui_title": "Hyperion - Web Konfiguration",
From 35d8992bcc68eec8ba47a33220197817e036b635 Mon Sep 17 00:00:00 2001
From: Hyperion-Bot <20935312+Hyperion-Bot@users.noreply.github.com>
Date: Sat, 23 Mar 2024 14:08:54 +0100
Subject: [PATCH 3/9] Update sv.json (POEditor.com)
---
assets/webconfig/i18n/sv.json | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/assets/webconfig/i18n/sv.json b/assets/webconfig/i18n/sv.json
index b768e74b..2bf66b95 100644
--- a/assets/webconfig/i18n/sv.json
+++ b/assets/webconfig/i18n/sv.json
@@ -78,10 +78,10 @@
"conf_leds_layout_checkp1": "Den svartfärgade lysdioden är den första lysdioden. Detta är den punkt där data matas.",
"conf_leds_layout_checkp2": "Layouten är utsikten från att stå framför TV:n, inte bakom den.",
"conf_leds_layout_checkp3": "Se till att riktningen är korrekt inställd, den andra och tredje lysdioden är markerade med grått för att visa dataflödet.",
- "conf_leds_layout_checkp4": "Processgap: Om du behöver ett gap, ignorera det när du anger LED topp/botten/höger/vänster och skriv sedan in under gap length hur många lysdioder du vill ta bort. Ändra nu mellanrummet för att placera mellanrummet på rätt plats.",
- "conf_leds_layout_cl_bottom": "Under",
- "conf_leds_layout_cl_bottomleft": "Nedre vänstra hörnet",
- "conf_leds_layout_cl_bottomright": "Nedre högra hörnet",
+ "conf_leds_layout_checkp4": "Fallmellanrum: För att skapa ett mellanrum, ignorera det först när du definierar Övre/Nedre/Vänster/Höger och ställ sedan in din mellanrums längd för att ta bort ett antal LED-lampor. Modifiera mellanrumspositionen tills den matchar.",
+ "conf_leds_layout_cl_bottom": "Nedre",
+ "conf_leds_layout_cl_bottomleft": "Nedre vänster (hörn)",
+ "conf_leds_layout_cl_bottomright": "Nedre höger (hörn)",
"conf_leds_layout_cl_cornergap": "Hörnavstånd",
"conf_leds_layout_cl_edgegap": "Ramavstånd",
"conf_leds_layout_cl_entertainment": "Underhållningsområde",
@@ -115,6 +115,10 @@
"conf_leds_layout_cl_topright": "Övre högra hörnet",
"conf_leds_layout_cl_vleddepth": "Vertikalt LED-djup",
"conf_leds_layout_frame": "Klassisk layout (ram)",
+ "conf_leds_layout_gapbottom": "Nedre mellanrum",
+ "conf_leds_layout_gapleft": "Vänster mellanrum",
+ "conf_leds_layout_gapright": "Höger mellanrum",
+ "conf_leds_layout_gaptop": "Övre mellanrum",
"conf_leds_layout_generatedconf": "Genererad/aktuell LED-konfiguration",
"conf_leds_layout_generation_error": "LED-layout genererades inte",
"conf_leds_layout_generation_success": "LED-layout genererad framgångsrikt",
@@ -541,7 +545,7 @@
"edt_conf_v4l2_cecDetection_expl": "USB-insamling är tillfälligt inaktiverad när en CEC-standbysignal tas emot från HDMI-bussen.",
"edt_conf_v4l2_cecDetection_title": "CEC-detektering",
"edt_conf_v4l2_cropBottom_expl": "Antal pixlar på under som ska tas bort från bilden.",
- "edt_conf_v4l2_cropBottom_title": "Beskär under",
+ "edt_conf_v4l2_cropBottom_title": "Beskär nedre",
"edt_conf_v4l2_cropHeightValidation_error": "Beskärningstopp + Beskärningsbotten kan inte vara större än höjd ($1)",
"edt_conf_v4l2_cropLeft_expl": "Antal pixlar till vänster som ska tas bort från bilden.",
"edt_conf_v4l2_cropLeft_title": "Beskär vänster",
@@ -850,7 +854,7 @@
"edt_eff_traces_header": "Färgspår",
"edt_eff_traces_header_desc": "Kräver en ny design",
"edt_eff_trails_header": "Stjärnfall",
- "edt_eff_trails_header_desc": "I olika färger, gör en önskan!",
+ "edt_eff_trails_header_desc": "Färgade stjärnor som faller från toppen till botten.",
"edt_eff_url": "Bildadress",
"edt_eff_waves_header": "Vågor",
"edt_eff_waves_header_desc": "Skapa vågor av färg! Blanda dina favoritfärger och välj en mittpunkt.",
@@ -969,7 +973,9 @@
"general_speech_en": "Engelska",
"general_speech_es": "Spanska",
"general_speech_fr": "Franska",
+ "general_speech_he": "Hebreiska",
"general_speech_hu": "Ungerska",
+ "general_speech_id": "Indonesiska",
"general_speech_it": "Italienska",
"general_speech_ja": "Japanska",
"general_speech_nb": "Norska (Bokmål)",
@@ -980,6 +986,7 @@
"general_speech_ru": "Ryska",
"general_speech_sv": "Svenska",
"general_speech_tr": "Turkiska",
+ "general_speech_uk": "Ukrainska",
"general_speech_vi": "Vietnamesiska",
"general_speech_zh-CN": "Kinesiska (förenklad)",
"general_webui_title": "Hyperion - Webbkonfiguration",
@@ -1183,7 +1190,7 @@
"wiz_nanoleaf_user_auth_title": "Guiden för generering av auktorisationsnyckel",
"wiz_noLights": "Inga $1s hittades! Anslut $1s till nätverket eller konfigurera dem manuellt.",
"wiz_pos": "Position/status",
- "wiz_rgb_expl": "Färgpunkten ändrar färg (röd, grön) var x sekund, samtidigt ändrar dina lysdioder färg. Svara på frågorna nedan för att kontrollera/korrigera din RGB-byteordning.",
+ "wiz_rgb_expl": "Färgpricken byter färg (röd, grön) varje x sekunder, samtidigt som dina LED-lampor också byter färg. Besvara frågorna längst ner för att kontrollera/korrigera byteordningen.",
"wiz_rgb_intro1": "Den här guiden hjälper dig att hitta rätt byteordning för dina lysdioder. Klicka på Fortsätt för att börja.",
"wiz_rgb_intro2": "När behöver du denna assistent? För initial konfiguration eller om dina lysdioder ska vara röda, till exempel, men de är blå eller gröna.",
"wiz_rgb_q": "Vilken färg visar dina lysdioder när den färgade pricken överst...",
From ac57fea09a219efd89550c7409e2404163db649e Mon Sep 17 00:00:00 2001
From: LordGrey <48840279+Lord-Grey@users.noreply.github.com>
Date: Sat, 30 Mar 2024 15:43:50 +0100
Subject: [PATCH 4/9] Fix Kodi Color Calibration, Refactor Wizards (#1718)
* Fix #1674 and refactor wizards
* Have own code file per LED-Device Wizard
* Include SonarLint feedback
* Cleanups
* Apply module pattern
* Address CodeQL findings
* Address CodeQL findings
---
assets/webconfig/js/content_huebridge.js | 52 -
assets/webconfig/js/content_leds.js | 35 +-
assets/webconfig/js/ui_utils.js | 29 +
assets/webconfig/js/wizard.js | 2301 +----------------
.../webconfig/js/wizards/LedDevice_atmoorb.js | 283 ++
.../js/wizards/LedDevice_nanoleaf.js | 94 +
.../js/wizards/LedDevice_philipshue.js | 988 +++++++
.../webconfig/js/wizards/LedDevice_utils.js | 60 +
.../js/wizards/LedDevice_yeelight.js | 300 +++
.../js/wizards/colorCalibrationKodiWizard.js | 485 ++++
.../js/wizards/rgbByteOrderWizard.js | 143 +
11 files changed, 2432 insertions(+), 2338 deletions(-)
delete mode 100644 assets/webconfig/js/content_huebridge.js
create mode 100644 assets/webconfig/js/wizards/LedDevice_atmoorb.js
create mode 100644 assets/webconfig/js/wizards/LedDevice_nanoleaf.js
create mode 100644 assets/webconfig/js/wizards/LedDevice_philipshue.js
create mode 100644 assets/webconfig/js/wizards/LedDevice_utils.js
create mode 100644 assets/webconfig/js/wizards/LedDevice_yeelight.js
create mode 100644 assets/webconfig/js/wizards/colorCalibrationKodiWizard.js
create mode 100644 assets/webconfig/js/wizards/rgbByteOrderWizard.js
diff --git a/assets/webconfig/js/content_huebridge.js b/assets/webconfig/js/content_huebridge.js
deleted file mode 100644
index 99da3c76..00000000
--- a/assets/webconfig/js/content_huebridge.js
+++ /dev/null
@@ -1,52 +0,0 @@
-$(document).ready( function() {
-
- $("#create_user").on("click", function() {
- var connectionRetries = 15;
- var data = {"devicetype":"hyperion#"+Date.now()};
- var UserInterval = setInterval(function(){
- $.ajax({
- type: "POST",
- url: 'http://'+$("#ip").val()+'/api',
- processData: false,
- timeout: 1000,
- contentType: 'application/json',
- data: JSON.stringify(data),
- success: function(r) {
- connectionRetries--;
- $("#connectionTime").html(connectionRetries);
- if(connectionRetries == 0) {
- abortConnection(UserInterval);
- }
- else
- {
- $("#abortConnection").hide();
- $('#pairmodal').modal('show');
- $("#ip_alert").hide();
- if (typeof r[0].error != 'undefined') {
- console.log("link not pressed");
- }
- if (typeof r[0].success != 'undefined') {
- $('#pairmodal').modal('hide');
- $('#user').val(r[0].success.username);
-
- $( "#hue_lights" ).empty();
- get_hue_lights();
- clearInterval(UserInterval);
- }
- }
- },
- error: function(XMLHttpRequest, textStatus, errorThrown) {
- $("#ip_alert").show();
- clearInterval(UserInterval);
- }
- });
- },1000);
-});
-
-function abortConnection(UserInterval){
- clearInterval(UserInterval);
- $("#abortConnection").show();
- $('#pairmodal').modal('hide');
-}
-
-});
diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js
index 0432524a..938bf8ee 100755
--- a/assets/webconfig/js/content_leds.js
+++ b/assets/webconfig/js/content_leds.js
@@ -1086,40 +1086,7 @@ $(document).ready(function () {
conf_editor.validate().length || window.readOnlyMode ? $('#btn_submit_controller').prop('disabled', true) : $('#btn_submit_controller').prop('disabled', false);
// LED controller specific wizards
- $('#btn_wiz_holder').html("");
- $('#btn_led_device_wiz').off();
-
- if (ledType == "philipshue") {
- var ledWizardType = ledType;
- var data = { type: ledWizardType };
- var hue_title = 'wiz_hue_title';
- changeWizard(data, hue_title, startWizardPhilipsHue);
- }
- else if (ledType == "nanoleaf") {
- var ledWizardType = ledType;
- var data = { type: ledWizardType };
- var nanoleaf_user_auth_title = 'wiz_nanoleaf_user_auth_title';
- changeWizard(data, nanoleaf_user_auth_title, startWizardNanoleafUserAuth);
- $('#btn_wiz_holder').hide();
- }
- else if (ledType == "atmoorb") {
- var ledWizardType = (this.checked) ? "atmoorb" : ledType;
- var data = { type: ledWizardType };
- var atmoorb_title = 'wiz_atmoorb_title';
- changeWizard(data, atmoorb_title, startWizardAtmoOrb);
- }
- else if (ledType == "yeelight") {
- var ledWizardType = (this.checked) ? "yeelight" : ledType;
- var data = { type: ledWizardType };
- var yeelight_title = 'wiz_yeelight_title';
- changeWizard(data, yeelight_title, startWizardYeelight);
- }
-
- function changeWizard(data, hint, fn) {
- $('#btn_wiz_holder').html("")
- createHint("wizard", $.i18n(hint), "btn_wiz_holder", "btn_led_device_wiz");
- $('#btn_led_device_wiz').off().on('click', data, fn);
- }
+ createLedDeviceWizards(ledType);
conf_editor.on('ready', function () {
var hwLedCountDefault = 1;
diff --git a/assets/webconfig/js/ui_utils.js b/assets/webconfig/js/ui_utils.js
index 0061dde9..4cbb7967 100644
--- a/assets/webconfig/js/ui_utils.js
+++ b/assets/webconfig/js/ui_utils.js
@@ -1393,3 +1393,32 @@ function isValidHostnameOrIP(value) {
return (isValidHostnameOrIP4(value) || isValidIPv6(value) || isValidServicename(value));
}
+const loadedScripts = [];
+
+function isScriptLoaded(src) {
+ return loadedScripts.indexOf(src) > -1;
+}
+
+function loadScript(src, callback, ...params) {
+ if (isScriptLoaded(src)) {
+ debugMessage('Script ' + src + ' already loaded');
+ if (callback && typeof callback === 'function') {
+ callback( ...params);
+ }
+ return;
+ }
+
+ const script = document.createElement('script');
+ script.src = src;
+
+ script.onload = function () {
+ debugMessage('Script ' + src + ' loaded successfully');
+ loadedScripts.push(src);
+
+ if (callback && typeof callback === 'function') {
+ callback(...params);
+ }
+ };
+
+ document.head.appendChild(script);
+}
diff --git a/assets/webconfig/js/wizard.js b/assets/webconfig/js/wizard.js
index 70584ddb..2524924f 100755
--- a/assets/webconfig/js/wizard.js
+++ b/assets/webconfig/js/wizard.js
@@ -3,2274 +3,71 @@ $(window.hyperion).one("ready", function (event) {
if (getStorage("wizardactive") === 'true') {
requestPriorityClear();
setStorage("wizardactive", false);
- if (getStorage("kodiAddress") != null) {
- kodiAddress = getStorage("kodiAddress");
-
- if (getStorage("kodiPort") != null) {
- kodiPort = getStorage("kodiPort");
- }
- sendToKodi("stop");
- }
}
});
+$("#btn_wizard_colorcalibration").click(async function () {
+ const { colorCalibrationKodiWizard } = await import('./wizards/colorCalibrationKodiWizard.js');
+ colorCalibrationKodiWizard.start();
+});
+
+$('#btn_wizard_byteorder').on('click', async () => {
+ const { rgbByteOrderWizard } = await import('./wizards/rgbByteOrderWizard.js');
+ rgbByteOrderWizard.start();
+});
+
function resetWizard(reload) {
$("#wizard_modal").modal('hide');
- clearInterval(wIntveralId);
requestPriorityClear();
setStorage("wizardactive", false);
$('#wizp1').toggle(true);
$('#wizp2').toggle(false);
$('#wizp3').toggle(false);
- //cc
- if (withKodi)
- sendToKodi("stop");
- step = 0;
- if (!reload) location.reload();
-}
-
-//rgb byte order wizard
-var wIntveralId;
-var new_rgb_order;
-
-function changeColor() {
- var color = $("#wiz_canv_color").css('background-color');
-
- if (color == 'rgb(255, 0, 0)') {
- $("#wiz_canv_color").css('background-color', 'rgb(0, 255, 0)');
- requestSetColor('0', '255', '0');
- }
- else {
- $("#wiz_canv_color").css('background-color', 'rgb(255, 0, 0)');
- requestSetColor('255', '0', '0');
+ if (!reload) {
+ location.reload();
}
}
-function startWizardRGB() {
- //create html
- $('#wiz_header').html('' + $.i18n('wiz_rgb_title'));
- $('#wizp1_body').html('
' + $.i18n('wiz_rgb_title') + '
' + $.i18n('wiz_rgb_intro1') + '
' + $.i18n('wiz_rgb_intro2') + '
');
- $('#wizp1_footer').html('');
- $('#wizp2_body').html('' + $.i18n('wiz_rgb_expl') + '
');
- $('#wizp2_body').append('');
- $('#wizp2_body').append('');
- $('#wizp2_body').append(' | |
| |
');
- $('#wizp2_footer').html('');
+function createLedDeviceWizards(ledType) {
- if (getStorage("darkMode") == "on")
- $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
+ let data = {};
+ let title;
- //open modal
- $("#wizard_modal").modal({
- backdrop: "static",
- keyboard: false,
- show: true
- });
+ $('#btn_wiz_holder').html("");
+ $('#btn_led_device_wiz').off();
+ if (ledType == "philipshue") {
+ $('#btn_wiz_holder').show();
+ data = { ledType };
+ title = 'wiz_hue_title';
+ }
+ else if (ledType == "nanoleaf") {
+ $('#btn_wiz_holder').hide();
+ data = { ledType };
+ title = 'wiz_nanoleaf_user_auth_title';
+ }
+ else if (ledType == "atmoorb") {
+ $('#btn_wiz_holder').show();
+ data = { ledType };
+ title = 'wiz_atmoorb_title';
+ }
+ else if (ledType == "yeelight") {
+ $('#btn_wiz_holder').show();
+ data = { ledType };
+ title = 'wiz_yeelight_title';
+ }
- //listen for continue
- $('#btn_wiz_cont').off().on('click', function () {
- beginWizardRGB();
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
+ if (Object.keys(data).length !== 0) {
+ startLedDeviceWizard(data, title, ledType + "Wizard");
+ }
+}
+
+function startLedDeviceWizard(data, hint, wizardName) {
+ $('#btn_wiz_holder').html("")
+ createHint("wizard", $.i18n(hint), "btn_wiz_holder", "btn_led_device_wiz");
+ $('#btn_led_device_wiz').off();
+ $('#btn_led_device_wiz').on('click', async (e) => {
+ const { [wizardName]: winzardObject } = await import('./wizards/LedDevice_' + data.ledType + '.js');
+ winzardObject.start(e);
});
}
-function beginWizardRGB() {
- $("#wiz_switchtime_select").off().on('change', function () {
- clearInterval(wIntveralId);
- var time = $("#wiz_switchtime_select").val();
- wIntveralId = setInterval(function () { changeColor(); }, time * 1000);
- });
-
- $('.wselect').on("change", function () {
- var rgb_order = window.serverConfig.device.colorOrder.split("");
- var redS = $("#wiz_r_select").val();
- var greenS = $("#wiz_g_select").val();
- var blueS = rgb_order.toString().replace(/,/g, "").replace(redS, "").replace(greenS, "");
-
- for (var i = 0; i < rgb_order.length; i++) {
- if (redS == rgb_order[i])
- $('#wiz_g_select option[value=' + rgb_order[i] + ']').prop('disabled', true);
- else
- $('#wiz_g_select option[value=' + rgb_order[i] + ']').prop('disabled', false);
- if (greenS == rgb_order[i])
- $('#wiz_r_select option[value=' + rgb_order[i] + ']').prop('disabled', true);
- else
- $('#wiz_r_select option[value=' + rgb_order[i] + ']').prop('disabled', false);
- }
-
- if (redS != 'null' && greenS != 'null') {
- $('#btn_wiz_save').prop('disabled', false);
-
- for (var i = 0; i < rgb_order.length; i++) {
- if (rgb_order[i] == "r")
- rgb_order[i] = redS;
- else if (rgb_order[i] == "g")
- rgb_order[i] = greenS;
- else
- rgb_order[i] = blueS;
- }
-
- rgb_order = rgb_order.toString().replace(/,/g, "");
-
- if (redS == "r" && greenS == "g") {
- $('#btn_wiz_save').toggle(false);
- $('#btn_wiz_checkok').toggle(true);
-
- window.readOnlyMode ? $('#btn_wiz_checkok').prop('disabled', true) : $('#btn_wiz_checkok').prop('disabled', false);
- }
- else {
- $('#btn_wiz_save').toggle(true);
- window.readOnlyMode ? $('#btn_wiz_save').prop('disabled', true) : $('#btn_wiz_save').prop('disabled', false);
-
- $('#btn_wiz_checkok').toggle(false);
- }
- new_rgb_order = rgb_order;
- }
- else
- $('#btn_wiz_save').prop('disabled', true);
- });
-
- $("#wiz_switchtime_select").append(createSelOpt('5', '5'), createSelOpt('10', '10'), createSelOpt('15', '15'), createSelOpt('30', '30'));
- $("#wiz_switchtime_select").trigger('change');
-
- $("#wiz_r_select").append(createSelOpt("null", ""), createSelOpt('r', $.i18n('general_col_red')), createSelOpt('g', $.i18n('general_col_green')), createSelOpt('b', $.i18n('general_col_blue')));
- $("#wiz_g_select").html($("#wiz_r_select").html());
- $("#wiz_r_select").trigger('change');
-
- requestSetColor('255', '0', '0');
- setTimeout(requestSetSource, 100, 'auto');
- setStorage("wizardactive", true);
-
- $('#btn_wiz_abort').off().on('click', function () { resetWizard(true); });
-
- $('#btn_wiz_checkok').off().on('click', function () {
- showInfoDialog('success', "", $.i18n('infoDialog_wizrgb_text'));
- resetWizard();
- });
-
- $('#btn_wiz_save').off().on('click', function () {
- resetWizard();
- window.serverConfig.device.colorOrder = new_rgb_order;
- requestWriteConfig({ "device": window.serverConfig.device });
- });
-}
-
-$('#btn_wizard_byteorder').off().on('click', startWizardRGB);
-
-//color calibration wizard
-
-const defaultKodiPort = 9090;
-
-var kodiAddress = document.location.hostname;
-var kodiPort = defaultKodiPort;
-
-var kodiUrl = new URL("ws://" + kodiAddress);
-kodiUrl.port = kodiPort;
-kodiUrl.pathname = "/jsonrpc/websocket";
-
-var wiz_editor;
-var colorLength;
-var cobj;
-var step = 0;
-var withKodi = false;
-var profile = 0;
-var websAddress;
-var imgAddress;
-var vidAddress = "https://sourceforge.net/projects/hyperion-project/files/resources/vid/";
-var picnr = 0;
-var availVideos = ["Sweet_Cocoon", "Caminandes_2_GranDillama", "Caminandes_3_Llamigos"];
-
-if (getStorage("kodiAddress") != null) {
-
- kodiAddress = getStorage("kodiAddress");
- kodiUrl.host = kodiAddress;
-}
-
-if (getStorage("kodiPort") != null) {
- kodiPort = getStorage("kodiPort");
- kodiUrl.port = kodiPort;
-}
-
-function switchPicture(pictures) {
- if (typeof pictures[picnr] === 'undefined')
- picnr = 0;
-
- sendToKodi('playP', pictures[picnr]);
- picnr++;
-}
-
-function sendToKodi(type, content, cb) {
- var command;
-
- switch (type) {
- case "msg":
- command = { "jsonrpc": "2.0", "method": "GUI.ShowNotification", "params": { "title": $.i18n('wiz_cc_title'), "message": content, "image": "info", "displaytime": 5000 }, "id": "1" };
- break;
- case "stop":
- command = { "jsonrpc": "2.0", "method": "Player.Stop", "params": { "playerid": 2 }, "id": "1" };
- break;
- case "playP":
- content = imgAddress + content + '.png';
- command = { "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "file": content } }, "id": "1" };
- break;
- case "playV":
- content = vidAddress + content;
- command = { "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "file": content } }, "id": "1" };
- break;
- case "rotate":
- command = { "jsonrpc": "2.0", "method": "Player.Rotate", "params": { "playerid": 2 }, "id": "1" };
- break;
- default:
- if (cb != undefined) {
- cb("error");
- }
- }
-
- if ("WebSocket" in window) {
-
- if (kodiUrl.port === '') {
- kodiUrl.port = defaultKodiPort;
- }
- var ws = new WebSocket(kodiUrl);
-
- ws.onopen = function () {
- ws.send(JSON.stringify(command));
- };
-
- ws.onmessage = function (evt) {
- var response = JSON.parse(evt.data);
- if (response.method === "System.OnQuit") {
- ws.close();
- } else {
- if (cb != undefined) {
- if (response.result != undefined) {
- if (response.result === "OK") {
- cb("success");
- ws.close();
- } else {
- cb("error");
- ws.close();
- }
- }
- }
- }
- };
-
- ws.onerror = function (evt) {
- if (cb != undefined) {
- cb("error");
- ws.close();
- }
- };
-
- ws.onclose = function (evt) {
- };
-
- }
- else {
- console.log("Kodi Access: WebSocket NOT supported by this browser");
- cb("error");
- }
-}
-
-function performAction() {
- var h;
-
- if (step == 1) {
- $('#wiz_cc_desc').html($.i18n('wiz_cc_chooseid'));
- updateWEditor(["id"]);
- $('#btn_wiz_back').prop("disabled", true);
- }
- else
- $('#btn_wiz_back').prop("disabled", false);
-
- if (step == 2) {
- updateWEditor(["white"]);
- h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_white_title'));
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_white_title'));
- sendToKodi('playP', "white");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_white_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 3) {
- updateWEditor(["gammaRed", "gammaGreen", "gammaBlue"]);
- h = '' + $.i18n('wiz_cc_adjustgamma') + '
';
- if (withKodi) {
- sendToKodi('playP', "HGradient");
- h += '';
- }
- else
- h += '' + $.i18n('wiz_cc_lettvshowm', "grey_1, grey_2, grey_3, HGradient, VGradient") + '
';
- $('#wiz_cc_desc').html(h);
- $('#wiz_cc_btn_sp').off().on('click', function () {
- switchPicture(["VGradient", "grey_1", "grey_2", "grey_3", "HGradient"]);
- });
- }
- if (step == 4) {
- updateWEditor(["red"]);
- h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_red_title'));
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_red_title'));
- sendToKodi('playP', "red");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_red_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 5) {
- updateWEditor(["green"]);
- h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_green_title'));
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_green_title'));
- sendToKodi('playP', "green");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_green_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 6) {
- updateWEditor(["blue"]);
- h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_blue_title'));
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_blue_title'));
- sendToKodi('playP', "blue");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_blue_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 7) {
- updateWEditor(["cyan"]);
- h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_cyan_title'));
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_cyan_title'));
- sendToKodi('playP', "cyan");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_cyan_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 8) {
- updateWEditor(["magenta"]);
- h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_magenta_title'));
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_magenta_title'));
- sendToKodi('playP', "magenta");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_magenta_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 9) {
- updateWEditor(["yellow"]);
- h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_yellow_title'));
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_yellow_title'));
- sendToKodi('playP', "yellow");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_yellow_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 10) {
- updateWEditor(["backlightThreshold", "backlightColored"]);
- h = $.i18n('wiz_cc_backlight');
- if (withKodi) {
- h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_black_title'));
- sendToKodi('playP', "black");
- }
- else
- h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_black_title'));
- $('#wiz_cc_desc').html(h);
- }
- if (step == 11) {
- updateWEditor([""], true);
- h = '' + $.i18n('wiz_cc_testintro') + '
';
- if (withKodi) {
- h += '' + $.i18n('wiz_cc_testintrok') + '
';
- sendToKodi('stop');
- for (var i = 0; i < availVideos.length; i++) {
- var txt = availVideos[i].replace(/_/g, " ");
- h += '';
- }
- h += '';
- }
- else
- h += '' + $.i18n('wiz_cc_testintrowok') + ' ' + $.i18n('wiz_cc_link') + '
';
- h += '' + $.i18n('wiz_cc_summary') + '
';
- $('#wiz_cc_desc').html(h);
-
- $('.videobtn').off().on('click', function (e) {
- if (e.target.id == "stop")
- sendToKodi("stop");
- else
- sendToKodi("playV", e.target.id + '.mp4');
-
- $(this).prop("disabled", true);
- setTimeout(function () { $('.videobtn').prop("disabled", false) }, 10000);
- });
-
- $('#btn_wiz_next').prop("disabled", true);
- $('#btn_wiz_save').toggle(true);
- window.readOnlyMode ? $('#btn_wiz_save').prop('disabled', true) : $('#btn_wiz_save').prop('disabled', false);
- }
- else {
- $('#btn_wiz_next').prop("disabled", false);
- $('#btn_wiz_save').toggle(false);
- }
-}
-
-function updateWEditor(el, all) {
- for (var key in cobj) {
- if (all === true || el[0] == key || el[1] == key || el[2] == key)
- $('#editor_container_wiz [data-schemapath*=".' + profile + '.' + key + '"]').toggle(true);
- else
- $('#editor_container_wiz [data-schemapath*=".' + profile + '.' + key + '"]').toggle(false);
- }
-}
-
-function startWizardCC() {
-
- //create html
- $('#wiz_header').html('' + $.i18n('wiz_cc_title'));
- $('#wizp1_body').html('' + $.i18n('wiz_cc_title') + '
' +
- '' + $.i18n('wiz_cc_intro1') + '
' +
- '' +
- '' +
- ''
- );
- $('#wizp1_footer').html('' +
- ''
- );
- $('#wizp2_body').html(''
- );
- $('#wizp2_footer').html('' +
- '' +
- '' +
- ''
- );
-
- if (getStorage("darkMode") == "on")
- $('#wizard_logo').prop("src", 'img/hyperion/logo_negativ.png');
-
- //open modal
- $("#wizard_modal").modal({
- backdrop: "static",
- keyboard: false,
- show: true
- });
-
- $('#wiz_cc_kodiip').off().on('change', function () {
-
- kodiAddress = encodeURIComponent($(this).val().trim());
-
- $('#kodi_status').html('');
- if (kodiAddress !== "") {
-
- if (!isValidHostnameOrIP(kodiAddress)) {
-
- $('#kodi_status').html('' + $.i18n('edt_msgcust_error_hostname_ip') + '
');
- withKodi = false;
-
- } else {
-
- if (isValidIPv6(kodiAddress)) {
- kodiUrl.hostname = "[" + kodiAddress + "]";
- } else {
- kodiUrl.hostname = kodiAddress;
- }
-
- $('#kodi_status').html('' + $.i18n('wiz_cc_try_connect') + '
');
- $('#btn_wiz_cont').prop('disabled', true);
-
- sendToKodi("msg", $.i18n('wiz_cc_kodimsg_start'), function (cb) {
- if (cb == "error") {
- $('#kodi_status').html('' + $.i18n('wiz_cc_kodidiscon') + '
' + $.i18n('wiz_cc_kodidisconlink') + ' ' + $.i18n('wiz_cc_link') + '
');
- withKodi = false;
- }
- else {
- setStorage("kodiAddress", kodiAddress);
- setStorage("kodiPort", defaultKodiPort);
-
- $('#kodi_status').html('' + $.i18n('wiz_cc_kodicon') + '
');
- withKodi = true;
- }
-
- $('#btn_wiz_cont').prop('disabled', false);
- });
- }
- }
- });
-
- //listen for continue
- $('#btn_wiz_cont').off().on('click', function () {
- beginWizardCC();
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- });
-
- $('#wiz_cc_kodiip').trigger("change");
- colorLength = window.serverConfig.color.channelAdjustment;
- cobj = window.schema.color.properties.channelAdjustment.items.properties;
- websAddress = document.location.hostname + ':' + window.serverConfig.webConfig.port;
- imgAddress = 'http://' + websAddress + '/img/cc/';
- setStorage("wizardactive", true);
-
- //check profile count
- if (colorLength.length > 1) {
- $('#multi_cali').html('' + $.i18n('wiz_cc_morethanone') + '
');
- for (var i = 0; i < colorLength.length; i++)
- $('#wiz_select').append(createSelOpt(i, i + 1 + ' (' + colorLength[i].id + ')'));
-
- $('#wiz_select').off().on('change', function () {
- profile = $(this).val();
- });
- }
-
- //prepare editor
- wiz_editor = createJsonEditor('editor_container_wiz', {
- color: window.schema.color
- }, true, true);
-
- $('#editor_container_wiz h4').toggle(false);
- $('#editor_container_wiz .btn-group').toggle(false);
- $('#editor_container_wiz [data-schemapath="root.color.imageToLedMappingType"]').toggle(false);
- for (var i = 0; i < colorLength.length; i++)
- $('#editor_container_wiz [data-schemapath*="root.color.channelAdjustment.' + i + '."]').toggle(false);
-}
-
-function beginWizardCC() {
- $('#btn_wiz_next').off().on('click', function () {
- step++;
- performAction();
- });
-
- $('#btn_wiz_back').off().on('click', function () {
- step--;
- performAction();
- });
-
- $('#btn_wiz_abort').off().on('click', resetWizard);
-
- $('#btn_wiz_save').off().on('click', function () {
- requestWriteConfig(wiz_editor.getValue());
- resetWizard();
- });
-
- wiz_editor.on("change", function (e) {
- var val = wiz_editor.getEditor('root.color.channelAdjustment.' + profile + '').getValue();
- var temp = JSON.parse(JSON.stringify(val));
- delete temp.leds
- requestAdjustment(JSON.stringify(temp), "", true);
- });
-
- step++
- performAction();
-}
-
-$('#btn_wizard_colorcalibration').off().on('click', startWizardCC);
-
-// Layout positions
-var lightPosTop = { hmin: 0.15, hmax: 0.85, vmin: 0, vmax: 0.2 };
-var lightPosTopLeft = { hmin: 0, hmax: 0.15, vmin: 0, vmax: 0.15 };
-var lightPosTopRight = { hmin: 0.85, hmax: 1.0, vmin: 0, vmax: 0.15 };
-var lightPosBottom = { hmin: 0.15, hmax: 0.85, vmin: 0.8, vmax: 1.0 };
-var lightPosBottomLeft = { hmin: 0, hmax: 0.15, vmin: 0.85, vmax: 1.0 };
-var lightPosBottomRight = { hmin: 0.85, hmax: 1.0, vmin: 0.85, vmax: 1.0 };
-var lightPosLeft = { hmin: 0, hmax: 0.15, vmin: 0.15, vmax: 0.85 };
-var lightPosLeftTop = { hmin: 0, hmax: 0.15, vmin: 0, vmax: 0.5 };
-var lightPosLeftMiddle = { hmin: 0, hmax: 0.15, vmin: 0.25, vmax: 0.75 };
-var lightPosLeftBottom = { hmin: 0, hmax: 0.15, vmin: 0.5, vmax: 1.0 };
-var lightPosRight = { hmin: 0.85, hmax: 1.0, vmin: 0.15, vmax: 0.85 };
-var lightPosRightTop = { hmin: 0.85, hmax: 1.0, vmin: 0, vmax: 0.5 };
-var lightPosRightMiddle = { hmin: 0.85, hmax: 1.0, vmin: 0.25, vmax: 0.75 };
-var lightPosRightBottom = { hmin: 0.85, hmax: 1.0, vmin: 0.5, vmax: 1.0 };
-var lightPosEntire = { hmin: 0.0, hmax: 1.0, vmin: 0.0, vmax: 1.0 };
-
-var lightPosBottomLeft14 = { hmin: 0, hmax: 0.25, vmin: 0.85, vmax: 1.0 };
-var lightPosBottomLeft12 = { hmin: 0.25, hmax: 0.5, vmin: 0.85, vmax: 1.0 };
-var lightPosBottomLeft34 = { hmin: 0.5, hmax: 0.75, vmin: 0.85, vmax: 1.0 };
-var lightPosBottomLeft11 = { hmin: 0.75, hmax: 1, vmin: 0.85, vmax: 1.0 };
-
-var lightPosBottomLeft112 = { hmin: 0, hmax: 0.5, vmin: 0.85, vmax: 1.0 };
-var lightPosBottomLeft121 = { hmin: 0.5, hmax: 1, vmin: 0.85, vmax: 1.0 };
-var lightPosBottomLeftNewMid = { hmin: 0.25, hmax: 0.75, vmin: 0.85, vmax: 1.0 };
-
-var lightPosTopLeft112 = { hmin: 0, hmax: 0.5, vmin: 0, vmax: 0.15 };
-var lightPosTopLeft121 = { hmin: 0.5, hmax: 1, vmin: 0, vmax: 0.15 };
-var lightPosTopLeftNewMid = { hmin: 0.25, hmax: 0.75, vmin: 0, vmax: 0.15 };
-
-function assignLightPos(pos, name) {
- var i = null;
-
- if (pos === "top")
- i = lightPosTop;
- else if (pos === "topleft")
- i = lightPosTopLeft;
- else if (pos === "topright")
- i = lightPosTopRight;
- else if (pos === "bottom")
- i = lightPosBottom;
- else if (pos === "bottomleft")
- i = lightPosBottomLeft;
- else if (pos === "bottomright")
- i = lightPosBottomRight;
- else if (pos === "left")
- i = lightPosLeft;
- else if (pos === "lefttop")
- i = lightPosLeftTop;
- else if (pos === "leftmiddle")
- i = lightPosLeftMiddle;
- else if (pos === "leftbottom")
- i = lightPosLeftBottom;
- else if (pos === "right")
- i = lightPosRight;
- else if (pos === "righttop")
- i = lightPosRightTop;
- else if (pos === "rightmiddle")
- i = lightPosRightMiddle;
- else if (pos === "rightbottom")
- i = lightPosRightBottom;
- else if (pos === "lightPosBottomLeft14")
- i = lightPosBottomLeft14;
- else if (pos === "lightPosBottomLeft12")
- i = lightPosBottomLeft12;
- else if (pos === "lightPosBottomLeft34")
- i = lightPosBottomLeft34;
- else if (pos === "lightPosBottomLeft11")
- i = lightPosBottomLeft11;
- else if (pos === "lightPosBottomLeft112")
- i = lightPosBottomLeft112;
- else if (pos === "lightPosBottomLeft121")
- i = lightPosBottomLeft121;
- else if (pos === "lightPosBottomLeftNewMid")
- i = lightPosBottomLeftNewMid;
- else if (pos === "lightPosTopLeft112")
- i = lightPosTopLeft112;
- else if (pos === "lightPosTopLeft121")
- i = lightPosTopLeft121;
- else if (pos === "lightPosTopLeftNewMid")
- i = lightPosTopLeftNewMid;
- else
- i = lightPosEntire;
-
- i.name = name;
- return i;
-}
-
-function getHostInLights(hostname) {
- return lights.filter(
- function (lights) {
- return lights.host === hostname
- }
- );
-}
-
-function getIpInLights(ip) {
- return lights.filter(
- function (lights) {
- return lights.ip === ip
- }
- );
-}
-
-function getIdInLights(id) {
- return lights.filter(
- function (lights) {
- return lights.id === id
- }
- );
-}
-
-// External properties properties, 2-dimensional arry of [ledType][key]
-devicesProperties = {};
-
-//****************************
-// Wizard Philips Hue
-//****************************
-
-var hueIPs = [];
-var hueIPsinc = 0;
-var hueLights = [];
-var hueEntertainmentConfigs = [];
-var hueEntertainmentServices = [];
-var lightLocation = [];
-var groupLights = [];
-var groupChannels = [];
-var groupLightsLocations = [];
-var isAPIv2Ready = true;
-var isEntertainmentReady = true;
-
-function startWizardPhilipsHue(e) {
- //create html
-
- var hue_title = 'wiz_hue_title';
- var hue_intro1 = 'wiz_hue_e_intro1';
- var hue_desc1 = 'wiz_hue_desc1';
- var hue_create_user = 'wiz_hue_create_user';
-
- $('#wiz_header').html('' + $.i18n(hue_title));
- $('#wizp1_body').html('' + $.i18n(hue_title) + '
' + $.i18n(hue_intro1) + '
');
- $('#wizp1_footer').html('');
- $('#wizp2_body').html('');
-
- var topContainer_html = '' + $.i18n(hue_desc1) + '
' +
- '' +
- '
' +
- '
' + $.i18n('wiz_hue_ip') + '
' +
- '
' +
- ' ' +
- ' ' + '
' +
- '
';
-
- if (storedAccess === 'expert') {
- topContainer_html += '
';
- }
-
- topContainer_html += '
';
- topContainer_html += '';
-
- $('#wh_topcontainer').append(topContainer_html);
-
- $('#usrcont').append('' + $.i18n('wiz_hue_username') + '
' +
- '
' +
- ''
- );
-
- $('#usrcont').append('
');
-
- $('#usrcont').append('<\p>' +
- '');
-
- $('#wizp2_body').append('
' + $.i18n('wiz_hue_e_desc2') + '
');
- createTable("gidsh", "gidsb", "hue_grp_ids_t");
- $('.gidsh').append(createTableRow([$.i18n('edt_dev_spec_groupId_title'), ""], true));
-
- $('#wizp2_body').append('' + $.i18n('wiz_hue_e_desc3') + '
');
-
- createTable("lidsh", "lidsb", "hue_ids_t");
- $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lightid_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
- $('#wizp2_footer').html('');
- $('#wizp3_body').html('' + $.i18n('wiz_hue_press_link') + '
');
-
- if (getStorage("darkMode") == "on")
- $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
-
- //open modal
- $("#wizard_modal").modal({
- backdrop: "static",
- keyboard: false,
- show: true
- });
-
- //listen for continue
- $('#btn_wiz_cont').off().on('click', function () {
- beginWizardHue();
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- });
-}
-
-function checkHueBridge(cb, hueUser) {
- var usr = (typeof hueUser != "undefined") ? hueUser : 'config';
- if (usr === 'config') {
- $('#wiz_hue_discovered').html("");
- }
-
- if (hueIPs[hueIPsinc]) {
- var host = hueIPs[hueIPsinc].host;
- var port = hueIPs[hueIPsinc].port;
-
- if (usr != '')
- {
- getProperties_hue_bridge(cb, decodeURIComponent(host), port, usr);
- }
- else
- {
- cb(false, usr);
- }
-
- if (isAPIv2Ready) {
- $('#port').val(443);
- }
- }
-}
-
-function checkBridgeResult(reply, usr) {
- if (reply) {
- //abort checking, first reachable result is used
- $('#wiz_hue_ipstate').html("");
- $('#host').val(hueIPs[hueIPsinc].host)
- $('#port').val(hueIPs[hueIPsinc].port)
-
- $('#usrcont').toggle(true);
-
- checkHueBridge(checkUserResult, $('#user').val());
- }
- else {
- $('#usrcont').toggle(false);
- $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
- }
-};
-
-function checkUserResult(reply, username) {
- $('#usrcont').toggle(true);
-
- var hue_create_user = 'wiz_hue_e_create_user';
- if (!isEntertainmentReady) {
- hue_create_user = 'wiz_hue_create_user';
- $('#hue_client_key_r').toggle(false);
- } else {
- $('#hue_client_key_r').toggle(true);
- }
-
- $('#wiz_hue_create_user').text($.i18n(hue_create_user));
- $('#wiz_hue_create_user').toggle(true);
-
- if (reply) {
- $('#user').val(username);
-
- if (isEntertainmentReady && $('#clientkey').val() == "") {
- $('#wiz_hue_usrstate').html($.i18n('wiz_hue_e_clientkey_needed'));
- $('#wiz_hue_create_user').toggle(true);
- } else {
- $('#wiz_hue_usrstate').html("");
- $('#wiz_hue_create_user').toggle(false);
-
- if (isEntertainmentReady) {
- $('#hue_id_headline').text($.i18n('wiz_hue_e_desc3'));
- $('#hue_grp_ids_t').toggle(true);
-
- get_hue_groups(username);
-
- } else {
- $('#hue_id_headline').text($.i18n('wiz_hue_desc2'));
- $('#hue_grp_ids_t').toggle(false);
-
- get_hue_lights(username);
-
- }
- }
- }
- else {
- //abort checking, first reachable result is used
- $('#wiz_hue_usrstate').html($.i18n('wiz_hue_failure_user'));
- $('#wiz_hue_create_user').toggle(true);
- }
-};
-
-function useGroupId(id, username) {
- $('#groupId').val(hueEntertainmentConfigs[id].id);
- if (isAPIv2Ready) {
- var group = hueEntertainmentConfigs[id];
-
- groupLights = [];
- for (const light of group.light_services) {
- groupLights.push(light.rid);
- }
-
- groupChannels = [];
- for (const channel of group.channels) {
- groupChannels.push(channel);
- }
-
- groupLightsLocations = [];
- for (const location of group.locations.service_locations) {
- groupLightsLocations.push(location);
- }
- } else {
- //Ensure ligthIDs are strings
- groupLights = hueEntertainmentConfigs[id].lights.map(num => {
- return String(num);
- });
-
- var lightLocations = hueEntertainmentConfigs[id].locations;
- for (var locationID in lightLocations) {
- var lightLocation = {};
-
- let position = {
- x: lightLocations[locationID][0],
- y: lightLocations[locationID][1],
- z: lightLocations[locationID][2]
- };
- lightLocation.position = position;
-
- groupLightsLocations.push(lightLocation);
- }
- }
-
- get_hue_lights(username);
-}
-
-function updateBridgeDetails(properties) {
- var ledDeviceProperties = properties.config;
-
- if (!jQuery.isEmptyObject(ledDeviceProperties)) {
- isEntertainmentReady = properties.isEntertainmentReady;
- isAPIv2Ready = properties.isAPIv2Ready;
-
- if (ledDeviceProperties.name && ledDeviceProperties.bridgeid && ledDeviceProperties.modelid) {
- $('#wiz_hue_discovered').html(
- "Bridge: " + ledDeviceProperties.name +
- ", Modelid: " + ledDeviceProperties.modelid +
- ", Firmware: " + ledDeviceProperties.swversion + "
" +
- "API-Version: " + ledDeviceProperties.apiversion +
- ", Entertainment: " + (isEntertainmentReady ? "✓" : "-") +
- ", APIv2: " + (isAPIv2Ready ? "✓" : "-")
- );
- }
- }
-}
-
-async function discover_hue_bridges() {
- $('#wiz_hue_ipstate').html($.i18n('edt_dev_spec_devices_discovery_inprogress'));
-
- // $('#wiz_hue_discovered').html("")
- const res = await requestLedDeviceDiscovery('philipshue');
- if (res && !res.error) {
- const r = res.info;
-
- // Process devices returned by discovery
- if (r.devices.length == 0) {
- $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
- $('#wiz_hue_discovered').html("")
- }
- else {
- hueIPs = [];
- hueIPsinc = 0;
-
- var discoveryMethod = "ssdp";
- if (res.info.discoveryMethod) {
- discoveryMethod = res.info.discoveryMethod;
- }
-
- for (const device of r.devices) {
- if (device) {
- var host;
- var port;
- if (discoveryMethod === "ssdp") {
- if (device.hostname && device.domain) {
- host = device.hostname + "." + device.domain;
- port = device.port;
- } else {
- host = device.ip;
- port = device.port;
- }
- } else {
- host = device.service;
- port = device.port;
- }
-
- if (host) {
-
- if (!hueIPs.some(item => item.host === host)) {
- hueIPs.push({ host: host, port: port });
- }
- }
- }
- }
-
- $('#wiz_hue_ipstate').html("");
- $('#host').val(hueIPs[hueIPsinc].host)
- $('#port').val(hueIPs[hueIPsinc].port)
-
- $('#hue_bridge_select').html("");
-
- for (var key in hueIPs) {
- $('#hue_bridge_select').append(createSelOpt(key, hueIPs[key].host));
- }
-
- $('.hue_bridge_sel_watch').on("click", function () {
- hueIPsinc = $(this).val();
-
- var name = $("#hue_bridge_select option:selected").text();
- $('#host').val(name);
- $('#port').val(hueIPs[hueIPsinc].port)
-
- var usr = $('#user').val();
- if (usr != "") {
- checkHueBridge(checkUserResult, usr);
- } else {
- checkHueBridge(checkBridgeResult);
- }
- });
-
- $('.hue_bridge_sel_watch').click();
- }
- }
-}
-
-async function getProperties_hue_bridge(cb, hostAddress, port, username, resourceFilter) {
- let params = { host: hostAddress, username: username, filter: resourceFilter };
- if (port !== 'undefined') {
- params.port = parseInt(port);
- }
-
- var ledType = 'philipshue';
- var key = hostAddress;
-
- //Create ledType cache entry
- if (!devicesProperties[ledType]) {
- devicesProperties[ledType] = {};
- }
-
- // Use device's properties, if properties in chache
- if (devicesProperties[ledType][key] && devicesProperties[ledType][key][username]) {
- updateBridgeDetails(devicesProperties[ledType][key]);
- cb(true, username);
- } else {
- const res = await requestLedDeviceProperties(ledType, params);
- if (res && !res.error) {
- var ledDeviceProperties = res.info.properties;
- if (!jQuery.isEmptyObject(ledDeviceProperties)) {
-
- devicesProperties[ledType][key] = {};
- devicesProperties[ledType][key][username] = ledDeviceProperties;
-
- isAPIv2Ready = res.info.isAPIv2Ready;
- devicesProperties[ledType][key].isAPIv2Ready = isAPIv2Ready;
- isEntertainmentReady = res.info.isEntertainmentReady;
- devicesProperties[ledType][key].isEntertainmentReady = isEntertainmentReady;
-
- updateBridgeDetails(devicesProperties[ledType][key]);
- if (username === "config") {
- cb(true);
- } else {
- cb(true, username);
- }
- } else {
- cb(false, username);
- }
- } else {
- cb(false, username);
- }
- }
-}
-
-async function identify_hue_device(hostAddress, port, username, name, id, id_v1) {
- var disabled = $('#btn_wiz_save').is(':disabled');
- // Take care that new record cannot be save during background process
- $('#btn_wiz_save').prop('disabled', true);
-
- let params = { host: decodeURIComponent(hostAddress), username: username, lightName: decodeURIComponent(name), lightId: id, lightId_v1: id_v1 };
-
- if (port !== 'undefined') {
- params.port = parseInt(port);
- }
-
- await requestLedDeviceIdentification('philipshue', params);
-
- if (!window.readOnlyMode) {
- $('#btn_wiz_save').prop('disabled', disabled);
- }
-}
-
-//return editor Value
-function eV(vn, defaultVal = "") {
- var editor = (vn) ? conf_editor.getEditor("root.specificOptions." + vn) : null;
- return (editor == null) ? defaultVal : ((defaultVal != "" && !isNaN(defaultVal) && isNaN(editor.getValue())) ? defaultVal : editor.getValue());
-}
-
-function beginWizardHue() {
- var usr = eV("username");
- if (usr != "") {
- $('#user').val(usr);
- }
-
- var clkey = eV("clientkey");
- if (clkey != "") {
- $('#clientkey').val(clkey);
- }
-
- //check if host is empty/reachable/search for bridge
- if (eV("host") == "") {
- hueIPs = [];
- hueIPsinc = 0;
-
- discover_hue_bridges();
- }
- else {
- var host = eV("host");
- $('#host').val(host);
-
- var port = eV("port");
- if (port > 0) {
- $('#port').val(port);
- }
- else {
- $('#port').val('');
- }
- hueIPs.push({ host: host, port: port });
-
- if (usr != "") {
- checkHueBridge(checkUserResult, usr);
- } else {
- checkHueBridge(checkBridgeResult);
- }
- }
-
- $('#retry_bridge').off().on('click', function () {
- var host = $('#host').val();
- var port = parseInt($('#port').val());
-
- if (host != "") {
-
- var idx = hueIPs.findIndex(item => item.host === host && item.port === port);
- if (idx === -1) {
- hueIPs.push({ host: host, port: port });
- hueIPsinc = hueIPs.length - 1;
- } else {
- hueIPsinc = idx;
- }
- }
- else {
- discover_hue_bridges();
- }
-
- var usr = $('#user').val();
- if (usr != "") {
- checkHueBridge(checkUserResult, usr);
- } else {
- checkHueBridge(checkBridgeResult);
- }
- });
-
- $('#retry_usr').off().on('click', function () {
- checkHueBridge(checkUserResult, $('#user').val());
- });
-
- $('#wiz_hue_create_user').off().on('click', function () {
- createHueUser();
- });
-
- function assignLightEntertainmentPos(isFocusCenter, position, name, id) {
-
- var x = position.x;
- var z = position.z;
-
- if (isFocusCenter) {
- // Map lights as in centered range -0.5 to 0.5
- if (x < -0.5) {
- x = -0.5;
- } else if (x > 0.5) {
- x = 0.5;
- }
- if (z < -0.5) {
- z = -0.5;
- } else if (z > 0.5) {
- z = 0.5;
- }
- } else {
- // Map lights as in full range -1 to 1
- x /= 2;
- z /= 2;
- }
-
- var h = x + 0.5;
- var v = -z + 0.5;
-
- var hmin = h - 0.05;
- var hmax = h + 0.05;
- var vmin = v - 0.05;
- var vmax = v + 0.05;
-
- let layoutObject = {
- hmin: hmin < 0 ? 0 : hmin,
- hmax: hmax > 1 ? 1 : hmax,
- vmin: vmin < 0 ? 0 : vmin,
- vmax: vmax > 1 ? 1 : vmax,
- name: name
- };
-
- if (id) {
- layoutObject.name += "_" + id;
- }
- return layoutObject;
- }
-
- function assignSegmentedLightPos(segment, position, name) {
- var layoutObjects = [];
-
- var segTotalLength = 0;
- for (var key in segment) {
-
- segTotalLength += segment[key].length;
- }
-
- var min;
- var max;
- var horizontal = true;
-
- var layoutObject = assignLightPos(position, name);
- if (position === "left" || position === "right") {
- // vertical distribution
- min = layoutObject.vmin;
- max = layoutObject.vmax;
- horizontal = false;
-
- } else {
- // horizontal distribution
- min = layoutObject.hmin;
- max = layoutObject.hmax;
- }
-
- var step = (max - min) / segTotalLength;
- var start = min;
-
- for (var key in segment) {
- min = start;
- max = round(start + segment[key].length * step);
-
- if (horizontal) {
- layoutObject.hmin = min;
- layoutObject.hmax = max;
- } else {
- layoutObject.vmin = min;
- layoutObject.vmax = max;
- }
- layoutObject.name = name + "_" + key;
- layoutObjects.push(JSON.parse(JSON.stringify(layoutObject)));
-
- start = max;
- }
-
- return layoutObjects;
- }
-
- $('#btn_wiz_save').off().on("click", function () {
- var hueLedConfig = [];
- var finalLightIds = [];
- var channelNumber = 0;
-
- //create hue led config
- for (var key in groupLights) {
- var lightId = groupLights[key];
-
- if ($('#hue_' + lightId).val() != "disabled") {
- finalLightIds.push(lightId);
-
- var lightName;
- if (isAPIv2Ready) {
- var light = hueLights.find(light => light.id === lightId);
- lightName = light.metadata.name;
- } else {
- lightName = hueLights[lightId].name;
- }
-
- var position = $('#hue_' + lightId).val();
- var lightIdx = groupLights.indexOf(lightId);
- var lightLocation = groupLightsLocations[lightIdx];
-
- var serviceID;
- if (isAPIv2Ready) {
- serviceID = lightLocation.service.rid;
- }
-
- if (position.startsWith("entertainment")) {
-
- // Layout per entertainment area definition at bridge
- var isFocusCenter = false;
- if (position === "entertainment_center") {
- isFocusCenter = true;
- }
-
- if (isAPIv2Ready) {
-
- groupChannels.forEach((channel) => {
- if (channel.members[0].service.rid === serviceID) {
- var layoutObject = assignLightEntertainmentPos(isFocusCenter, channel.position, lightName, channel.channel_id);
- hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
- ++channelNumber;
- }
- });
- } else {
- var layoutObject = assignLightEntertainmentPos(isFocusCenter, lightLocation.position, lightName);
- hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
- }
- }
- else {
- // Layout per manual settings
- var maxSegments = 1;
-
- if (isAPIv2Ready) {
- var service = hueEntertainmentServices.find(service => service.id === serviceID);
- maxSegments = service.segments.max_segments;
- }
-
- if (maxSegments > 1) {
- var segment = service.segments.segments;
- var layoutObjects = assignSegmentedLightPos(segment, position, lightName);
- hueLedConfig.push(...layoutObjects);
- } else {
- var layoutObject = assignLightPos(position, lightName);
- hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
- }
- channelNumber += maxSegments;
- }
- }
- }
-
- var sc = window.serverConfig;
- sc.leds = hueLedConfig;
-
- //Adjust gamma, brightness and compensation
- var c = sc.color.channelAdjustment[0];
- c.gammaBlue = 1.0;
- c.gammaRed = 1.0;
- c.gammaGreen = 1.0;
- c.brightness = 100;
- c.brightnessCompensation = 0;
-
- //device config
-
- //Start with a clean configuration
- var d = {};
- d.host = $('#host').val();
- d.port = parseInt($('#port').val());
- d.username = $('#user').val();
- d.type = 'philipshue';
- d.colorOrder = 'rgb';
- d.lightIds = finalLightIds;
- d.transitiontime = parseInt(eV("transitiontime", 1));
- d.restoreOriginalState = (eV("restoreOriginalState", false) == true);
- d.switchOffOnBlack = (eV("switchOffOnBlack", false) == true);
-
- d.blackLevel = parseFloat(eV("blackLevel", 0.009));
- d.onBlackTimeToPowerOff = parseInt(eV("onBlackTimeToPowerOff", 600));
- d.onBlackTimeToPowerOn = parseInt(eV("onBlackTimeToPowerOn", 300));
- d.brightnessFactor = parseFloat(eV("brightnessFactor", 1));
-
- d.clientkey = $('#clientkey').val();
- d.groupId = $('#groupId').val();
- d.blackLightsTimeout = parseInt(eV("blackLightsTimeout", 5000));
- d.brightnessMin = parseFloat(eV("brightnessMin", 0));
- d.brightnessMax = parseFloat(eV("brightnessMax", 1));
- d.brightnessThreshold = parseFloat(eV("brightnessThreshold", 0.0001));
- d.handshakeTimeoutMin = parseInt(eV("handshakeTimeoutMin", 300));
- d.handshakeTimeoutMax = parseInt(eV("handshakeTimeoutMax", 1000));
- d.verbose = (eV("verbose") == true);
-
- d.autoStart = conf_editor.getEditor("root.generalOptions.autoStart").getValue();
- d.enableAttempts = parseInt(conf_editor.getEditor("root.generalOptions.enableAttempts").getValue());
- d.enableAttemptsInterval = parseInt(conf_editor.getEditor("root.generalOptions.enableAttemptsInterval").getValue());
-
- d.useEntertainmentAPI = isEntertainmentReady;
- d.useAPIv2 = isAPIv2Ready;
-
- if (isEntertainmentReady) {
- d.hardwareLedCount = channelNumber;
- if (window.serverConfig.device.type !== d.type) {
- //smoothing on, if new device
- sc.smoothing = { enable: true };
- }
- } else {
- d.hardwareLedCount = finalLightIds.length;
- d.verbose = false;
- if (window.serverConfig.device.type !== d.type) {
- //smoothing off, if new device
- sc.smoothing = { enable: false };
- }
- }
-
- window.serverConfig.device = d;
-
- requestWriteConfig(sc, true);
- resetWizard();
- });
-
- $('#btn_wiz_abort').off().on('click', resetWizard);
-}
-
-function createHueUser() {
- var host = hueIPs[hueIPsinc].host;
- var port = hueIPs[hueIPsinc].port;
-
- let params = { host: host };
- if (port !== 'undefined') {
- params.port = parseInt(port);
- }
-
- var retryTime = 30;
- var retryInterval = 2;
-
- var UserInterval = setInterval(function () {
-
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(false);
- $('#wizp3').toggle(true);
-
- (async () => {
-
- retryTime -= retryInterval;
- $("#connectionTime").html(retryTime);
- if (retryTime <= 0) {
- abortConnection(UserInterval);
- clearInterval(UserInterval);
- }
- else {
- const res = await requestLedDeviceAddAuthorization('philipshue', params);
- if (res && !res.error) {
- var response = res.info;
-
- if (jQuery.isEmptyObject(response)) {
- debugMessage(retryTime + ": link button not pressed or device not reachable");
- } else {
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- $('#wizp3').toggle(false);
-
- var username = response.username;
- if (username != 'undefined') {
- $('#user').val(username);
- conf_editor.getEditor("root.specificOptions.username").setValue(username);
- conf_editor.getEditor("root.specificOptions.host").setValue(host);
- conf_editor.getEditor("root.specificOptions.port").setValue(port);
- }
-
- if (isEntertainmentReady) {
- var clientkey = response.clientkey;
- if (clientkey != 'undefined') {
- $('#clientkey').val(clientkey);
- conf_editor.getEditor("root.specificOptions.clientkey").setValue(clientkey);
- }
- }
- checkHueBridge(checkUserResult, username);
- clearInterval(UserInterval);
- }
- } else {
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- $('#wizp3').toggle(false);
- clearInterval(UserInterval);
- }
- }
- })();
-
- }, retryInterval * 1000);
-}
-
-function get_hue_groups(username) {
- var host = hueIPs[hueIPsinc].host;
-
- if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
- var ledProperties = devicesProperties['philipshue'][host][username];
-
- if (isAPIv2Ready) {
- if (!jQuery.isEmptyObject(ledProperties.data)) {
- if (Object.keys(ledProperties.data).length > 0) {
- hueEntertainmentConfigs = ledProperties.data.filter(config => {
- return config.type === "entertainment_configuration";
- });
- hueEntertainmentServices = ledProperties.data.filter(config => {
- return (config.type === "entertainment" && config.renderer === true);
- });
- }
- }
- } else {
- if (!jQuery.isEmptyObject(ledProperties.groups)) {
- hueEntertainmentConfigs = [];
- var hueGroups = ledProperties.groups;
- for (var groupid in hueGroups) {
- if (hueGroups[groupid].type == 'Entertainment') {
- hueGroups[groupid].id = groupid;
- hueEntertainmentConfigs.push(hueGroups[groupid]);
- }
- }
- }
- }
-
- if (Object.keys(hueEntertainmentConfigs).length > 0) {
-
- $('.lidsb').html("");
- $('#wh_topcontainer').toggle(false);
- $('#hue_grp_ids_t').toggle(true);
-
- for (var groupid in hueEntertainmentConfigs) {
- $('.gidsb').append(createTableRow([groupid + ' (' + hueEntertainmentConfigs[groupid].name + ')', '']));
- }
- } else {
- noAPISupport('wiz_hue_e_noegrpids', username);
- }
- }
-}
-
-function noAPISupport(txt, username) {
- showNotification('danger', $.i18n('wiz_hue_e_title'), $.i18n('wiz_hue_e_noapisupport_hint'));
- conf_editor.getEditor("root.specificOptions.useEntertainmentAPI").setValue(false);
- $("#root_specificOptions_useEntertainmentAPI").trigger("change");
- $('#btn_wiz_holder').append('' + $.i18n('wiz_hue_e_noapisupport_hint') + '
');
- $('#hue_grp_ids_t').toggle(false);
- var txt = (txt) ? $.i18n(txt) : $.i18n('wiz_hue_e_nogrpids');
- $('' + txt + '
' + $.i18n('wiz_hue_e_noapisupport') + '
').insertBefore('#wizp2_body #hue_ids_t');
- $('#hue_id_headline').html($.i18n('wiz_hue_desc2'));
-
- get_hue_lights(username);
-}
-
-function get_hue_lights(username) {
- var host = hueIPs[hueIPsinc].host;
-
- if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
- var ledProperties = devicesProperties['philipshue'][host][username];
-
- if (isAPIv2Ready) {
- if (!jQuery.isEmptyObject(ledProperties.data)) {
- if (Object.keys(ledProperties.data).length > 0) {
- hueLights = ledProperties.data.filter(config => {
- return config.type === "light";
- });
- }
- }
- } else {
- if (!jQuery.isEmptyObject(ledProperties.lights)) {
- hueLights = ledProperties.lights;
- }
- }
-
- if (Object.keys(hueLights).length > 0) {
- if (!isEntertainmentReady) {
- $('#wh_topcontainer').toggle(false);
- }
- $('#hue_ids_t, #btn_wiz_save').toggle(true);
-
- var lightOptions = [
- "top", "topleft", "topright",
- "bottom", "bottomleft", "bottomright",
- "left", "lefttop", "leftmiddle", "leftbottom",
- "right", "righttop", "rightmiddle", "rightbottom",
- "entire",
- "lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
- "lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
- "lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
- ];
-
- if (isEntertainmentReady) {
- lightOptions.unshift("entertainment_center");
- lightOptions.unshift("entertainment");
- } else {
- lightOptions.unshift("disabled");
- groupLights = Object.keys(hueLights);
- }
-
- $('.lidsb').html("");
-
- var pos = "";
- for (var id in groupLights) {
- var lightId = groupLights[id];
- var lightId_v1 = "/lights/" + lightId;
-
- var lightName;
- if (isAPIv2Ready) {
- var light = hueLights.find(light => light.id === lightId);
- lightName = light.metadata.name;
- lightId_v1 = light.id_v1;
- } else {
- lightName = hueLights[lightId].name;
- }
-
- if (isEntertainmentReady) {
- var lightLocation = {};
- lightLocation = groupLightsLocations[id];
- if (lightLocation) {
- if (isAPIv2Ready) {
- pos = 0;
- } else {
- var x = lightLocation.position.x;
- var y = lightLocation.position.y;
- var z = lightLocation.position.z;
-
- var xval = (x < 0) ? "left" : "right";
- if (z != 1 && x >= -0.25 && x <= 0.25) xval = "";
- switch (z) {
- case 1: // top / Ceiling height
- pos = "top" + xval;
- break;
- case 0: // middle / TV height
- pos = (xval == "" && y >= 0.75) ? "bottom" : xval + "middle";
- break;
- case -1: // bottom / Ground height
- pos = xval + "bottom";
- break;
- }
- }
- }
- }
-
- var options = "";
- for (var opt in lightOptions) {
- var val = lightOptions[opt];
- var txt = (val != 'entire' && val != 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
- options += '';
- }
-
- $('.lidsb').append(createTableRow([id + ' (' + lightName + ')', '', '']));
- }
-
- if (!isEntertainmentReady) {
- $('.hue_sel_watch').on("change", function () {
- var cC = 0;
- for (var key in hueLights) {
- if ($('#hue_' + key).val() != "disabled") {
- cC++;
- }
- }
-
- (cC == 0 || window.readOnlyMode) ? $('#btn_wiz_save').prop("disabled", true) : $('#btn_wiz_save').prop("disabled", false);
- });
- }
- $('.hue_sel_watch').trigger('change');
- }
- else {
- var txt = '' + $.i18n('wiz_hue_noids') + '
';
- $('#wizp2_body').append(txt);
- }
- }
-}
-
-function abortConnection(UserInterval) {
- clearInterval(UserInterval);
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- $('#wizp3').toggle(false);
- $("#wiz_hue_usrstate").html($.i18n('wiz_hue_failure_connection'));
-}
-
-//****************************
-// Wizard Yeelight
-//****************************
-var lights = null;
-function startWizardYeelight(e) {
- //create html
-
- var yeelight_title = 'wiz_yeelight_title';
- var yeelight_intro1 = 'wiz_yeelight_intro1';
-
- $('#wiz_header').html('' + $.i18n(yeelight_title));
- $('#wizp1_body').html('' + $.i18n(yeelight_title) + '
' + $.i18n(yeelight_intro1) + '
');
-
- $('#wizp1_footer').html('');
-
- $('#wizp2_body').html('');
-
- $('#wh_topcontainer').append('');
-
- $('#wizp2_body').append('' + $.i18n('wiz_yeelight_desc2') + '
');
-
- createTable("lidsh", "lidsb", "yee_ids_t");
- $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
- $('#wizp2_footer').html(''
- + $.i18n('general_btn_cancel') + '');
-
- if (getStorage("darkMode") == "on")
- $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
-
- //open modal
- $("#wizard_modal").modal({ backdrop: "static", keyboard: false, show: true });
-
- //listen for continue
- $('#btn_wiz_cont').off().on('click', function () {
- beginWizardYeelight();
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- });
-}
-
-function beginWizardYeelight() {
- lights = [];
- configuredLights = conf_editor.getEditor("root.specificOptions.lights").getValue();
-
- discover_yeelight_lights();
-
- $('#btn_wiz_save').off().on("click", function () {
- var yeelightLedConfig = [];
- var finalLights = [];
-
- //create yeelight led config
- for (var key in lights) {
- if ($('#yee_' + key).val() !== "disabled") {
-
- var name = lights[key].name;
- // Set Name to layout-position, if empty
- if (name === "") {
- name = lights[key].host;
- }
-
- finalLights.push(lights[key]);
-
- var idx_content = assignLightPos($('#yee_' + key).val(), name);
- yeelightLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
- }
- }
-
- //LED layout
- window.serverConfig.leds = yeelightLedConfig;
-
- //LED device config
- var currentDeviceType = window.serverConfig.device.type;
-
- //Start with a clean configuration
- var d = {};
-
- d.type = 'yeelight';
- d.hardwareLedCount = finalLights.length;
- d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
- d.colorModel = parseInt(conf_editor.getEditor("root.specificOptions.colorModel").getValue());
-
- d.transEffect = parseInt(conf_editor.getEditor("root.specificOptions.transEffect").getValue());
- d.transTime = parseInt(conf_editor.getEditor("root.specificOptions.transTime").getValue());
- d.extraTimeDarkness = parseInt(conf_editor.getEditor("root.specificOptions.extraTimeDarkness").getValue());
-
- d.brightnessMin = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMin").getValue());
- d.brightnessSwitchOffOnMinimum = JSON.parse(conf_editor.getEditor("root.specificOptions.brightnessSwitchOffOnMinimum").getValue());
- d.brightnessMax = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMax").getValue());
- d.brightnessFactor = parseFloat(conf_editor.getEditor("root.specificOptions.brightnessFactor").getValue());
-
- d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
- d.debugLevel = parseInt(conf_editor.getEditor("root.specificOptions.debugLevel").getValue());
-
- d.lights = finalLights;
-
- window.serverConfig.device = d;
-
- if (currentDeviceType !== d.type) {
- //smoothing off, if new device
- window.serverConfig.smoothing = { enable: false };
- }
-
- requestWriteConfig(window.serverConfig, true);
- resetWizard();
- });
-
- $('#btn_wiz_abort').off().on('click', resetWizard);
-}
-
-async function discover_yeelight_lights() {
- var light = {};
- // Get discovered lights
- const res = await requestLedDeviceDiscovery('yeelight');
-
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if (res && !res.error) {
- const r = res.info;
-
- var discoveryMethod = "ssdp";
- if (res.info.discoveryMethod) {
- discoveryMethod = res.info.discoveryMethod;
- }
-
- // Process devices returned by discovery
- for (const device of r.devices) {
- if (device.hostname !== "") {
- if (getHostInLights(device.hostname).length === 0) {
- var light = {};
-
-
-
- if (discoveryMethod === "ssdp") {
- //Create a valid hostname
- if (device.domain) {
- light.host += '.' + device.domain;
- }
- } else {
- light.host = device.service;
- light.name = device.name;
- }
- light.port = device.port;
-
- if (device.txt) {
- light.model = device.txt.md;
- //Yeelight does not provide correct API port with mDNS response, use default one
- light.port = 55443;
- }
- else {
- light.name = device.other.name;
- light.model = device.other.model;
- }
- lights.push(light);
- }
- }
- }
-
- // Add additional items from configuration
- for (var keyConfig in configuredLights) {
- var host = configuredLights[keyConfig].host;
-
- //In case port has been explicitly provided, overwrite port given as part of hostname
- if (configuredLights[keyConfig].port !== 0)
- port = configuredLights[keyConfig].port;
-
- if (host !== "")
- if (getHostInLights(host).length === 0) {
- var light = {};
- light.host = host;
- light.port = port;
- light.name = configuredLights[keyConfig].name;
- light.model = "color4";
- lights.push(light);
- }
- }
-
- assign_yeelight_lights();
- }
-}
-
-function assign_yeelight_lights() {
- // Model mappings, see https://www.home-assistant.io/integrations/yeelight/
- var models = ['color', 'color1', 'YLDP02YL', 'YLDP02YL', 'color2', 'YLDP06YL', 'color4', 'YLDP13YL', 'color6', 'YLDP13AYL', 'colorb', "YLDP005", 'colorc', "YLDP004-A", 'stripe', 'YLDD04YL', 'strip1', 'YLDD01YL', 'YLDD02YL', 'strip4', 'YLDD05YL', 'strip6', 'YLDD05YL'];
-
- // If records are left for configuration
- if (Object.keys(lights).length > 0) {
- $('#wh_topcontainer').toggle(false);
- $('#yee_ids_t, #btn_wiz_save').toggle(true);
-
- var lightOptions = [
- "top", "topleft", "topright",
- "bottom", "bottomleft", "bottomright",
- "left", "lefttop", "leftmiddle", "leftbottom",
- "right", "righttop", "rightmiddle", "rightbottom",
- "entire",
- "lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
- "lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
- "lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
- ];
-
- lightOptions.unshift("disabled");
-
- $('.lidsb').html("");
- var pos = "";
-
- for (var lightid in lights) {
- var lightHostname = lights[lightid].host;
- var lightPort = lights[lightid].port;
- var lightName = lights[lightid].name;
-
- if (lightName === "")
- lightName = $.i18n('edt_dev_spec_lights_itemtitle') + '(' + lightHostname + ')';
-
- var options = "";
- for (var opt in lightOptions) {
- var val = lightOptions[opt];
- var txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
- options += '';
- }
-
- var enabled = 'enabled';
- if (!models.includes(lights[lightid].model)) {
- var enabled = 'disabled';
- options = '';
- }
-
- $('.lidsb').append(createTableRow([(parseInt(lightid, 10) + 1) + '. ' + lightName, '', '']));
- }
-
- $('.yee_sel_watch').on("change", function () {
- var cC = 0;
- for (var key in lights) {
- if ($('#yee_' + key).val() !== "disabled") {
- cC++;
- }
- }
-
- if (cC === 0 || window.readOnlyMode)
- $('#btn_wiz_save').prop("disabled", true);
- else
- $('#btn_wiz_save').prop("disabled", false);
- });
- $('.yee_sel_watch').trigger('change');
- }
- else {
- var noLightsTxt = '' + $.i18n('wiz_noLights', 'Yeelights') + '
';
- $('#wizp2_body').append(noLightsTxt);
- }
-}
-
-async function getProperties_yeelight(host, port) {
- let params = { host: host, port: port };
-
- const res = await requestLedDeviceProperties('yeelight', params);
-
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if (res && !res.error) {
- const r = res.info
- console.log("Yeelight properties: ", r);
- }
-}
-
-async function identify_yeelight_device(host, port) {
-
- var disabled = $('#btn_wiz_save').is(':disabled');
-
- // Take care that new record cannot be save during background process
- $('#btn_wiz_save').prop('disabled', true);
-
- let params = { host: host, port: port };
- await requestLedDeviceIdentification("yeelight", params);
-
- if (!window.readOnlyMode) {
- $('#btn_wiz_save').prop('disabled', disabled);
- }
-}
-
-//****************************
-// Wizard AtmoOrb
-//****************************
-var lights = null;
-function startWizardAtmoOrb(e) {
- //create html
-
- var atmoorb_title = 'wiz_atmoorb_title';
- var atmoorb_intro1 = 'wiz_atmoorb_intro1';
-
- $('#wiz_header').html('' + $.i18n(atmoorb_title));
- $('#wizp1_body').html('' + $.i18n(atmoorb_title) + '
' + $.i18n(atmoorb_intro1) + '
');
-
- $('#wizp1_footer').html('');
-
- $('#wizp2_body').html('');
-
- $('#wh_topcontainer').append('');
-
- $('#wizp2_body').append('' + $.i18n('wiz_atmoorb_desc2') + '
');
-
- createTable("lidsh", "lidsb", "orb_ids_t");
- $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
- $('#wizp2_footer').html(''
- + $.i18n('general_btn_cancel') + '');
-
- if (getStorage("darkMode") == "on")
- $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
-
- //open modal
- $("#wizard_modal").modal({ backdrop: "static", keyboard: false, show: true });
-
- //listen for continue
- $('#btn_wiz_cont').off().on('click', function () {
- beginWizardAtmoOrb();
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- });
-}
-
-function beginWizardAtmoOrb() {
- lights = [];
- configuredLights = [];
-
- var configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
- if (configruedOrbIds.length !== 0) {
- configuredLights = configruedOrbIds.split(",").map(Number);
- }
-
- var multiCastGroup = conf_editor.getEditor("root.specificOptions.host").getValue();
- var multiCastPort = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
-
- discover_atmoorb_lights(multiCastGroup, multiCastPort);
-
- $('#btn_wiz_save').off().on("click", function () {
- var atmoorbLedConfig = [];
- var finalLights = [];
-
- //create atmoorb led config
- for (var key in lights) {
- if ($('#orb_' + key).val() !== "disabled") {
- // Set Name to layout-position, if empty
- if (lights[key].name === "") {
- lights[key].name = $.i18n('conf_leds_layout_cl_' + $('#orb_' + key).val());
- }
-
- finalLights.push(lights[key].id);
-
- var name = lights[key].id;
- if (lights[key].host !== "")
- name += ':' + lights[key].host;
-
- var idx_content = assignLightPos($('#orb_' + key).val(), name);
- atmoorbLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
- }
- }
-
- //LED layout
- window.serverConfig.leds = atmoorbLedConfig;
-
- //LED device config
- //Start with a clean configuration
- var d = {};
-
- d.type = 'atmoorb';
- d.hardwareLedCount = finalLights.length;
- d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
-
- d.orbIds = finalLights.toString();
- d.useOrbSmoothing = (eV("useOrbSmoothing") == true);
-
- d.host = conf_editor.getEditor("root.specificOptions.host").getValue();
- d.port = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
- d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
-
- window.serverConfig.device = d;
-
- requestWriteConfig(window.serverConfig, true);
- resetWizard();
- });
-
- $('#btn_wiz_abort').off().on('click', resetWizard);
-}
-
-async function discover_atmoorb_lights(multiCastGroup, multiCastPort) {
- var light = {};
-
- var params = {};
- if (multiCastGroup !== "") {
- params.multiCastGroup = multiCastGroup;
- }
-
- if (multiCastPort !== 0) {
- params.multiCastPort = multiCastPort;
- }
-
- // Get discovered lights
- const res = await requestLedDeviceDiscovery('atmoorb', params);
-
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if (res && !res.error) {
- const r = res.info;
-
- // Process devices returned by discovery
- for (const device of r.devices) {
- if (device.id !== "") {
- if (getIdInLights(device.id).length === 0) {
- var light = {};
- light.id = device.id;
- light.ip = device.ip;
- light.host = device.hostname;
- lights.push(light);
- }
- }
- }
-
- // Add additional items from configuration
- for (const keyConfig in configuredLights) {
- if (configuredLights[keyConfig] !== "" && !isNaN(configuredLights[keyConfig])) {
- if (getIdInLights(configuredLights[keyConfig]).length === 0) {
- var light = {};
- light.id = configuredLights[keyConfig];
- light.ip = "";
- light.host = "";
- lights.push(light);
- }
- }
- }
-
- lights.sort((a, b) => (a.id > b.id) ? 1 : -1);
-
- assign_atmoorb_lights();
- }
-}
-
-function assign_atmoorb_lights() {
- // If records are left for configuration
- if (Object.keys(lights).length > 0) {
- $('#wh_topcontainer').toggle(false);
- $('#orb_ids_t, #btn_wiz_save').toggle(true);
-
- var lightOptions = [
- "top", "topleft", "topright",
- "bottom", "bottomleft", "bottomright",
- "left", "lefttop", "leftmiddle", "leftbottom",
- "right", "righttop", "rightmiddle", "rightbottom",
- "entire",
- "lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
- "lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
- "lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
- ];
-
- lightOptions.unshift("disabled");
-
- $('.lidsb').html("");
- var pos = "";
-
- for (var lightid in lights) {
- var orbId = lights[lightid].id;
- var orbIp = lights[lightid].ip;
- var orbHostname = lights[lightid].host;
-
- if (orbHostname === "")
- orbHostname = $.i18n('edt_dev_spec_lights_itemtitle');
-
- var options = "";
- for (var opt in lightOptions) {
- var val = lightOptions[opt];
- var txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
- options += '';
- }
-
- var enabled = 'enabled';
- if (orbId < 1 || orbId > 255) {
- enabled = 'disabled';
- options = '';
- }
-
- var lightAnnotation = "";
- if (orbIp !== "") {
- lightAnnotation = ': ' + orbIp + '
(' + orbHostname + ')';
- }
-
- $('.lidsb').append(createTableRow([orbId + lightAnnotation, '', '']));
- }
-
- $('.orb_sel_watch').on("change", function () {
- var cC = 0;
- for (var key in lights) {
- if ($('#orb_' + key).val() !== "disabled") {
- cC++;
- }
- }
- if (cC === 0 || window.readOnlyMode)
- $('#btn_wiz_save').prop("disabled", true);
- else
- $('#btn_wiz_save').prop("disabled", false);
- });
- $('.orb_sel_watch').trigger('change');
- }
- else {
- var noLightsTxt = '' + $.i18n('wiz_noLights', 'AtmoOrbs') + '
';
- $('#wizp2_body').append(noLightsTxt);
- }
-}
-
-async function identify_atmoorb_device(orbId) {
- var disabled = $('#btn_wiz_save').is(':disabled');
-
- // Take care that new record cannot be save during background process
- $('#btn_wiz_save').prop('disabled', true);
-
- let params = { id: orbId };
- await requestLedDeviceIdentification("atmoorb", params);
-
- if (!window.readOnlyMode) {
- $('#btn_wiz_save').prop('disabled', disabled);
- }
-}
-
-//****************************
-// Nanoleaf Token Wizard
-//****************************
-var lights = null;
-function startWizardNanoleafUserAuth(e) {
- //create html
- var nanoleaf_user_auth_title = 'wiz_nanoleaf_user_auth_title';
- var nanoleaf_user_auth_intro = 'wiz_nanoleaf_user_auth_intro';
-
- $('#wiz_header').html('' + $.i18n(nanoleaf_user_auth_title));
- $('#wizp1_body').html('' + $.i18n(nanoleaf_user_auth_title) + '
' + $.i18n(nanoleaf_user_auth_intro) + '
');
-
- $('#wizp1_footer').html('');
-
- $('#wizp3_body').html('' + $.i18n('wiz_nanoleaf_press_onoff_button') + '
');
-
- if (getStorage("darkMode") == "on")
- $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
-
- //open modal
- $("#wizard_modal").modal({ backdrop: "static", keyboard: false, show: true });
-
- //listen for continue
- $('#btn_wiz_cont').off().on('click', function () {
- createNanoleafUserAuthorization();
- $('#wizp1').toggle(false);
- $('#wizp3').toggle(true);
- });
-}
-
-function createNanoleafUserAuthorization() {
- var host = conf_editor.getEditor("root.specificOptions.host").getValue();
-
- let params = { host: host };
-
- var retryTime = 30;
- var retryInterval = 2;
-
- var UserInterval = setInterval(function () {
-
- $('#wizp1').toggle(false);
- $('#wizp3').toggle(true);
-
- (async () => {
-
- retryTime -= retryInterval;
- $("#connectionTime").html(retryTime);
- if (retryTime <= 0) {
- abortConnection(UserInterval);
- clearInterval(UserInterval);
-
- showNotification('warning', $.i18n('wiz_nanoleaf_failure_auth_token'), $.i18n('wiz_nanoleaf_failure_auth_token_t'));
-
- resetWizard(true);
- }
- else {
- const res = await requestLedDeviceAddAuthorization('nanoleaf', params);
- if (res && !res.error) {
- var response = res.info;
-
- if (jQuery.isEmptyObject(response)) {
- debugMessage(retryTime + ": Power On/Off button not pressed or device not reachable");
- } else {
- $('#wizp1').toggle(false);
- $('#wizp3').toggle(false);
-
- var token = response.auth_token;
- if (token != 'undefined') {
- conf_editor.getEditor("root.specificOptions.token").setValue(token);
- }
- clearInterval(UserInterval);
- resetWizard(true);
- }
- } else {
- $('#wizp1').toggle(false);
- $('#wizp3').toggle(false);
- clearInterval(UserInterval);
- resetWizard(true);
- }
- }
- })();
-
- }, retryInterval * 1000);
-}
-
diff --git a/assets/webconfig/js/wizards/LedDevice_atmoorb.js b/assets/webconfig/js/wizards/LedDevice_atmoorb.js
new file mode 100644
index 00000000..67d9bd5a
--- /dev/null
+++ b/assets/webconfig/js/wizards/LedDevice_atmoorb.js
@@ -0,0 +1,283 @@
+//****************************
+// Wizard AtmoOrb
+//****************************
+
+import { ledDeviceWizardUtils as utils } from './LedDevice_utils.js';
+
+const atmoorbWizard = (() => {
+
+ const lights = [];
+ let configuredLights = [];
+
+ function getIdInLights(id) {
+ return lights.filter(
+ function (lights) {
+ return lights.id === id
+ }
+ );
+ }
+
+ function begin() {
+
+ const configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
+ if (configruedOrbIds.length !== 0) {
+ configuredLights = configruedOrbIds.split(",").map(Number);
+ }
+
+ const multiCastGroup = conf_editor.getEditor("root.specificOptions.host").getValue();
+ const multiCastPort = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
+
+ discover(multiCastGroup, multiCastPort);
+
+ $('#btn_wiz_save').off().on("click", function () {
+ let ledConfig = [];
+ let finalLights = [];
+
+ //create atmoorb led config
+ for (let key in lights) {
+ if ($('#orb_' + key).val() !== "disabled") {
+ // Set Name to layout-position, if empty
+ if (lights[key].name === "") {
+ lights[key].name = $.i18n('conf_leds_layout_cl_' + $('#orb_' + key).val());
+ }
+
+ finalLights.push(lights[key].id);
+
+ let name = lights[key].id;
+ if (lights[key].host !== "")
+ name += ':' + lights[key].host;
+
+ const idx_content = utils.assignLightPos($('#orb_' + key).val(), name);
+ ledConfig.push(JSON.parse(JSON.stringify(idx_content)));
+ }
+ }
+
+ //LED layout
+ window.serverConfig.leds = ledConfig;
+
+ //LED device config
+ //Start with a clean configuration
+ let d = {};
+
+ d.type = 'atmoorb';
+ d.hardwareLedCount = finalLights.length;
+ d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
+
+ d.orbIds = finalLights.toString();
+ d.useOrbSmoothing = utils.eV("useOrbSmoothing");
+
+ d.host = conf_editor.getEditor("root.specificOptions.host").getValue();
+ d.port = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
+ d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
+
+ window.serverConfig.device = d;
+
+ requestWriteConfig(window.serverConfig, true);
+ resetWizard();
+ });
+
+ $('#btn_wiz_abort').off().on('click', resetWizard);
+ }
+
+ async function discover(multiCastGroup, multiCastPort) {
+ let params = {};
+ if (multiCastGroup !== "") {
+ params.multiCastGroup = multiCastGroup;
+ }
+
+ if (multiCastPort !== 0) {
+ params.multiCastPort = multiCastPort;
+ }
+
+ // Get discovered lights
+ const res = await requestLedDeviceDiscovery('atmoorb', params);
+ if (res && !res.error) {
+ const r = res.info;
+
+ // Process devices returned by discovery
+ processDiscoveredDevices(r.devices);
+
+ // Add additional items from configuration
+ for (const configuredLight of configuredLights) {
+ processConfiguredLight(configuredLight);
+ }
+
+ sortLightsById();
+ assign_lights();
+ }
+ }
+
+ function processDiscoveredDevices(devices) {
+ for (const device of devices) {
+ if (device.id !== "" && getIdInLights(device.id).length === 0) {
+ const light = {
+ id: device.id,
+ ip: device.ip,
+ host: device.hostname
+ };
+ lights.push(light);
+ }
+ }
+ }
+
+ function processConfiguredLight(configuredLight) {
+ if (configuredLight !== "" && !isNaN(configuredLight)) {
+ if (getIdInLights(configuredLight).length === 0) {
+ const light = {
+ id: configuredLight,
+ ip: "",
+ host: ""
+ };
+ lights.push(light);
+ }
+ }
+ }
+
+ function attachIdentifyButtonEvent() {
+ // Use event delegation to handle clicks on buttons with class "btn-identify"
+ $('#wizp2_body').on('click', '.btn-identify', function () {
+ const orbId = $(this).data('orb-id');
+ identify(orbId);
+ });
+ }
+
+ function sortLightsById() {
+ lights.sort((a, b) => (a.id > b.id) ? 1 : -1);
+ }
+
+ function assign_lights() {
+ // If records are left for configuration
+ if (Object.keys(lights).length > 0) {
+ $('#wh_topcontainer').toggle(false);
+ $('#orb_ids_t, #btn_wiz_save').toggle(true);
+
+ const lightOptions = [
+ "top", "topleft", "topright",
+ "bottom", "bottomleft", "bottomright",
+ "left", "lefttop", "leftmiddle", "leftbottom",
+ "right", "righttop", "rightmiddle", "rightbottom",
+ "entire",
+ "lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
+ "lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
+ "lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
+ ];
+
+ lightOptions.unshift("disabled");
+
+ $('.lidsb').html("");
+ let pos = "";
+
+ for (const lightid in lights) {
+ const orbId = lights[lightid].id;
+ const orbIp = lights[lightid].ip;
+ let orbHostname = lights[lightid].host;
+
+ if (orbHostname === "")
+ orbHostname = $.i18n('edt_dev_spec_lights_itemtitle');
+
+ let options = "";
+ for (const opt in lightOptions) {
+ const val = lightOptions[opt];
+ const txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
+ options += '';
+ }
+
+ let enabled = 'enabled';
+ if (orbId < 1 || orbId > 255) {
+ enabled = 'disabled';
+ options = '';
+ }
+
+ let lightAnnotation = "";
+ if (orbIp !== "") {
+ lightAnnotation = ': ' + orbIp + '
(' + orbHostname + ')';
+ }
+
+ $('.lidsb').append(createTableRow([orbId + lightAnnotation, '', '']));
+ }
+ attachIdentifyButtonEvent();
+
+ $('.orb_sel_watch').on("change", function () {
+ let cC = 0;
+ for (const key in lights) {
+ if ($('#orb_' + key).val() !== "disabled") {
+ cC++;
+ }
+ }
+ if (cC === 0 || window.readOnlyMode)
+ $('#btn_wiz_save').prop("disabled", true);
+ else
+ $('#btn_wiz_save').prop("disabled", false);
+ });
+ $('.orb_sel_watch').trigger('change');
+ }
+ else {
+ const noLightsTxt = '' + $.i18n('wiz_noLights', 'AtmoOrbs') + '
';
+ $('#wizp2_body').append(noLightsTxt);
+ }
+
+
+ }
+
+ async function identify(orbId) {
+ const disabled = $('#btn_wiz_save').is(':disabled');
+
+ // Take care that new record cannot be save during background process
+ $('#btn_wiz_save').prop('disabled', true);
+
+ const params = { id: orbId };
+ await requestLedDeviceIdentification("atmoorb", params);
+
+ if (!window.readOnlyMode) {
+ $('#btn_wiz_save').prop('disabled', disabled);
+ }
+ }
+
+ return {
+ start: function (e) {
+
+ //create html
+ const atmoorb_title = 'wiz_atmoorb_title';
+ const atmoorb_intro1 = 'wiz_atmoorb_intro1';
+
+ $('#wiz_header').html('' + $.i18n(atmoorb_title));
+ $('#wizp1_body').html('' + $.i18n(atmoorb_title) + '
' + $.i18n(atmoorb_intro1) + '
');
+
+ $('#wizp1_footer').html('');
+
+ $('#wizp2_body').html('');
+
+ $('#wh_topcontainer').append('');
+
+ $('#wizp2_body').append('' + $.i18n('wiz_atmoorb_desc2') + '
');
+
+ createTable("lidsh", "lidsb", "orb_ids_t");
+ $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
+ $('#wizp2_footer').html(''
+ + $.i18n('general_btn_cancel') + '');
+
+ if (getStorage("darkMode") == "on")
+ $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
+
+ //open modal
+ $("#wizard_modal").modal({ backdrop: "static", keyboard: false, show: true });
+
+ //listen for continue
+ $('#btn_wiz_cont').off().on('click', function () {
+ begin();
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ });
+ }
+ };
+})();
+
+export { atmoorbWizard };
diff --git a/assets/webconfig/js/wizards/LedDevice_nanoleaf.js b/assets/webconfig/js/wizards/LedDevice_nanoleaf.js
new file mode 100644
index 00000000..83220003
--- /dev/null
+++ b/assets/webconfig/js/wizards/LedDevice_nanoleaf.js
@@ -0,0 +1,94 @@
+//****************************
+// Wizard Nanoleaf
+//****************************
+
+const nanoleafWizard = (() => {
+
+ const retryInterval = 2;
+
+ async function createNanoleafUserAuthorization() {
+ const host = conf_editor.getEditor("root.specificOptions.host").getValue();
+ const params = { host };
+ let retryTime = 30;
+
+ const UserInterval = setInterval(async function () {
+ retryTime -= retryInterval;
+ $("#connectionTime").html(retryTime);
+
+ if (retryTime <= 0) {
+ handleTimeout();
+ } else {
+ const res = await requestLedDeviceAddAuthorization('nanoleaf', params);
+ handleResponse(res);
+ }
+ }, retryInterval * 1000);
+
+ function handleTimeout() {
+ clearInterval(UserInterval);
+ showNotification(
+ 'warning',
+ $.i18n('wiz_nanoleaf_failure_auth_token'),
+ $.i18n('wiz_nanoleaf_failure_auth_token_t')
+ );
+ resetWizard(true);
+ }
+
+ function handleResponse(res) {
+ if (res && !res.error) {
+ const response = res.info;
+ if (jQuery.isEmptyObject(response)) {
+ debugMessage(`${retryTime}: Power On/Off button not pressed or device not reachable`);
+ } else {
+ const token = response.auth_token;
+ if (token !== 'undefined') {
+ conf_editor.getEditor("root.specificOptions.token").setValue(token);
+ }
+ clearInterval(UserInterval);
+ resetWizard(true);
+ }
+ } else {
+ clearInterval(UserInterval);
+ resetWizard(true);
+ }
+ }
+ }
+
+ return {
+ start: function () {
+ const nanoleaf_user_auth_title = 'wiz_nanoleaf_user_auth_title';
+ const nanoleaf_user_auth_intro = 'wiz_nanoleaf_user_auth_intro';
+
+ $('#wiz_header').html(
+ `${$.i18n(nanoleaf_user_auth_title)}`
+ );
+ $('#wizp1_body').html(
+ `${$.i18n(nanoleaf_user_auth_title)}
${$.i18n(nanoleaf_user_auth_intro)}
`
+ );
+ $('#wizp1_footer').html(
+ ``
+ );
+ $('#wizp3_body').html(
+ `${$.i18n('wiz_nanoleaf_press_onoff_button')}
`
+ );
+
+ if (getStorage("darkMode") == "on") {
+ $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
+ }
+
+ $("#wizard_modal").modal({
+ backdrop: "static",
+ keyboard: false,
+ show: true
+ });
+
+ $('#btn_wiz_cont').off().on('click', function () {
+ createNanoleafUserAuthorization();
+ $('#wizp1').toggle(false);
+ $('#wizp3').toggle(true);
+ });
+ }
+ };
+})();
+
+export { nanoleafWizard };
+
diff --git a/assets/webconfig/js/wizards/LedDevice_philipshue.js b/assets/webconfig/js/wizards/LedDevice_philipshue.js
new file mode 100644
index 00000000..92f1c173
--- /dev/null
+++ b/assets/webconfig/js/wizards/LedDevice_philipshue.js
@@ -0,0 +1,988 @@
+//****************************
+// Wizard Philips Hue
+//****************************
+
+import { ledDeviceWizardUtils as utils } from './LedDevice_utils.js';
+
+const philipshueWizard = (() => {
+
+ // External properties, 2-dimensional arry of [ledType][key]
+ let devicesProperties = {};
+
+ let hueIPs = [];
+ let hueIPsinc = 0;
+ let hueLights = [];
+ let hueEntertainmentConfigs = [];
+ let hueEntertainmentServices = [];
+ let groupLights = [];
+ let groupChannels = [];
+ let groupLightsLocations = [];
+ let isAPIv2Ready = true;
+ let isEntertainmentReady = true;
+
+ function checkHueBridge(cb, hueUser) {
+ const usr = (typeof hueUser != "undefined") ? hueUser : 'config';
+ if (usr === 'config') {
+ $('#wiz_hue_discovered').html("");
+ }
+
+ if (hueIPs[hueIPsinc]) {
+ const host = hueIPs[hueIPsinc].host;
+ const port = hueIPs[hueIPsinc].port;
+
+ if (usr != '') {
+ getProperties(cb, decodeURIComponent(host), port, usr);
+ }
+ else {
+ cb(false, usr);
+ }
+
+ if (isAPIv2Ready) {
+ $('#port').val(443);
+ }
+ }
+ }
+
+ function checkBridgeResult(reply, usr) {
+ if (reply) {
+ //abort checking, first reachable result is used
+ $('#wiz_hue_ipstate').html("");
+ $('#host').val(hueIPs[hueIPsinc].host)
+ $('#port').val(hueIPs[hueIPsinc].port)
+
+ $('#usrcont').toggle(true);
+
+ checkHueBridge(checkUserResult, $('#user').val());
+ }
+ else {
+ $('#usrcont').toggle(false);
+ $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
+ }
+ };
+
+ function checkUserResult(reply, username) {
+ $('#usrcont').toggle(true);
+
+ let hue_create_user = 'wiz_hue_e_create_user';
+ if (!isEntertainmentReady) {
+ hue_create_user = 'wiz_hue_create_user';
+ $('#hue_client_key_r').toggle(false);
+ } else {
+ $('#hue_client_key_r').toggle(true);
+ }
+
+ $('#wiz_hue_create_user').text($.i18n(hue_create_user));
+ $('#wiz_hue_create_user').toggle(true);
+
+ if (reply) {
+ $('#user').val(username);
+
+ if (isEntertainmentReady && $('#clientkey').val() == "") {
+ $('#wiz_hue_usrstate').html($.i18n('wiz_hue_e_clientkey_needed'));
+ $('#wiz_hue_create_user').toggle(true);
+ } else {
+ $('#wiz_hue_usrstate').html("");
+ $('#wiz_hue_create_user').toggle(false);
+
+ if (isEntertainmentReady) {
+ $('#hue_id_headline').text($.i18n('wiz_hue_e_desc3'));
+ $('#hue_grp_ids_t').toggle(true);
+
+ get_hue_groups(username);
+
+ } else {
+ $('#hue_id_headline').text($.i18n('wiz_hue_desc2'));
+ $('#hue_grp_ids_t').toggle(false);
+
+ get_hue_lights(username);
+
+ }
+ }
+ }
+ else {
+ //abort checking, first reachable result is used
+ $('#wiz_hue_usrstate').html($.i18n('wiz_hue_failure_user'));
+ $('#wiz_hue_create_user').toggle(true);
+ }
+ };
+
+ function useGroupId(id, username) {
+ $('#groupId').val(hueEntertainmentConfigs[id].id);
+ if (isAPIv2Ready) {
+ const group = hueEntertainmentConfigs[id];
+
+ groupLights = [];
+ for (const light of group.light_services) {
+ groupLights.push(light.rid);
+ }
+
+ groupChannels = [];
+ for (const channel of group.channels) {
+ groupChannels.push(channel);
+ }
+
+ groupLightsLocations = [];
+ for (const location of group.locations.service_locations) {
+ groupLightsLocations.push(location);
+ }
+ } else {
+ //Ensure ligthIDs are strings
+ groupLights = hueEntertainmentConfigs[id].lights.map(num => {
+ return String(num);
+ });
+
+ const lightLocations = hueEntertainmentConfigs[id].locations;
+ for (const locationID in lightLocations) {
+ let lightLocation = {};
+
+ let position = {
+ x: lightLocations[locationID][0],
+ y: lightLocations[locationID][1],
+ z: lightLocations[locationID][2]
+ };
+ lightLocation.position = position;
+
+ groupLightsLocations.push(lightLocation);
+ }
+ }
+
+ get_hue_lights(username);
+ }
+
+ function assignLightEntertainmentPos(isFocusCenter, position, name, id) {
+
+ let x = position.x;
+ let z = position.z;
+
+ if (isFocusCenter) {
+ // Map lights as in centered range -0.5 to 0.5
+ if (x < -0.5) {
+ x = -0.5;
+ } else if (x > 0.5) {
+ x = 0.5;
+ }
+ if (z < -0.5) {
+ z = -0.5;
+ } else if (z > 0.5) {
+ z = 0.5;
+ }
+ } else {
+ // Map lights as in full range -1 to 1
+ x /= 2;
+ z /= 2;
+ }
+
+ const h = x + 0.5;
+ const v = -z + 0.5;
+
+ const hmin = h - 0.05;
+ const hmax = h + 0.05;
+ const vmin = v - 0.05;
+ const vmax = v + 0.05;
+
+ let layoutObject = {
+ hmin: hmin < 0 ? 0 : hmin,
+ hmax: hmax > 1 ? 1 : hmax,
+ vmin: vmin < 0 ? 0 : vmin,
+ vmax: vmax > 1 ? 1 : vmax,
+ name: name
+ };
+
+ if (id !== undefined && id !== null) {
+ layoutObject.name += "_" + id;
+ }
+ return layoutObject;
+ }
+
+ function assignSegmentedLightPos(segment, position, name) {
+ let layoutObjects = [];
+
+ let segTotalLength = 0;
+ for (const key in segment) {
+
+ segTotalLength += segment[key].length;
+ }
+
+ let min;
+ let max;
+ let horizontal = true;
+
+ let layoutObject = utils.assignLightPos(position, name);
+ if (position === "left" || position === "right") {
+ // vertical distribution
+ min = layoutObject.vmin;
+ max = layoutObject.vmax;
+ horizontal = false;
+
+ } else {
+ // horizontal distribution
+ min = layoutObject.hmin;
+ max = layoutObject.hmax;
+ }
+
+ const step = (max - min) / segTotalLength;
+ let start = min;
+
+ for (const key in segment) {
+ min = start;
+ max = round(start + segment[key].length * step);
+
+ if (horizontal) {
+ layoutObject.hmin = min;
+ layoutObject.hmax = max;
+ } else {
+ layoutObject.vmin = min;
+ layoutObject.vmax = max;
+ }
+ layoutObject.name = name + "_" + key;
+ layoutObjects.push(JSON.parse(JSON.stringify(layoutObject)));
+
+ start = max;
+ }
+
+ return layoutObjects;
+ }
+
+ function updateBridgeDetails(properties) {
+ const ledDeviceProperties = properties.config;
+
+ if (!jQuery.isEmptyObject(ledDeviceProperties)) {
+ isEntertainmentReady = properties.isEntertainmentReady;
+ isAPIv2Ready = properties.isAPIv2Ready;
+
+ if (ledDeviceProperties.name && ledDeviceProperties.bridgeid && ledDeviceProperties.modelid) {
+ $('#wiz_hue_discovered').html(
+ "Bridge: " + ledDeviceProperties.name +
+ ", Modelid: " + ledDeviceProperties.modelid +
+ ", Firmware: " + ledDeviceProperties.swversion + "
" +
+ "API-Version: " + ledDeviceProperties.apiversion +
+ ", Entertainment: " + (isEntertainmentReady ? "✓" : "-") +
+ ", APIv2: " + (isAPIv2Ready ? "✓" : "-")
+ );
+ }
+ }
+ }
+
+ async function discover() {
+ $('#wiz_hue_ipstate').html($.i18n('edt_dev_spec_devices_discovery_inprogress'));
+
+ // $('#wiz_hue_discovered').html("")
+ const res = await requestLedDeviceDiscovery('philipshue');
+ if (res && !res.error) {
+ const r = res.info;
+
+ // Process devices returned by discovery
+ if (r.devices.length == 0) {
+ $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
+ $('#wiz_hue_discovered').html("")
+ }
+ else {
+ hueIPs = [];
+ hueIPsinc = 0;
+
+ let discoveryMethod = "ssdp";
+ if (res.info.discoveryMethod) {
+ discoveryMethod = res.info.discoveryMethod;
+ }
+
+ for (const device of r.devices) {
+ if (device) {
+ let host;
+ let port;
+ if (discoveryMethod === "ssdp") {
+ if (device.hostname && device.domain) {
+ host = device.hostname + "." + device.domain;
+ port = device.port;
+ } else {
+ host = device.ip;
+ port = device.port;
+ }
+ } else {
+ host = device.service;
+ port = device.port;
+ }
+ if (host) {
+
+ if (!hueIPs.some(item => item.host === host)) {
+ hueIPs.push({ host: host, port: port });
+ }
+ }
+ }
+ }
+
+ $('#wiz_hue_ipstate').html("");
+ $('#host').val(hueIPs[hueIPsinc].host)
+ $('#port').val(hueIPs[hueIPsinc].port)
+
+ $('#hue_bridge_select').html("");
+
+ for (const key in hueIPs) {
+ $('#hue_bridge_select').append(createSelOpt(key, hueIPs[key].host));
+ }
+
+ $('.hue_bridge_sel_watch').on("click", function () {
+ hueIPsinc = $(this).val();
+
+ const name = $("#hue_bridge_select option:selected").text();
+ $('#host').val(name);
+ $('#port').val(hueIPs[hueIPsinc].port)
+
+ const usr = $('#user').val();
+ if (usr != "") {
+ checkHueBridge(checkUserResult, usr);
+ } else {
+ checkHueBridge(checkBridgeResult);
+ }
+ });
+
+ $('.hue_bridge_sel_watch').click();
+ }
+ }
+ }
+
+ async function getProperties(cb, hostAddress, port, username, resourceFilter) {
+ let params = { host: hostAddress, username: username, filter: resourceFilter };
+ if (port !== 'undefined') {
+ params.port = parseInt(port);
+ }
+
+ const ledType = 'philipshue';
+ const key = hostAddress;
+
+ //Create ledType cache entry
+ if (!devicesProperties[ledType]) {
+ devicesProperties[ledType] = {};
+ }
+
+ // Use device's properties, if properties in chache
+ if (devicesProperties[ledType][key] && devicesProperties[ledType][key][username]) {
+ updateBridgeDetails(devicesProperties[ledType][key]);
+ cb(true, username);
+ } else {
+ const res = await requestLedDeviceProperties(ledType, params);
+ if (res && !res.error) {
+ const ledDeviceProperties = res.info.properties;
+ if (!jQuery.isEmptyObject(ledDeviceProperties)) {
+
+ devicesProperties[ledType][key] = {};
+ devicesProperties[ledType][key][username] = ledDeviceProperties;
+
+ isAPIv2Ready = res.info.isAPIv2Ready;
+ devicesProperties[ledType][key].isAPIv2Ready = isAPIv2Ready;
+ isEntertainmentReady = res.info.isEntertainmentReady;
+ devicesProperties[ledType][key].isEntertainmentReady = isEntertainmentReady;
+
+ updateBridgeDetails(devicesProperties[ledType][key]);
+ if (username === "config") {
+ cb(true);
+ } else {
+ cb(true, username);
+ }
+ } else {
+ cb(false, username);
+ }
+ } else {
+ cb(false, username);
+ }
+ }
+ }
+
+ async function identify(hostAddress, port, username, name, id, id_v1) {
+ const disabled = $('#btn_wiz_save').is(':disabled');
+ // Take care that new record cannot be save during background process
+ $('#btn_wiz_save').prop('disabled', true);
+
+ let params = { host: decodeURIComponent(hostAddress), username: username, lightName: decodeURIComponent(name), lightId: id, lightId_v1: id_v1 };
+
+ if (port !== 'undefined') {
+ params.port = parseInt(port);
+ }
+
+ await requestLedDeviceIdentification('philipshue', params);
+
+ if (!window.readOnlyMode) {
+ $('#btn_wiz_save').prop('disabled', disabled);
+ }
+ }
+
+ function begin() {
+ const usr = utils.eV("username");
+ if (usr != "") {
+ $('#user').val(usr);
+ }
+
+ const clkey = utils.eV("clientkey");
+ if (clkey != "") {
+ $('#clientkey').val(clkey);
+ }
+
+ //check if host is empty/reachable/search for bridge
+ if (utils.eV("host") == "") {
+ hueIPs = [];
+ hueIPsinc = 0;
+
+ discover();
+ }
+ else {
+ const host = utils.eV("host");
+ $('#host').val(host);
+
+ const port = utils.eV("port");
+ if (port > 0) {
+ $('#port').val(port);
+ }
+ else {
+ $('#port').val('');
+ }
+ hueIPs.push({ host: host, port: port });
+
+ if (usr != "") {
+ checkHueBridge(checkUserResult, usr);
+ } else {
+ checkHueBridge(checkBridgeResult);
+ }
+ }
+
+ $('#retry_bridge').off().on('click', function () {
+ const host = $('#host').val();
+ const port = parseInt($('#port').val());
+
+ if (host != "") {
+
+ const idx = hueIPs.findIndex(item => item.host === host && item.port === port);
+ if (idx === -1) {
+ hueIPs.push({ host: host, port: port });
+ hueIPsinc = hueIPs.length - 1;
+ } else {
+ hueIPsinc = idx;
+ }
+ }
+ else {
+ discover();
+ }
+
+ const usr = $('#user').val();
+ if (usr != "") {
+ checkHueBridge(checkUserResult, usr);
+ } else {
+ checkHueBridge(checkBridgeResult);
+ }
+ });
+
+ $('#retry_usr').off().on('click', function () {
+ checkHueBridge(checkUserResult, $('#user').val());
+ });
+
+ $('#wiz_hue_create_user').off().on('click', function () {
+ createHueUser();
+ });
+ $('#btn_wiz_save').off().on("click", function () {
+ let hueLedConfig = [];
+ let finalLightIds = [];
+ let channelNumber = 0;
+
+ //create hue led config
+ for (const key in groupLights) {
+ const lightId = groupLights[key];
+
+ if ($('#hue_' + lightId).val() != "disabled") {
+ finalLightIds.push(lightId);
+
+ let lightName;
+ if (isAPIv2Ready) {
+ const light = hueLights.find(light => light.id === lightId);
+ lightName = light.metadata.name;
+ } else {
+ lightName = hueLights[lightId].name;
+ }
+
+ const position = $('#hue_' + lightId).val();
+ const lightIdx = groupLights.indexOf(lightId);
+ const lightLocation = groupLightsLocations[lightIdx];
+
+ let serviceID;
+ if (isAPIv2Ready) {
+ serviceID = lightLocation.service.rid;
+ }
+
+ if (position.startsWith("entertainment")) {
+
+ // Layout per entertainment area definition at bridge
+ let isFocusCenter = false;
+ if (position === "entertainment_center") {
+ isFocusCenter = true;
+ }
+
+ if (isAPIv2Ready) {
+
+ groupChannels.forEach((channel) => {
+ if (channel.members[0].service.rid === serviceID) {
+ const layoutObject = assignLightEntertainmentPos(isFocusCenter, channel.position, lightName, channel.channel_id);
+ hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
+ ++channelNumber;
+ }
+ });
+ } else {
+ const layoutObject = assignLightEntertainmentPos(isFocusCenter, lightLocation.position, lightName);
+ hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
+ }
+ }
+ else {
+ // Layout per manual settings
+ let maxSegments = 1;
+
+ if (isAPIv2Ready) {
+ const service = hueEntertainmentServices.find(service => service.id === serviceID);
+ maxSegments = service.segments.max_segments;
+ }
+
+ if (maxSegments > 1) {
+ const segment = service.segments.segments;
+ const layoutObjects = assignSegmentedLightPos(segment, position, lightName);
+ hueLedConfig.push(...layoutObjects);
+ } else {
+ const layoutObject = utils.assignLightPos(position, lightName);
+ hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
+ }
+ channelNumber += maxSegments;
+ }
+ }
+ }
+
+ let sc = window.serverConfig;
+ sc.leds = hueLedConfig;
+
+ //Adjust gamma, brightness and compensation
+ let c = sc.color.channelAdjustment[0];
+ c.gammaBlue = 1.0;
+ c.gammaRed = 1.0;
+ c.gammaGreen = 1.0;
+ c.brightness = 100;
+ c.brightnessCompensation = 0;
+
+ //device config
+
+ //Start with a clean configuration
+ let d = {};
+ d.host = $('#host').val();
+ d.port = parseInt($('#port').val());
+ d.username = $('#user').val();
+ d.type = 'philipshue';
+ d.colorOrder = 'rgb';
+ d.lightIds = finalLightIds;
+ d.transitiontime = parseInt(utils.eV("transitiontime", 1));
+ d.restoreOriginalState = utils.eV("restoreOriginalState", false);
+ d.switchOffOnBlack = utils.eV("switchOffOnBlack", false);
+
+ d.blackLevel = parseFloat(utils.eV("blackLevel", 0.009));
+ d.onBlackTimeToPowerOff = parseInt(utils.eV("onBlackTimeToPowerOff", 600));
+ d.onBlackTimeToPowerOn = parseInt(utils.eV("onBlackTimeToPowerOn", 300));
+ d.brightnessFactor = parseFloat(utils.eV("brightnessFactor", 1));
+
+ d.clientkey = $('#clientkey').val();
+ d.groupId = $('#groupId').val();
+ d.blackLightsTimeout = parseInt(utils.eV("blackLightsTimeout", 5000));
+ d.brightnessMin = parseFloat(utils.eV("brightnessMin", 0));
+ d.brightnessMax = parseFloat(utils.eV("brightnessMax", 1));
+ d.brightnessThreshold = parseFloat(utils.eV("brightnessThreshold", 0.0001));
+ d.handshakeTimeoutMin = parseInt(utils.eV("handshakeTimeoutMin", 300));
+ d.handshakeTimeoutMax = parseInt(utils.eV("handshakeTimeoutMax", 1000));
+ d.verbose = utils.eV("verbose");
+
+ d.autoStart = conf_editor.getEditor("root.generalOptions.autoStart").getValue();
+ d.enableAttempts = parseInt(conf_editor.getEditor("root.generalOptions.enableAttempts").getValue());
+ d.enableAttemptsInterval = parseInt(conf_editor.getEditor("root.generalOptions.enableAttemptsInterval").getValue());
+
+ d.useEntertainmentAPI = isEntertainmentReady;
+ d.useAPIv2 = isAPIv2Ready;
+
+ if (isEntertainmentReady) {
+ d.hardwareLedCount = channelNumber;
+ if (window.serverConfig.device.type !== d.type) {
+ //smoothing on, if new device
+ sc.smoothing = { enable: true };
+ }
+ } else {
+ d.hardwareLedCount = finalLightIds.length;
+ d.verbose = false;
+ if (window.serverConfig.device.type !== d.type) {
+ //smoothing off, if new device
+ sc.smoothing = { enable: false };
+ }
+ }
+
+ window.serverConfig.device = d;
+
+ requestWriteConfig(sc, true);
+ resetWizard();
+ });
+
+ $('#btn_wiz_abort').off().on('click', resetWizard);
+ }
+
+ function createHueUser() {
+ const host = hueIPs[hueIPsinc].host;
+ const port = hueIPs[hueIPsinc].port;
+
+ let params = { host: host };
+ if (port !== 'undefined') {
+ params.port = parseInt(port);
+ }
+
+ let retryTime = 30;
+ const retryInterval = 2;
+
+ const UserInterval = setInterval(function () {
+
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(false);
+ $('#wizp3').toggle(true);
+
+ (async () => {
+
+ retryTime -= retryInterval;
+ $("#connectionTime").html(retryTime);
+ if (retryTime <= 0) {
+ abortConnection(UserInterval);
+ clearInterval(UserInterval);
+ }
+ else {
+ const res = await requestLedDeviceAddAuthorization('philipshue', params);
+ if (res && !res.error) {
+ const response = res.info;
+
+ if (jQuery.isEmptyObject(response)) {
+ debugMessage(retryTime + ": link button not pressed or device not reachable");
+ } else {
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ $('#wizp3').toggle(false);
+
+ const username = response.username;
+ if (username != 'undefined') {
+ $('#user').val(username);
+ conf_editor.getEditor("root.specificOptions.username").setValue(username);
+ conf_editor.getEditor("root.specificOptions.host").setValue(host);
+ conf_editor.getEditor("root.specificOptions.port").setValue(port);
+ }
+
+ if (isEntertainmentReady) {
+ const clientkey = response.clientkey;
+ if (clientkey != 'undefined') {
+ $('#clientkey').val(clientkey);
+ conf_editor.getEditor("root.specificOptions.clientkey").setValue(clientkey);
+ }
+ }
+ checkHueBridge(checkUserResult, username);
+ clearInterval(UserInterval);
+ }
+ } else {
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ $('#wizp3').toggle(false);
+ clearInterval(UserInterval);
+ }
+ }
+ })();
+
+ }, retryInterval * 1000);
+ }
+
+ function get_hue_groups(username) {
+ const host = hueIPs[hueIPsinc].host;
+
+ if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
+ const ledProperties = devicesProperties['philipshue'][host][username];
+
+ if (isAPIv2Ready) {
+ if (!jQuery.isEmptyObject(ledProperties.data)) {
+ if (Object.keys(ledProperties.data).length > 0) {
+ hueEntertainmentConfigs = ledProperties.data.filter(config => {
+ return config.type === "entertainment_configuration";
+ });
+ hueEntertainmentServices = ledProperties.data.filter(config => {
+ return (config.type === "entertainment" && config.renderer === true);
+ });
+ }
+ }
+ } else if (!jQuery.isEmptyObject(ledProperties.groups)) {
+ hueEntertainmentConfigs = [];
+ let hueGroups = ledProperties.groups;
+ for (const groupid in hueGroups) {
+ if (hueGroups[groupid].type == 'Entertainment') {
+ hueGroups[groupid].id = groupid;
+ hueEntertainmentConfigs.push(hueGroups[groupid]);
+ }
+ }
+ }
+
+ if (Object.keys(hueEntertainmentConfigs).length > 0) {
+
+ $('.lidsb').html("");
+ $('#wh_topcontainer').toggle(false);
+ $('#hue_grp_ids_t').toggle(true);
+
+ for (const groupid in hueEntertainmentConfigs) {
+ $('.gidsb').append(createTableRow([groupid + ' (' + hueEntertainmentConfigs[groupid].name + ')',
+ '']));
+ }
+ attachGroupButtonEvent();
+
+ } else {
+ noAPISupport('wiz_hue_e_noegrpids', username);
+ }
+ }
+ }
+ function attachIdentifyButtonEvent() {
+ $('#wizp2_body').on('click', '.btn-identify', function () {
+ const hostname = $(this).data('hostname');
+ const port = $(this).data('port');
+ const user = $(this).data('user');
+ const lightName = $(this).data('light-name');
+ const lightId = $(this).data('light-id');
+ const lightId_v1 = $(this).data('light-id-v1');
+
+ identify(hostname, port, user, lightName, lightId, lightId_v1);
+ });
+ }
+ function attachGroupButtonEvent() {
+ $('#wizp2_body').on('click', '.btn-group', function () {
+ const groupid = $(this).data('groupid');
+ const username = $(this).data('username');
+
+ useGroupId(groupid, username);
+ });
+ }
+
+ function noAPISupport(txt, username) {
+ showNotification('danger', $.i18n('wiz_hue_e_title'), $.i18n('wiz_hue_e_noapisupport_hint'));
+ conf_editor.getEditor("root.specificOptions.useEntertainmentAPI").setValue(false);
+ $("#root_specificOptions_useEntertainmentAPI").trigger("change");
+ $('#btn_wiz_holder').append('' + $.i18n('wiz_hue_e_noapisupport_hint') + '
');
+ $('#hue_grp_ids_t').toggle(false);
+ const errorMessage = txt ? $.i18n(txt) : $.i18n('wiz_hue_e_nogrpids');
+ $('' + errorMessage + '
' + $.i18n('wiz_hue_e_noapisupport') + '
').insertBefore('#wizp2_body #hue_ids_t');
+ $('#hue_id_headline').html($.i18n('wiz_hue_desc2'));
+
+ get_hue_lights(username);
+ }
+
+ function get_hue_lights(username) {
+ const host = hueIPs[hueIPsinc].host;
+
+ if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
+ const ledProperties = devicesProperties['philipshue'][host][username];
+
+ if (isAPIv2Ready) {
+ if (!jQuery.isEmptyObject(ledProperties.data)) {
+ if (Object.keys(ledProperties.data).length > 0) {
+ hueLights = ledProperties.data.filter(config => {
+ return config.type === "light";
+ });
+ }
+ }
+ } else if (!jQuery.isEmptyObject(ledProperties.lights)) {
+ hueLights = ledProperties.lights;
+ }
+
+ if (Object.keys(hueLights).length > 0) {
+ if (!isEntertainmentReady) {
+ $('#wh_topcontainer').toggle(false);
+ }
+ $('#hue_ids_t, #btn_wiz_save').toggle(true);
+
+ const lightOptions = [
+ "top", "topleft", "topright",
+ "bottom", "bottomleft", "bottomright",
+ "left", "lefttop", "leftmiddle", "leftbottom",
+ "right", "righttop", "rightmiddle", "rightbottom",
+ "entire",
+ "lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
+ "lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
+ "lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
+ ];
+
+ if (isEntertainmentReady) {
+ lightOptions.unshift("entertainment_center");
+ lightOptions.unshift("entertainment");
+ } else {
+ lightOptions.unshift("disabled");
+ groupLights = Object.keys(hueLights);
+ }
+
+ $('.lidsb').html("");
+
+ let pos = "";
+ for (const id in groupLights) {
+ const lightId = groupLights[id];
+ let lightId_v1 = "/lights/" + lightId;
+
+ let lightName;
+ if (isAPIv2Ready) {
+ const light = hueLights.find(light => light.id === lightId);
+ lightName = light.metadata.name;
+ lightId_v1 = light.id_v1;
+ } else {
+ lightName = hueLights[lightId].name;
+ }
+
+ if (isEntertainmentReady) {
+ let lightLocation = {};
+ lightLocation = groupLightsLocations[id];
+ if (lightLocation) {
+ if (isAPIv2Ready) {
+ pos = 0;
+ } else {
+ const x = lightLocation.position.x;
+ const y = lightLocation.position.y;
+ const z = lightLocation.position.z;
+
+ let xval = (x < 0) ? "left" : "right";
+ if (z != 1 && x >= -0.25 && x <= 0.25) xval = "";
+ switch (z) {
+ case 1: // top / Ceiling height
+ pos = "top" + xval;
+ break;
+ case 0: // middle / TV height
+ pos = (xval == "" && y >= 0.75) ? "bottom" : xval + "middle";
+ break;
+ case -1: // bottom / Ground height
+ pos = xval + "bottom";
+ break;
+ }
+ }
+ }
+ }
+
+ let options = "";
+ for (const opt in lightOptions) {
+ const val = lightOptions[opt];
+ const txt = (val != 'entire' && val != 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
+ options += '';
+ }
+
+ $('.lidsb').append(createTableRow([id + ' (' + lightName + ')',
+ '',
+ '']));
+ }
+ attachIdentifyButtonEvent();
+
+ if (!isEntertainmentReady) {
+ $('.hue_sel_watch').on("change", function () {
+ let cC = 0;
+ for (const key in hueLights) {
+ if ($('#hue_' + key).val() != "disabled") {
+ cC++;
+ }
+ }
+
+ (cC == 0 || window.readOnlyMode) ? $('#btn_wiz_save').prop("disabled", true) : $('#btn_wiz_save').prop("disabled", false);
+ });
+ }
+ $('.hue_sel_watch').trigger('change');
+ }
+ else {
+ const txt = '' + $.i18n('wiz_hue_noids') + '
';
+ $('#wizp2_body').append(txt);
+ }
+ }
+ }
+
+ function abortConnection(UserInterval) {
+ clearInterval(UserInterval);
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ $('#wizp3').toggle(false);
+ $("#wiz_hue_usrstate").html($.i18n('wiz_hue_failure_connection'));
+ }
+
+ return {
+ start: function (e) {
+ //create html
+ const hue_title = 'wiz_hue_title';
+ const hue_intro1 = 'wiz_hue_e_intro1';
+ const hue_desc1 = 'wiz_hue_desc1';
+ const hue_create_user = 'wiz_hue_create_user';
+
+ $('#wiz_header').html('' + $.i18n(hue_title));
+ $('#wizp1_body').html('' + $.i18n(hue_title) + '
' + $.i18n(hue_intro1) + '
');
+ $('#wizp1_footer').html('');
+ $('#wizp2_body').html('');
+
+ let topContainer_html = '' + $.i18n(hue_desc1) + '
' +
+ '' +
+ '
' +
+ '
' + $.i18n('wiz_hue_ip') + '
' +
+ '
' +
+ ' ' +
+ ' ' + '
' +
+ '
';
+
+ if (storedAccess === 'expert') {
+ topContainer_html += '
';
+ }
+
+ topContainer_html += '
';
+ topContainer_html += '';
+
+ $('#wh_topcontainer').append(topContainer_html);
+
+ $('#usrcont').append('' + $.i18n('wiz_hue_username') + '
' +
+ '
' +
+ ''
+ );
+
+ $('#usrcont').append('
');
+
+ $('#usrcont').append('
' +
+ '');
+
+ $('#wizp2_body').append('' + $.i18n('wiz_hue_e_desc2') + '
');
+ createTable("gidsh", "gidsb", "hue_grp_ids_t");
+ $('.gidsh').append(createTableRow([$.i18n('edt_dev_spec_groupId_title'), ""], true));
+
+ $('#wizp2_body').append('' + $.i18n('wiz_hue_e_desc3') + '
');
+
+ createTable("lidsh", "lidsb", "hue_ids_t");
+ $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lightid_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
+ $('#wizp2_footer').html('');
+ $('#wizp3_body').html('' + $.i18n('wiz_hue_press_link') + '
');
+
+ if (getStorage("darkMode") == "on")
+ $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
+
+ //open modal
+ $("#wizard_modal").modal({
+ backdrop: "static",
+ keyboard: false,
+ show: true
+ });
+
+ //listen for continue
+ $('#btn_wiz_cont').off().on('click', function () {
+ begin();
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ });
+ }
+ };
+})();
+
+export { philipshueWizard }
+
diff --git a/assets/webconfig/js/wizards/LedDevice_utils.js b/assets/webconfig/js/wizards/LedDevice_utils.js
new file mode 100644
index 00000000..1f3eab3e
--- /dev/null
+++ b/assets/webconfig/js/wizards/LedDevice_utils.js
@@ -0,0 +1,60 @@
+
+const ledDeviceWizardUtils = (() => {
+
+ // Layout positions
+ const positionMap = {
+ "top": { hmin: 0.15, hmax: 0.85, vmin: 0, vmax: 0.2 },
+ "topleft": { hmin: 0, hmax: 0.15, vmin: 0, vmax: 0.15 },
+ "topright": { hmin: 0.85, hmax: 1.0, vmin: 0, vmax: 0.15 },
+ "bottom": { hmin: 0.15, hmax: 0.85, vmin: 0.8, vmax: 1.0 },
+ "bottomleft": { hmin: 0, hmax: 0.15, vmin: 0.85, vmax: 1.0 },
+ "bottomright": { hmin: 0.85, hmax: 1.0, vmin: 0.85, vmax: 1.0 },
+ "left": { hmin: 0, hmax: 0.15, vmin: 0.15, vmax: 0.85 },
+ "lefttop": { hmin: 0, hmax: 0.15, vmin: 0, vmax: 0.5 },
+ "leftmiddle": { hmin: 0, hmax: 0.15, vmin: 0.25, vmax: 0.75 },
+ "leftbottom": { hmin: 0, hmax: 0.15, vmin: 0.5, vmax: 1.0 },
+ "right": { hmin: 0.85, hmax: 1.0, vmin: 0.15, vmax: 0.85 },
+ "righttop": { hmin: 0.85, hmax: 1.0, vmin: 0, vmax: 0.5 },
+ "rightmiddle": { hmin: 0.85, hmax: 1.0, vmin: 0.25, vmax: 0.75 },
+ "rightbottom": { hmin: 0.85, hmax: 1.0, vmin: 0.5, vmax: 1.0 },
+ "lightPosBottomLeft14": { hmin: 0, hmax: 0.25, vmin: 0.85, vmax: 1.0 },
+ "lightPosBottomLeft12": { hmin: 0.25, hmax: 0.5, vmin: 0.85, vmax: 1.0 },
+ "lightPosBottomLeft34": { hmin: 0.5, hmax: 0.75, vmin: 0.85, vmax: 1.0 },
+ "lightPosBottomLeft11": { hmin: 0.75, hmax: 1, vmin: 0.85, vmax: 1.0 },
+ "lightPosBottomLeft112": { hmin: 0, hmax: 0.5, vmin: 0.85, vmax: 1.0 },
+ "lightPosBottomLeft121": { hmin: 0.5, hmax: 1, vmin: 0.85, vmax: 1.0 },
+ "lightPosBottomLeftNewMid": { hmin: 0.25, hmax: 0.75, vmin: 0.85, vmax: 1.0 },
+ "lightPosTopLeft112": { hmin: 0, hmax: 0.5, vmin: 0, vmax: 0.15 },
+ "lightPosTopLeft121": { hmin: 0.5, hmax: 1, vmin: 0, vmax: 0.15 },
+ "lightPosTopLeftNewMid": { hmin: 0.25, hmax: 0.75, vmin: 0, vmax: 0.15 },
+ "lightPosEntire": { hmin: 0.0, hmax: 1.0, vmin: 0.0, vmax: 1.0 }
+ };
+
+ return {
+
+ //return editor Value
+ eV: function (vn, defaultVal = "") {
+ let editor = null;
+ if (vn) {
+ editor = conf_editor.getEditor("root.specificOptions." + vn);
+ }
+
+ if (editor === null) {
+ return defaultVal;
+ } else if (defaultVal !== "" && !isNaN(defaultVal) && isNaN(editor.getValue())) {
+ return defaultVal;
+ } else {
+ return editor.getValue();
+ }
+ },
+ assignLightPos: function (pos, name) {
+ // Retrieve the corresponding position object from the positionMap
+ const i = positionMap[pos] || positionMap["lightPosEntire"];
+ i.name = name;
+ return i;
+ }
+ };
+
+})();
+
+export { ledDeviceWizardUtils };
diff --git a/assets/webconfig/js/wizards/LedDevice_yeelight.js b/assets/webconfig/js/wizards/LedDevice_yeelight.js
new file mode 100644
index 00000000..4f53eb07
--- /dev/null
+++ b/assets/webconfig/js/wizards/LedDevice_yeelight.js
@@ -0,0 +1,300 @@
+//****************************
+// Wizard Yeelight
+//****************************
+
+import { ledDeviceWizardUtils as utils } from './LedDevice_utils.js';
+
+const yeelightWizard = (() => {
+
+ const lights = [];
+ let configuredLights = conf_editor.getEditor("root.specificOptions.lights").getValue();
+
+ function getHostInLights(hostname) {
+ return lights.filter(
+ function (lights) {
+ return lights.host === hostname
+ }
+ );
+ }
+
+ function begin() {
+ discover();
+
+ $('#btn_wiz_save').off().on("click", function () {
+ let ledConfig = [];
+ let finalLights = [];
+
+ //create yeelight led config
+ for (const key in lights) {
+ if ($('#yee_' + key).val() !== "disabled") {
+
+ let name = lights[key].name;
+ // Set Name to layout-position, if empty
+ if (name === "") {
+ name = lights[key].host;
+ }
+
+ finalLights.push(lights[key]);
+
+ const idx_content = utils.assignLightPos($('#yee_' + key).val(), name);
+ ledConfig.push(JSON.parse(JSON.stringify(idx_content)));
+ }
+ }
+
+ //LED layout
+ window.serverConfig.leds = ledConfig;
+
+ //LED device config
+ const currentDeviceType = window.serverConfig.device.type;
+
+ //Start with a clean configuration
+ let d = {};
+
+ d.type = 'yeelight';
+ d.hardwareLedCount = finalLights.length;
+ d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
+ d.colorModel = parseInt(conf_editor.getEditor("root.specificOptions.colorModel").getValue());
+
+ d.transEffect = parseInt(conf_editor.getEditor("root.specificOptions.transEffect").getValue());
+ d.transTime = parseInt(conf_editor.getEditor("root.specificOptions.transTime").getValue());
+ d.extraTimeDarkness = parseInt(conf_editor.getEditor("root.specificOptions.extraTimeDarkness").getValue());
+
+ d.brightnessMin = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMin").getValue());
+ d.brightnessSwitchOffOnMinimum = JSON.parse(conf_editor.getEditor("root.specificOptions.brightnessSwitchOffOnMinimum").getValue());
+ d.brightnessMax = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMax").getValue());
+ d.brightnessFactor = parseFloat(conf_editor.getEditor("root.specificOptions.brightnessFactor").getValue());
+
+ d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
+ d.debugLevel = parseInt(conf_editor.getEditor("root.specificOptions.debugLevel").getValue());
+
+ d.lights = finalLights;
+
+ window.serverConfig.device = d;
+
+ if (currentDeviceType !== d.type) {
+ //smoothing off, if new device
+ window.serverConfig.smoothing = { enable: false };
+ }
+
+ requestWriteConfig(window.serverConfig, true);
+ resetWizard();
+ });
+
+ $('#btn_wiz_abort').off().on('click', resetWizard);
+ }
+
+ async function discover() {
+ // Get discovered lights
+ const res = await requestLedDeviceDiscovery('yeelight');
+ if (res && !res.error) {
+ const r = res.info;
+
+ let discoveryMethod = "ssdp";
+ if (res.info.discoveryMethod) {
+ discoveryMethod = res.info.discoveryMethod;
+ }
+
+ // Process devices returned by discovery
+ for (const device of r.devices) {
+ if (device.hostname !== "") {
+ processDiscoverdDevice(device, discoveryMethod);
+ }
+ }
+
+ // Add additional items from configuration
+ for (const configuredLight of configuredLights) {
+ processConfiguredLight(configuredLight);
+ }
+
+ assign_lights();
+ }
+ }
+
+ function processDiscoverdDevice(device, discoveryMethod) {
+ if (getHostInLights(device.hostname).length > 0) {
+ return;
+ }
+
+ const light = {
+ host: device.hostname
+ };
+
+ if (discoveryMethod === "ssdp") {
+ if (device.domain) {
+ light.host += '.' + device.domain;
+ }
+ } else {
+ light.host = device.service;
+ light.name = device.name;
+ }
+
+ light.port = device.port;
+
+ if (device.txt) {
+ light.model = device.txt.md;
+ light.port = 55443; // Yeelight default port
+ } else {
+ light.name = device.other.name;
+ light.model = device.other.model;
+ }
+
+ lights.push(light);
+ }
+ function processConfiguredLight(configuredLight) {
+ const host = configuredLight.host;
+ let port = configuredLight.port || 0;
+
+ if (host !== "" && getHostInLights(host).length === 0) {
+ const light = {
+ host: host,
+ port: port,
+ name: configuredLight.name,
+ model: "color4"
+ };
+
+ lights.push(light);
+ }
+ }
+
+ function attachIdentifyButtonEvent() {
+ $('#wizp2_body').on('click', '.btn-identify', function () {
+ const hostname = $(this).data('hostname');
+ const port = $(this).data('port');
+ identify(hostname, port);
+ });
+ }
+
+ function assign_lights() {
+ // Model mappings, see https://www.home-assistant.io/integrations/yeelight/
+ const models = ['color', 'color1', 'YLDP02YL', 'YLDP02YL', 'color2', 'YLDP06YL', 'color4', 'YLDP13YL', 'color6', 'YLDP13AYL', 'colorb', "YLDP005", 'colorc', "YLDP004-A", 'stripe', 'YLDD04YL', 'strip1', 'YLDD01YL', 'YLDD02YL', 'strip4', 'YLDD05YL', 'strip6', 'YLDD05YL'];
+
+ // If records are left for configuration
+ if (Object.keys(lights).length > 0) {
+ $('#wh_topcontainer').toggle(false);
+ $('#yee_ids_t, #btn_wiz_save').toggle(true);
+
+ const lightOptions = [
+ "top", "topleft", "topright",
+ "bottom", "bottomleft", "bottomright",
+ "left", "lefttop", "leftmiddle", "leftbottom",
+ "right", "righttop", "rightmiddle", "rightbottom",
+ "entire",
+ "lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
+ "lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
+ "lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
+ ];
+
+ lightOptions.unshift("disabled");
+
+ $('.lidsb').html("");
+ let pos = "";
+
+ for (const lightid in lights) {
+ const lightHostname = lights[lightid].host;
+ const lightPort = lights[lightid].port;
+ let lightName = lights[lightid].name;
+
+ if (lightName === "")
+ lightName = $.i18n('edt_dev_spec_lights_itemtitle') + '(' + lightHostname + ')';
+
+ let options = "";
+ for (const opt in lightOptions) {
+ const val = lightOptions[opt];
+ const txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
+ options += '';
+ }
+
+ let enabled = 'enabled';
+ if (!models.includes(lights[lightid].model)) {
+ enabled = 'disabled';
+ options = '';
+ }
+
+ $('.lidsb').append(createTableRow([(parseInt(lightid, 10) + 1) + '. ' + lightName, '', '']));
+ }
+ attachIdentifyButtonEvent();
+
+ $('.yee_sel_watch').on("change", function () {
+ let cC = 0;
+ for (const key in lights) {
+ if ($('#yee_' + key).val() !== "disabled") {
+ cC++;
+ }
+ }
+
+ if (cC === 0 || window.readOnlyMode)
+ $('#btn_wiz_save').prop("disabled", true);
+ else
+ $('#btn_wiz_save').prop("disabled", false);
+ });
+ $('.yee_sel_watch').trigger('change');
+ }
+ else {
+ const noLightsTxt = '' + $.i18n('wiz_noLights', 'lights') + '
';
+ $('#wizp2_body').append(noLightsTxt);
+ }
+ }
+
+ async function identify(host, port) {
+
+ const disabled = $('#btn_wiz_save').is(':disabled');
+
+ // Take care that new record cannot be save during background process
+ $('#btn_wiz_save').prop('disabled', true);
+
+ const params = { host: host, port: port };
+ await requestLedDeviceIdentification("yeelight", params);
+
+ if (!window.readOnlyMode) {
+ $('#btn_wiz_save').prop('disabled', disabled);
+ }
+ }
+
+ return {
+ start: function (e) {
+ //create html
+ const yeelight_title = 'wiz_yeelight_title';
+ const yeelight_intro1 = 'wiz_yeelight_intro1';
+
+ $('#wiz_header').html('' + $.i18n(yeelight_title));
+ $('#wizp1_body').html('' + $.i18n(yeelight_title) + '
' + $.i18n(yeelight_intro1) + '
');
+
+ $('#wizp1_footer').html('');
+
+ $('#wizp2_body').html('');
+
+ $('#wh_topcontainer').append('');
+
+ $('#wizp2_body').append('' + $.i18n('wiz_yeelight_desc2') + '
');
+
+ createTable("lidsh", "lidsb", "yee_ids_t");
+ $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
+ $('#wizp2_footer').html(''
+ + $.i18n('general_btn_cancel') + '');
+
+ if (getStorage("darkMode") == "on")
+ $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
+
+ //open modal
+ $("#wizard_modal").modal({ backdrop: "static", keyboard: false, show: true });
+
+ //listen for continue
+ $('#btn_wiz_cont').off().on('click', function () {
+ begin();
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ });
+ }
+};
+}) ();
+
+export { yeelightWizard };
+
diff --git a/assets/webconfig/js/wizards/colorCalibrationKodiWizard.js b/assets/webconfig/js/wizards/colorCalibrationKodiWizard.js
new file mode 100644
index 00000000..7879d641
--- /dev/null
+++ b/assets/webconfig/js/wizards/colorCalibrationKodiWizard.js
@@ -0,0 +1,485 @@
+//****************************
+// Wizard Color calibration via Kodi
+//****************************
+const colorCalibrationKodiWizard = (() => {
+
+ let ws;
+ const defaultKodiPort = 9090;
+
+ let kodiAddress = document.location.hostname;
+ let kodiPort = defaultKodiPort;
+
+ const kodiUrl = new URL("ws://" + kodiAddress);
+ kodiUrl.port = kodiPort;
+ kodiUrl.pathname = "/jsonrpc/websocket";
+
+ let wiz_editor;
+ let colorLength;
+ let cobj;
+ let step = 0;
+ let withKodi = false;
+ let profile = 0;
+ let websAddress;
+ let imgAddress;
+ let picnr = 0;
+ let id = 1;
+ const vidAddress = "https://sourceforge.net/projects/hyperion-project/files/resources/vid/";
+ const availVideos = ["Sweet_Cocoon", "Caminandes_2_GranDillama", "Caminandes_3_Llamigos"];
+
+ if (getStorage("kodiAddress") != null) {
+
+ kodiAddress = getStorage("kodiAddress");
+ kodiUrl.host = kodiAddress;
+ }
+
+ if (getStorage("kodiPort") != null) {
+ kodiPort = getStorage("kodiPort");
+ kodiUrl.port = kodiPort;
+ }
+
+ $(window).on('beforeunload', function () {
+ closeWebSocket();
+ });
+
+ function closeWebSocket() {
+ // Check if the WebSocket is open
+ if (ws && ws.readyState === WebSocket.OPEN) {
+ ws.close();
+ }
+ }
+
+ function sendToKodi(type, content) {
+ let command;
+
+ switch (type) {
+ case "msg":
+ command = { "jsonrpc": "2.0", "method": "GUI.ShowNotification", "params": { "title": $.i18n('wiz_cc_title'), "message": content, "image": "info", "displaytime": 5000 }, "id": id };
+ break;
+ case "stop":
+ command = { "jsonrpc": "2.0", "method": "Player.Stop", "params": { "playerid": 2 }, "id": id };
+ break;
+ case "playP":
+ content = imgAddress + content + '.png';
+ command = { "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "file": content } }, "id": id };
+ break;
+ case "playV":
+ content = vidAddress + content;
+ command = { "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "file": content } }, "id": id };
+ break;
+ case "rotate":
+ command = { "jsonrpc": "2.0", "method": "Player.Rotate", "params": { "playerid": 2 }, "id": id };
+ break;
+ default:
+ console.error('Unknown Kodi command type: ', type);
+ }
+
+ if (ws.readyState === WebSocket.OPEN) {
+ ws.send(JSON.stringify(command));
+ ++id;
+ } else {
+ console.error('WebSocket connection is not open. Unable to send command.');
+ }
+ }
+
+ function performAction() {
+ let h;
+
+ if (step == 1) {
+ $('#wiz_cc_desc').html($.i18n('wiz_cc_chooseid'));
+ updateEditor(["id"]);
+ $('#btn_wiz_back').prop("disabled", true);
+ }
+ else
+ $('#btn_wiz_back').prop("disabled", false);
+
+ if (step == 2) {
+ updateEditor(["white"]);
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_white_title'));
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_white_title'));
+ sendToKodi('playP', "white");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_white_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 3) {
+ updateEditor(["gammaRed", "gammaGreen", "gammaBlue"]);
+ h = '' + $.i18n('wiz_cc_adjustgamma') + '
';
+ if (withKodi) {
+ sendToKodi('playP', "HGradient");
+ h += '';
+ }
+ else
+ h += '' + $.i18n('wiz_cc_lettvshowm', "grey_1, grey_2, grey_3, HGradient, VGradient") + '
';
+ $('#wiz_cc_desc').html(h);
+ $('#wiz_cc_btn_sp').off().on('click', function () {
+ switchPicture(["VGradient", "grey_1", "grey_2", "grey_3", "HGradient"]);
+ });
+ }
+ if (step == 4) {
+ updateEditor(["red"]);
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_red_title'));
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_red_title'));
+ sendToKodi('playP', "red");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_red_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 5) {
+ updateEditor(["green"]);
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_green_title'));
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_green_title'));
+ sendToKodi('playP', "green");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_green_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 6) {
+ updateEditor(["blue"]);
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_blue_title'));
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_blue_title'));
+ sendToKodi('playP', "blue");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_blue_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 7) {
+ updateEditor(["cyan"]);
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_cyan_title'));
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_cyan_title'));
+ sendToKodi('playP', "cyan");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_cyan_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 8) {
+ updateEditor(["magenta"]);
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_magenta_title'));
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_magenta_title'));
+ sendToKodi('playP', "magenta");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_magenta_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 9) {
+ updateEditor(["yellow"]);
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_yellow_title'));
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_yellow_title'));
+ sendToKodi('playP', "yellow");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_yellow_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 10) {
+ updateEditor(["backlightThreshold", "backlightColored"]);
+ h = $.i18n('wiz_cc_backlight');
+ if (withKodi) {
+ h += '
' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_black_title'));
+ sendToKodi('playP', "black");
+ }
+ else
+ h += '
' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_black_title'));
+ $('#wiz_cc_desc').html(h);
+ }
+ if (step == 11) {
+ updateEditor([""], true);
+ h = '' + $.i18n('wiz_cc_testintro') + '
';
+ if (withKodi) {
+ h += '' + $.i18n('wiz_cc_testintrok') + '
';
+ sendToKodi('stop');
+ availVideos.forEach(video => {
+ const txt = video.replace(/_/g, " ");
+ h += ``;
+ });
+
+ h += '';
+ }
+ else
+ h += '' + $.i18n('wiz_cc_testintrowok') + ' ' + $.i18n('wiz_cc_link') + '
';
+ h += '' + $.i18n('wiz_cc_summary') + '
';
+ $('#wiz_cc_desc').html(h);
+
+ $('.videobtn').off().on('click', function (e) {
+ if (e.target.id == "stop")
+ sendToKodi("stop");
+ else
+ sendToKodi("playV", e.target.id + '.mp4');
+
+ $(this).prop("disabled", true);
+ setTimeout(function () { $('.videobtn').prop("disabled", false) }, 10000);
+ });
+
+ $('#btn_wiz_next').prop("disabled", true);
+ $('#btn_wiz_save').toggle(true);
+ window.readOnlyMode ? $('#btn_wiz_save').prop('disabled', true) : $('#btn_wiz_save').prop('disabled', false);
+ }
+ else {
+ $('#btn_wiz_next').prop("disabled", false);
+ $('#btn_wiz_save').toggle(false);
+ }
+ }
+
+
+
+ function switchPicture(pictures) {
+ if (typeof pictures[picnr] === 'undefined')
+ picnr = 0;
+
+ sendToKodi('playP', pictures[picnr]);
+ picnr++;
+ }
+
+
+ function initializeWebSocket(cb) {
+ if ("WebSocket" in window) {
+
+ if (kodiUrl.port === '') {
+ kodiUrl.port = defaultKodiPort;
+ }
+
+ if (!ws || ws.readyState !== WebSocket.OPEN) {
+
+ // Establish WebSocket connection
+ ws = new WebSocket(kodiUrl);
+
+ // WebSocket onopen event
+ ws.onopen = function (event) {
+ withKodi = true;
+ cb("opened");
+ };
+
+ // WebSocket onmessage event (handle incoming messages)
+ ws.onmessage = function (event) {
+ const response = JSON.parse(event.data);
+ if (response.method === "System.OnQuit") {
+ closeWebSocket();
+ } else if (response.result != undefined) {
+ if (response.result !== "OK") {
+ cb("error");
+ }
+ }
+ };
+
+ // WebSocket onerror event
+ ws.onerror = function (error) {
+ cb("error");
+ };
+
+ // WebSocket onclose event
+ ws.onclose = function (event) {
+ withKodi = false;
+ if (event.code === 1006) {
+ // Ignore error 1006 due to Kodi issue
+ console.log("WebSocket closed with error code 1006. Ignoring due to Kodi bug.");
+ }
+ else {
+ console.error("WebSocket closed with code:", event.code);
+ }
+ };
+ } else {
+ console.log("WebSocket connection is already open.");
+ }
+ }
+ else {
+ console.log("Kodi Access: WebSocket NOT supported by this browser");
+ cb("error");
+ }
+ }
+
+ function setupEventListeners() {
+ $('#btn_wiz_cancel').off().on('click', function () {
+ stop(true);
+ });
+ $('#wiz_cc_kodiip').off().on('change', function () {
+
+ kodiAddress = encodeURIComponent($(this).val().trim());
+
+ $('#kodi_status').html('');
+ if (kodiAddress !== "") {
+
+ if (!isValidHostnameOrIP(kodiAddress)) {
+
+ $('#kodi_status').html('' + $.i18n('edt_msgcust_error_hostname_ip') + '
');
+ withKodi = false;
+
+ } else {
+
+ if (isValidIPv6(kodiAddress)) {
+ kodiUrl.hostname = "[" + kodiAddress + "]";
+ } else {
+ kodiUrl.hostname = kodiAddress;
+ }
+
+ $('#kodi_status').html('' + $.i18n('wiz_cc_try_connect') + '
');
+ $('#btn_wiz_cont').prop('disabled', true);
+
+ closeWebSocket();
+ initializeWebSocket(function (cb) {
+
+ if (cb == "opened") {
+ setStorage("kodiAddress", kodiAddress);
+ setStorage("kodiPort", defaultKodiPort);
+
+ $('#kodi_status').html('' + $.i18n('wiz_cc_kodicon') + '
');
+ $('#btn_wiz_cont').prop('disabled', false);
+
+ if (withKodi) {
+ sendToKodi("msg", $.i18n('wiz_cc_kodimsg_start'));
+ }
+ }
+ else {
+ $('#kodi_status').html('' + $.i18n('wiz_cc_kodidiscon') + '
' + $.i18n('wiz_cc_kodidisconlink') + ' ' + $.i18n('wiz_cc_link') + '
');
+ withKodi = false;
+ }
+
+ $('#btn_wiz_cont').prop('disabled', false);
+ });
+ }
+ }
+ });
+
+ //listen for continue
+ $('#btn_wiz_cont').off().on('click', function () {
+ begin();
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ });
+ }
+
+ function init() {
+ colorLength = window.serverConfig.color.channelAdjustment;
+ cobj = window.schema.color.properties.channelAdjustment.items.properties;
+ websAddress = document.location.hostname + ':' + window.serverConfig.webConfig.port;
+ imgAddress = 'http://' + websAddress + '/img/cc/';
+ setStorage("wizardactive", true);
+ }
+
+ function initProfiles() {
+ //check profile count
+ if (colorLength.length > 1) {
+ $('#multi_cali').html('' + $.i18n('wiz_cc_morethanone') + '
');
+ for (let i = 0; i < colorLength.length; i++)
+ $('#wiz_select').append(createSelOpt(i, i + 1 + ' (' + colorLength[i].id + ')'));
+
+ $('#wiz_select').off().on('change', function () {
+ profile = $(this).val();
+ });
+ }
+ }
+
+ function createEditor() {
+ wiz_editor = createJsonEditor('editor_container_wiz', {
+ color: window.schema.color
+ }, true, true);
+
+ $('#editor_container_wiz h4').toggle(false);
+ $('#editor_container_wiz .btn-group').toggle(false);
+ $('#editor_container_wiz [data-schemapath="root.color.imageToLedMappingType"]').toggle(false);
+ $('#editor_container_wiz [data-schemapath="root.color.reducedPixelSetFactorFactor"]').toggle(false);
+ for (let i = 0; i < colorLength.length; i++)
+ $('#editor_container_wiz [data-schemapath*="root.color.channelAdjustment.' + i + '."]').toggle(false);
+ }
+ function updateEditor(el, all) {
+ for (let key in cobj) {
+ if (all === true || el[0] == key || el[1] == key || el[2] == key)
+ $('#editor_container_wiz [data-schemapath*=".' + profile + '.' + key + '"]').toggle(true);
+ else
+ $('#editor_container_wiz [data-schemapath*=".' + profile + '.' + key + '"]').toggle(false);
+ }
+ }
+
+ function stop(reload) {
+ if (withKodi) {
+ sendToKodi("stop");
+ }
+ closeWebSocket();
+ resetWizard(reload);
+ }
+
+ function begin() {
+ step = 0;
+
+ $('#btn_wiz_next').off().on('click', function () {
+ step++;
+ performAction();
+ });
+
+ $('#btn_wiz_back').off().on('click', function () {
+ step--;
+ performAction();
+ });
+
+ $('#btn_wiz_abort').off().on('click', function () {
+ stop(true);
+ });
+
+ $('#btn_wiz_save').off().on('click', function () {
+ requestWriteConfig(wiz_editor.getValue());
+ stop(true);
+ });
+
+ wiz_editor.on("change", function (e) {
+ const val = wiz_editor.getEditor('root.color.channelAdjustment.' + profile + '').getValue();
+ const temp = JSON.parse(JSON.stringify(val));
+ delete temp.leds
+ requestAdjustment(JSON.stringify(temp), "", true);
+ });
+
+ step++
+ performAction();
+ }
+
+ return {
+ start: function () {
+ //create html
+ $('#wiz_header').html('' + $.i18n('wiz_cc_title'));
+ $('#wizp1_body').html('' + $.i18n('wiz_cc_title') + '
' +
+ '' + $.i18n('wiz_cc_intro1') + '
' +
+ '' +
+ '' +
+ ''
+ );
+ $('#wizp1_footer').html('' +
+ ''
+ );
+ $('#wizp2_body').html(''
+ );
+ $('#wizp2_footer').html('' +
+ '' +
+ '' +
+ ''
+ );
+
+ if (getStorage("darkMode") == "on")
+ $('#wizard_logo').prop("src", 'img/hyperion/logo_negativ.png');
+
+ //open modal
+ $("#wizard_modal").modal({
+ backdrop: "static",
+ keyboard: false,
+ show: true
+ });
+
+ setupEventListeners();
+ $('#wiz_cc_kodiip').trigger("change");
+ init();
+ initProfiles();
+ createEditor();
+ }
+ };
+})();
+
+export { colorCalibrationKodiWizard };
diff --git a/assets/webconfig/js/wizards/rgbByteOrderWizard.js b/assets/webconfig/js/wizards/rgbByteOrderWizard.js
new file mode 100644
index 00000000..5d612174
--- /dev/null
+++ b/assets/webconfig/js/wizards/rgbByteOrderWizard.js
@@ -0,0 +1,143 @@
+//****************************
+// Wizard RGB byte order
+//****************************
+
+const rgbByteOrderWizard = (() => {
+
+ let wIntveralId;
+ let new_rgb_order;
+
+ function changeColor() {
+ let color = $("#wiz_canv_color").css('background-color');
+
+ if (color == 'rgb(255, 0, 0)') {
+ $("#wiz_canv_color").css('background-color', 'rgb(0, 255, 0)');
+ requestSetColor('0', '255', '0');
+ }
+ else {
+ $("#wiz_canv_color").css('background-color', 'rgb(255, 0, 0)');
+ requestSetColor('255', '0', '0');
+ }
+ }
+
+
+ function stopWizardRGB(reload) {
+ console.log("stopWizardRGB - reload: ", reload);
+ clearInterval(wIntveralId);
+ resetWizard(reload);
+ }
+
+ function beginWizardRGB() {
+ $("#wiz_switchtime_select").off().on('change', function () {
+ clearInterval(wIntveralId);
+ const time = $("#wiz_switchtime_select").val();
+ wIntveralId = setInterval(function () { changeColor(); }, time * 1000);
+ });
+
+ $('.wselect').on("change", function () {
+ let rgb_order = window.serverConfig.device.colorOrder.split("");
+ const redS = $("#wiz_r_select").val();
+ const greenS = $("#wiz_g_select").val();
+ const blueS = rgb_order.toString().replace(/,/g, "").replace(redS, "").replace(greenS, "");
+
+ for (const color of rgb_order) {
+ if (redS == color)
+ $('#wiz_g_select option[value=' + color + ']').prop('disabled', true);
+ else
+ $('#wiz_g_select option[value=' + color + ']').prop('disabled', false);
+ if (greenS == color)
+ $('#wiz_r_select option[value=' + color + ']').prop('disabled', true);
+ else
+ $('#wiz_r_select option[value=' + color + ']').prop('disabled', false);
+ }
+
+ if (redS != 'null' && greenS != 'null') {
+ $('#btn_wiz_save').prop('disabled', false);
+
+ for (let i = 0; i < rgb_order.length; i++) {
+ if (rgb_order[i] == "r")
+ rgb_order[i] = redS;
+ else if (rgb_order[i] == "g")
+ rgb_order[i] = greenS;
+ else
+ rgb_order[i] = blueS;
+ }
+
+ rgb_order = rgb_order.toString().replace(/,/g, "");
+
+ if (redS == "r" && greenS == "g") {
+ $('#btn_wiz_save').toggle(false);
+ $('#btn_wiz_checkok').toggle(true);
+
+ window.readOnlyMode ? $('#btn_wiz_checkok').prop('disabled', true) : $('#btn_wiz_checkok').prop('disabled', false);
+ }
+ else {
+ $('#btn_wiz_save').toggle(true);
+ window.readOnlyMode ? $('#btn_wiz_save').prop('disabled', true) : $('#btn_wiz_save').prop('disabled', false);
+
+ $('#btn_wiz_checkok').toggle(false);
+ }
+ new_rgb_order = rgb_order;
+ }
+ else
+ $('#btn_wiz_save').prop('disabled', true);
+ });
+
+ $("#wiz_switchtime_select").append(createSelOpt('5', '5'), createSelOpt('10', '10'), createSelOpt('15', '15'), createSelOpt('30', '30'));
+ $("#wiz_switchtime_select").trigger('change');
+
+ $("#wiz_r_select").append(createSelOpt("null", ""), createSelOpt('r', $.i18n('general_col_red')), createSelOpt('g', $.i18n('general_col_green')), createSelOpt('b', $.i18n('general_col_blue')));
+ $("#wiz_g_select").html($("#wiz_r_select").html());
+ $("#wiz_r_select").trigger('change');
+
+ requestSetColor('255', '0', '0');
+ setTimeout(requestSetSource, 100, 'auto');
+ setStorage("wizardactive", true);
+
+ $('#btn_wiz_abort').off().on('click', function () { stopWizardRGB(true); });
+
+ $('#btn_wiz_checkok').off().on('click', function () {
+ showInfoDialog('success', "", $.i18n('infoDialog_wizrgb_text'));
+ stopWizardRGB();
+ });
+
+ $('#btn_wiz_save').off().on('click', function () {
+ stopWizardRGB();
+ window.serverConfig.device.colorOrder = new_rgb_order;
+ requestWriteConfig({ "device": window.serverConfig.device });
+ });
+ }
+
+ return {
+ start: function () {
+ //create html
+ $('#wiz_header').html('' + $.i18n('wiz_rgb_title'));
+ $('#wizp1_body').html('' + $.i18n('wiz_rgb_title') + '
' + $.i18n('wiz_rgb_intro1') + '
' + $.i18n('wiz_rgb_intro2') + '
');
+ $('#wizp1_footer').html('');
+ $('#wizp2_body').html('' + $.i18n('wiz_rgb_expl') + '
');
+ $('#wizp2_body').append('');
+ $('#wizp2_body').append('');
+ $('#wizp2_body').append(' | |
| |
');
+ $('#wizp2_footer').html('');
+
+ if (getStorage("darkMode") == "on")
+ $('#wizard_logo').attr("src", 'img/hyperion/logo_negativ.png');
+
+ //open modal
+ $("#wizard_modal").modal({
+ backdrop: "static",
+ keyboard: false,
+ show: true
+ });
+
+ //listen for continue
+ $('#btn_wiz_cont').off().on('click', function () {
+ beginWizardRGB();
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ });
+ }
+ };
+})();
+
+export { rgbByteOrderWizard };
From 86d08823a81740f8ab893e4059193b3400e59c13 Mon Sep 17 00:00:00 2001
From: LordGrey <48840279+Lord-Grey@users.noreply.github.com>
Date: Sat, 30 Mar 2024 15:44:18 +0100
Subject: [PATCH 5/9] Add workaround for issue #1692 (#1695)
---
libsrc/webserver/StaticFileServing.cpp | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/libsrc/webserver/StaticFileServing.cpp b/libsrc/webserver/StaticFileServing.cpp
index 4c550280..4133ce66 100644
--- a/libsrc/webserver/StaticFileServing.cpp
+++ b/libsrc/webserver/StaticFileServing.cpp
@@ -132,7 +132,16 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl
QMimeType mime = _mimeDb->mimeTypeForFile (file.fileName ());
if (file.open (QFile::ReadOnly)) {
QByteArray data = file.readAll ();
- reply->addHeader ("Content-Type", mime.name ().toLocal8Bit ());
+
+ // Workaround https://bugreports.qt.io/browse/QTBUG-97392
+ if (mime.name() == QStringLiteral("application/x-extension-html"))
+ {
+ reply->addHeader ("Content-Type", "text/html");
+ }
+ else
+ {
+ reply->addHeader ("Content-Type", mime.name().toLocal8Bit());
+ }
reply->addHeader(QtHttpHeader::AccessControlAllow, "*" );
reply->appendRawData (data);
file.close ();
From d5438acbf4e27de61f5f7fe20c2acba793652233 Mon Sep 17 00:00:00 2001
From: LordGrey <48840279+Lord-Grey@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:44:46 +0200
Subject: [PATCH 6/9] Fix Cross Site Scripting Vulnerability 1 (#1720)
---
libsrc/webserver/StaticFileServing.cpp | 14 +++++++++-----
libsrc/webserver/StaticFileServing.h | 2 +-
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/libsrc/webserver/StaticFileServing.cpp b/libsrc/webserver/StaticFileServing.cpp
index 4133ce66..3f3bc5a7 100644
--- a/libsrc/webserver/StaticFileServing.cpp
+++ b/libsrc/webserver/StaticFileServing.cpp
@@ -39,12 +39,15 @@ void StaticFileServing::setBaseUrl(const QString& url)
void StaticFileServing::setSSDPDescription(const QString& desc)
{
if(desc.isEmpty())
+ {
_ssdpDescription.clear();
- else
+ } else
+ {
_ssdpDescription = desc.toLocal8Bit();
+ }
}
-void StaticFileServing::printErrorToReply (QtHttpReply * reply, QtHttpReply::StatusCode code, QString errorMessage)
+void StaticFileServing::printErrorToReply (QtHttpReply * reply, QtHttpReply::StatusCode code, const QString& errorMessage)
{
reply->setStatusCode(code);
reply->addHeader ("Content-Type", QByteArrayLiteral ("text/html"));
@@ -62,13 +65,13 @@ void StaticFileServing::printErrorToReply (QtHttpReply * reply, QtHttpReply::Sta
if (errorPage.open (QFile::ReadOnly))
{
QByteArray data = errorPage.readAll();
- data = data.replace("{MESSAGE}", errorMessage.toLocal8Bit() );
+ data = data.replace("{MESSAGE}", QString(errorMessage.toLocal8Bit()).toHtmlEscaped().toLocal8Bit() );
reply->appendRawData (data);
errorPage.close ();
}
else
{
- reply->appendRawData (QString(QString::number(code) + " - " +errorMessage).toLocal8Bit());
+ reply->appendRawData (QString(QString::number(code) + " - " +errorMessage.toLocal8Bit()).toHtmlEscaped().toLocal8Bit());
}
if (errorPageFooter.open (QFile::ReadOnly))
@@ -103,7 +106,8 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl
}
return;
}
- else if(uri_parts.at(0) == "description.xml" && !_ssdpDescription.isNull())
+
+ if(uri_parts.at(0) == "description.xml" && !_ssdpDescription.isNull())
{
reply->addHeader ("Content-Type", "text/xml");
reply->appendRawData (_ssdpDescription);
diff --git a/libsrc/webserver/StaticFileServing.h b/libsrc/webserver/StaticFileServing.h
index b328bf16..8a058ea6 100644
--- a/libsrc/webserver/StaticFileServing.h
+++ b/libsrc/webserver/StaticFileServing.h
@@ -37,7 +37,7 @@ private:
Logger * _log;
QByteArray _ssdpDescription;
- void printErrorToReply (QtHttpReply * reply, QtHttpReply::StatusCode code, QString errorMessage);
+ void printErrorToReply (QtHttpReply * reply, QtHttpReply::StatusCode code, const QString& errorMessage);
};
From c2fe42a7314cce3289444204951badfe2d6dd42b Mon Sep 17 00:00:00 2001
From: LordGrey <48840279+Lord-Grey@users.noreply.github.com>
Date: Sat, 13 Apr 2024 22:54:17 +0200
Subject: [PATCH 7/9] Fix #1722 (#1723)
---
src/hyperion-v4l2/hyperion-v4l2.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp
index b166948b..ecc6ed58 100644
--- a/src/hyperion-v4l2/hyperion-v4l2.cpp
+++ b/src/hyperion-v4l2/hyperion-v4l2.cpp
@@ -231,6 +231,7 @@ int main(int argc, char** argv)
ScreenshotHandler handler("screenshot.png", signalDetectionOffset);
QObject::connect(&grabber, SIGNAL(newFrame(Image)), &handler, SLOT(receiveImage(Image)));
+ grabber.prepare();
grabber.start();
QCoreApplication::exec();
grabber.stop();
From aca757138ef50931454b68f92a5ba27a0f8f5d46 Mon Sep 17 00:00:00 2001
From: LordGrey <48840279+Lord-Grey@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:57:51 +0200
Subject: [PATCH 8/9] Nanoleaf Updates (#1724)
* Add new devices
* Do not restore ExtControl state
---
assets/webconfig/js/content_leds.js | 4 ++++
libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp | 4 ++--
libsrc/leddevice/dev_net/LedDeviceNanoleaf.h | 6 +++++-
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js
index 938bf8ee..f058450a 100755
--- a/assets/webconfig/js/content_leds.js
+++ b/assets/webconfig/js/content_leds.js
@@ -2510,6 +2510,10 @@ function nanoleafGeneratelayout(panelLayout, panelOrderTopDown, panelOrderLeftRi
18: { name: "LightLinesSingleZone", led: true, sideLengthX: 77, sideLengthY: 77 },
19: { name: "ControllerCap", led: false, sideLengthX: 11, sideLengthY: 11 },
20: { name: "PowerConnector", led: false, sideLengthX: 11, sideLengthY: 11 },
+ 29: { name: "4DLightstrip", led: true, sideLengthX: 50, sideLengthY: 50 },
+ 30: { name: "Skylight Panel", led: true, sideLengthX: 180, sideLengthY: 180 },
+ 31: { name: "SkylightControllerPrimary", led: true, sideLengthX: 180, sideLengthY: 180 },
+ 32: { name: "SkylightControllerPassive", led: true, sideLengthX: 180, sideLengthY: 180 },
999: { name: "Unknown", led: true, sideLengthX: 100, sideLengthY: 100 }
};
diff --git a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp
index e2b8b3fb..d7711a02 100644
--- a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp
+++ b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp
@@ -708,7 +708,7 @@ bool LedDeviceNanoleaf::storeState()
QJsonObject effects = responseEffects.getBody().object();
DebugIf(verbose, _log, "effects: [%s]", QString(QJsonDocument(_originalStateProperties).toJson(QJsonDocument::Compact)).toUtf8().constData());
_originalEffect = effects[API_EFFECT_SELECT].toString();
- _originalIsDynEffect = _originalEffect == "*Dynamic*" || _originalEffect == "*Solid*";
+ _originalIsDynEffect = _originalEffect != "*Dynamic*" || _originalEffect == "*Solid*" || _originalEffect == "*ExtControl*";
}
break;
}
@@ -759,7 +759,7 @@ bool LedDeviceNanoleaf::restoreState()
}
}
else {
- Warning(_log, "%s restoring effect failed with error: Cannot restore dynamic or solid effect. Device is switched off", QSTRING_CSTR(_activeDeviceType));
+ Info(_log, "%s cannot restore dynamic or solid effects. Device is switched off instead", QSTRING_CSTR(_activeDeviceType));
_originalIsOn = false;
}
break;
diff --git a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h
index 8aae03ec..dd9353b6 100644
--- a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h
+++ b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h
@@ -179,7 +179,11 @@ private:
LIGHT_LINES = 17,
LIGHT_LINES_SINGLZONE = 18,
CONTROLLER_CAP = 19,
- POWER_CONNECTOR = 20
+ POWER_CONNECTOR = 20,
+ NL_4D_LIGHTSTRIP = 29,
+ SKYLIGHT_PANEL = 30,
+ SKYLIGHT_CONTROLLER_PRIMARY = 31,
+ SKYLIGHT_CONTROLLER_PASSIV = 32
};
///
From 7645ebb526c9cb4618015201fbcef23fdf151152 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:58:33 +0200
Subject: [PATCH 9/9] Bump softprops/action-gh-release from 1 to 2 (#1719)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)
---
updated-dependencies:
- dependency-name: softprops/action-gh-release
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/qt5_6.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/qt5_6.yml b/.github/workflows/qt5_6.yml
index 2af9e875..b8096150 100644
--- a/.github/workflows/qt5_6.yml
+++ b/.github/workflows/qt5_6.yml
@@ -232,7 +232,7 @@ jobs:
path: all-artifacts
- name: 📦 Upload
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v2
with:
name: Hyperion ${{ env.VERSION }}
tag_name: ${{ env.TAG }}