Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

  1. ioBroker Community Home
  2. Deutsch
  3. Tester
  4. Test Adapter iQontrol 2.0.x Vis (Entwicklungs-Thread)

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.4k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.0k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    15
    1
    2.5k

Test Adapter iQontrol 2.0.x Vis (Entwicklungs-Thread)

Geplant Angeheftet Gesperrt Verschoben Tester
appdark-modeiqontrolresponsivevisvisualisierungvisualizationwidget
7.6k Beiträge 296 Kommentatoren 7.0m Aufrufe 201 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • dslraserD dslraser

    @s-bormann sagte in Test Adapter iQontrol 1.3.x:

    iQontrol erzeugt dann die Datenpunkte iqontrol.0.Widgets.Map.Position.latitude, .altitude und .zoom, mit denen man die Position der Karte festlegen kann.
    Mehr geht erst mal noch nicht, aber ich würde mich schon mal freuen, wenn ich Rückmeldung bekäme, dass das so weit bei Euch funktioniert. Dann kann man weitere Funktionen einbauen.

    Erstmal vielen Dank für das einfügen der Karte.👍
    "Grundsätzlich" funktioniert die Karte. Zwei Dinge sind mir aufgefallen:

    • klick auf das minus funktioniert

    • klick auf das plus funktioniert nicht

    (mit zwei Fingern zoomen funktioniert)

    Wo setzt Du in der Karte den Focus für die Koordinaten ? (oben links/oben rechts/ unten links/ unten rechts / zentriert ?) Mit meinen Koordinaten startet die Ansicht bei größerem Zoom immer weit unten links, so das der Standort nicht auf dem Bild zu sehen ist.

    20201011_183605 (1).gif

    s.bormannS Offline
    s.bormannS Offline
    s.bormann
    Most Active
    schrieb am zuletzt editiert von
    #3378

    @dslraser sagte in Test Adapter iQontrol 1.3.x:

    @s-bormann sagte in Test Adapter iQontrol 1.3.x:

    iQontrol erzeugt dann die Datenpunkte iqontrol.0.Widgets.Map.Position.latitude, .altitude und .zoom, mit denen man die Position der Karte festlegen kann.
    Mehr geht erst mal noch nicht, aber ich würde mich schon mal freuen, wenn ich Rückmeldung bekäme, dass das so weit bei Euch funktioniert. Dann kann man weitere Funktionen einbauen.

    Erstmal vielen Dank für das einfügen der Karte.👍
    "Grundsätzlich" funktioniert die Karte. Zwei Dinge sind mir aufgefallen:

    • klick auf das minus funktioniert

    • klick auf das plus funktioniert nicht

    (mit zwei Fingern zoomen funktioniert)

    Wo setzt Du in der Karte den Focus für die Koordinaten ? (oben links/oben rechts/ unten links/ unten rechts / zentriert ?) Mit meinen Koordinaten startet die Ansicht bei größerem Zoom immer weite unten links, so das der Standort nicht auf dem Bild zu sehen ist.

    20201011_183605 (1).gif

    Zum Plus/Minus: Schalte mal die Option "Mauszeiger-Events für das Icon ignorieren" für aktiv, inaktiv und vergrößert ein, ich denke das unsichtbare Geräte-Icon hängt Dir vorm plus-Knopf :)

    Zum Focus: Habe da gerade den Bug gefunden. In der Datei kommt 3 x parseInt vor, das muss parseFloat heißen (sonst wird auf ganzzahlige Koordinaten abgerundet...)...

    Versuche die Datei im ursprünglichen Beitrag zu ändern.

    dslraserD 1 Antwort Letzte Antwort
    1
    • s.bormannS s.bormann

      @dslraser sagte in Test Adapter iQontrol 1.3.x:

      @s-bormann sagte in Test Adapter iQontrol 1.3.x:

      iQontrol erzeugt dann die Datenpunkte iqontrol.0.Widgets.Map.Position.latitude, .altitude und .zoom, mit denen man die Position der Karte festlegen kann.
      Mehr geht erst mal noch nicht, aber ich würde mich schon mal freuen, wenn ich Rückmeldung bekäme, dass das so weit bei Euch funktioniert. Dann kann man weitere Funktionen einbauen.

      Erstmal vielen Dank für das einfügen der Karte.👍
      "Grundsätzlich" funktioniert die Karte. Zwei Dinge sind mir aufgefallen:

      • klick auf das minus funktioniert

      • klick auf das plus funktioniert nicht

      (mit zwei Fingern zoomen funktioniert)

      Wo setzt Du in der Karte den Focus für die Koordinaten ? (oben links/oben rechts/ unten links/ unten rechts / zentriert ?) Mit meinen Koordinaten startet die Ansicht bei größerem Zoom immer weite unten links, so das der Standort nicht auf dem Bild zu sehen ist.

      20201011_183605 (1).gif

      Zum Plus/Minus: Schalte mal die Option "Mauszeiger-Events für das Icon ignorieren" für aktiv, inaktiv und vergrößert ein, ich denke das unsichtbare Geräte-Icon hängt Dir vorm plus-Knopf :)

      Zum Focus: Habe da gerade den Bug gefunden. In der Datei kommt 3 x parseInt vor, das muss parseFloat heißen (sonst wird auf ganzzahlige Koordinaten abgerundet...)...

      Versuche die Datei im ursprünglichen Beitrag zu ändern.

      dslraserD Offline
      dslraserD Offline
      dslraser
      Forum Testing Most Active
      schrieb am zuletzt editiert von dslraser
      #3379

      @s-bormann sagte in Test Adapter iQontrol 1.3.x:

      Zum Plus/Minus: Schalte mal die Option "Mauszeiger-Events für das Icon ignorieren" für aktiv, inaktiv und vergrößert ein, ich denke das unsichtbare Geräte-Icon hängt Dir vorm plus-Knopf
      Zum Focus: Habe da gerade den Bug gefunden. In der Datei kommt 3 x parseInt vor, das muss parseFloat heißen (sonst wird auf ganzzahlige Koordinaten abgerundet...)...

      hat beides funktioniert :+1:

      Jetzt bräuchte es noch die Möglichkeit mehrere User mit eigenen Koordinaten und ein zugehöriges Symbol auf der Karte, dann wäre es schon perfekt für mich.:blush:

      EDIT: @blackeagle998
      auch die Datei map.html hilft vielleicht etwas das ganze Prinzip zu verstehen.

      <!doctype html>
      <html style="width: 100%; height: 100%; margin: 0px;">
      <head>
         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
         <meta name="widget-datapoint" content="Map.Position.latitude" data-type="number" data-role="value.gps.latitude" />
         <meta name="widget-datapoint" content="Map.Position.longitude" data-type="number" data-role="value.gps.longitude" />
         <meta name="widget-datapoint" content="Map.Position.zoom" data-type="number" data-role="value.zoom" />
         <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
         <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
         <title>iQontrol Map Widget</title>
      </head>
      <body style="width: 100%; height: 100%; margin: 0px;">
         <div id="mapid" style="width: 100%; height: 100%; margin: 0px;"></div>
         <script type="text/javascript">
           //Declarations
           var mapPositionLatitude = 20;
           var mapPositionLongitude = 30;
           var mapPositionZoom = 10;
           var mymap = false;
      
           //Subscribe to WidgetDatapoints now
           sendPostMessage("getWidgetStateSubscribed", "Map.Position.latitude");
           sendPostMessage("getWidgetStateSubscribed", "Map.Position.longitude");
           sendPostMessage("getWidgetStateSubscribed", "Map.Position.zoom");
      
           //Initialize map (with timeout to give script the time go get the initial position values)
           setTimeout(function(){
              console.log("Init map: " + mapPositionLatitude + "|" + mapPositionLongitude + "|" + mapPositionZoom);
               mymap = L.map('mapid').setView([mapPositionLatitude, mapPositionLongitude], mapPositionZoom);        
               L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                   'attribution':  'Kartendaten &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> Mitwirkende',
                   'useCache': true
               }).addTo(mymap);
           }, 250);
           
           //Reposition map
           function repositionMap(){
             console.log("Reposition map: " + mapPositionLatitude + "|" + mapPositionLongitude + "|" + mapPositionZoom);
             if(mymap) mymap.setView([mapPositionLatitude, mapPositionLongitude], mapPositionZoom); else console.log("   Abort, map not initialized yet");
           }
           
           //send postMessages
           function sendPostMessage(command, stateId, value){
               message = { command: command, stateId: stateId, value: value };
               window.parent.postMessage(message, "*");
           }
      
           //receive postMessages
           window.addEventListener("message", receivePostMessage, false);
           function receivePostMessage(event) { //event = {data: message data, origin: url of origin, source: id of sending element}
               if(event.data && event.data.command) switch(event.data.command){
                   case "getState":
                       if(event.data.stateId && event.data.value) switch(event.data.stateId){
                         case "Map.Position.latitude":
                           	console.log("Set latitude to " + event.data.value.val);
                         	mapPositionLatitude = parseFloat(event.data.value.val) || 0;
                           	if(mymap) repositionMap();
                         break;
      
                         case "Map.Position.longitude":
                           	console.log("Set longitude to " + event.data.value.val);
                         	mapPositionLongitude = parseFloat(event.data.value.val) || 0;
                           	if(mymap) repositionMap();
                         break;
                           
                         case "Map.Position.zoom":
                           	console.log("Set zoom to " + event.data.value.val);
                         	mapPositionZoom = parseFloat(event.data.value.val) || 0;
                           	if(mymap) repositionMap();
                         break;
                       }
                   break;
               }
           }
         </script>
      </body>
      </html>
      


      20201011_202151.gif

      B dslraserD 2 Antworten Letzte Antwort
      0
      • dslraserD dslraser

        @s-bormann sagte in Test Adapter iQontrol 1.3.x:

        Zum Plus/Minus: Schalte mal die Option "Mauszeiger-Events für das Icon ignorieren" für aktiv, inaktiv und vergrößert ein, ich denke das unsichtbare Geräte-Icon hängt Dir vorm plus-Knopf
        Zum Focus: Habe da gerade den Bug gefunden. In der Datei kommt 3 x parseInt vor, das muss parseFloat heißen (sonst wird auf ganzzahlige Koordinaten abgerundet...)...

        hat beides funktioniert :+1:

        Jetzt bräuchte es noch die Möglichkeit mehrere User mit eigenen Koordinaten und ein zugehöriges Symbol auf der Karte, dann wäre es schon perfekt für mich.:blush:

        EDIT: @blackeagle998
        auch die Datei map.html hilft vielleicht etwas das ganze Prinzip zu verstehen.

        <!doctype html>
        <html style="width: 100%; height: 100%; margin: 0px;">
        <head>
           <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
           <meta name="widget-datapoint" content="Map.Position.latitude" data-type="number" data-role="value.gps.latitude" />
           <meta name="widget-datapoint" content="Map.Position.longitude" data-type="number" data-role="value.gps.longitude" />
           <meta name="widget-datapoint" content="Map.Position.zoom" data-type="number" data-role="value.zoom" />
           <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
           <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
           <title>iQontrol Map Widget</title>
        </head>
        <body style="width: 100%; height: 100%; margin: 0px;">
           <div id="mapid" style="width: 100%; height: 100%; margin: 0px;"></div>
           <script type="text/javascript">
             //Declarations
             var mapPositionLatitude = 20;
             var mapPositionLongitude = 30;
             var mapPositionZoom = 10;
             var mymap = false;
        
             //Subscribe to WidgetDatapoints now
             sendPostMessage("getWidgetStateSubscribed", "Map.Position.latitude");
             sendPostMessage("getWidgetStateSubscribed", "Map.Position.longitude");
             sendPostMessage("getWidgetStateSubscribed", "Map.Position.zoom");
        
             //Initialize map (with timeout to give script the time go get the initial position values)
             setTimeout(function(){
                console.log("Init map: " + mapPositionLatitude + "|" + mapPositionLongitude + "|" + mapPositionZoom);
                 mymap = L.map('mapid').setView([mapPositionLatitude, mapPositionLongitude], mapPositionZoom);        
                 L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                     'attribution':  'Kartendaten &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> Mitwirkende',
                     'useCache': true
                 }).addTo(mymap);
             }, 250);
             
             //Reposition map
             function repositionMap(){
               console.log("Reposition map: " + mapPositionLatitude + "|" + mapPositionLongitude + "|" + mapPositionZoom);
               if(mymap) mymap.setView([mapPositionLatitude, mapPositionLongitude], mapPositionZoom); else console.log("   Abort, map not initialized yet");
             }
             
             //send postMessages
             function sendPostMessage(command, stateId, value){
                 message = { command: command, stateId: stateId, value: value };
                 window.parent.postMessage(message, "*");
             }
        
             //receive postMessages
             window.addEventListener("message", receivePostMessage, false);
             function receivePostMessage(event) { //event = {data: message data, origin: url of origin, source: id of sending element}
                 if(event.data && event.data.command) switch(event.data.command){
                     case "getState":
                         if(event.data.stateId && event.data.value) switch(event.data.stateId){
                           case "Map.Position.latitude":
                             	console.log("Set latitude to " + event.data.value.val);
                           	mapPositionLatitude = parseFloat(event.data.value.val) || 0;
                             	if(mymap) repositionMap();
                           break;
        
                           case "Map.Position.longitude":
                             	console.log("Set longitude to " + event.data.value.val);
                           	mapPositionLongitude = parseFloat(event.data.value.val) || 0;
                             	if(mymap) repositionMap();
                           break;
                             
                           case "Map.Position.zoom":
                             	console.log("Set zoom to " + event.data.value.val);
                           	mapPositionZoom = parseFloat(event.data.value.val) || 0;
                             	if(mymap) repositionMap();
                           break;
                         }
                     break;
                 }
             }
           </script>
        </body>
        </html>
        


        20201011_202151.gif

        B Offline
        B Offline
        blackeagle998
        schrieb am zuletzt editiert von
        #3380

        @dslraser @s-bormann
        Dankeschön, das ist sehr hilfreich.
        Bitte nicht wundern, wenn ich die nächsten zwei / drei Wochen nur eingeschränkt entwickeln / kommunizieren werde.

        1 Antwort Letzte Antwort
        0
        • B Offline
          B Offline
          blackeagle998
          schrieb am zuletzt editiert von blackeagle998
          #3381

          @s-bormann
          Hab noch kleinen Bug bei der Bearbeitung von .html, .css und .js Dateien gefunden.
          Wenn ich das erste mal gespeichert habe und danach noch etwas ändere, ist der speichern Button zwar aktiv aber es passiert nichts mehr wenn ich darauf klicke.
          Ich muss das Fenster schließen und erneut öffnen, dann kann ich wieder einmal speichern usw.

          s.bormannS 1 Antwort Letzte Antwort
          0
          • B blackeagle998

            @s-bormann
            Hab noch kleinen Bug bei der Bearbeitung von .html, .css und .js Dateien gefunden.
            Wenn ich das erste mal gespeichert habe und danach noch etwas ändere, ist der speichern Button zwar aktiv aber es passiert nichts mehr wenn ich darauf klicke.
            Ich muss das Fenster schließen und erneut öffnen, dann kann ich wieder einmal speichern usw.

            s.bormannS Offline
            s.bormannS Offline
            s.bormann
            Most Active
            schrieb am zuletzt editiert von
            #3382

            @blackeagle998 sagte in Test Adapter iQontrol 1.3.x:

            @s-bormann
            Hab noch kleinen Bug bei der Bearbeitung von .html, .css und .js Dateien gefunden.
            Wenn ich das erste mal gespeichert habe und danach noch etwas ändere, ist der speichern Button zwar aktiv aber es passiert nichts mehr wenn ich darauf klicke.
            Ich muss das Fenster schließen und erneut öffnen, dann kann ich wieder einmal speichern usw.

            Hi, ist mir heute auch aufgefallen. Ist schon behoben (die neue Version kommt dann demnächst online).

            1 Antwort Letzte Antwort
            0
            • s.bormannS Offline
              s.bormannS Offline
              s.bormann
              Most Active
              schrieb am zuletzt editiert von
              #3383

              1.3.2 (2020-10-12)

              • (sbormann) Added icons to REMOTE_ADDITIONAL_BUTTONS of remote control.
              • (sbormann) Added REMOTE_CHANNELS to display channel buttons inside remote control.
              • (sbormann) Enhanced positioning of dialog if URL/HTML is set.
              • (sbormann) When writing data to an iframe replace encoded cr chars.
              • (sbormann) Added option to remove overlay of tile, if device is enlarged.
              • (sbormann) Added possibility to add and edit html/css/js files to folder /userwidgets.
              • (sbormann) Withdrawn changes to blank icons (now they catch mouse events again) - but for that added an option to optionally ignore mouse events for icons.
              • (sbormann) Added option which sections of remote are opened at start.
              • (sbormann) Added new postMessage-communication options for widgets and allow widgets to create datapoints unter iqontrol.x.Widgets by using a meta-tag inside html-code.
              1 Antwort Letzte Antwort
              1
              • B Offline
                B Offline
                blackeagle998
                schrieb am zuletzt editiert von
                #3384

                @s-bormann
                Ich brauche nochmal deine Hilfe, das Thema receivePostMessage ist mir noch nicht klar.

                Ich habe eine Funktion getRoomLocked die ermitteln soll, ob der zugehörige Datenpunkt auf true oder false steht. Mir ist klar, dass ich ein getState auf den Datenpunkt mache und dass dann die Funktion receivePostMessage das Ergebnis erhält, aber wie zur Hölle bekomme ich das Ergebnis in meine Funktion getRoomLocked um damit weiter arbeiten zu können?

                Ich steh aufm Schlauch...

                dslraserD 1 Antwort Letzte Antwort
                0
                • B blackeagle998

                  @s-bormann
                  Ich brauche nochmal deine Hilfe, das Thema receivePostMessage ist mir noch nicht klar.

                  Ich habe eine Funktion getRoomLocked die ermitteln soll, ob der zugehörige Datenpunkt auf true oder false steht. Mir ist klar, dass ich ein getState auf den Datenpunkt mache und dass dann die Funktion receivePostMessage das Ergebnis erhält, aber wie zur Hölle bekomme ich das Ergebnis in meine Funktion getRoomLocked um damit weiter arbeiten zu können?

                  Ich steh aufm Schlauch...

                  dslraserD Offline
                  dslraserD Offline
                  dslraser
                  Forum Testing Most Active
                  schrieb am zuletzt editiert von
                  #3385

                  @blackeagle998 sagte in Test Adapter iQontrol 1.3.x:

                  ob der zugehörige Datenpunkt auf true oder false steht.

                  Ich habe es auch noch nicht kapiert !
                  Ich denke es gehen nur Datenpunkte die iQontrol selbst erstellt hat, oder ?
                  Oder kann man auch auf eigenen Datenpunkte, z.B. in 0_userdata.0 oder javascript.x zugreifen ?

                  s.bormannS 1 Antwort Letzte Antwort
                  0
                  • dslraserD dslraser

                    @blackeagle998 sagte in Test Adapter iQontrol 1.3.x:

                    ob der zugehörige Datenpunkt auf true oder false steht.

                    Ich habe es auch noch nicht kapiert !
                    Ich denke es gehen nur Datenpunkte die iQontrol selbst erstellt hat, oder ?
                    Oder kann man auch auf eigenen Datenpunkte, z.B. in 0_userdata.0 oder javascript.x zugreifen ?

                    s.bormannS Offline
                    s.bormannS Offline
                    s.bormann
                    Most Active
                    schrieb am zuletzt editiert von
                    #3386

                    @dslraser sagte in Test Adapter iQontrol 1.3.x:

                    @blackeagle998 sagte in Test Adapter iQontrol 1.3.x:

                    ob der zugehörige Datenpunkt auf true oder false steht.

                    Ich habe es auch noch nicht kapiert !
                    Ich denke es gehen nur Datenpunkte die iQontrol selbst erstellt hat, oder ?
                    Oder kann man auch auf eigenen Datenpunkte, z.B. in 0_userdata.0 oder javascript.x zugreifen ?

                    Beides geht. Mit getWidgetStateSubscribed bekommt man die unter iQontrol mittels meta-tag angelegten Datenpunkte. Mit getStateSubscribed kommt man auf alle Datenpunkte, also auch die unter userdata.

                    Für die Widget Entwicklung ist es aber natürlich von Vorteil, alle benötigten Datenpunkten über die meta-Tags unter iqontrol.x... anlegen zu lassen und zu nutzen. So ist sichergestellt, dass die Widgets bei allen ohne zusätzlichen Konfigurationsaufwand laufen.

                    B 1 Antwort Letzte Antwort
                    1
                    • s.bormannS s.bormann

                      @dslraser sagte in Test Adapter iQontrol 1.3.x:

                      @blackeagle998 sagte in Test Adapter iQontrol 1.3.x:

                      ob der zugehörige Datenpunkt auf true oder false steht.

                      Ich habe es auch noch nicht kapiert !
                      Ich denke es gehen nur Datenpunkte die iQontrol selbst erstellt hat, oder ?
                      Oder kann man auch auf eigenen Datenpunkte, z.B. in 0_userdata.0 oder javascript.x zugreifen ?

                      Beides geht. Mit getWidgetStateSubscribed bekommt man die unter iQontrol mittels meta-tag angelegten Datenpunkte. Mit getStateSubscribed kommt man auf alle Datenpunkte, also auch die unter userdata.

                      Für die Widget Entwicklung ist es aber natürlich von Vorteil, alle benötigten Datenpunkten über die meta-Tags unter iqontrol.x... anlegen zu lassen und zu nutzen. So ist sichergestellt, dass die Widgets bei allen ohne zusätzlichen Konfigurationsaufwand laufen.

                      B Offline
                      B Offline
                      blackeagle998
                      schrieb am zuletzt editiert von blackeagle998
                      #3387

                      @s-bormann
                      Du bist uns definitiv einige Schritte / Meilen voraus :blush:

                      1. wie kriege ich von einem State nicht den Wert, sondern den dazugehörigen String (bspw. "Ampel rot")?
                        Beispiel im RAW:
                      states: {
                      "0": "Ampel rot",
                      "1": "Ampel gelb",
                      "2": "Ampel grün"
                      }
                      

                      --> getState liefert hier ja nur 0, 1 oder 2.
                      Irgendwann habe ich mal im Forum dafür folgende funktionierende Funktionen gefunden:

                      function getStatetxt(id, val) {
                          let states = getStatesObj(id);
                          if(states) return states[val];
                          else return null;
                      }
                      
                      function getStatesObj(id) {
                          if(!getObject(id)) {
                              log(id + ': kein Objekt', 'warn');
                              return null;
                          }
                          let obj = getObject(id);
                          if (!obj.common.states) {
                              log(id + ': keine Zustandtexte', 'warn');
                              return null;
                          }
                          var states = obj.common.states;
                          if (typeof states == 'string') {
                              var arr = states.split(';');
                              states = {};
                              for(var i = 0; i < arr.length; i++) {
                                  var ele = arr[i].split(':');
                                  states[ele[0]] = ele[1];
                              }
                          }
                          return states;
                      }
                      
                      1. Nochmal die Frage, wie ich den getState Rückgabewert in eine andere Funktion als receivePostMessage bekomme.
                        Folgendes Beispiel soll ungefähr verdeutlichen worauf ich hinaus will:
                      function showBatteryGIF() {
                         let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                         if (vacuum_state == 8){
                             blende GIF Battery ein
                         }
                      }
                      
                      function clearCleanCounter(){
                          let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                          if (vacuum_state == 1){
                             setze CleanCounter auf 0 zurück
                         }
                      }
                      

                      Ich habe zwei verschiedene Funktionen, die beide den State desselben Datenpunktes abfragen, aber zu völlig unterschiedlichen Zeiten benutzt werden können.

                      Bisher habe ich verstanden, dass die Funktion receivePostMessage den Rückgabewert verarbeiten kann, deshalb habe ich teshalber folgendes gebaut, was auch funktioniert:

                      var img_locked 		= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/locked.png';
                      var img_unlocked 	= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/unlocked.png';
                      
                      window.addEventListener("message", receivePostMessage, false);
                      function receivePostMessage(event) { //event = {data: message data, origin: url of origin, source: id of sending element}
                        if(event.data && event.data.command) switch(event.data.command){
                          case "getState":
                            if (((event.data.stateId == '0_userdata.0.vacuum.rooms.Bad.locked'){
                      	let img_room_locked = document.getElementById('img_room_locked');
                      	if (event.data.value.val){
                                img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                      	  img_room_locked.setAttribute("src", img_locked);
                      	}else{
                                img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                      	  img_room_locked.setAttribute("src", img_unlocked);
                      	}
                            }
                            break;
                        }
                      }
                      

                      Momentan sehe ich mit dieser Funktion nur die Möglichkeit, jeden einzelnen Datenpunkt innerhalb jedes einzelnen Case (getState oder setState oder.....) abzufragen und den Rückgabewert auszuwerten.
                      Im obigen Beispiel ist genau definiert, was passieren soll, wenn der Rückgabewert true / false ist. Was wäre jetzt aber, wenn ich im true-Fall was anderes ausführen lassen will, aber nicht parallel zu dem Beispiel, sondern alternativ?

                      Ich hoffe das ist halbwegs verständlich ausgedrückt, ansonsten müssen wir mal chatten :-)

                      s.bormannS 1 Antwort Letzte Antwort
                      0
                      • Julian 0J Julian 0

                        @dslraser aber klar doch :-)

                        Die API ist lhier
                        ganz gut beschrieben:

                        schedule('*/1 * * * *', function(){
                            var url = 'http://IP-ADRESSE/api/epgbouquet?bRef=1:7:1:0:0:0:0:0:0:0:FROM%20BOUQUET%20%22userbouquet.dbe00.tv%22%20ORDER%20BY%20bouquet'; //bRef der entsprechenden Favoritenliste
                            request(url, function (err, state, body){
                                if (body) {
                                    body = JSON.parse(body);    
                                    for(var i=0;i<body.events.length;i++) {    
                                        var current_service = body['events'][i]['sname'];
                                        var title = body['events'][i]['title'];
                                        var shortdesc = body['events'][i]['shortdesc'];
                                        var longdesc = body['events'][i]['longdesc'];
                                        var begin_timestamp = body['events'][i]['begin_timestamp'];
                                        var duration = (body['events'][i]['duration_sec'])/60;
                                        duration = Math.floor(duration);
                                        var time;
                        
                                        time = new Date(begin_timestamp*1000).toLocaleTimeString();
                                        
                                        createState("javascript.0.EPG.jetzt." + current_service + ".title");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".shortdesc");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".longdesc");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".begin_timestamp");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".duration_sec");
                        
                                        setState("javascript.0.EPG.jetzt." + current_service + ".title", title);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".shortdesc", shortdesc);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".longdesc", longdesc);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".begin_timestamp", time);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".duration_sec", duration);
                                    }
                                } else {
                                    log('EPG_now meldet Fehler: ' + err, 'error');
                                }
                            });
                        });
                        
                        dslraserD Offline
                        dslraserD Offline
                        dslraser
                        Forum Testing Most Active
                        schrieb am zuletzt editiert von
                        #3388

                        @Julian-0 sagte in Test Adapter iQontrol 1.3.x:

                        @dslraser aber klar doch :-)

                        Die API ist lhier
                        ganz gut beschrieben:

                        schedule('*/1 * * * *', function(){
                            var url = 'http://IP-ADRESSE/api/epgbouquet?bRef=1:7:1:0:0:0:0:0:0:0:FROM%20BOUQUET%20%22userbouquet.dbe00.tv%22%20ORDER%20BY%20bouquet'; //bRef der entsprechenden Favoritenliste
                            request(url, function (err, state, body){
                                if (body) {
                                    body = JSON.parse(body);    
                                    for(var i=0;i<body.events.length;i++) {    
                                        var current_service = body['events'][i]['sname'];
                                        var title = body['events'][i]['title'];
                                        var shortdesc = body['events'][i]['shortdesc'];
                                        var longdesc = body['events'][i]['longdesc'];
                                        var begin_timestamp = body['events'][i]['begin_timestamp'];
                                        var duration = (body['events'][i]['duration_sec'])/60;
                                        duration = Math.floor(duration);
                                        var time;
                        
                                        time = new Date(begin_timestamp*1000).toLocaleTimeString();
                                        
                                        createState("javascript.0.EPG.jetzt." + current_service + ".title");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".shortdesc");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".longdesc");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".begin_timestamp");
                                        createState("javascript.0.EPG.jetzt." + current_service + ".duration_sec");
                        
                                        setState("javascript.0.EPG.jetzt." + current_service + ".title", title);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".shortdesc", shortdesc);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".longdesc", longdesc);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".begin_timestamp", time);
                                        setState("javascript.0.EPG.jetzt." + current_service + ".duration_sec", duration);
                                    }
                                } else {
                                    log('EPG_now meldet Fehler: ' + err, 'error');
                                }
                            });
                        });
                        

                        Ich habe mal etwas Dein Script verändert. (nur die Fehlermeldungen nach dem ersten Start, bis alles befüllt ist, ist noch da, das nervt mich etwas)
                        Sieht dann so aus
                        Bildschirmfoto 2020-10-12 um 21.37.34.png

                        Damit lässt sich dann die iQontrol Fernbedienung ganz gut einrichten. Den Button kann mann dann ganz gut in iot einbinden und als Trigger benutzen--mit der Servicereference über ein Blockly schalten, aber das ist noch ungetestet.

                        schedule('*/1 * * * *', function(){
                           var url = 'http://192.168.1.53/api/epgbouquet?bRef=1%3A7%3A1%3A0%3A0%3A0%3A0%3A0%3A0%3A0%3AFROM%20BOUQUET%20%22userbouquet.favourites.tv%22%20ORDER%20BY%20bouquet&stype=tv'; //bRef der entsprechenden Favoritenliste
                           request(url, function (err, state, body){
                               if (body) {
                                   body = JSON.parse(body);    
                                   for(var i=0;i<body.events.length;i++) {    
                                       var current_service = body['events'][i]['sname'];
                                       var title = body['events'][i]['title'];
                                       var shortdesc = body['events'][i]['shortdesc'];
                                       var longdesc = body['events'][i]['longdesc'];
                                       var sref = body['events'][i]['sref'];
                                       var begin_timestamp = body['events'][i]['begin_timestamp'];
                                       var duration = (body['events'][i]['duration_sec'])/60;
                                       duration = Math.floor(duration);
                                       var time;
                        
                                       time = new Date(begin_timestamp*1000).toLocaleTimeString();
                        
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".00Alexa_Trigger",{name: current_service + ' Button_Alexa_Trigger', 'type':'boolean', 'read':true, 'write':true, 'role':'button'});                                
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".01Sendername",{name: current_service + ' Sender Name', 'type':'string', 'read':true, 'write':true, 'role':'string'});                
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".02EPG_jetzt_Beginn",{name: current_service + ' 02EPG jetzt Beginn', 'type':'string', 'read':true, 'write':true, 'role':'string'});
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".03EPG_jetzt_Dauer",{name: current_service + ' EPG jetzt Dauer', 'type':'number', 'read':true, 'write':true, 'role':'number'});                
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".04EPG_jetzt_Titel",{name: current_service + ' EPG jetzt Titel', 'type':'string', 'read':true, 'write':true, 'role':'string'});
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".05EPG_jetzt_Kurzinfo",{name: current_service + ' EPG jetzt Kurzinfo', 'type':'string', 'read':true, 'write':true, 'role':'string'});
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".06EPG_jetzt_Langinfo",{name: current_service + ' EPG jetzt Langinfo', 'type':'string', 'read':true, 'write':true, 'role':'string'});
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".07EPG_gesamt",{name: current_service + ' EPG gesamt', 'type':'string', 'read':true, 'write':true, 'role':'string'});
                                       createState("javascript.0.VU.Wohnzimmer." + current_service + ".08Servicereference",{name: current_service + ' Servicereference', 'type':'string', 'read':true, 'write':true, 'role':'string'});
                        
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".01Sendername", current_service);
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".02EPG_jetzt_Beginn", time);
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".03EPG_jetzt_Dauer", duration);
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".04EPG_jetzt_Titel", title);
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".05EPG_jetzt_Kurzinfo", shortdesc);
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".06EPG_jetzt_Langinfo", longdesc);   
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".07EPG_gesamt", 'Beginn: ' + time + '\n' + 'Dauer: ' + duration + '\n' + title + '\n' + shortdesc + '\n' + longdesc);  
                                       setState("javascript.0.VU.Wohnzimmer." + current_service + ".08Servicereference", sref); 
                        
                                   }
                               } else {
                                   log('EPG_now meldet Fehler: ' + err, 'error');
                               }
                           });
                        });
                        
                        

                        1 Antwort Letzte Antwort
                        1
                        • B blackeagle998

                          @s-bormann
                          Du bist uns definitiv einige Schritte / Meilen voraus :blush:

                          1. wie kriege ich von einem State nicht den Wert, sondern den dazugehörigen String (bspw. "Ampel rot")?
                            Beispiel im RAW:
                          states: {
                          "0": "Ampel rot",
                          "1": "Ampel gelb",
                          "2": "Ampel grün"
                          }
                          

                          --> getState liefert hier ja nur 0, 1 oder 2.
                          Irgendwann habe ich mal im Forum dafür folgende funktionierende Funktionen gefunden:

                          function getStatetxt(id, val) {
                              let states = getStatesObj(id);
                              if(states) return states[val];
                              else return null;
                          }
                          
                          function getStatesObj(id) {
                              if(!getObject(id)) {
                                  log(id + ': kein Objekt', 'warn');
                                  return null;
                              }
                              let obj = getObject(id);
                              if (!obj.common.states) {
                                  log(id + ': keine Zustandtexte', 'warn');
                                  return null;
                              }
                              var states = obj.common.states;
                              if (typeof states == 'string') {
                                  var arr = states.split(';');
                                  states = {};
                                  for(var i = 0; i < arr.length; i++) {
                                      var ele = arr[i].split(':');
                                      states[ele[0]] = ele[1];
                                  }
                              }
                              return states;
                          }
                          
                          1. Nochmal die Frage, wie ich den getState Rückgabewert in eine andere Funktion als receivePostMessage bekomme.
                            Folgendes Beispiel soll ungefähr verdeutlichen worauf ich hinaus will:
                          function showBatteryGIF() {
                             let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                             if (vacuum_state == 8){
                                 blende GIF Battery ein
                             }
                          }
                          
                          function clearCleanCounter(){
                              let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                              if (vacuum_state == 1){
                                 setze CleanCounter auf 0 zurück
                             }
                          }
                          

                          Ich habe zwei verschiedene Funktionen, die beide den State desselben Datenpunktes abfragen, aber zu völlig unterschiedlichen Zeiten benutzt werden können.

                          Bisher habe ich verstanden, dass die Funktion receivePostMessage den Rückgabewert verarbeiten kann, deshalb habe ich teshalber folgendes gebaut, was auch funktioniert:

                          var img_locked 		= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/locked.png';
                          var img_unlocked 	= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/unlocked.png';
                          
                          window.addEventListener("message", receivePostMessage, false);
                          function receivePostMessage(event) { //event = {data: message data, origin: url of origin, source: id of sending element}
                            if(event.data && event.data.command) switch(event.data.command){
                              case "getState":
                                if (((event.data.stateId == '0_userdata.0.vacuum.rooms.Bad.locked'){
                          	let img_room_locked = document.getElementById('img_room_locked');
                          	if (event.data.value.val){
                                    img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                          	  img_room_locked.setAttribute("src", img_locked);
                          	}else{
                                    img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                          	  img_room_locked.setAttribute("src", img_unlocked);
                          	}
                                }
                                break;
                            }
                          }
                          

                          Momentan sehe ich mit dieser Funktion nur die Möglichkeit, jeden einzelnen Datenpunkt innerhalb jedes einzelnen Case (getState oder setState oder.....) abzufragen und den Rückgabewert auszuwerten.
                          Im obigen Beispiel ist genau definiert, was passieren soll, wenn der Rückgabewert true / false ist. Was wäre jetzt aber, wenn ich im true-Fall was anderes ausführen lassen will, aber nicht parallel zu dem Beispiel, sondern alternativ?

                          Ich hoffe das ist halbwegs verständlich ausgedrückt, ansonsten müssen wir mal chatten :-)

                          s.bormannS Offline
                          s.bormannS Offline
                          s.bormann
                          Most Active
                          schrieb am zuletzt editiert von
                          #3389

                          @blackeagle998 sagte in Test Adapter iQontrol 1.3.x:

                          @s-bormann
                          Du bist uns definitiv einige Schritte / Meilen voraus :blush:

                          1. wie kriege ich von einem State nicht den Wert, sondern den dazugehörigen String (bspw. "Ampel rot")?
                            Beispiel im RAW:
                          states: {
                          "0": "Ampel rot",
                          "1": "Ampel gelb",
                          "2": "Ampel grün"
                          }
                          

                          --> getState liefert hier ja nur 0, 1 oder 2.

                          Nein, ich bin Euch da nicht sehr weit voraus. Auch bei mir ist das viel abgucken und sehr viel try'n'error.

                          So habe ich das mit dem String (oder wie ich es bei mir intern genannt habe 'plainText') gar nicht bedacht. Habe deshalb die Rückmeldung für die postMessage-Kommunikation jetzt in der aktuellen Github-Version noch mal erweitert:

                          Jetzt wird nicht nur der nackte State geliefert, sondern es werden noch einige Daten (z.B. value, min, max, readonly etc.) aus dem zugehörigen Objekt des Datenpunktes geliefert - oder einfach gesagt, genau das, was iQontrol auch intern auswertet und sieht. Die Rückmeldung auf ein getState, getStateSubscribed, getWidgetState oder getWidgetStateSubscribed sieht jetzt so aus:

                          event.data.value = {
                          	val: <value>,
                          	unit: "<unit>",
                          	plainText: "<clear text of val, for example taken from valuelist>",
                          	min: <minimum>,
                          	max: <maximum>,
                          	valuelist: {<object with possible values and corresponding clear text>},
                          	targetValues: {<target value list>},
                          	ack: <true|false>,
                          	readonly: <true|false>,
                          	custom: {<object with custom settings>},
                          	from: "<source of state>",
                          	lc: <timestamp of last change>,
                          	ts: <timestamp of last actualization>,
                          	q: <quality of signal>,
                          	role: "<role of state>",
                          	type: "<string|number|boolean>"
                          }
                          
                          1. Nochmal die Frage, wie ich den getState Rückgabewert in eine andere Funktion als receivePostMessage bekomme.
                            Folgendes Beispiel soll ungefähr verdeutlichen worauf ich hinaus will:
                          function showBatteryGIF() {
                             let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                             if (vacuum_state == 8){
                                 blende GIF Battery ein
                             }
                          }
                          
                          function clearCleanCounter(){
                              let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                              if (vacuum_state == 1){
                                 setze CleanCounter auf 0 zurück
                             }
                          }
                          

                          Ja, da muss man etwas umdenken und weg vom "linearen", hin zum parallelen oder - fachlich korrekt "synchronen" ausführen von Befehlen. Musste ich auch erst mal kapieren. Die Idee ist die:

                          Als erstes definierst Du, was passieren soll, wenn Dir ein State geliefert wird. Das machst Du alles (wie Du es unten schon im nächsten Beispiel getan hast) innerhalb der receivePostMessage-Funktion. Die wird also am Ende ziemlich lang werden, weil da die ganze Logik reingepackt wird. Also im konkreten Beispiel müsste da stehen:
                          Wenn Du einen neuen Zustand der Batterie empfängst, dann zeige das Battrie-Logo, wenn der Zustand leer ist. Ansonsten verstecke das Bild.

                          Erst als letztes subscribest Du dann, ganz am Ende des Scripts, alle States, die Du für Dein Widget benötigst.

                          Ich habe zwei verschiedene Funktionen, die beide den State desselben Datenpunktes abfragen, aber zu völlig unterschiedlichen Zeiten benutzt werden können.

                          Bisher habe ich verstanden, dass die Funktion receivePostMessage den Rückgabewert verarbeiten kann, deshalb habe ich teshalber folgendes gebaut, was auch funktioniert:

                          var img_locked 		= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/locked.png';
                          var img_unlocked 	= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/unlocked.png';
                          
                          window.addEventListener("message", receivePostMessage, false);
                          function receivePostMessage(event) { //event = {data: message data, origin: url of origin, source: id of sending element}
                            if(event.data && event.data.command) switch(event.data.command){
                              case "getState":
                                if (((event.data.stateId == '0_userdata.0.vacuum.rooms.Bad.locked'){
                          	let img_room_locked = document.getElementById('img_room_locked');
                          	if (event.data.value.val){
                                    img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                          	  img_room_locked.setAttribute("src", img_locked);
                          	}else{
                                    img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                          	  img_room_locked.setAttribute("src", img_unlocked);
                          	}
                                }
                                break;
                            }
                          }
                          

                          Genau so ist es richtig. Hier muss alle Logik rein.
                          Wenn man Logiken benötigt, die mehrere States kombinieren, dann muss man sich die States, die man empfängt, in Variablen ablegen und dann jeweils eine ausgelagerte Funktion aufrufen. Schau mal das map.html-Beispiel an:

                          map.html

                          Hier wird jeweils für altitude, longitude und zoom beim Empfangen des States eine entsprechende Variable gesetzt und danach repositionMap() aufgerufen:

                          case "Map.Position.latitude":
                          console.log("Set latitude to " + event.data.value.val);
                          mapPositionLatitude = parseFloat(event.data.value.val) || 0;
                          if(mymap) repositionMap();
                          break;
                          

                          In der repositionMap()-Funktion wird dann aus den drei Variablen altitude, longitude und zoom die neue Kartenposition angefahren. Wenn sich eine der drei Variablen ändert, weil eben ein aktualisierter State geliefert wird, wird die Karte neu positioniert.
                          Man könnte das jetzt auch noch so erweitern, dass die repositionMap()-Funktion zuerst schaut, ob schon alle drei Variablen empfangen wurden if(altitude != null && longitude != null && zoom != null){...} (das fehlt im map.html-Beispiel eigentlich noch).

                          Wenn man dann die drei States für alt, long und zoom subscribed, kommen die Werte (in ggf. auch zufälliger Reihenfolge!) kurze Zeit später an:
                          Dann wird meinetwegen zuerst altitude empfangen, repositionMap() aufgerufen -> bricht ab, weil longitude und zoom noch fehlen.
                          Dann kommt z.B. zoom als nächstes rein, repositionMap() wird wieder aufgerufen -> bricht ab, weil longitude immer noch fehlt.
                          Dann kommt als letztes irgendwann longitude rein -> jetzt läuft die Funktion durch, weil alle drei Werte da sind.

                          Jetzt etwas verständlicher?

                          B 1 Antwort Letzte Antwort
                          1
                          • s.bormannS s.bormann

                            @blackeagle998 sagte in Test Adapter iQontrol 1.3.x:

                            @s-bormann
                            Du bist uns definitiv einige Schritte / Meilen voraus :blush:

                            1. wie kriege ich von einem State nicht den Wert, sondern den dazugehörigen String (bspw. "Ampel rot")?
                              Beispiel im RAW:
                            states: {
                            "0": "Ampel rot",
                            "1": "Ampel gelb",
                            "2": "Ampel grün"
                            }
                            

                            --> getState liefert hier ja nur 0, 1 oder 2.

                            Nein, ich bin Euch da nicht sehr weit voraus. Auch bei mir ist das viel abgucken und sehr viel try'n'error.

                            So habe ich das mit dem String (oder wie ich es bei mir intern genannt habe 'plainText') gar nicht bedacht. Habe deshalb die Rückmeldung für die postMessage-Kommunikation jetzt in der aktuellen Github-Version noch mal erweitert:

                            Jetzt wird nicht nur der nackte State geliefert, sondern es werden noch einige Daten (z.B. value, min, max, readonly etc.) aus dem zugehörigen Objekt des Datenpunktes geliefert - oder einfach gesagt, genau das, was iQontrol auch intern auswertet und sieht. Die Rückmeldung auf ein getState, getStateSubscribed, getWidgetState oder getWidgetStateSubscribed sieht jetzt so aus:

                            event.data.value = {
                            	val: <value>,
                            	unit: "<unit>",
                            	plainText: "<clear text of val, for example taken from valuelist>",
                            	min: <minimum>,
                            	max: <maximum>,
                            	valuelist: {<object with possible values and corresponding clear text>},
                            	targetValues: {<target value list>},
                            	ack: <true|false>,
                            	readonly: <true|false>,
                            	custom: {<object with custom settings>},
                            	from: "<source of state>",
                            	lc: <timestamp of last change>,
                            	ts: <timestamp of last actualization>,
                            	q: <quality of signal>,
                            	role: "<role of state>",
                            	type: "<string|number|boolean>"
                            }
                            
                            1. Nochmal die Frage, wie ich den getState Rückgabewert in eine andere Funktion als receivePostMessage bekomme.
                              Folgendes Beispiel soll ungefähr verdeutlichen worauf ich hinaus will:
                            function showBatteryGIF() {
                               let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                               if (vacuum_state == 8){
                                   blende GIF Battery ein
                               }
                            }
                            
                            function clearCleanCounter(){
                                let vacuum_state = sendPostMessage("getState", 'mihome-vacuum.0.info.state');
                                if (vacuum_state == 1){
                                   setze CleanCounter auf 0 zurück
                               }
                            }
                            

                            Ja, da muss man etwas umdenken und weg vom "linearen", hin zum parallelen oder - fachlich korrekt "synchronen" ausführen von Befehlen. Musste ich auch erst mal kapieren. Die Idee ist die:

                            Als erstes definierst Du, was passieren soll, wenn Dir ein State geliefert wird. Das machst Du alles (wie Du es unten schon im nächsten Beispiel getan hast) innerhalb der receivePostMessage-Funktion. Die wird also am Ende ziemlich lang werden, weil da die ganze Logik reingepackt wird. Also im konkreten Beispiel müsste da stehen:
                            Wenn Du einen neuen Zustand der Batterie empfängst, dann zeige das Battrie-Logo, wenn der Zustand leer ist. Ansonsten verstecke das Bild.

                            Erst als letztes subscribest Du dann, ganz am Ende des Scripts, alle States, die Du für Dein Widget benötigst.

                            Ich habe zwei verschiedene Funktionen, die beide den State desselben Datenpunktes abfragen, aber zu völlig unterschiedlichen Zeiten benutzt werden können.

                            Bisher habe ich verstanden, dass die Funktion receivePostMessage den Rückgabewert verarbeiten kann, deshalb habe ich teshalber folgendes gebaut, was auch funktioniert:

                            var img_locked 		= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/locked.png';
                            var img_unlocked 	= 'http://192.x.x.x:8082/iqontrol.meta/userimages/usericons/vacuum/unlocked.png';
                            
                            window.addEventListener("message", receivePostMessage, false);
                            function receivePostMessage(event) { //event = {data: message data, origin: url of origin, source: id of sending element}
                              if(event.data && event.data.command) switch(event.data.command){
                                case "getState":
                                  if (((event.data.stateId == '0_userdata.0.vacuum.rooms.Bad.locked'){
                            	let img_room_locked = document.getElementById('img_room_locked');
                            	if (event.data.value.val){
                                      img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                            	  img_room_locked.setAttribute("src", img_locked);
                            	}else{
                                      img_room_locked.setAttribute("onclick", "setState('0_userdata.0.vacuum.room_lock', 'Bad')");
                            	  img_room_locked.setAttribute("src", img_unlocked);
                            	}
                                  }
                                  break;
                              }
                            }
                            

                            Genau so ist es richtig. Hier muss alle Logik rein.
                            Wenn man Logiken benötigt, die mehrere States kombinieren, dann muss man sich die States, die man empfängt, in Variablen ablegen und dann jeweils eine ausgelagerte Funktion aufrufen. Schau mal das map.html-Beispiel an:

                            map.html

                            Hier wird jeweils für altitude, longitude und zoom beim Empfangen des States eine entsprechende Variable gesetzt und danach repositionMap() aufgerufen:

                            case "Map.Position.latitude":
                            console.log("Set latitude to " + event.data.value.val);
                            mapPositionLatitude = parseFloat(event.data.value.val) || 0;
                            if(mymap) repositionMap();
                            break;
                            

                            In der repositionMap()-Funktion wird dann aus den drei Variablen altitude, longitude und zoom die neue Kartenposition angefahren. Wenn sich eine der drei Variablen ändert, weil eben ein aktualisierter State geliefert wird, wird die Karte neu positioniert.
                            Man könnte das jetzt auch noch so erweitern, dass die repositionMap()-Funktion zuerst schaut, ob schon alle drei Variablen empfangen wurden if(altitude != null && longitude != null && zoom != null){...} (das fehlt im map.html-Beispiel eigentlich noch).

                            Wenn man dann die drei States für alt, long und zoom subscribed, kommen die Werte (in ggf. auch zufälliger Reihenfolge!) kurze Zeit später an:
                            Dann wird meinetwegen zuerst altitude empfangen, repositionMap() aufgerufen -> bricht ab, weil longitude und zoom noch fehlen.
                            Dann kommt z.B. zoom als nächstes rein, repositionMap() wird wieder aufgerufen -> bricht ab, weil longitude immer noch fehlt.
                            Dann kommt als letztes irgendwann longitude rein -> jetzt läuft die Funktion durch, weil alle drei Werte da sind.

                            Jetzt etwas verständlicher?

                            B Offline
                            B Offline
                            blackeagle998
                            schrieb am zuletzt editiert von
                            #3390

                            @s-bormann
                            Super, jetzt habe ich es verstanden, denke ich zumindest. Da ist tatsächlich Umdenken gefragt.
                            Ich denke, dass ich mit dem Zeit/Wetter Widget dann mal anfangen werde, das Staubsauger-Skript ist zu komplex für den Anfang.

                            V 1 Antwort Letzte Antwort
                            1
                            • dslraserD Offline
                              dslraserD Offline
                              dslraser
                              Forum Testing Most Active
                              schrieb am zuletzt editiert von dslraser
                              #3391

                              @Julian-0

                              Ich habe das Script nochmal angepasst. Beim Scriptstart wird die Ordnerstruktur erstellt und danach werden dann durch das scheudele die Daten eingelesen und aktualisiert. So gibt es jetzt bei mir keine Fehlermeldung mehr.

                              ///////////////Struktur erstellen
                              var url = 'http://192.168.1.53/api/epgbouquet?bRef=1%3A7%3A1%3A0%3A0%3A0%3A0%3A0%3A0%3A0%3AFROM%20BOUQUET%20%22userbouquet.favourites.tv%22%20ORDER%20BY%20bouquet&stype=tv'; //bRef der entsprechenden Favoritenliste
                              request(url, function(err, state, body) {
                                 if (body) {
                                     body = JSON.parse(body);
                                     for (var i = 0; i < body.events.length; i++) {
                                         var current_service = body['events'][i]['sname'];
                                         var title = body['events'][i]['title'];
                                         var shortdesc = body['events'][i]['shortdesc'];
                                         var longdesc = body['events'][i]['longdesc'];
                                         var sref = body['events'][i]['sref'];
                                         var begin_timestamp = body['events'][i]['begin_timestamp'];
                                         var duration = (body['events'][i]['duration_sec']) / 60;
                                         duration = Math.floor(duration);
                                         var time;
                              
                                         time = new Date(begin_timestamp * 1000).toLocaleTimeString();
                              
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".00Alexa_Trigger", {
                                             name: current_service + ' Button_Alexa_Trigger',
                                             'type': 'boolean',
                                             'read': true,
                                             'write': true,
                                             'role': 'button'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".01Sendername", {
                                             name: current_service + ' Sender Name',
                                             'type': 'string',
                                             'read': true,
                                             'write': true,
                                             'role': 'string'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".02EPG_jetzt_Beginn", {
                                             name: current_service + ' 02EPG jetzt Beginn',
                                             'type': 'string',
                                             'read': true,
                                             'write': true,
                                             'role': 'string'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".03EPG_jetzt_Dauer", {
                                             name: current_service + ' EPG jetzt Dauer',
                                             'type': 'number',
                                             'read': true,
                                             'write': true,
                                             'role': 'number'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".04EPG_jetzt_Titel", {
                                             name: current_service + ' EPG jetzt Titel',
                                             'type': 'string',
                                             'read': true,
                                             'write': true,
                                             'role': 'string'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".05EPG_jetzt_Kurzinfo", {
                                             name: current_service + ' EPG jetzt Kurzinfo',
                                             'type': 'string',
                                             'read': true,
                                             'write': true,
                                             'role': 'string'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".06EPG_jetzt_Langinfo", {
                                             name: current_service + ' EPG jetzt Langinfo',
                                             'type': 'string',
                                             'read': true,
                                             'write': true,
                                             'role': 'string'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".07EPG_gesamt", {
                                             name: current_service + ' EPG gesamt',
                                             'type': 'string',
                                             'read': true,
                                             'write': true,
                                             'role': 'string'
                                         });
                                         createState("javascript.0.VU.Wohnzimmer." + current_service + ".08Servicereference", {
                                             name: current_service + ' Servicereference',
                                             'type': 'string',
                                             'read': true,
                                             'write': true,
                                             'role': 'string'
                                         });
                              
                                     }
                                 } else {
                                     log('EPG_now meldet Fehler: ' + err, 'error');
                                 }
                              });
                              
                              ///////////////Daten einlesen
                              schedule('*/1 * * * *', function() {
                                 var url = 'http://192.168.1.53/api/epgbouquet?bRef=1%3A7%3A1%3A0%3A0%3A0%3A0%3A0%3A0%3A0%3AFROM%20BOUQUET%20%22userbouquet.favourites.tv%22%20ORDER%20BY%20bouquet&stype=tv'; //bRef der entsprechenden Favoritenliste
                                 request(url, function(err, state, body) {
                                     if (body) {
                                         body = JSON.parse(body);
                                         for (var i = 0; i < body.events.length; i++) {
                                             var current_service = body['events'][i]['sname'];
                                             var title = body['events'][i]['title'];
                                             var shortdesc = body['events'][i]['shortdesc'];
                                             var longdesc = body['events'][i]['longdesc'];
                                             var sref = body['events'][i]['sref'];
                                             var begin_timestamp = body['events'][i]['begin_timestamp'];
                                             var duration = (body['events'][i]['duration_sec']) / 60;
                                             duration = Math.floor(duration);
                                             var time;
                              
                                             time = new Date(begin_timestamp * 1000).toLocaleTimeString();
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".01Sendername", current_service);
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".02EPG_jetzt_Beginn", time);
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".03EPG_jetzt_Dauer", duration);
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".04EPG_jetzt_Titel", title);
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".05EPG_jetzt_Kurzinfo", shortdesc);
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".06EPG_jetzt_Langinfo", longdesc);
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".07EPG_gesamt", 'Beginn: ' + time + '\n' + 'Dauer: ' + duration + '\n' + title + '\n' + shortdesc + '\n' + longdesc);
                                             setState("javascript.0.VU.Wohnzimmer." + current_service + ".08Servicereference", sref);
                              
                                         }
                                     } else {
                                         log('EPG_now meldet Fehler: ' + err, 'error');
                                     }
                                 });
                              });
                              

                              1 Antwort Letzte Antwort
                              0
                              • s.bormannS s.bormann

                                @dslraser sagte in Test Adapter iQontrol 1.3.x:

                                @s-bormann sagte in Test Adapter iQontrol 1.3.x:

                                Für die REMOTE-Sektionen wurde jetzt eine eigene Option eingebaut (aktuelle Github-Version).

                                Funktioniert auch bei mir, dann werde ich mal alle meine Sender einbauen :+1:
                                Kannst Du bitte die Beschriftung für "Channels:" auch "umbenennbar" machen.

                                Bildschirmfoto 2020-10-09 um 23.03.35.png

                                Ist es schon. Guck noch mal in den Optionen. LG

                                K Offline
                                K Offline
                                Kueppert
                                schrieb am zuletzt editiert von
                                #3392

                                @s-bormann sagte in Test Adapter iQontrol 1.3.x:

                                @dslraser sagte in Test Adapter iQontrol 1.3.x:

                                @s-bormann sagte in Test Adapter iQontrol 1.3.x:

                                Für die REMOTE-Sektionen wurde jetzt eine eigene Option eingebaut (aktuelle Github-Version).

                                Funktioniert auch bei mir, dann werde ich mal alle meine Sender einbauen :+1:
                                Kannst Du bitte die Beschriftung für "Channels:" auch "umbenennbar" machen.

                                Bildschirmfoto 2020-10-09 um 23.03.35.png

                                Ist es schon. Guck noch mal in den Optionen. LG

                                Wie hast du die Channels jeweils hinterlegt? Du nutzt doch auch den HarmonyHub, oder? Da kannst ja nur 0-9 auswählen als Button. Nutzt du hier im Hintergrund noch ein SKript? zB für "0012, select"?

                                UDM Pro, Intel NUC - ioBroker in Proxmox-VM, PiHole+Grafana&Influx+TasmoAdmin in LXCs, Raspberry Pi3 (als CCU), Zigbee-Stick Sonoff, Synology DS918+

                                dslraserD 1 Antwort Letzte Antwort
                                0
                                • K Kueppert

                                  @s-bormann sagte in Test Adapter iQontrol 1.3.x:

                                  @dslraser sagte in Test Adapter iQontrol 1.3.x:

                                  @s-bormann sagte in Test Adapter iQontrol 1.3.x:

                                  Für die REMOTE-Sektionen wurde jetzt eine eigene Option eingebaut (aktuelle Github-Version).

                                  Funktioniert auch bei mir, dann werde ich mal alle meine Sender einbauen :+1:
                                  Kannst Du bitte die Beschriftung für "Channels:" auch "umbenennbar" machen.

                                  Bildschirmfoto 2020-10-09 um 23.03.35.png

                                  Ist es schon. Guck noch mal in den Optionen. LG

                                  Wie hast du die Channels jeweils hinterlegt? Du nutzt doch auch den HarmonyHub, oder? Da kannst ja nur 0-9 auswählen als Button. Nutzt du hier im Hintergrund noch ein SKript? zB für "0012, select"?

                                  dslraserD Offline
                                  dslraserD Offline
                                  dslraser
                                  Forum Testing Most Active
                                  schrieb am zuletzt editiert von
                                  #3393

                                  @Kueppert sagte in Test Adapter iQontrol 1.3.x:

                                  Wie hast du die Channels jeweils hinterlegt? Du nutzt doch auch den HarmonyHub, oder?

                                  Die Sender schalte ich über meine VU und ein Blockly.

                                  Harmony Aktionen (activity) habe ich hier drinn.
                                  Screenshot_20201013-142354_Chrome.jpg

                                  1 Antwort Letzte Antwort
                                  0
                                  • E Offline
                                    E Offline
                                    eMd
                                    schrieb am zuletzt editiert von
                                    #3394

                                    Hallo,

                                    ich habe gerade für eine Kachel Additional Controls hinterlegt, diese hätte ich gerne in 4 weiteren bestehenden Kacheln auch drin.
                                    Kann man die irgendwie kopieren?

                                    MfG
                                    eMd

                                    Master: Intel NUC 16GB/500GB
                                    Slave: Raspberry Pi 3 + Homematicmodul
                                    Shelly, Google Home, Zigbee Aqara, Sonoff

                                    Meine VIS: https://youtu.be/JMYr2KYlpME

                                    s.bormannS 1 Antwort Letzte Antwort
                                    0
                                    • dslraserD Offline
                                      dslraserD Offline
                                      dslraser
                                      Forum Testing Most Active
                                      schrieb am zuletzt editiert von dslraser
                                      #3395

                                      @s-bormann
                                      siehst Du eine Möglichkeit die Ansicht "sortierbar" bzw. die "Anzeigenreihenfolge" verschiebbar zu machen ? Ich hätte z.B. gern die Sender ganz oben (da wo jetzt Pad steht) und darunter EPG usw....

                                      Bildschirmfoto 2020-10-13 um 19.55.18.png

                                      EDIT: Zusatzfrage
                                      Kann man die Hintergrundfarbe der Button oder der ganzen Mediaplayer/Fernbedienung verändern ?
                                      Hintergrund: manche TV Logos haben teilweise transparente Inhalte und sind dann schlechter zu erkennen.

                                      Bildschirmfoto 2020-10-13 um 20.14.38.png

                                      s.bormannS 1 Antwort Letzte Antwort
                                      0
                                      • s.bormannS Offline
                                        s.bormannS Offline
                                        s.bormann
                                        Most Active
                                        schrieb am zuletzt editiert von
                                        #3396

                                        @dslraser hi, kannst Du mir bitte noch mal zeigen, wie genau bzw. in welchem Datenformat die Positionsdaten Deiner Familie in die Map kommen? Ggf. mit Screenshot vom Datenpunkt. Danke!

                                        dslraserD 1 Antwort Letzte Antwort
                                        0
                                        • s.bormannS s.bormann

                                          @dslraser hi, kannst Du mir bitte noch mal zeigen, wie genau bzw. in welchem Datenformat die Positionsdaten Deiner Familie in die Map kommen? Ggf. mit Screenshot vom Datenpunkt. Danke!

                                          dslraserD Offline
                                          dslraserD Offline
                                          dslraser
                                          Forum Testing Most Active
                                          schrieb am zuletzt editiert von
                                          #3397

                                          @s-bormann sagte in Test Adapter iQontrol 1.3.x:

                                          @dslraser hi, kannst Du mir bitte noch mal zeigen, wie genau bzw. in welchem Datenformat die Positionsdaten Deiner Familie in die Map kommen? Ggf. mit Screenshot vom Datenpunkt. Danke!

                                          Ich habe Dir per Chat geschrieben.

                                          s.bormannS 1 Antwort Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          522

                                          Online

                                          32.4k

                                          Benutzer

                                          81.4k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe