Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Dexxter

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    D
    • Profile
    • Following 0
    • Followers 0
    • Topics 1
    • Posts 19
    • Best 0
    • Groups 1

    Dexxter

    @Dexxter

    Starter

    0
    Reputation
    4
    Profile views
    19
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Dexxter Follow
    Starter

    Latest posts made by Dexxter

    • RE: Sonoff NSPanel

      @armilar said in Sonoff NSPanel:

      @dexxter sagte in Sonoff NSPanel:

      @armilar said in Sonoff NSPanel:

      @dexxter sagte in Sonoff NSPanel:

      Ich bin nämlich in der Teufel Raumfeld ecke unterwegs.

      Nee, ganz im Gegenteil - perfekter Tester - ich wünschte, es gäbe mehr wie dich 👍 . Genau die bringen die Ideen und runden das Produkt ab. Mit echten Use-Cases macht es ohnehin mehr Spaß.

      Gibt es dazu einen Adapter? Was hat der für Datenpunkte? Die Readme ist ja sehr bescheiden.

      Was gibt es noch für Möglichkeiten für den Mediaplayer?:

      • Ich hatte kurz vor dem Wechsel auf Alexa den Spotify-Premium-Adapter drin. Funktionierte ebenso gut (Sourcen weiter am Anfang). Hab mich dann dazu entschieden, den Alexa2-Adapter anzugraben, da der doch etwas flexibler ist. Das was der Spotify-Premium steuert, sieht der Alexa2-Adapter auch (und weitere wie TuneIn, Amazon-Music- und Spotify-Playlists, etc.).
      • Ich denke, das sich der Media-Alias ebenso mit Google steuern lässt - ich kann es nur nicht testen
      • Ebenso sollte der Media-Alias mit Kodi oder evtl. mit Raumfeld (siehe Datenpunkte) oder andern Marken laufen.
      • Folgende Datenpunkte (On/Off; Play; Stop; Previous; Next; Artist; Track; Playlist) können über den Media-Alias übergeben werden
      • Die Speaker-List kann auch deaktiviert werden

      Einen Adapter gibt es nicht aber Nodes für Node-Red.
      Mit denen arbeite ich.
      Grundsätzlich kann ich also mit jedem vorhandenen Alias auskommen und den für mich umbiegen.
      Müsste nur wissen welche Aliase alles benutzt werden, dann kann ich das testen.
      2022-04-25 20_59_19-Node-RED _ 192.168.178.14 – Opera.jpg

      Das sind die Datenpunkte in meinem Media-Alias (wurden so automatisch angelegt)
      b67e500c-882d-4deb-a70f-f087c36b35f3-image.png

      Einige werde aber gar nicht benötigt (Cover, Duration, Elapsed, Repeat, Shuffle). Der Rest kann in der cardMedia verwendet werden.

      Hallöle.....bin zurück von der Testfront.
      Ich hab jetzt die letzten 2 Tage versucht meine Teufel Raumfeld mit der Media Seite anzusteuern und ich muss sagen ich bin grandios gescheitert😂
      Als erstes hab ich versucht den Alias genau wie bei Dir anzulegen und die Datenpunkte einfach auf meine Raumfelds umzubiegen.
      Aber nix da.......ich denke mal es liegt daran das mir der Alexa Adapter fehlt und deswegen das Script nicht weiß welchen Speaker es jetzt ansprechen soll.
      Danach hab ich versucht direkt im Script die Punkte .SET, .Volume usw. direkt mit den Datenpunkten vom Raumfeld zu verknüpfen aber auch da tut sich einfach gar nichts.
      Bin grad etwas ratlos aber ich muss auch gestehen das ich die letzten 2 Tage nicht so richtig Zeit hatte zum testen, die Frau hatte da andere Pläne 😂
      Ich bleibe auf jeden Fall dran und werde über Fortschritte berichen.

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar said in Sonoff NSPanel:

      @dexxter sagte in Sonoff NSPanel:

      Ich bin nämlich in der Teufel Raumfeld ecke unterwegs.

      Nee, ganz im Gegenteil - perfekter Tester - ich wünschte, es gäbe mehr wie dich 👍 . Genau die bringen die Ideen und runden das Produkt ab. Mit echten Use-Cases macht es ohnehin mehr Spaß.

      Gibt es dazu einen Adapter? Was hat der für Datenpunkte? Die Readme ist ja sehr bescheiden.

      Was gibt es noch für Möglichkeiten für den Mediaplayer?:

      • Ich hatte kurz vor dem Wechsel auf Alexa den Spotify-Premium-Adapter drin. Funktionierte ebenso gut (Sourcen weiter am Anfang). Hab mich dann dazu entschieden, den Alexa2-Adapter anzugraben, da der doch etwas flexibler ist. Das was der Spotify-Premium steuert, sieht der Alexa2-Adapter auch (und weitere wie TuneIn, Amazon-Music- und Spotify-Playlists, etc.).
      • Ich denke, das sich der Media-Alias ebenso mit Google steuern lässt - ich kann es nur nicht testen
      • Ebenso sollte der Media-Alias mit Kodi oder evtl. mit Raumfeld (siehe Datenpunkte) oder andern Marken laufen.
      • Folgende Datenpunkte (On/Off; Play; Stop; Previous; Next; Artist; Track; Playlist) können über den Media-Alias übergeben werden
      • Die Speaker-List kann auch deaktiviert werden

      Einen Adapter gibt es nicht aber Nodes für Node-Red.
      Mit denen arbeite ich.
      Grundsätzlich kann ich also mit jedem vorhandenen Alias auskommen und den für mich umbiegen.
      Müsste nur wissen welche Aliase alles benutzt werden, dann kann ich das testen.
      2022-04-25 20_59_19-Node-RED _ 192.168.178.14 – Opera.jpg

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @great-sun
      Also ich hab solche schwarzen mit so`nem verbindungskamin damit man 2 zusammen stecken kann und da passt das Panel definitiv nicht.
      Ich hab dann mit nem Cuttermesser unten 2 Steifen raus geschnitten und den Gips etwas entfernt damit die Ecken von dem Panel in die Dose passen.
      Nicht schön aber funktioniert.

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar
      Perfekt, so läuft es bei mir super 👍 😊
      Vielen Dank bis hier hin, ich hoffe ich bin Dir nicht zu sehr auf die Nerven gegangen.
      Code lesen und verstehen wird bei mir langsam besser aber vom schreiben bin ich noch meilenweit entfernt😏
      Jetzt spinnt zwar mein Controller etwas rum aber das hat mit dem Code nix zu tun.
      Ist es eigentlich möglich mit dem Alexa case auch etwas anderes zu steuern?
      Ich bin nämlich in der Teufel Raumfeld ecke unterwegs.

      EDIT: Hat schon jemand das Panel einbauen wollen? Ich hab meins gestern eingebaut und das passt ja mal so gar nicht in eine normale UP Dose!
      Ich musste echt ein paar Stücke der Dose raus schneiden bevor ich das Ding rein bekommen hab 😕

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar
      Kann es sein das Du den case "hue" vergessen hast?
      minValueBrightness und maxValueBrightness funktionieren beim Dimmer super aber beim Hue
      haben sie keine Funktion.
      slider_LI.jpg

      kann das vielleicht daran liegen?

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar
      Alles klar, dann wünsch ich Dir mal noch einen schönen RestSonntag 😊

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar
      Also das läuft für mich schon "fast" perfekt 😁
      Das einzige Problem was ich jetzt noch habe ist das ich ja den Dimmerslider vom Hue Gerät begrenzen muss.
      Und da dort ja schon minValue und maxValue für die Farbtemperatur vergeben sind wird das so ja nicht gehen.
      Ich habe mal ein bisschen in Deinem Code rumgepfuscht ( sorry, ich hab da echt keine Ahnung von ) und versucht noch nen anderen Übergabewert hinein zu bekommen.
      Der nennt sich dann
      minValueBRI
      und
      maxValueBRI.
      Sollte dann für den Brightnessslider im Hue Gerät sein und dort den Dimmwert begrenzen.
      So wie ich das verpfuscht habe läuft das Script auch nicht.
      Wenn Du mal herzlich lachen möchtest dann kannst Du Dir das ja mal anschauen.

      var Icons = new IconsSelector();
      
      const Months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"];
      const Days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];
      const Off: RGB = { red: 68, green: 115, blue: 158 };
      const On: RGB = { red: 253, green: 216, blue: 53 };
      const MSRed: RGB = { red: 251, green: 105, blue: 98 };
      const MSGreen: RGB = { red: 121, green: 222, blue: 121 };
      const Red: RGB = { red: 255, green: 0, blue: 0 };
      const White: RGB = { red: 255, green: 255, blue: 255 };
      const Yellow: RGB = { red: 255, green: 255, blue: 0 };
      const Green: RGB = { red: 0, green: 255, blue: 0 };
      const Blue: RGB = { red: 0, green: 0, blue: 255 };
      const Gray: RGB = { red: 136, green: 136, blue: 136 };
      const Black: RGB = { red: 0, green: 0, blue: 0 };
      const colorSpotify: RGB = { red: 30, green: 215, blue: 96 };
      const colorAlexa: RGB = { red: 49, green: 196, blue: 243 };
      const colorRadio: RGB = { red: 255, green: 127, blue: 0 };
      const BatteryFull: RGB = { red: 96, green: 176, blue: 62 };
      const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 };
      
      
      //----Möglichkeit, im Screensaver zwischen Accu-Weather Forecast oder selbstdefinierten Werten zu wählen---------------------------------
      var weatherForecast = false; //true = WheatherForecast 5 Days --- false = Config --> firstScreensaverEntity - fourthScreensaverEntity ...
      
      //Alexa-Instanz
      var alexaInstanz = "alexa2.0"
      var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuendes Device
      
      // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz
      // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists
      const alexaSpeakerList = []; //Beispiel ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino"];
      //const alexaSpeakerList = ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino","Echo Dot Küche"];
      
      //Datenpunkte für Nachricht an Screensaver 
      var popupNotifyHeading = "0_userdata.0.NSPanel.1.popupNotifyHeading";
      var popupNotifyText = "0_userdata.0.NSPanel.1.popupNotifyText";
      
      var Test_Licht: PageEntities =
      {
          "type": "cardEntities",
          "heading": "Büro",
          "useColor": true,
          "items": [
              <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"},
              <PageItem>{ id: "alias.0.NSPanel_1.Testlampe2", name: "Filamentlampe", minValue: 0, maxValue: 70},
              <PageItem>{ id: "alias.0.NSPanel_1.TestCTmitHUE", name: "HUE-Light-CT"},
              <PageItem>{ id: "alias.0.NSPanel_1.TestHUELicht", name: "HUE-Light-Color", minValue: 500, maxValue: 6500}
          ]
      };
      
      var Buero_Seite_1: PageEntities =
      {
          "type": "cardEntities",
          "heading": "Büro",
          "useColor": true,
          "items": [
              <PageItem>{ id: "alias.0.CTmitHUE", name: "Computer Decke", minValue: 500, maxValue: 6500, minValueBRI: 1, maxValueBRI: 70}, //HUE o.a. über --> Alias HUE mit CT ohne Color
              <PageItem>{ id: "alias.0.COMPUTER_LED", name: "Computer Tisch", minValue: 0, maxValue: 70}, //Dimmer
              <PageItem>{ id: "alias.0.NSPanel_1.Testlampe2"},
              <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen}
          ]
      };
      
      var Fenster_1: PageEntities =
      {
          "type": "cardEntities",
          "heading": "Fenster und Türen",
          "useColor": true,
          "items": [
              <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"},
              <PageItem>{ id: "alias.0.NSPanel_1.Haustuer", offColor: MSRed, onColor: MSGreen, name: "Haustür"},
              <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", onColor: White, name: "IKEA Fyrtur"}
          ]
      };
      
      var Abfall: PageEntities =
      {
          "type": "cardEntities",
          "heading": "Abfallkalender",
          "useColor": true,
          "items": [
              <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event1",icon: "trash-can"},
              <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event2",icon: "trash-can"},
              <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event3",icon: "trash-can"},
              <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event4",icon: "trash-can"}
          ]
      };
      
      var Buero_Seite_2: PageGrid =
      {
          "type": "cardGrid",
          "heading": "Büro 2",
          "useColor": true,
          "items": [
              <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe", name: "Schreibtisch"},
              <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung", name: "Deckenlampe"},
              <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"},
              <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen},
              <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", icon: "projector-screen", onColor: White, name: "Beamer"},
              <PageItem>{ id: "alias.0.NSPanel_1.Radio.TuneIn", icon: "play", onColor: White}
          ]
      };
      
      var Alexa: PageMedia = 
      {
          "type": "cardMedia",
          "heading": "Alexa",
          "useColor": true,
          "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alexa.PlayerBuero" }]
      };
      
      var Buero_Themostat: PageThermo = 
      {
          "type": "cardThermo",
          "heading": "Thermostat",
          "useColor": true,
          "items": [<PageItem>{ id: "alias.0.NSPanel_1.Thermostat_Büro" }]
      };
      
      var Buero_Alarm: PageAlarm = 
      {
          "type": "cardAlarm",
          "heading": "Alarm",
          "useColor": true,
          "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alarm" }]
      };
      
      var button1Page: PageGrid =
      {
          "type": "cardGrid",
          "heading": "Radio",
          "useColor": true,
          "items": [
              <PageItem>{ id: "alias.0.NSPanel_1.Radio.FFN", icon: "radio", name: "FFN", onColor: colorRadio},
              <PageItem>{ id: "alias.0.NSPanel_1.Radio.Antenne" , icon: "radio", name: "Antenne Nds.", onColor: colorRadio},
              <PageItem>{ id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "NDR2", onColor: colorRadio},
              <PageItem>{ id: "alias.0.NSPanel_1.Radio.Bob", icon: "radio", name: "Radio BOB", onColor: colorRadio},
              <PageItem>{ id: "alias.0.NSPanel_1.Radio.Spotify", icon: "spotify", name: "Party Playlist", onColor: colorSpotify},
              <PageItem>{ id: "alias.0.NSPanel_1.Radio.Alexa", icon: "playlist-music", name: "Playlist 2021", onColor: colorAlexa}
          ]
      };
      
      var button2Page: PageEntities =
      {
          "type": "cardEntities",
          "heading": "Büro",
          "useColor": true,
          "items": [
              <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"},
              <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung"}
          ]
      };
      
      export const config: Config = {
          panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT",       //anpassen
          panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend",   //anpassen
          firstScreensaverEntity: { ScreensaverEntity: "hm-rpc.0.000EDA4995B568.1.HUMIDITY", ScreensaverEntityIcon: "water-percent", ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" },
          secondScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.PRECIPITATION_CHANCE", ScreensaverEntityIcon: "weather-pouring", ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" },
          thirdScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.Wind_SPEED", ScreensaverEntityIcon: "weather-windy", ScreensaverEntityText: "Wind", ScreensaverEntityUnitText: "bft" },
          fourthScreensaverEntity: { ScreensaverEntity: "accuweather.0.Current.UVIndex", ScreensaverEntityIcon: "solar-power", ScreensaverEntityText: "UV", ScreensaverEntityUnitText: "" },
          timeoutScreensaver: 5,
          dimmode: 8,
          screenSaverDoubleClick: false,
          locale: "de_DE",
          timeFormat: "%H:%M",
          dateFormat: "%A, %d. %B %Y",
          weatherEntity: "alias.0.Wetter",
          defaultOffColor: Off,
          defaultOnColor: On,
          defaultColor: Off,
          temperatureUnit: "°C",
          pages: [
                  Buero_Seite_1,
                  //Test_Licht,
                  Fenster_1,
                  Abfall,
                  //Buero_Seite_2,
                  Alexa,
                  Buero_Themostat,
                  Buero_Alarm
          ],
          button1Page: button1Page,
          button2Page: button2Page
      };
      
      // _________________________________ Ab hier keine Konfiguration mehr _____________________________________
      
      //Notification an Screensaver
      on({id: [popupNotifyHeading, popupNotifyText], change: "ne"}, async function (obj) {
          setState(config.panelSendTopic,(['notify~',getState(popupNotifyHeading).val,'~',getState(popupNotifyText).val].join('')));
      });
      
      var subscriptions: any = {};
      var screensaverEnabled : boolean = false;
      var pageId = 0;
      
      schedule("* * * * *", function () {
          SendTime();
      });
      schedule("0 * * * *", function () {
          SendDate();
      });
      
      
      // Only monitor the extra nodes if present
      var updateArray: string[] = [];
      if (config.firstScreensaverEntity !== null && config.firstScreensaverEntity.ScreensaverEntity != null && existsState(config.firstScreensaverEntity.ScreensaverEntity)) {
          updateArray.push(config.firstScreensaverEntity.ScreensaverEntity)
      }
      if (config.secondScreensaverEntity !== null && config.secondScreensaverEntity.ScreensaverEntity != null && existsState(config.secondScreensaverEntity.ScreensaverEntity)) {
          updateArray.push(config.secondScreensaverEntity.ScreensaverEntity)
      }
      if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.ScreensaverEntity != null && existsState(config.thirdScreensaverEntity.ScreensaverEntity)) {
          updateArray.push(config.thirdScreensaverEntity.ScreensaverEntity)
      }
      if (config.fourthScreensaverEntity !== null && config.fourthScreensaverEntity.ScreensaverEntity != null && existsState(config.fourthScreensaverEntity.ScreensaverEntity)) {
          updateArray.push(config.fourthScreensaverEntity.ScreensaverEntity)
      }
      
      if (updateArray.length > 0) {
          on(updateArray, function () {
              HandleScreensaverUpdate();
          })
      }
      on({ id: config.panelRecvTopic }, function (obj) {
          if (obj.state.val.startsWith('\{"CustomRecv":')) {
              var json = JSON.parse(obj.state.val);
      
              var split = json.CustomRecv.split(",");
              HandleMessage(split[0], split[1], parseInt(split[2]), split);
          }
      });
      
      function SendToPanel(val: Payload | Payload[]): void {
          if (Array.isArray(val)) {
              val.forEach(function (id, i) {
                  setState(config.panelSendTopic, id.payload);
              });
          }
          else
              setState(config.panelSendTopic, val.payload);
      }
      
      function HandleMessage(typ: string, method: string, page: number, words: Array<string>): void {
          if (typ == "event") {
              switch (method) {
                  case "startup":
                      screensaverEnabled = false;
                      UnsubscribeWatcher();
                      HandleStartupProcess();
                      pageId = 0;
                      GeneratePage(config.pages[0]);
                      break;
                  case "sleepReached":
                      screensaverEnabled = true;
                      if (pageId < 0)
                          pageId = 0;
                      HandleScreensaver();
                      break;
                  case "pageOpenDetail":
                      screensaverEnabled = false;
                      UnsubscribeWatcher();
                      let pageItem = config.pages[pageId].items.find(e => e.id === words[3]);
                      if (pageItem !== undefined)
                          SendToPanel(GenerateDetailPage(words[2], pageItem));
                  case "buttonPress2":
                      screensaverEnabled = false;
                      HandleButtonEvent(words);
                      break;
                  case "button1":
                  case "button2":
                      screensaverEnabled = false;
                      HandleHardwareButton(method);
                  default:
                      break;
              }
          }
      }
      
      function GeneratePage(page: Page): void {
          switch (page.type) {
              case "cardEntities":
                  SendToPanel(GenerateEntitiesPage(<PageEntities>page));
                  break;
              case "cardThermo":
                  SendToPanel(GenerateThermoPage(<PageThermo>page));
                  break;
              case "cardGrid":
                  SendToPanel(GenerateGridPage(<PageGrid>page));
                  break;
              case "cardMedia":
                  SendToPanel(GenerateMediaPage(<PageMedia>page));
                  break;
              case "cardAlarm":
                  SendToPanel(GenerateAlarmPage(<PageAlarm>page));
                  break;
          }
      }
      
      function HandleHardwareButton(method: string): void {
          let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid);
          if (config.button1Page !== null && method == "button1") {
              page = config.button1Page;
              pageId = -1;
          }
          else if (config.button2Page !== null && method == "button2") {
              page = config.button2Page;
              pageId = -2;
          }
          else {
              return;
          }
          GeneratePage(page);
      }
      
      function HandleStartupProcess(): void {
          SendDate();
          SendTime();
          SendToPanel({ payload: "timeout~" + config.timeoutScreensaver });
          SendToPanel({ payload: "dimmode~" + config.dimmode });
      }
      
      function SendDate(): void {
          var d = new Date();
          var day = Days[d.getDay()];
          var date = d.getDate();
          var month = Months[d.getMonth()];
          var year = d.getFullYear();
          var _sendDate = "date~" + day + " " + date + " " + month + " " + year;
          SendToPanel(<Payload>{ payload: _sendDate });
      }
      
      function SendTime(): void {
          var d = new Date();
          var hr = d.getHours().toString();
          var min = d.getMinutes().toString();
      
          if (d.getHours() < 10) {
              hr = "0" + d.getHours().toString();
          }
          if (d.getMinutes() < 10) {
              min = "0" + d.getMinutes().toString();
          }
          SendToPanel(<Payload>{ payload: "time~" + hr + ":" + min });
      }
      
      function GenerateEntitiesPage(page: PageEntities): Payload[] {
          var out_msgs: Array<Payload> = [];
          out_msgs = [{ payload: "pageType~cardEntities" }]
          out_msgs.push({ payload: GeneratePageElements(page) });
          return out_msgs
      }
      
      function GenerateGridPage(page: PageGrid): Payload[] {
          var out_msgs: Array<Payload> = [];
          out_msgs = [{ payload: "pageType~cardGrid" }]
          out_msgs.push({ payload: GeneratePageElements(page) });
          return out_msgs
      }
      
      function GeneratePageElements(page: Page): string {
          let maxItems = 0;
          switch (page.type) {
              case "cardThermo":
                  maxItems = 1;
                  break;
              case "cardAlarm":
                  maxItems = 1;
                  break;
              case "cardMedia":
                  maxItems = 1;
                  break;
              case "cardEntities":
                  maxItems = 4;
                  break;
              case "cardGrid":
                  maxItems = 6;
                  break;
          }
          let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId)
          for (let index = 0; index < maxItems; index++) {
              if (page.items[index] !== undefined) {
                  pageData += CreateEntity(page.items[index], index + 1, page.useColor);
              }
              else {
                  pageData += CreateEntity(<PageItem>{ id: "delete" }, index + 1);
              }
          }
          return pageData;
      }
      
      function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = false): string {
          var iconId = "0"
          if (pageItem.id == "delete") {
              return "~delete~~~~~"
          }
          var name: string;
          var type: string;
      
          // ioBroker
          if (existsObject(pageItem.id)) {
              let o = getObject(pageItem.id)
              var val = null;
              name = pageItem.name !== undefined ? pageItem.name : o.common.name.de
      
              if (existsState(pageItem.id + ".GET")) {
                  val = getState(pageItem.id + ".GET").val;
                  RegisterEntityWatcher(pageItem.id + ".GET");
              }
              else if (existsState(pageItem.id + ".SET")) {
                  val = getState(pageItem.id + ".SET").val;
                  RegisterEntityWatcher(pageItem.id + ".SET");
              }
              var iconColor = rgb_dec565(config.defaultColor);
      
              switch (o.common.role) {
                  
                  case "socket":
                  
                  case "light":
                      type = "light"
                      iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "socket"  ? Icons.GetIcon("power-socket-de") : Icons.GetIcon("lightbulb");
                      var optVal = "0"
      
                      if (val === true || val === "true") {
                          optVal = "1"
                          iconColor = GetIconColor(pageItem, true, useColors);
                      } else {
                          iconColor = GetIconColor(pageItem, false, useColors);
                      }
      
                      return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal;
      
                  case "hue":
      
                      type = "light"
                      iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb");
                      var optVal = "0"
      
                      if (existsState(pageItem.id + ".ON_ACTUAL")) {
                          val = getState(pageItem.id + ".ON_ACTUAL").val;
                          RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL");
                      }
      
                      if (val === true || val === "true") {
                          optVal = "1"
                          iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ON") ? getState(pageItem.id + ".ON").val : true, useColors);
                      }
      
                      return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal;
      
                  case "dimmer":
                      type = "light"
                      iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb");
                      var optVal = "0"
                      if (existsState(pageItem.id + ".ON_ACTUAL")) {
                          val = getState(pageItem.id + ".ON_ACTUAL").val;
                          RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL");
                      }
                      else if (existsState(pageItem.id + ".ON_SET")) {
                          val = getState(pageItem.id + ".ON_SET").val;
                          RegisterEntityWatcher(pageItem.id + ".ON_SET");
                      }
                      if (val === true || val === "true") {
                          optVal = "1"
                          iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors);
                      }
      
                      return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal;
                      
                  case "blind":
                      type = "shutter"
                      iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("window-open");
                      iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors);
                      return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~"
      
                  case "door":
      
                  case "window":
                      type = "text";
                      if (existsState(pageItem.id + ".ACTUAL")) {
                          if (getState(pageItem.id + ".ACTUAL").val) {
                              iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door"  ? Icons.GetIcon("door-open") : Icons.GetIcon("window-open-variant");
                              iconColor = GetIconColor(pageItem, false, useColors);
                              var windowState = "opened"
                          } else {
                              iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door"  ? Icons.GetIcon("door-closed") : Icons.GetIcon("window-closed-variant");
                              //iconId = Icons.GetIcon("window-closed-variant");
                              iconColor = GetIconColor(pageItem, true, useColors);
                              var windowState = "closed"
                          }
                          RegisterEntityWatcher(pageItem.id + ".ACTUAL");
                      }
                      return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + windowState;
      
                  case "info":
      
                  case "humidity":
      
                  case "value.temperature":
      
                  case "value.humidity":
      
                  case "sensor.door": 
      
                  case "sensor.window":
                      
                  case "thermostat":
                      type = "text";
                      iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "value.temperature" || o.common.role == "thermostat" ? Icons.GetIcon("thermometer") : Icons.GetIcon("information-outline");
                      let unit = "";
                      var optVal = "0"
                      if (existsState(pageItem.id + ".ON_ACTUAL")) {
                          optVal = getState(pageItem.id + ".ON_ACTUAL").val;
                          unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL");
                          RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL");
                      }
                      else if (existsState(pageItem.id + ".ACTUAL")) {
                          optVal = getState(pageItem.id + ".ACTUAL").val;
                          unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ACTUAL");
                          RegisterEntityWatcher(pageItem.id + ".ACTUAL");
                      }
      
                      if (o.common.role == "value.temperature") {
                          iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("thermometer");
                      }
      
                      iconColor = GetIconColor(pageItem, parseInt(optVal), useColors);
      
                      return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal + " " + unit;
      
                  case "button":
                      type = "button";
                      iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("gesture-tap-button");
                      let buttonText = pageItem.name !== undefined ? pageItem.name : "PRESS";
                      iconColor = GetIconColor(pageItem, true, useColors);
                      return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + buttonText;
      
                  case "warning":
                      type = "text";
                      iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("alert-outline");
                      iconColor = getState(([pageItem.id,'.LEVEL'].join(''))).val;
                      let itemName = getState(([pageItem.id,'.TITLE'].join(''))).val;
                      let itemInfo = getState(([pageItem.id,'.INFO'].join(''))).val;
                      return "~" + type + "~" + itemName + "~" + iconId + "~" + iconColor + "~" + itemName + "~" + itemInfo;
      
                  default:
                      return "~delete~~~~~";
              }
          }
          return "~delete~~~~~"
      }
      
      function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: boolean): number {
          // dimmer
          if ((pageItem.useColor || useColors) && pageItem.interpolateColor && typeof (value) === "number") {
              let maxValue = pageItem.maxValue !== undefined ? pageItem.maxValue : 100;
              let minValue = pageItem.minValue !== undefined ? pageItem.minValue : 0;
      		let maxValueBRI = pageItem.maxValueBRI !== undefined ? pageItem.maxValueBRI : 100;
              let minValueBRI = pageItem.minValueBRI !== undefined ? pageItem.minValueBRI : 0;
              value = value > maxValue ? maxValue : value;
              value = value < minValue ? minValue : value;
      		value = value > maxValueBRI ? maxValueBRI : value;
              value = value < minValueBRI ? minValueBRI : value;
              return rgb_dec565(
                  Interpolate(
                      pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor,
                      pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor,
                      scale(value, minValue, maxValue, 0, 1),
      				scale(value, minValueBRI, maxValueBRI, 0, 1)
                  ));
          }
      
          if ((pageItem.useColor || useColors) && ((typeof (value) === "boolean" && value) || value > (pageItem.minValue !== undefined ? pageItem.minValue : 0))) {
              return rgb_dec565(pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor)
          }
          
          return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor);
      }
      
      function RegisterEntityWatcher(id: string): void {
          if (subscriptions.hasOwnProperty(id)) {
              return;
          }
          subscriptions[id] = (on({ id: id, change: 'any' }, function (data) {
              if(pageId >= 0)
                  SendToPanel({ payload: GeneratePageElements(config.pages[pageId]) });
              if(pageId == -1 && config.button1Page != undefined)
                  SendToPanel({ payload: GeneratePageElements(config.button1Page) });
              if(pageId == -2 && config.button2Page != undefined)
                  SendToPanel({ payload: GeneratePageElements(config.button2Page) });
          }))
      }
      
      function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void {
          if (subscriptions.hasOwnProperty(id)) {
              return;
          }
          subscriptions[id] = (on({ id: id, change: 'any' }, function () {
              SendToPanel(GenerateDetailPage(type, pageItem));
          }))
      }
      
      function GetUnitOfMeasurement(id: string): string {
          if (!existsObject(id))
              return "";
      
          let obj = getObject(id);
          if (typeof obj.common.unit !== 'undefined') {
              return obj.common.unit
          }
      
          if (typeof obj.common.alias !== 'undefined' && typeof obj.common.alias.id !== 'undefined') {
              return GetUnitOfMeasurement(obj.common.alias.id);
          }
          return "";
      }
      
      function GenerateThermoPage(page: PageThermo): Payload[] {
          var id = page.items[0].id
          var out_msgs: Array<Payload> = [];
          out_msgs.push({ payload: "pageType~cardThermo" });
      
          // ioBroker
          if (existsObject(id)) {
              let o = getObject(id)
              let name = page.items[0].name !== undefined ? page.items[0].name : o.common.name.de
              let currentTemp = 0;
              if (existsState(id + ".ACTUAL"))
                  currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10)*10;
      
              let destTemp = 0;
              if (existsState(id + ".SET")) {
                  destTemp = getState(id + ".SET").val.toFixed(2) * 10;
              }
      
              let status = ""
              if (existsState(id + ".MODE"))
                  status = getState(id + ".MODE").val;
              let minTemp = 50 //Min Temp 5°C
              let maxTemp = 300 //Max Temp 30°C
              let stepTemp = 5
      
              //0-4 verwendet bei ungerader Anzahl Parametern
              let bt0 = "~~~~"; //verwendet bei ungleichen Parametern
              let bt1 = "~~~~"; //verwendet bei ungleichen Parametern
              let bt2 = "~~~~"; //verwendet bei ungleichen Parametern
              let bt3 = "~~~~"; //verwendet bei ungleichen Parametern
              let bt4 = "~~~~"; //verwendet bei ungleichen Parametern
              //5-8 verwendet bei gerader Anzahl Parametern
              let bt5 = Icons.GetIcon("water-percent") + "~0~1~~";    
              let bt6 = Icons.GetIcon("fire") + "~0~1~~";             
              let bt7 = Icons.GetIcon("wifi") + "~0~1~~";             
              let bt8 = Icons.GetIcon("battery-high") + "~0~1~~";     
      
              if (existsState(id + ".HUMIDITY")){
                  bt5 =  Icons.GetIcon("water-percent") + "~2016~1~bt8~";
                  if (parseInt(getState(id + ".HUMIDITY").val) < 40) {
                      bt5 =  Icons.GetIcon("water-percent") + "~65504~1~bt8~";
                  } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) {
                      bt5 =  Icons.GetIcon("water-percent") + "~63488~1~bt8~";
                  } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) {
                      bt5 =  Icons.GetIcon("water-percent") + "~65504~1~bt8~";
                  } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) {
                      bt5 =  Icons.GetIcon("water-percent") + "~63488~1~bt8~";
                  }
              }
      
              if (existsState(id + ".MAINTAIN")){
                  if (getState(id + ".MAINTAIN").val >> .1) {
                      bt6 =  Icons.GetIcon("fire") + "~60897~1~bt8~";
                  } else {
                      bt6 =  Icons.GetIcon("fire") + "~33840~0~bt8~";
                  }
              }
      
              if (existsState(id + ".UNREACH")){
                  if (getState(id + ".UNREACH").val) {
                      bt7 =  Icons.GetIcon("wifi-off") + "~63488~1~bt8~";
                  } else {
                      bt7 =  Icons.GetIcon("wifi") + "~2016~1~bt8~";
                  }
              }
      
              if (existsState(id + ".LOWBAT")){
                  if (getState(id + ".LOWBAT").val) {
                      bt8 =  Icons.GetIcon("battery-low") + "~63488~1~bt8~";
                  } else {
                      bt8 =  Icons.GetIcon("battery-high") + "~2016~1~bt8~";
                  }
              }
      
              let icon_res = bt0 + bt1 + bt2 + bt3 + bt4 + bt5 + bt6 + bt7 + bt8;
      
              out_msgs.push({ payload: "entityUpd~" + name + "~" + GetNavigationString(pageId) + "~" + id + "~" + currentTemp + "~" + destTemp + "~" + status + "~" + minTemp + "~" + maxTemp + "~" + stepTemp + "~" +icon_res})
          }
      
          return out_msgs
      }
      
      function GenerateMediaPage(page: PageMedia): Payload[] {
          var id = page.items[0].id
          var out_msgs: Array<Payload> = [];
          out_msgs.push({ payload: "pageType~cardMedia" });
          if (existsObject(id)) {
      
              let name = getState(id + ".ALBUM").val;     
              let media_icon = Icons.GetIcon("playlist-music");
              let title = getState(id + ".TITLE").val;
              let author = getState(id + ".ARTIST").val;
              let volume = getState(id + ".VOLUME").val;
              var iconplaypause = Icons.GetIcon("pause"); //pause
              var onoffbutton = 1374;
              if (getState(id + ".STATE").val) {
                  onoffbutton = 65535;
                  iconplaypause = Icons.GetIcon("pause"); //pause
              } else {
                  iconplaypause = Icons.GetIcon("play"); //play
              }
              let currentSpeaker = getState(([alexaInstanz,'.Echo-Devices.',alexaDevice,'.Info.name'].join(''))).val;
              //console.log(id);
                      
      //-------------------------------------------------------------------------------------------------------------
      // nachfolgend alle Alexa-Devices (ist Online / Player- und Commands-Verzeichnis vorhanden) auflisten und verketten
      // Wenn Konstante alexaSpeakerList mind. einen Eintrag enthält, wird die Konstante verwendet - ansonsten Alle Devices aus dem Alexa Adapter
              let speakerlist = "";
              if (alexaSpeakerList.length > 0) {
                  for (let i_index in alexaSpeakerList) {
                      speakerlist = speakerlist + alexaSpeakerList[i_index] + "?";
                  } 
              } else {        
                  let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]'));
                  for (let i_index in i_list) {
                      let i = i_list[i_index];
                      let deviceId = i;
                      deviceId = deviceId.split('.');
                      if (getState(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.online'].join(''))).val && 
                          existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Player'].join(''))) &&
                          existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Commands'].join('')))) {
                              speakerlist = speakerlist + getState(i).val + "?";
                      }
                  }
              }
              speakerlist = speakerlist.substring(0,speakerlist.length-1);
      //--------------------------------------------------------------------------------------------------------------
      
              out_msgs.push({ payload: "entityUpd~" + 
                                        name + "~" +
                                        id + "~" +
                                        id + "~" +         //????
                                        media_icon + "~" +
                                        title + "~" +
                                        author + "~" +
                                        volume + "~" +
                                        iconplaypause + "~" +
                                        currentSpeaker + "~" +
                                        speakerlist + "~" +
                                        onoffbutton});
          }
      
          return out_msgs
      }
      
      function GenerateAlarmPage(page: PageAlarm): Payload[] {
          var id = page.items[0].id
          var out_msgs: Array<Payload> = [];
          out_msgs.push({ payload: "pageType~cardAlarm" });
      
          var armed: boolean = true;
          
          if (armed) {
              var arm1 = "Deaktivieren";                  //arm1*~*
              var arm1ActionName = "D1";                  //arm1ActionName*~*
              var arm2 = "";                              //arm2*~*
              var arm2ActionName = "";                    //arm2ActionName*~*
              var arm3 = "";                              //arm3*~*
              var arm3ActionName = "";                    //arm3ActionName*~*
              var arm4 = "";                              //arm4*~*
              var arm4ActionName = "";                    //arm4ActionName*~*
              var icon = Icons.GetIcon("shield-home");    //icon*~*
              var iconcolor = 63488;                      //iconcolor*~*
              var numpadStatus = 1;                       //numpadStatus*~*
              var flashing = 1;                           //flashing*
          } 
          else {
              var arm1 = "Alarm 1";                       //arm1*~*
              var arm1ActionName = "A1";                  //arm1ActionName*~*
              var arm2 = "Alarm 2";                       //arm2*~*
              var arm2ActionName = "A2";                  //arm2ActionName*~*
              var arm3 = "Alarm 3";                       //arm3*~*
              var arm3ActionName = "A3";                  //arm3ActionName*~*
              var arm4 = "Alarm 4";                       //arm4*~*
              var arm4ActionName = "A4";                  //arm4ActionName*~*
              var icon = Icons.GetIcon("shield-off");     //icon*~*
              var iconcolor = 2016;                       //iconcolor*~*
              var numpadStatus = 1;                       //numpadStatus*~*
              var flashing = 1;                           //flashing*        
          }
              
          out_msgs.push({ payload:    "entityUpd~" +             //entityUpd~*
                                      id + "~" +                 //internalNameEntity*~* //navigation*~*
                                      "~" +                      //???
                                      arm1 + "~" +               //arm1*~*
                                      arm1ActionName + "~" +     //arm1ActionName*~*
                                      arm2 + "~" +               //arm2*~*
                                      arm2ActionName + "~" +     //arm2ActionName*~*
                                      arm3 + "~" +               //arm3*~*
                                      arm3ActionName + "~" +     //arm3ActionName*~*
                                      arm4 + "~" +               //arm4*~*
                                      arm4ActionName + "~" +     //arm4ActionName*~*
                                      icon + "~" +               //icon*~* 39=Disarmed 35=Shield_Home, 40
                                      iconcolor + "~" +          //iconcolor*~* 2016=green  63488=red
                                      numpadStatus + "~" +       //numpadStatus*~*
                                      flashing});                //flashing*
      
          return out_msgs
      }
      
      function setIfExists(id: string, value: any, type: string | null = null): boolean {
          if (type === null) {
              if (existsState(id)) {
                  setState(id, value);
                  return true;
              }
          }
          else {
              let obj = getObject(id);
              if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) {
                  setState(id, value);
                  return true;
              }
          }
          return false;
      }
      
      function toggleState(id: string): boolean {
          let obj = getObject(id);
          if (existsState(id) && obj.common.type !== undefined && obj.common.type === "boolean") {
              setState(id, !getState(id).val);
              return true;
          }
          return false;
      }
      
      function HandleButtonEvent(words): void {
          let id = words[2]
          let buttonAction = words[3];
      
          console.log(words[0] + " - " + words[1] + " - " + words[2] + " - " + words[3] + " - " + words[4] + " - PageId: " + pageId);
      
          switch (buttonAction) {
              case "bNext":
                  var pageNum = ((pageId + 1) % config.pages.length);
                  pageId = Math.abs(pageNum);
                  UnsubscribeWatcher();
                  GeneratePage(config.pages[pageId]);
                  break;
              case "bPrev":
                  var pageNum = ((pageId - 1) % config.pages.length);
                  pageId = Math.abs(pageNum);
                  UnsubscribeWatcher();
                  GeneratePage(config.pages[pageId]);
                  break;
              case "bExit":
                  if (config.screenSaverDoubleClick) {
                      if (words[4] == 2)
                          GeneratePage(config.pages[pageId]);
                  }
                  else
                      GeneratePage(config.pages[pageId]);
                  break;
              case "OnOff":
                  if (existsObject(id)) {
                      var action = false
                      if (words[4] == "1")
                          action = true
                      let o = getObject(id)
                      switch (o.common.role) {
                          case "light":
                              setIfExists(id + ".SET", action);
                              break;
                          case "dimmer":
                              setIfExists(id + ".ON_SET", action) ? true : setIfExists(id + ".ON_ACTUAL", action);
                              break;
                          case "hue": // Armilar
                              setIfExists(id + ".ON_ACTUAL", action);
                      }
                  }
                  break;
              case "up":
                  setIfExists(id + ".OPEN", true)
                  break;
              case "stop":
                  setIfExists(id + ".STOP", true)
                  break;
              case "down":
                  setIfExists(id + ".CLOSE", true)
                  break;
              case "button":
                  toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET")
                  break;
              case "positionSlider":
                  setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4]));
                  break;
              case "brightnessSlider":
                  if (existsObject(id)) {
                      let o = getObject(id);
                      let pageItem = config.pages[pageId].items.find(e => e.id === id);
                      switch (o.common.role) {
                          case "dimmer":
                              if (pageItem.minValue != undefined && pageItem.maxValue != undefined) {  
                                  let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValue, pageItem.minValue))
                                  setIfExists(id + ".SET", sliderPos) ? true : setIfExists(id + ".ACTUAL", sliderPos);
                              } else {
                                  setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4]));
                              }
                              break;
                          case "hue":
      					    if (pageItem.minValueBRI != undefined && pageItem.maxValueBRI != undefined) {  
                                  let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValueBRI, pageItem.minValueBRI))
                                  setIfExists(id + ".DIMMER", parseInt(words[4]));
                      }
                  }
                  break;
              case "colorTempSlider": // Armilar - Slider tickt verkehrt - Hell = 0 / Dunkel = 100 -> Korrektur
                  let pageItem = config.pages[pageId].items.find(e => e.id === id);
                  if (pageItem.minValue !== undefined && pageItem.minValue !== undefined) {
                      let colorTempK = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.minValue, pageItem.maxValue));
                      setIfExists(id + ".TEMPERATURE", (colorTempK));
                  } else {
                      setIfExists(id + ".TEMPERATURE", 100 - words[4]);
                  }
                  break;
              case "colorWheel":
                  let colorCoordinates = words[4].split('|');
                  let rgb = pos_to_color(colorCoordinates[0], colorCoordinates[1]);
                  //console.log(rgb);
                  //console.log(getHue(rgb.red, rgb.green, rgb.blue));
                  setIfExists(id + ".HUE", getHue(rgb.red, rgb.green, rgb.blue));
                  break;
              case "tempUpd":
                  setIfExists(id + ".SET", parseInt(words[4]) / 10)
                  break;
              case "media-back":
                  setIfExists(id + ".PREV", true)
                  break;
              case "media-pause":
                  if (getState(id + ".STATE").val === true) {
                      setIfExists(id + ".PAUSE", true)
                  } else {
                      setIfExists(id + ".PLAY", true)
                  }
                  break;
              case "media-next":
                  setIfExists(id + ".NEXT", true)
                  break;
              case "volumeSlider":
                  setIfExists(id + ".VOLUME", parseInt(words[4]))
                  break;
              case "speaker-sel":
                  let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]'));
                  for (let i_index in i_list) {
                      let i = i_list[i_index];
                      if ((getState(i).val) === words[4]){
                          let deviceId = i;
                          deviceId = deviceId.split('.');
                          setIfExists(alexaInstanz + ".Echo-Devices." + alexaDevice + ".Commands.textCommand", "Schiebe meine Musik auf " + words[4]);
                          alexaDevice = deviceId[3]
                      }
                  }
                  break;
              case "media-OnOff":
                  setIfExists(id + ".STOP", true)
                  break;
                  
              case "A1": //Alarm-Page Alarm 1 aktivieren
                  console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert");
                  break;
              case "A2": //Alarm-Page Alarm 2 aktivieren
                  console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert");
                  break;  
              case "A3": //Alarm-Page Alarm 3 aktivieren
                  console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert");
                  break;  
              case "A4": //Alarm-Page Alarm 4 aktivieren
                  console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert");
                  break;         
              case "D1": //Alarm-Page Alarm Deaktivieren
                  console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert");
                  break;  
              default:
                  break;
          }
      }
      
      function GetNavigationString(pageId: number): string {
          switch (pageId) {
              case 0:
                  return "0|1";
              case config.pages.length - 1:
                  return "1|0";
              case -1:
                  return "0|0";
              default:
                  return "1|1";
          }
      }
      
      function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] {
      
          var out_msgs: Array<Payload> = [];
          let id = pageItem.id
          if (existsObject(id)) {
              var o = getObject(id)
              var val: (boolean | number) = 0;
              let icon = Icons.GetIcon("lightbulb");
              var iconColor = rgb_dec565(config.defaultColor);
              if (type == "popupLight") {
                  let switchVal = "0"
                  if (o.common.role == "light") {
                      if (existsState(id + ".GET")) {
                          val = getState(id + ".GET").val;
                          RegisterDetailEntityWatcher(id + ".GET", pageItem, type);
                      }
                      else if (existsState(id + ".SET")) {
                          val = getState(id + ".SET").val;
                          RegisterDetailEntityWatcher(id + ".SET", pageItem, type);
                      }
      
                      if (val) {
                          switchVal = "1";
                          iconColor = GetIconColor(pageItem, true, false);
                      }
      
                      out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + + iconColor + "~" + switchVal + ",disable,disable,disable" })
                  }
      
                  if (o.common.role == "dimmer") {
                      if (existsState(id + ".ON_ACTUAL")) {
                          val = getState(id + ".ON_ACTUAL").val;
                          RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type);
                      }
      
                      else if (existsState(id + ".ON_SET")) {
                          val = getState(id + ".ON_SET").val;
                          RegisterDetailEntityWatcher(id + ".ON_SET", pageItem, type);
                      }
      
                      if (val === true) {
                          var iconColor = GetIconColor(pageItem, val, false);
                          switchVal = "1"
                      }
                      let brightness = 0;
                      if (existsState(id + ".ACTUAL")) {
                          if (pageItem.minValue != undefined && pageItem.maxValue != undefined) {
                              brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, pageItem.minValue, pageItem.maxValue, 100, 0));
                          } else {
                              brightness = getState(id + ".ACTUAL").val;
                          }
                      } else {
                          console.warn("Datenpunkt: " + id + ".DIMMER kann nicht gelesen werden");
                      }
                      //iconColor = GetIconColor(pageItem, brightness, false);
                      //Farbe muss noch korrekt ermittelt werden
                      if (val === true) {
                          iconColor = GetIconColor(pageItem, true, true);
                          switchVal = "1";
                      } else {
                          iconColor = GetIconColor(pageItem, false, true);
                      }
      
                      RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type);
                      
                      let colorTemp = "disable"
                      let colorMode = "disable"
                      //let attr_support_color = attr.supported_color_modes
                      //if (attr_support_color.includes("color_temp"))
                      // colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100))
                      out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode })
                  }
      
                  if (o.common.role == "hue") {
                      if (existsState(id + ".ON_ACTUAL")) {
                          val = getState(id + ".ON_ACTUAL").val;
                          RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type);
                      }
      
                      //Farbe muss noch korrekt ermittelt werden
                      if (val === true) {
                          iconColor = GetIconColor(pageItem, true, true);
                          switchVal = "1";
                      } else {
                          iconColor = GetIconColor(pageItem, false, true);
                      }
      
                      let brightness = 0;
                      if (existsState(id + ".DIMMER")) {
      					if (pageItem.minValueBRI !== undefined && pageItem.minValueBRI !== undefined) {
                          brightness = Math.trunc(scale2(getState(id + ".DIMMER").val, 0, 100, 0, 100));
                          RegisterDetailEntityWatcher(id + ".DIMMER", pageItem, type);
                      } else {
                          console.warn("Datenpunkt: " + id + ".DIMMER kann nicht gelesen werden");
                      }
      
                      var colorMode = "disable";
                      if (existsState(id + ".HUE")) {
                          if (getState(id + ".HUE").val != null)
                              colorMode = "enable";  
                      }
      
                      var colorTemp = 0;
                      if (existsState(id + ".TEMPERATURE")) {
                          if (getState(id + ".TEMPERATURE").val != null) {
      
                              if (pageItem.minValue !== undefined && pageItem.minValue !== undefined) {
                                  colorTemp = Math.trunc(scale(getState(id + ".TEMPERATURE").val, pageItem.minValue, pageItem.maxValue, 0, 100));
                              } else {
                                  colorTemp = 100 - getState(id + ".TEMPERATURE").val;
                              }
                              RegisterDetailEntityWatcher(id + ".TEMPERATURE", pageItem, type);
                          } 
                      }
      
                      //let attr_support_color = attr.supported_color_modes
                      //if (attr_support_color.includes("color_temp"))
                      //let colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100))
      
                      out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode })
                  }
      
              }
      
              if (type == "popupShutter") {
                  if (existsState(id + ".ACTUAL")) {
                      val = getState(id + ".ACTUAL").val;
                      RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type);
                      console.log(val);
                  } else if (existsState(id + ".SET")) {
                      val = getState(id + ".SET").val;
                      RegisterDetailEntityWatcher(id + ".SET", pageItem, type);
                      console.log(val);
                  }
                  out_msgs.push({ payload: "entityUpdateDetail~" + val })
              }
          }
          return out_msgs
      }
      
      function scale(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number {
          return (outMax+outMin)-((number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin);
      }
      
      function scale2(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number {
          return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
      }
      
      function UnsubscribeWatcher(): void {
          for (const [key, value] of Object.entries(subscriptions)) {
              unsubscribe(value);
              delete subscriptions[key]
          }
      }
      
      function HandleScreensaver(): void {
          SendToPanel({ payload: "pageType~screensaver"})
          UnsubscribeWatcher();
          HandleScreensaverUpdate();
      }
      
      function HandleScreensaverUpdate(): void {
          if (screensaverEnabled && config.weatherEntity != null && existsObject(config.weatherEntity)) {
              var icon = getState(config.weatherEntity + ".ICON").val;
       
              let temperature: string =
                  existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val :
                      existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val : "null";
       
              let payloadString =
                  "weatherUpdate~" + Icons.GetIcon(GetAccuWeatherIcon(parseInt(icon))) + "~"
                  + temperature + " " + config.temperatureUnit + "~"
       
      /*-------------------------------------------------------------------------------------------------------------------------------------*/
              if (weatherForecast == true) {
                  // Accu-Weather Forecast Tag 2 - Tag 5 -- Wenn weatherForecast = true
                  for (let i = 2; i < 6; i++) {
                      let TempMax = getState("accuweather.0.Summary.TempMax_d" + i).val;
                      let DayOfWeek = getState("accuweather.0.Summary.DayOfWeek_d" + i).val;
                      let WeatherIcon = GetAccuWeatherIcon(getState("accuweather.0.Summary.WeatherIcon_d" + i).val);
                      payloadString += DayOfWeek + "~" + Icons.GetIcon(WeatherIcon) + "~" + TempMax + " °C~";
                  }
              } 
              else {
                  //In Config definierte Zustände wenn weatherForecast = false
                  payloadString += GetScreenSaverEntityString(config.firstScreensaverEntity);
                  payloadString += GetScreenSaverEntityString(config.secondScreensaverEntity);
                  payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity);
                  payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity);
              }
      /*-------------------------------------------------------------------------------------------------------------------------------------*/
       
              SendToPanel(<Payload>{ payload: payloadString });
          }
      }
      
      function GetScreenSaverEntityString(configElement: ScreenSaverElement | null): string {
          if (configElement != null && configElement.ScreensaverEntity != null && existsState(configElement.ScreensaverEntity)) {
              let u1 = getState(configElement.ScreensaverEntity).val;
              return configElement.ScreensaverEntityText + "~" + Icons.GetIcon(configElement.ScreensaverEntityIcon) + "~" + u1 + " " + configElement.ScreensaverEntityUnitText + "~";
          }
          else {
              return "~~~";
          }
      }
      
      function GetAccuWeatherIcon(icon: number): string {
          switch (icon) {
              case 24:        // Ice        
              case 30:        // Hot    
              case 31:        // Cold    
                  return "window-open";  // exceptional
      
              case 7:         // Cloudy
              case 8:         // Dreary (Overcast)        
              case 38:        // Mostly Cloudy
                  return "weather-cloudy";  // cloudy
      
              case 11:        // fog
                  return "weather-fog";  // fog
      
              case 25:        // Sleet    
                  return "weather-hail";  // Hail
      
              case 15:        // T-Storms    
                  return "weather-lightning";  // lightning
      
              case 16:        // Mostly Cloudy w/ T-Storms
              case 17:        // Partly Sunny w/ T-Storms
              case 41:        // Partly Cloudy w/ T-Storms       
              case 42:        // Mostly Cloudy w/ T-Storms
                  return "weather-lightning-rainy";  // lightning-rainy
      
              case 33:        // Clear
              case 34:        // Mostly Clear
              case 37:        // Hazy Moonlight
                  return "weather-night";
      
              case 3:         // Partly Sunny
              case 4:         // Intermittent Clouds
              case 6:         // Mostly Cloudy
              case 35: 	    // Partly Cloudy
              case 36: 	    // Intermittent Clouds
                  return "weather-partly-cloudy";  // partlycloudy 
      
              case 18:        // pouring
                  return "weather-pouring";  // pouring
      
              case 12:        // Showers
              case 13:        // Mostly Cloudy w/ Showers
              case 14:        // Partly Sunny w/ Showers      
              case 26:        // Freezing Rain
              case 39:        // Partly Cloudy w/ Showers
              case 40:        // Mostly Cloudy w/ Showers
                  return "weather-rainy";  // rainy
      
              case 19:        // Flurries
              case 20:        // Mostly Cloudy w/ Flurries
              case 21:        // Partly Sunny w/ Flurries
              case 22:        // Snow
              case 23:        // Mostly Cloudy w/ Snow
              case 43:        // Mostly Cloudy w/ Flurries
              case 44:        // Mostly Cloudy w/ Snow
                  return "weather-snowy";  // snowy
      
              case 29:        // Rain and Snow
                  return "weather-snowy-rainy";  // snowy-rainy
      
              case 1:         // Sunny
              case 2: 	    // Mostly Sunny
              case 5:         // Hazy Sunshine
                  return "weather-sunny";  // sunny
      
              case 32:        // windy
                  return "weather-windy";  // windy
      
              default:
                  return "alert-circle-outline";
          }
      }
      
      function sleep(milliseconds) {
        const date = Date.now();
        let currentDate = null;
        do {
          currentDate = Date.now();
        } while (currentDate - date < milliseconds);
      }
      
      function GetBlendedColor(percentage: number): RGB {
          if (percentage < 50)
              return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0);
          return Interpolate(Red, White, (percentage - 50) / 50.0);
      }
      
      function Interpolate(color1: RGB, color2: RGB, fraction: number): RGB {
          var r: number = InterpolateNum(color1.red, color2.red, fraction);
          var g: number = InterpolateNum(color1.green, color2.green, fraction);
          var b: number = InterpolateNum(color1.blue, color2.blue, fraction);
          return <RGB>{ red: Math.round(r), green: Math.round(g), blue: Math.round(b) };
      }
      
      function InterpolateNum(d1: number, d2: number, fraction: number): number {
          return d1 + (d2 - d1) * fraction;
      }
      
      function rgb_dec565(rgb: RGB): number {
          return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31)));
      }
      
      /* Convert radians to degrees
      rad - radians to convert, expects rad in range +/- PI per Math.atan2
      returns {number} degrees equivalent of rad
      */
      function rad2deg(rad) {
        return (360 + 180 * rad / Math.PI) % 360;
      }
      
      /* Convert h,s,v values to r,g,b
      hue - in range [0, 360]
      saturation - in range 0 to 1
      value - in range 0 to 1
      returns {Array|number} [r, g,b] in range 0 to 255
       */
      function hsv2rgb(hue: number, saturation: number, value: number) {
        hue /= 60;
        let chroma = value * saturation;
        let x = chroma * (1 - Math.abs((hue % 2) - 1));
        let rgb = hue <= 1? [chroma, x, 0]:
                  hue <= 2? [x, chroma, 0]:
                  hue <= 3? [0, chroma, x]:
                  hue <= 4? [0, x, chroma]:
                  hue <= 5? [x, 0, chroma]:
                            [chroma, 0, x];
      
        return rgb.map(v => (v + value - chroma) * 255);
      }
      
      function getHue(red: number, green: number, blue:number) {
      
          var min = Math.min(Math.min(red, green), blue);
          var max = Math.max(Math.max(red, green), blue);
      
          if (min == max) {
              return 0;
          }
      
          var hue = 0;
          if (max == red) {
              hue = (green - blue) / (max - min);
      
          } else if (max == green) {
              hue = 2 + (blue - red) / (max - min);
      
          } else {
              hue = 4 + (red - green) / (max - min);
          }
      
          hue = hue * 60;
          if (hue < 0) hue = hue + 360;
      
          return Math.round(hue);
      }
      
      function pos_to_color(x: number, y: number): RGB { 
          var r = 160/2;
          var x = Math.round((x - r) / r * 100) / 100;
          var y = Math.round((r - y) / r * 100) / 100;
          
          r = Math.sqrt(x*x + y*y);
          let sat = 0
          if (r > 1) {
              sat = 0;
          } else {
              sat = r;
          }
      
          var hsv = rad2deg(Math.atan2(y, x));
          var rgb = hsv2rgb(hsv,sat,1);
      
          return <RGB>{ red: Math.round(rgb[0]), green: Math.round(rgb[1]), blue: Math.round(rgb[2]) };
      }
      
      type RGB = {
          red: number,
          green: number,
          blue: number
      };
      
      type Payload = {
          payload: string;
      };
      
      type Page = {
          type: string,
          heading: string,
          items: PageItem[],
          useColor: boolean
      };
      
      interface PageEntities extends Page {
          type: "cardEntities",
          items: PageItem[],
      
      };
      interface PageGrid extends Page {
          type: "cardGrid",
          items: PageItem[],
      };
      
      interface PageThermo extends Page {
          type: "cardThermo",
          items: PageItem[],
      };
      
      interface PageMedia extends Page {
          type: "cardMedia",
          items: PageItem[],
      };
      
      interface PageAlarm extends Page {
          type: "cardAlarm",
          items: PageItem[],
      };
      
      type PageItem = {
          id: string,
          icon: (string | undefined),
          onColor: (RGB | undefined),
          offColor: (RGB | undefined),
          useColor: (boolean | undefined),
          interpolateColor: (boolean | undefined),
          minValue: (number | undefined),
          maxValue: (number | undefined),
          name: (string | undefined),
          unit: (string | undefined)
      }
      
      type Config = {
          panelRecvTopic: string,
          panelSendTopic: string,
          timeoutScreensaver: number,
          dimmode: number,
          //brightnessScreensaver:
          locale: string,
          timeFormat: string,
          dateFormat: string,
          weatherEntity: string | null,
          screenSaverDoubleClick: boolean,
          temperatureUnit: string,
          firstScreensaverEntity: ScreenSaverElement | null,
          secondScreensaverEntity: ScreenSaverElement | null,
          thirdScreensaverEntity: ScreenSaverElement | null,
          fourthScreensaverEntity: ScreenSaverElement | null,
          defaultColor: RGB,
          defaultOnColor: RGB,
          defaultOffColor: RGB,
          pages: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid)[],
          button1Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null),
          button2Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null),
      };
      
      type ScreenSaverElement = {
          ScreensaverEntity: string | null,
          ScreensaverEntityIcon: string | null,
          ScreensaverEntityText: string | null,
          ScreensaverEntityUnitText: string | null,
      }
      
      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar said in Sonoff NSPanel:

      @dexxter habe die Antwort eben noch erweitert

      Hi @Armilar
      Ich habe eben mal wie Du empfohlen hast den Dimmwert händisch eingegeben und folgendes beobachten können.
      Der Slider wird tatsächlich doch aktualisiert aber genau falsch herum.
      Also wenn ich 5% von Hand eingebe springt der Slider auf 95%
      Bei 20% springt er auf 80% usw.
      Er gibt aber die richtigen Werte raus wenn ich ihn schiebe.
      Also, schiebe ich den Slider auf 20% werden diese auch eingestellt aber der Slider springt dann auf 80%.
      Kurz und knapp......Funktion ist da, Anzeige verkehrt herum.

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar said in Sonoff NSPanel:

      @dexxter sagte in Sonoff NSPanel:

      @armilar
      Ich bin grade dran.
      Aktuell passiert es das der Brightnessslider nicht den eingestellten Wert behält.
      Also, ich schiebe den Slider auf 20%.....gehe dann da raus, wieder rein und der Slider steht auf 100%.
      Der Temperaturslider funktioniert wie er soll.
      EDIT: Das verält sich beim "normalen" Dimmer genau so.

      Ich denke, dass da ein ALIAS noch nicht den Datenpunkt erreicht hat. Habe diverse Lampen unterschiedlichster Art und habe das Verhalten nicht 🙄

      Moin @Armilar ,
      ich hab mir das grade noch mal mit frischem Kopf angeschaut.
      Lustigerweise hat der "normale" Dimmer dieses Verhalten heute nicht mehr aber der "hue".
      Jetzt habe ich mir mal den Code angeschaut und das hier gefunden :
      slider_LI.jpg
      Kann es sein das da der .ACTUAL Wert fehlt?
      Greetz Dexxter

      posted in Hardware
      D
      Dexxter
    • RE: Sonoff NSPanel

      @armilar
      Ich bin grade dran.
      Aktuell passiert es das der Brightnessslider nicht den eingestellten Wert behält.
      Also, ich schiebe den Slider auf 20%.....gehe dann da raus, wieder rein und der Slider steht auf 100%.
      Der Temperaturslider funktioniert wie er soll.
      EDIT: Das verält sich beim "normalen" Dimmer genau so.

      posted in Hardware
      D
      Dexxter
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo