Navigation

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

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    Q
    • Profile
    • Following 0
    • Followers 0
    • Topics 72
    • Posts 859
    • Best 26
    • Groups 2

    Qlink

    @Qlink

    26
    Reputation
    211
    Profile views
    859
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Qlink Follow
    Pro Starter

    Best posts made by Qlink

    • RE: Windows Installer 2

      @klassisch said in Windows Installer 2:

      Und OneNote ist wohl auch abgekündigt.

      OT:

      Das hat sich Gott sei Dank wieder geändert : https://www.borncity.com/blog/2019/11/09/onenote-microsoft-legt-zukunftsplne-offen/

      Back to topic:

      ich stehe auch gerade vor der Wahl ob ich zukünftig wieder Windows (Server) als Betriebssystem für iobroker einsetze oder ob ich auf Linux umsteige sobald mein neuer Server geliefert wird ...
      Es ist leider schwierig objektive Meinungen zu finden, weil nur ganz wenige beide Welten gut kennen bzw. länger im Einsatz hatten und neutral ihre Erfahrungswerte kundtun ...
      Meistens lest man nur von Hardlinern der Windows Fraktion oder Hardlinern der Linux Fraktion ...

      Momentan tendiere ich (noch) zu Windows Server, da ich mich gut damit auskenne und die letzten Jahre ganz gut damit gefahren bin was iobroker betrifft und letztendlich auch immer alles so funktioniert hat wie ich das haben will.
      Es stimmt aber schon, dass leider viele Workarounds notwendig sind um so manche Funktionalität auf Windows zum Laufen zu bekommen ...
      Auch ist Windows, wenn man ein gepatchtes System haben will vorausgesetzt, schon alleine wegen der häufigen Reboots (mind. 2x im Monat) nicht gerade prädestiniert als Platform für ein Hausautomatisierungssystem...

      Da wäre Linux wohl wesentlich besser geeignet, aber mein Linux Know How ist höchstens als basic zu bewerten, was ebenfalls wieder einen erheblichen Mehraufwand für mich bedeuten würde ...

      Schwierige Sache mit der Wahl ...

      posted in Tester
      Q
      Qlink
    • RE: Windows Installer 2

      @Stabilostick said in Windows Installer 2:

      Hallo,

      melde mich zurück. Habe meine Entwicklungsumgebung upgedated und meinen Quellcode mit Stand vom März "durchgejagt".

      js-controller > 1.5.14 und < 2.2.10 haben einen Fehler, der dazu führt, dass bei der Installation von Adaptern wichtige javascript-Biblotheken manchmal sporadisch gelöscht werden. Auch deshalb die Auszeit.

      ioBroker wird jetzt, genau so wie Node.js, dynamisch über die GUI installiert. Allerdings noch ohne Service, Firewall usw. Das übernehme ich dann in den nächsten Tagen vom alten Setup. Diese Setup-Version ist also wieder nur ein technischer Schritt in Richtung fertigem Installer.

      http://iobroker.live/images/win/ioBroker-4-windows-installer.exe

      Viele Grüße
      Thomas

      @Stabilostick

      Ich weiß Zeitangaben sind immer schwierig in der Softwareentwicklung, ich versuchs dennoch:

      Kannst du schon in etwa abschätzen wann der Installer fertig sein wird ?

      Noch im Sommer ?
      Eher im Herbst ?
      Vermutlich Winter ?

      Beste Grüße

      posted in Tester
      Q
      Qlink
    • RE: Wallbox 22kw

      Hab mir die Keba KeContact P30x geholt: https://www.keba.com/de/emobility/products/x-series/x-serie

      Dazu gibts auch schon einen iobroker Adapter: https://github.com/UncleSamSwiss/ioBroker.kecontact

      Kann aber noch keine Erfahrungen berichten, weil der Elektriker das Ding erst in den nächsten 4 Wochen installieren wird...
      Sobald ich die Wallbox im Betrieb habe, kann ich aber gerne Rückmeldung geben ...

      Beste Grüße

      posted in Hardware
      Q
      Qlink
    • RE: Pool Dosierscript PH und Chlor

      @D3ltoroxp

      Hast du das Script dann eigentlich stabil zum Laufen gebracht und hast es im Einsatz ?
      Ich bin nämlich ebenfalls auf der Suche nach einer Blockly Version für die Dosierung von PH und Chlor.

      Ein funktionierender Export würde mir da sehr helfen.

      Danke.

      Beste Grüße

      posted in Blockly
      Q
      Qlink
    • RE: [Suche] LAN oder Wlan 6fach oder mehr Steckdosenleiste

      guck mal bei anel vorbei:

      https://de.anel.eu/produkte/adv/adv.htm

      hab mir die gerade vor kurzem geholt... lässt sich per http befehle steuern

      posted in Marktplatz
      Q
      Qlink
    • RE: Test Adapter Husqvarna Automower v0.3.x

      @StM47 Vielen Dank für das zur Verfügung stellen der View !

      Habs bei mir gleich auch mal importiert und schon etwas auf meine Bedürfnisse angepasst.
      Feintuning und weitere Anpassungen folgen noch ...
      7497ef56-3f67-4b63-90d7-7e3c8f77aa5d-image.png

      Falls jemand das transparente Husqvarna Automower Piktogramm für den View Button haben will, das ich schnell zusammengebastelt habe, hier bitteschön:

      maehroboter-trans.png

      Beste Grüße

      posted in Tester
      Q
      Qlink
    • RE: Stromverbrauch iobroker Server

      Ich bin vor kurzem ebenfalls von VMs auf Docker geswitcht und war/bin positiv überrascht.

      Zur Info bzgl Stromverbrauch:

      Hardware: Synology DS1821+ mit 4x 3,84TB SSDs (Kingston DC500M) im Raid 5, 20GB RAM und Dualport 10G Karte

      Ich habe aktuell 8 Container auf dem System laufen und nutze es zusätzlich als Fileserver bzw. Archiv und Backupserver für meine Clients (Active Backup for Business, sowie Active Backup for M365).

      Der Stromverbrauch schwankt zwischen 35W und 40W, womit ich durchaus zufrieden bin, wenn ich die Möglichkeiten und die gebotene Leistung gegenüberstelle.

      Was ich zusätzlich sehr schätze ist die Immutable Snapshot Funktionalität von Synology, die mir schon einmal bei einer Ransomware Attacke "das Leben gerettet" hat.
      Die Snapshots repliziere ich tägliche auf meinen alten HP Microserver N36L mit Xpenology, der sich für 1h einschaltet und danach wieder schlafen geht...
      Als Notnagel gehts per HyperBackup 1x im Monat noch auf eine externe USB HDD, die dann in der Schublade landet.

      Beste Grüße

      posted in Hardware
      Q
      Qlink
    • RE: Das Ultimative Markisen / Rolladen Blockly - Script

      @simatec

      Das sehe ich auch so, ich kriegs aber mit shuttercontrol nicht hin...
      So wie ich die Funktionsweise von shuttercontrol interpretiere (siehe Screenshots im oben verlinkten Thread) klappts nicht. Das meinte ich mit "Der Adapter entspricht (offentsichtlich) nicht meiner Denkweise"

      Daher das Ausweichen auf Blockly...

      Beste Grüße

      posted in Skripten / Logik
      Q
      Qlink
    • RE: Test Adapter Husqvarna Automower v0.3.x

      Also der Adapter läuft bei mir bisher problemlos und macht das was er soll... Wie lange das noch so läuft lässt sich natürlich nicht abschätzen ...
      Da der Adapter auf Github liegt, besteht ja die Chance, dass ihn jemand weiterentwickelt, falls greyhound sich nicht mehr melden sollte.

      posted in Tester
      Q
      Qlink
    • RE: PH / Redox Sensoren für Pool

      Ich verwende den neueren W2839 mit dem TUYA Adapter.

      Zum Messen der Werte verwende ich eine Acrylglas Messzelle von Gemke bei meiner D50 Festverrohrung:

      ca744675-8093-49b2-872c-59535d075e7d-image.png

      Die Doppel Bypass Messzelle von Gemke geht natürlich auch:

      14932b70-bc7b-4f9e-a756-87df33d6ffae-image.png

      Beste Grüße

      posted in Hardware
      Q
      Qlink

    Latest posts made by Qlink

    • RE: SMA Forecast Charging mit APG möglich ?

      @arteck

      Danke für die Rückmeldung, aber das hilft mir leider nicht wirklich weiter.

      Wie kann ich das lösen bzw. was ist die Ursache, dass das Array leer ist ?
      Wo liegt das Problem ?

      Beste Grüße

      posted in Skripten / Logik
      Q
      Qlink
    • RE: SMA Forecast Charging mit APG möglich ?

      @arteck

      das ist mir soweit klar...

      Jedoch hab ich in diesen Bereichen des Scripts nichts verändert (weil ist ja im Abschnitt "ab hier nix ändern")

      Zeile 156:

              const endtime   = Date.parse(array[i].period_end);
      

      bzw. hier ein größerer Ausschnitt der function:

      function datenErzeugen(array, seite) {
          const list          = [];  
          let heute           = true;
      
          for (let i = 0; i < array.length; i++) {                              
              const endtime   = Date.parse(array[i].period_end);
              const startTime = new Date(endtime - 1800000);
      
              let wert1   = array[i].pv_estimate;
              let wert2   = array[i].pv_estimate;
      
              switch(prognose1) {
                  case 1:
                      wert1 = array[i].pv_estimate10;
                      break;
                  case 2:
                      wert1 = array[i].pv_estimate90;
                      break;
                  default:
                      // nix
              } 
      
              switch(prognose2) {
                  case 1:
                      wert2 = array[i].pv_estimate10;
                      break;
                  case 2:
                      wert2 = array[i].pv_estimate90;
                      break;
                  default:
                      // nix
              } 
      
              list[i] = {
                  starttime: startTime / 1000,
                  endtime: endtime / 1000,
                  wert1: Math.round(wert1 * 1000),
                  wert2: Math.round(wert2 * 1000),
              };
      
           //   console.warn('list ' + JSON.stringify(list));
          }
      

      Was soll hier falsch sein ?

      Beste Grüße

      posted in Skripten / Logik
      Q
      Qlink
    • RE: SMA Forecast Charging mit APG möglich ?

      @arteck

      Ich bin dieses WE schon ein Stückchen weiter gekommen. Die DPs sind nun großteils alle angelegt worden.

      Den einen oder anderen Fehler bekomme ich allerdings noch angezeigt.
      Aber der Reihe nach.

      Ich würde gerne zuerst mal das get_solcast_data script zum Laufen bekommen.
      Ich bekomme folgende Fehlermeldungen im Log:

      2025-07-14 06:01:00.652 - error: javascript.0 (26929) script.js.PV_Regelung.get_solcast_data: TypeError: Cannot read properties of undefined (reading 'length')
      2025-07-14 06:01:00.652 - error: javascript.0 (26929) at datenErzeugen (script.js.PV_Regelung.get_solcast_data:156:31)
      2025-07-14 06:01:00.652 - error: javascript.0 (26929) at Object. (script.js.PV_Regelung.get_solcast_data:145:13)
      2025-07-14 06:01:00.652 - error: javascript.0 (26929) at /opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1228:38
      2025-07-14 06:01:00.652 - error: javascript.0 (26929) at processTicksAndRejections (node:internal/process/task_queues:95:5)
      2025-07-14 06:01:00.659 - info: javascript.0 (26929) State value to set for "0_userdata.0.Stromversorgung.pvforecast.response" has to be type "string" but received type "object"
      

      Hier das Script mit meinen ausgefüllten Daten: (meine key_id habe ich mit xxxx maskiert)

      // @ts-ignore
      const moment = require('moment');
      const options = { hour12: false, hour: '2-digit', minute: '2-digit' };
      
      // welche javascript instanz wird genutzt, für diese muss in Einstellungen ASTRO Zeit generierung aktiviert sein 
      const javascriptI = 'javascript.0';    
      
      // zum ändern ab hier
      const summeDpAnlegen = true;   // einmalig manuell für 24h auf true setzten, es werden summen Dp's angelegt   <<<<<<<<-----------------------------------  wichtig
      
      const key_id    = "xxxx-xxxx-xxxx-xxxx";
      
      const seite1    = 'Gesamt';                     // name dp1  frei wählbar, sonne vormittags 
      const seite1Key = "xxxx-xxxx-xxxx-xxxx";
      
      const seite2    = '';                    //name dp2  frei wählbar, sonne nachmittags, leer wenn nur eine Seite genutzt wird
      const seite2Key = "yyyy-yyyy-yyyy-yyyy";        // nicht ändern wenn nicht genutzt
      
      const gesamt    = 'gesamt';                     // dp für zusammenrechnen muss in ladenNachPrognose angepasst werden wenn hier geändert
      
      const _influxDb                     = false;   // wenn grafana output erwünscht benötigt wird eine influx.0 instanz
      const  influxInstance               = 'influxdb.0';
      const _influxDbMeasurementGesamt    = 'pvforecast.0.summary.power';
      const _influxDbMeasurementStrasse   = 'pvforecast.0.plants.strasse.power';
      const _influxDbMeasurementGarten    = 'pvforecast.0.plants.garten.power';
      
      const mainObject            = '0_userdata.0.Stromversorgung.pvforecast';
      const mainObjectToday       = '0_userdata.0.Stromversorgung.pvforecast.today';
      const mainObjectTomorrow    = '0_userdata.0.Stromversorgung.pvforecast.tomorrow';
      const _abbrechenBei         = '00:00';   // ab wieviel Uhr kommt nix mehr, kann so bleiben
      
      // pv_estimate   – Der Realist: Dies ist sozusagen die Standardvorhersage. Denk an ihn als den durchschnittlichen Wert, basierend auf den aktuellen Wetterdaten und Modellen. Er sagt uns, was wir in einem normalen Szenario erwarten können – weder zu optimistisch noch zu pessimistisch.
      // pv_estimate10 – Der Vorsichtige: Jetzt wird's interessant. Dieser Wert ist die 10. Perzentile, also eher auf der niedrigen Seite. Er sagt uns, dass es eine 90 %ige Chance gibt, dass die tatsächliche Leistung höher ausfällt. Wenn du also lieber auf Nummer sicher gehst und nicht gerne enttäuscht wirst, ist das dein Wert.
      // pv_estimate90 – Der Optimist: Im Gegensatz zum pv_estimate10 zeigt uns der pv_estimate90 die sonnige Seite. Dieser Wert ist die 90. Perzentile – eine Art Best-Case-Szenario. Hier sagen die Daten, dass es nur eine 10 %ige Chance gibt, dass die Leistung diesen Wert überschreitet. Ideal, wenn du die Dinge gerne von der besten Seite betrachtest.​
      let prognose1              = 1;    // 0 = realistisch, 1 = vorsichtig, 2 = optimistisch
      let prognose2              = 0;    // 0 = realistisch, 1 = vorsichtig, 2 = optimistisch
      const ersteTagAbfrage      = seite2;   // wir brauchen morgends werte, welche Seite soll zuerst abgefragt werden
      
      //-------------------------------------------------------------
      
      const _baseUrl = "https://api.solcast.com.au/rooftop_sites/";
      const _hours = 24;
      
      let _tickerAbholung = 0;
      let _errorMrk = false;
      
      let _aufrufUrl   = '';
      let _aufrufSeite = '';
      
      // ------------------------------------------------------------------------------------------------------------------
      
      //                       zum testen
      //const testDaten = getState(`${mainObject}.response`).val;
      //datenErzeugen(JSON.parse(testDaten), seite2);
      
      //  initialisiere einmal in den nacht um 2 Uhr
      schedule({ astro: 'sunset' }, () => {
          _tickerAbholung = 0;
      });
      
      schedule({ astro: 'sunrise' }, () => {
          initialPV();
      
          if (seite2.length > 0) {
              _aufrufUrl   = `${seite2Key}/forecasts?format=json&api_key=${key_id}`;
              _aufrufSeite = seite2;
              toLog(`Hole PV ${_aufrufSeite}`, true);
              requestData(_aufrufUrl, _aufrufSeite);
          }
      
          _aufrufUrl   = `${seite1Key}/forecasts?format=json&api_key=${key_id}`;
          _aufrufSeite = seite1;
          toLog(`Hole PV ${_aufrufSeite}`, true);
          requestData(_aufrufUrl, _aufrufSeite);
      
          _tickerAbholung = +1;
      });
      
      
      schedule('1 6 * * *', function () {   // um 6 immer abholen damit wir morgen gültige Tageswerte haben    
          if (_tickerAbholung < 1) {     // wurde schon mal abgeholt
              _aufrufUrl   = `${seite2Key}/forecasts?format=json&api_key=${key_id}`;
              _aufrufSeite = ersteTagAbfrage;
              requestData(_aufrufUrl, _aufrufSeite);
          }
      });
      
      // 10 request sind frei bei solcast.com
      schedule('1 7,9,10 * * *', function () {
          const _hhJetzt  = getHH();
          const sunup = getState(javascriptI + '.variables.astro.sunrise').val;  
          
          let seite = seite1;
          if (seite2.length > 0) { 
              seite = seite2;
          }
      
          if (_hhJetzt >= parseInt(sunup.slice(0, 2)) && seite2.length > 0) {  
              _aufrufUrl   = `${seite2Key}/forecasts?format=json&api_key=${key_id}`;
              _aufrufSeite = seite;
              requestData(_aufrufUrl, _aufrufSeite);
              _tickerAbholung = +1;
          }
      });
      
      schedule('2 8,12,13,15 * * *', function () {
          const _hhJetzt            = getHH();
          const sunup = getState(javascriptI + '.variables.astro.sunrise').val;  
          
          if (_hhJetzt >= parseInt(sunup.slice(0, 2))) {     
              _aufrufUrl   = `${seite1Key}/forecasts?format=json&api_key=${key_id}`;
              _aufrufSeite = seite1;
              requestData(_aufrufUrl, _aufrufSeite);
              _tickerAbholung = +1;
          }
      });
       
      schedule('5,10,15 * * * *', function () {
          if (_errorMrk) {
              toLog(`ERROR - Hole PV ${_aufrufSeite} ticker ${_tickerAbholung}`, true);
              requestData(_aufrufUrl, _aufrufSeite);
              _tickerAbholung = +1;
          }
      });
       
      // ------------------------------------------------------------------------------------------------------------------
      
      /*************** ab hier nix ändern  ***************************** */
      

      "Create states for all astro times" ist aktiviert im javascript Adapter.

      Habe ich was zum Ausfüllen übersehen ?
      Ich kann die Fehler leider nicht zuordnen.

      Die DPs werden angelegt, aber es sind alle nur mit 0W befüllt:
      2b5e2869-fb95-481d-935b-788bd1ec085f-image.png

      Vielen Dank für deine Hilfe.

      Beste Grüße

      posted in Skripten / Logik
      Q
      Qlink
    • RE: SMA Forecast Charging mit APG möglich ?

      @arteck

      Ah, okay das wusste ich nicht.
      Hab ich erledigt.

      Wenn ich das Script startet kommen im Log nun folgende Fehlermeldungen:

      ef76261f-42ec-4853-a7da-f2425c8efdb7-image.png

      Der DP "0_userdata.0.Stromversorgung.apg.extra.apgNutzenManuell" scheint nicht angelegt zu werden vom Script, daher wohl auch die Meldung dass er ihn nicht findet...

      Diese DPs sind angelegt worden:
      b4611e8d-1c49-42d6-8bc9-07cc7c97f56d-image.png

      posted in Skripten / Logik
      Q
      Qlink
    • RE: SMA Forecast Charging mit APG möglich ?

      @arteck said in SMA Forecast Charging mit APG möglich ?:

      @qlink du hast nicht alles so kopiert wie es sein sollte

      c876e483-e3c7-44ef-96f0-9b213ff3968e-grafik.png

      die müssen unter global scripts

      Stimmt, das global_scripts.js ist noch "original".
      Ich habs mir allerdings durchgeschaut und finde keine Stellen die ich offensichtlich anpassen muss.

      Kannst du mir hier helfen und sagen was ich hier wo anpassen muss ?

      Danke.

      Beste Grüße

      posted in Skripten / Logik
      Q
      Qlink
    • RE: SMA Forecast Charging mit APG möglich ?

      @arteck

      Danke für deine Rückmeldung.
      Dann versuche ich gerne selbst mein Glück, trotz meiner bescheidenen Scripting Skills.

      Ich hab das Script wie folgt nach bestem Wissen und Gewissen angepasst:

      const _apg = 'apg-info.0.marketprice.';     // Anpassen!
      
      const _apgDP1 = '0_userdata.0';
      const _apgDP2 = 'Stromversorgung.apg.';
      const _apgDP  = _apgDP1 + '.' + _apgDP2;
      
      const options = { hour12: false, hour: '2-digit', minute:'2-digit'};
         
      // bei jeder preisänderung wird die neue Stunde mit dem niedrigen Preis für die vis übernommen
      const apgPreisUebermnehmen = true;
      // 
      const _apgLevelErmitteln = false;
      
      createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgPvForcast', { 'name': 'apg formattierung für pv prognose', 'type':'array', 'read': true, 'write': false, 'role': 'json'}], function () {  }); 
      createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgPvForcastTomorrow', { 'name': 'apg rest preise für morgen', 'type':'array', 'read': true, 'write': false, 'role': 'json'}], function () {  }); 
      createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgBestPreisArrayLang', { 'name': 'apg bester preis als array', 'type':'array', 'read': true, 'write': false, 'role': 'json'}], function () {  });
      createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgBestPreisArrayLangTomorrow', { 'name': 'apg bester preis als array für Morgen', 'type':'array', 'read': true, 'write': false, 'role': 'json'}], function () {  });
      
      createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgBestPreis', { 'name': 'apg Best Preis', 'type':'number', 'read': true, 'write': false, 'role': 'state', 'def':0 , "unit": "ct" }], function () {      
        setState(_apgDP + 'extra.apgBestPreis', 0, true);
      }); 
      
      createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgPreisJetzt', { 'name': 'apg Preis Jetzt', 'type':'number', 'read': true, 'write': false, 'role': 'state', 'def':0, "unit": "ct" }], function () {        
        setState(_apgDP + 'extra.apgPreisJetzt', 0, true);
      }); 
      
      createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgPreisNächsteStunde', { 'name': 'apg Preis Nächste Stunde', 'type':'number', 'read': true, 'write': false, 'role': 'state', 'def':0, "unit": "ct" }], function () {        
        setState(_apgDP + 'extra.apgPreisNächsteStunde', 0, true);
      }); 
      
      if (_apgLevelErmitteln) {
          createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgLevelJetzt', { 'name': 'Preis Level', 'type':'string', 'read': true, 'write': false, 'role': 'text',  'def': '' }], function () {        
              setState(_apgDP + 'extra.apgLevelJetzt', '', true);
          });  
      
          createUserStates(_apgDP1, false, [_apgDP2 + 'extra.apgLevelNächsteStunde', { 'name': 'Preis Level', 'type':'string', 'read': true, 'write': false, 'role': 'text',  'def': '' }], function () {        
              setState(_apgDP + 'extra.apgLevelNächsteStunde', '', true);
          }); 
      }
      
      holePreis();
      preisJetzt();
      
      function holePreis() {
          let preiseHeute = [];
          let preiseMorgen = [];
          let preisePV = [];
          let preisePVTommorow = [];
          
          const arr1 = JSON.parse(getState(_apg +'today.jsonChartPricesToday.json').val);
          const arr2 = JSON.parse(getState(_apg +'tomorrow.jsonChart').val);
          let arrPrice = arr1;
      
          let now = new Date();
      
          if (arr2.length > 0) {
              now.setMinutes(0, 0, 0);
              const heutePreise = arrPrice.filter(price => new Date(price.startsAt) >= now);
              arrPrice = heutePreise.concat(arr2);           // füge beide zusammen
             
          } else {
              now.setHours(0, 0, 0, 0);
          }
          
          const next24Hours = new Date(now.getTime() + 24 * 60 * 60 * 1000);
      
          for (let i = 0; i < arrPrice.length; i++) {
              const element       = arrPrice[i];
              const startsAt      = element.startsAt;
              const start         = new Date(startsAt);
              const preis         = element.total;
              const end           = new Date(Date.parse(startsAt)).getTime()+3600000;            
              const startTime     = start.toLocaleTimeString('de-DE', options);
              const endTime       = new Date(end).toLocaleTimeString('de-DE', options);
              const hhStartTime   = startTime.split(':')[0];
      
              let objHeute = {};
                  
              if (start >= now && start < next24Hours) {        
      //      console.warn(`Starts at: ${start}, Total: ${preis}`);
                  objHeute.start = start.getHours();
                  objHeute.preis = preis;
                  preiseHeute.push(objHeute);
      
                  preisePV.push([preis, startTime , hhStartTime + ':30']);
                  preisePV.push([preis, hhStartTime + ':30', endTime]);            
              }
          }
      
      // preise für morgen für die VIS
          for (let m = 0; m < arr2.length; m++) {
              const element       = arr2[m];
              const startsAt      = element.startsAt;
              const start         = new Date(startsAt);
              const preis         = element.total;
              const end           = new Date(Date.parse(startsAt)).getTime()+3600000;            
              const startTime     = start.toLocaleTimeString('de-DE', options);
              const endTime       = new Date(end).toLocaleTimeString('de-DE', options);
              const hhStartTime   = startTime.split(':')[0];
      
              let objMorgen = {
                  start : start.getHours(),
                  preis : preis
              };
                         
              preiseMorgen.push(objMorgen);
      
              preisePVTommorow.push([preis, startTime , hhStartTime + ':30']);
              preisePVTommorow.push([preis, hhStartTime + ':30', endTime]);        
          }       
      
          let preiseSortLang = preiseHeute;
          preiseSortLang.sort(function(a, b) {
              return a.start - b.start;
          });
      
          let preiseSortLangTomorrow = preiseMorgen;
          preiseSortLangTomorrow.sort(function(a, b) {
              return a.start - b.start;
          });
          
          const preisePVSort = sortArrayByStartTime(preisePV, getHH());
          
          setState(_apgDP + 'extra.apgBestPreisArrayLang', preiseSortLang, true);
          setState(_apgDP + 'extra.apgBestPreisArrayLangTomorrow', preiseSortLangTomorrow, true);
          
          setState(_apgDP + 'extra.apgPvForcast', preisePVSort, true);
          setState(_apgDP + 'extra.apgPvForcastTomorrow', preisePVTommorow, true);
      
          errechneBesteUhrzeit(preiseSortLang);
      }
      
      function sortArrayByStartTime(array, currentHour) {
          // Sortiere den Array nach der Startzeit
          array.sort((a, b) => {
              const timeA = a[1].split(":").map(Number);
              const timeB = b[1].split(":").map(Number);
              
              // Vergleiche Stunden
              if (timeA[0] != timeB[0]) {
                  return timeA[0] - timeB[0];
              }
              
              // Wenn Stunden gleich sind, vergleiche Minuten
              return timeA[1] - timeB[1];
          });
      
          // Finde den Index des aktuellen Zeitpunkts
          let startIndex = array.findIndex(item => {
              const time = item[1].split(":").map(Number);
              return time[0] >= currentHour || (time[0] == currentHour && time[1] >= 30);
          });
      
          // Schneide den Array ab startIndex und setze ihn an das Ende
          const sortedArray = array.slice(startIndex).concat(array.slice(0, startIndex));
      
          return sortedArray;
      }
      
      
      
      function errechneBesteUhrzeit(allePreise) {
          const [niedrigsterIndex, zweitNiedrigsterIndex] = findeBenachbarteNiedrigstePreise(allePreise);
          const preiseKurzArr = [];
      
          preiseKurzArr.push(allePreise[niedrigsterIndex]);
          preiseKurzArr.push(allePreise[zweitNiedrigsterIndex]);
          startZeit(preiseKurzArr);
      }
      
      function findeBenachbarteNiedrigstePreise(preisArray) {     
          let niedrigsterPreisSumme = Number.POSITIVE_INFINITY;
          let niedrigsterPreisIndex1 = -1;
          let niedrigsterPreisIndex2 = -1;
      
          for (let i = 0; i < preisArray.length - 1; i++) {
              // wir bilden eine summer
              const summe = preisArray[i].preis + preisArray[i + 1].preis;
      
              // Prüfe, ob diese Summe kleiner als die bisher niedrigste ist
              if (summe < niedrigsterPreisSumme) {
                  niedrigsterPreisSumme = summe;
                  niedrigsterPreisIndex1 = i;
                  niedrigsterPreisIndex2 = i + 1;
              }
          }
      
          if (niedrigsterPreisIndex1 > niedrigsterPreisIndex2) {
              let temp = niedrigsterPreisIndex1;
              niedrigsterPreisIndex1 = niedrigsterPreisIndex2;
              niedrigsterPreisIndex2 = temp;        
          }
      
          // gebe den index raus
          return [niedrigsterPreisIndex1, niedrigsterPreisIndex2];
      }
      
      function startZeit(preiseKurz) {   
          const apgNutzenManuell = getState(_apgDP + 'extra.apgNutzenManuell').val; 
      
          const start = preiseKurz[0].start;
          const preis = preiseKurz[0].preis;
      
          preiseKurz.splice(0, 1);
      
          if (apgPreisUebermnehmen && !apgNutzenManuell) {
              setState(_apgDP + 'extra.apgNutzenManuellHH', start, true);
              setState(_apgDP + 'extra.apgBestPreis', preis, true);     
          }
      }
      
      function preisJetzt() {
          let hh          = Number(getHH());
          let preis       = getState(_apg + 'today.' + hh + '.total').val;
          let apgLevel = getState(_apg + 'today.' + hh + '.level').val;
      
          setState(_apgDP + 'extra.apgPreisJetzt', preis, true);
      
          if (_apgLevelErmitteln) {    
              setState(_apgDP + 'extra.apgLevelJetzt', apgLevel, true);
          }
      
          hh = hh + 1;
          if (hh > 23) {
              hh = 0;
          }
          
          preis       = getState(_apg + 'today.' + hh + '.total').val;
          setState(_apgDP + 'extra.apgPreisNächsteStunde', preis, true);
      
          if (_apgLevelErmitteln) {    
              apgLevel = getState(_apg + 'today.' + hh + '.level').val;
              setState(_apgDP + 'extra.apgLevelNächsteStunde', apgLevel, true);
          }
      }
      
      schedule('0 * * * *', function () {
          holePreis();
          preisJetzt();
      });
      

      Wenn ich es starte erhalte ich allerdings folgende Fehlermeldungen und es werden keine DPs unter "Objects" angelegt:

      12bebbe4-ff77-460a-a123-bc07d9682ec6-image.png

      Hast du eine Idee wo ich einen Fehler eingebaut habe ?

      Danke.

      Beste Grüße

      posted in Skripten / Logik
      Q
      Qlink
    • SMA Forecast Charging mit APG möglich ?

      Hi Leute,

      ich habe folgende PV Anlage bei mir:

      1x SMA Sunny Tripower 10 SE
      1x SMA Sunny Tripower 10
      1x SMA Sunny Home Manager 2.0
      1x BYD HVM 22.1

      Ich würde damit gerne die SMA Forecast Charging Lösung von @arteck hier: https://github.com/arteck/SMA_forecast_charging nutzen.
      Da ich allerdings in Österreich wohne und meine dynamischen Stromtarifdaten per APG Adapter hier: https://github.com/HGlab01/ioBroker.apg-info in iobroker reinbekomme, stellt sich für mich nun folgende Frage:

      Ist es möglich die Forecast Charging Lösung auch anstatt der Tibber Daten mit den APG Daten zu nutzen ?
      Falls ja, was müsste ich dazu anpassen, oder könnte jemand die Scripte entsprechend erweitern ?
      So würde die Lösung einem noch größeren Publikum von Nutzen sein.

      Hier noch ein Screenshot wie die Daten aus dem APG Adapter verfügbar sind:
      3073a9ee-60d4-4af1-a509-cc68d627e30a-image.png

      Beste Grüße

      posted in Skripten / Logik
      Q
      Qlink
    • RE: Blockly für Sturmerkennung so korrekt ?

      @paul53

      Vielen Dank für deine Hilfe!

      Lässt sich der Mehrverbrauch an Ressourcen durch diese "nicht optimale" Art Skripte quantifizieren ?

      posted in Blockly
      Q
      Qlink
    • RE: Blockly für Sturmerkennung so korrekt ?

      @paul53

      okay, habe ich somit jetzt alles richtig verstanden und zusammen geklickt ?

      146e0ec4-1997-4502-b145-b7761aee1361-image.png

      posted in Blockly
      Q
      Qlink
    • RE: Blockly für Sturmerkennung so korrekt ?

      @paul53

      "falls nicht sturm" in deinem Blockly ist gleichzusetzen mit "falls Wind < 40" richtig ?
      "sonst falls sturm" in deinem Blockly ist gleichzusetzen mit "falls Wind > 40" richtig ?

      Was das "und nicht Verzögerung timeout" bedeutet kann ich mir aber leider nicht zusammenreimen.
      Kannst du mir das in Worten erklären ?

      Beste Grüße

      posted in Blockly
      Q
      Qlink
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo