Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Log Error aus Script: Read-only state ... written without...

    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

    Log Error aus Script: Read-only state ... written without...

    This topic has been deleted. Only users with topic management privileges can see it.
    • rtwl
      rtwl last edited by rtwl

      Ich hab mir dieses Script kopiert: https://github.com/Mic-M/iobroker-pflanzen-giessen-script/blob/master/pflanzen-giessen-script.js
      Alle 3 Stunden kommt allerdings eine Fehlermeldung im Log, den ich zwar theoretisch verstehe, aber zu unwissend bin ihn zu beheben.

      Kann mir hier bitte jemand helfen?

      2023-02-12 21:05:00.102 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.Entkalken.daysOverdue" has been written without ack-flag with value "0"
      2023-02-12 21:05:00.103 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.Entkalken.daysLeft" has been written without ack-flag with value "59"
      2023-02-12 21:05:00.106 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.Entkalken.daysElapsed" has been written without ack-flag with value "1"
      2023-02-12 21:05:00.107 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.Entkalken.isOverdue" has been written without ack-flag with value "false"
      2023-02-12 21:05:00.108 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.Entkalken.percentElapsed" has been written without ack-flag with value "2"
      2023-02-12 21:05:00.109 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.Entkalken.level" has been written without ack-flag with value "green"
      2023-02-12 21:05:00.149 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenUG.daysOverdue" has been written without ack-flag with value "0"
      2023-02-12 21:05:00.151 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenUG.daysLeft" has been written without ack-flag with value "6"
      2023-02-12 21:05:00.154 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenUG.daysElapsed" has been written without ack-flag with value "1"
      2023-02-12 21:05:00.155 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenUG.isOverdue" has been written without ack-flag with value "false"
      2023-02-12 21:05:00.156 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenUG.percentElapsed" has been written without ack-flag with value "14"
      2023-02-12 21:05:00.157 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenUG.level" has been written without ack-flag with value "green"
      2023-02-12 21:05:00.157 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenOG.daysOverdue" has been written without ack-flag with value "0"
      2023-02-12 21:05:00.158 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenOG.daysLeft" has been written without ack-flag with value "6"
      2023-02-12 21:05:00.158 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenOG.daysElapsed" has been written without ack-flag with value "1"
      2023-02-12 21:05:00.159 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenOG.isOverdue" has been written without ack-flag with value "false"
      2023-02-12 21:05:00.160 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenOG.percentElapsed" has been written without ack-flag with value "14"
      2023-02-12 21:05:00.160 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.PflanzenOG.level" has been written without ack-flag with value "green"
      

      Mein personalisierter Code (Datenpunkt, usw). Vielleicht hab ich ja was falsch geändert?
      PS: Keine Ahnung woher diese "... created this issue in" herkommt.

      /**************************************************************************************************
       * Script "Timer" (ehemals: "Pflanzen gießen")
       * -------------------------------------------------------------------------------------
      
       * Autor:            Mic (ioBroker) | Mic-M (github)
       * Change Log
       *  0.3 Mic  Support creating states under 0_userdata.0
       *  0.2 Mic  Diverse Verbesserungen
       *  0.1 Mic  Initial version
       **************************************************************************************************/
      
      
      /*******************************************************************************
       * Konfiguration: Pfade / Datenpunkte
       ******************************************************************************/
      // Pfad, unter dem die States (Datenpunkte) in den Objekten angelegt werden.
      // Es wird die Anlage sowohl unterhalb '0_userdata.0' als auch 'javascript.x' unterstützt.
      //const STATE_PATH = 'javascript.'+ instance + '.' + 'VIS.Timer';
      const STATE_PATH = '0_userdata.0.VIS.Timer';
      
      // Beliebig viele einzelne Timer anlegen.
      // Zeilen leer lassen oder löschen, falls nicht benötigt.
      const TIMERS = [
          {'state': 'PflanzenOG', 'name': 'Pflanzen OG gießen'},
          {'state': 'PflanzenUG', 'name': 'Pflanzen UG gießen'},
          {'state': 'Entkalken', 'name': 'Geräte entkalken'},
          {'state': '', 'name': ''},
      ];
      
      
      // Datenpunkte: Einzelne Datenpunkte.
      // Kein Grund zur Änderung! Einfach so belassen.
      const STATE_INTERVAL        = 'interval';           // Number - Wie oft gießen? Anzahl Tage
      const STATE_RESTART         = 'reStartCounter';     // true (Button) - Neustart Zähler: Wir fangen neu an zu zählen, wird betätigt sobald die Pflanzen gegossen worden sind
      const STATE_OVERDUE         = 'isOverdue';          // true/false.  Wenn "faellig", dann müssen die Pflanzen gegossen werden. Wird false gesetzt, sobald Counter neu startet
      const STATE_PERCENT_ELAPSED = 'percentElapsed';     // Wann fällig, in %. D.h. bei 10 Tagen 'anzahlTageBisFaellig', und vor 3 Tagen gegossen = 30%
      const STATE_DAYS_OVERDUE    = 'daysOverdue';        // Number.  Anzahl Tage, seit dem die Pflanzen gegossen werden müssten (aber es noch nicht sind)
      const STATE_DAYS_LEFT       = 'daysLeft';           // Number.  Anzahl Tage, bis die Pflanzen gegossen werden müssen
      const STATE_DAYS_ELAPSED    = 'daysElapsed';        // Number.  Anzahl Tage, seit dem der Timer gestartet wurde
      const STATE_DATETIMESTART   = 'dateTimeCounterStart';   // Date/Time.  Wann wurde der Timer gestartet
      const STATE_LEVEL           = 'level';              // Grün / Gelb / Rot, je nach % vergangen. Siehe Konfiguration Schwellwerte
      
      
      /*******************************************************************************
       * Konfiguration: Rest
       ******************************************************************************/
      
      // Schwellwerte in %: Im Datenpunkt ".level" wird green/yellow/red ausgegeben, je nach Datenpunkt 'faelligProzent'.
      // Bitte einen Bereich angeben: [20, 40]: Bedeutet, dass %-Wert zwischen 20 und 40 liegen muss.
      const LEVEL_GREEN =  [0, 85];
      const LEVEL_YELLOW = [86, 99];
      const LEVEL_RED =    [100, 99999999];
      
      
      
      // Wie oft aktualisieren?
      const PLANTS_SCHEDULE = '5 */3 * * *'; // Alle 3 Stunden.
      
      // Logeinträge anzeigen?
      const LOGINFO = true;
      
      // Default: Anzahl Tage.
      // Kann jederzeit im State 'interval' geändert werden.
      const INTERVAL_PRESET = 14;
      
      
      /*************************************************************************************************************************
       * Ab hier nichts mehr ändern / Stop editing here!
       *************************************************************************************************************************/
      
      /****************************************************************************************
       * Global variables and constants
       ****************************************************************************************/
      // Final state path
      const FINAL_STATE_LOCATION = validateStatePath(STATE_PATH, false);
      const FINAL_STATE_PATH = validateStatePath(STATE_PATH, true) + '.'; // adding trailing dot
      
      // Schedule
      let mSchedule = [];
      
      
      /*******************************************************************************
       * Executed on every script start.
       *******************************************************************************/
      init();
      function init() {
       
          // Create states
          createUserStates(FINAL_STATE_LOCATION, false, buildScriptStates(), function() {
      
              // Main Script starten
              setTimeout(main, 2000);
      
          });
          
      }
      
      /*******************************************************************************
       * Haupt-Skript
       *******************************************************************************/
      function main() {
      
          for (let i = 0; i < TIMERS.length; i++) {
      
              // First: check if we have a valid configuration
              // TO DO: Further check TIMERS[i].state for valid state chars
              if (isLikeEmpty(TIMERS[i].state)) {
                  continue; // breaks current iteration in the loop and continues with the next
              }
      
              /***************************
               * Schedule beenden falls aktiv, dann starten.
               * Dies machen wir, damit z.B. bei JavaScript-Adapter-Neustart immer sichergestellt ist, dass das Schedule läuft.
               * Außerdem initiales Start-Datum setzen, falls nicht vorhanden.
               **************************/
              clearSchedule(mSchedule[i]);
      
              let dtStart = getState(FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DATETIMESTART).val;
              if ( (isNumber(dtStart)) && (dtStart > 0) ) {
                  mSchedule[i] = schedule(PLANTS_SCHEDULE, function() {
                      updateStates(TIMERS[i]);
                  });
                  if (LOGINFO) log('Timer ' + TIMERS[i].name + ': Script wurde neu gestartet. Ein Timer-Startdatum ist vorhanden, also wird nur aktualisiert.');
                  updateStates(TIMERS[i]);
              } else {
                  // Initial ist noch kein Start-Datum gesetzt, also setzen wir eines.
                  setState(FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DATETIMESTART, Date.now()); // Dies triggert automatisch updateStates(), da State STATE_DATETIMESTART per on(id) überwacht wird.
                  if (LOGINFO) log('Timer ' + TIMERS[i].name + ': Startdatum im State ist leer, daher werden Startdatum und Initialwerte frisch gesetzt.');
              }
      
              /***************************
               * Überwache State-Button reStartCounter
               **************************/
              on({id:FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_RESTART, val:true}, function (obj) {
                  // First_ need to get - within on...id - current state portion
                  let tmpArray = obj.id.split('.');
                  let statePortion = tmpArray[(tmpArray.length - 2)]
      
                  setState(FINAL_STATE_PATH + statePortion + '.' + STATE_DATETIMESTART, Date.now()); // Dies triggert automatisch updateStates(), da State STATE_DATETIMESTART per on(id) überwacht wird.
                  setStateDelayed(FINAL_STATE_PATH + statePortion + '.' + STATE_RESTART, false, 300); // wieder zurück setzen zur schönen Darstellung.
              });
      
              /***************************
               * Überwache State-Button interval, da diese Anzahl Tage vom User jederzeit geändert werden können
               **************************/
              on({id: FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_INTERVAL, change:'ne'}, function (obj) {
                  updateStates(TIMERS[i]);
              });
      
              /***************************
               * Überwache Datum/Uhrzeit Counter-Start, falls dieser manuell geändert wurde.
               **************************/
              on({id: FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DATETIMESTART, change:'ne'}, function (obj) {
                  updateStates(TIMERS[i]);
              });
      
              /***************************
               * Sobald die Planzen gegossen werden müssen, führen wir folgendes aus.
               * @param {object} objTimes  Objekt, also Array-Element von TIMERS
               **************************/
              function updateStates(objTimes) {
                  let now = new Date();
                  let nowTimeStamp = now.getTime();
      
                  let startTimeInState = new Date(getState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_DATETIMESTART).val);
                  let intervalInState = getState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_INTERVAL).val;
                  let dateTimeDue = dateAddMinutes(startTimeInState, intervalInState*60*24);
      
                  let numberOfMsDue = nowTimeStamp - dateTimeDue;  // https://stackoverflow.com/questions/7709803/javascript-get-minutes-between-two-dates
                  let numberOfMinutesDue = Math.floor((numberOfMsDue/1000)/60);
                  let numberOfDaysDue = Math.round((numberOfMinutesDue/60)/24);
      
                  let numberOfMsLeft      = dateTimeDue - nowTimeStamp;
                  let numberOfMinutesLeft = Math.floor((numberOfMsLeft/1000)/60);
                  let numberOfDaysLeft = Math.round((numberOfMinutesLeft/60)/24);
      
                  let numberOfMsElapsed = nowTimeStamp - startTimeInState.getTime();
                  let numberOfMinutesElapsed = Math.floor((numberOfMsElapsed/1000)/60);
                  let numberOfDaysElapsed = Math.round((numberOfMinutesElapsed/60)/24);
      
                  setState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_DAYS_OVERDUE, numberOfDaysDue);
                  setState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_DAYS_LEFT, numberOfDaysLeft);
                  setState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_DAYS_ELAPSED, numberOfDaysElapsed);
      
                  if ( dateTimeDue < nowTimeStamp ) {
                      // Jetzt die Pflanzen gießen
                      setState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_OVERDUE, true);
                      if (LOGINFO) log('Timer ' + objTimes.name + ': Prüfungsergebnis: Fällig seit ' + numberOfDaysDue + ' Tagen');
                  } else {
                      // Pflanzen noch nicht gießen
                      setState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_OVERDUE, false);
                      if (LOGINFO) log('Timer ' + objTimes.name + ': Prüfungsergebnis: Noch nicht fällig, erst in ' + numberOfDaysLeft + ' Tagen');
                  }        
                  // Setze Prozent
                  let percent = Math.round(numberOfDaysElapsed * 100 / intervalInState);
                  if (percent > 100) percent = 100;
                  setState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_PERCENT_ELAPSED, percent);
      
                  // Setze Level (Farben) je nach %
                  let levelResult = 'undefined';
                  if ( isInRange(percent, LEVEL_GREEN[0], LEVEL_GREEN[1]) ) levelResult = 'green';
                  if ( isInRange(percent, LEVEL_YELLOW[0], LEVEL_YELLOW[1]) ) levelResult = 'yellow';
                  if ( isInRange(percent, LEVEL_RED[0], LEVEL_RED[1]) ) levelResult = 'red';
                  setState(FINAL_STATE_PATH + objTimes.state + '.' + STATE_LEVEL, levelResult);
      
              }
      
          } // for
      
      }
      
      /*******************************************************************************
       * Weitere unterstützende Funktionen usw.
       *******************************************************************************/
      
      
      /**
       * Add certain number of minutes to a given date/time.
       * @param {object}    date      Provided date.
       * @param {number}    minutes   number of minutes to be added to a given date
       * @return {object}   new date with the minutes added
       */
      function dateAddMinutes(date, minutes) {
          return new Date(date.getTime() + minutes*60000);
      }
      
      /**
       * Prüft ob Variableninhalt eine Zahl ist.
       * isNumber ('123'); // true  
       * isNumber ('123abc'); // false  
       * isNumber (5); // true  
       * isNumber ('q345'); // false
       * isNumber(null); // false
       * isNumber(undefined); // false
       * isNumber(false); // false
       * isNumber('   '); // false
       * @source https://stackoverflow.com/questions/1303646/check-whether-variable-is-number-or-string-in-javascript
       * @param {any} n     Variable, die zu prüfen ist auf Zahl
       * @return {boolean}  true falls Zahl, false falls nicht.
        */
      function isNumber(n) { 
          return /^-?[\d.]+(?:e-?\d+)?$/.test(n); 
      }
      
      /**
       * Checks if a number is within a range. Returns true if in range, and false otherwise.
       * @param x {number}  Number to check if it is within range
       * @param min {number}   min value
       * @param max {number}  max value
       * @return {boolean} true if in range, and false otherwise.
       */
      function isInRange(x, min, max) {
          return ((x-min)*(x-max) <= 0);
      }
      
      
      /**
       * Build states
       */
      function buildScriptStates() {
      
          let finalStates = [];
          for (let i = 0; i < TIMERS.length; i++) {
      
              if (isLikeEmpty(TIMERS[i].state)) {
                  continue; // breaks current iteration in the loop and continues with the next
              }
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_INTERVAL, {'name':'Set interval in days', 'type':'number', 'unit':'d', 'min':1, 'max':60, 'read':true, 'write':true, 'role':'value', 'def':INTERVAL_PRESET}]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_RESTART, {'name':'Restart counter', 'type':'boolean', 'read':true, 'write':true, 'role':'button', 'def':false}]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_OVERDUE, {'name':'Overdue?', 'type':'boolean', 'read':true, 'write':false, 'role':'state'}]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DAYS_OVERDUE, {'name':'Number of days overdue', 'type':'number', 'unit':'d', 'min':0, 'max':9999, 'read':true, 'write':false, 'role':'value', 'def':0}]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_PERCENT_ELAPSED, {'name':'Elapsed in %', 'type':'number', 'unit':'%', 'min':0, 'max':100, 'read':true, 'write':false, 'role':'value', 'def':0}]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DAYS_ELAPSED, {'name':'Elapsed in number of days', 'type':'number', 'unit':'d', 'min':0, 'max':9999, 'read':true, 'write':false, 'role':'value', 'def':0}]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DAYS_LEFT, {'name':'Days left', 'type':'number', 'unit':'d', 'min':0, 'max':9999, 'read':true, 'write':false, 'role':'value', 'def':0}]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DATETIMESTART, {'name':'Date/Time of counter start', 'type':'number', 'read':true, 'write':true, 'role':'value.time' }]);
              finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_LEVEL, {'name':'green/yellow/red per elapsed %', 'type':'string', 'read':true, 'write':false, 'role':'value'}]);
      
          }
      
          return finalStates;
      
      }
      
      /**
       * Checks if Array or String is not undefined, null or empty.
       * 08-Sep-2019: added check for [ and ] to also catch arrays with empty strings.
       * @param inputVar - Input Array or String, Number, etc.
       * @return true if it is undefined/null/empty, false if it contains value(s)
       * Array or String containing just whitespaces or >'< or >"< or >[< or >]< is considered empty
       */
      function isLikeEmpty(inputVar) {
          if (typeof inputVar !== 'undefined' && inputVar !== null) {
              let strTemp = JSON.stringify(inputVar);
              strTemp = strTemp.replace(/\s+/g, ''); // remove all whitespaces
              strTemp = strTemp.replace(/\"+/g, "");  // remove all >"<
              strTemp = strTemp.replace(/\'+/g, "");  // remove all >'<
              strTemp = strTemp.replace(/[+/g, "");  // remove all >[<
              strTemp = strTemp.replace(/]+/g, "");  // remove all >]<
              if (strTemp !== '') {
                  return false;
              } else {
                  return true;
              }
          } else {
              return true;
          }
      }
      
      /**
       * For a given state path, we extract the location '0_userdata.0' or 'javascript.0' or add '0_userdata.0', if missing.
       * @param {string}  path            Like: 'Computer.Control-PC', 'javascript.0.Computer.Control-PC', '0_userdata.0.Computer.Control-PC'
       * @param {boolean} returnFullPath  If true: full path like '0_userdata.0.Computer.Control-PC', if false: just location like '0_userdata.0' or 'javascript.0'
       * @return {string}                 Path
       */
      function validateStatePath(path, returnFullPath) {
          if (path.startsWith('.')) path = path.substr(1);    // Remove first dot
          if (path.endsWith('.'))   path = path.slice(0, -1); // Remove trailing dot
          if (path.length < 1) log('Provided state path is not valid / too short.', 'error')
          let match = path.match(/^((javascript\.([1-9][0-9]|[0-9])\.)|0_userdata\.0\.)/);
          let location = (match == null) ? '0_userdata.0' : match[0].slice(0, -1); // default is '0_userdata.0'.
          if(returnFullPath) {
              return (path.indexOf(location) == 0) ? path : (location + '.' + path);
          } else {
              return location;
          }
      }
      
      
      /**
       * Create states under 0_userdata.0 or javascript.x
       * Support:             https://forum.iobroker.net/topic/26839/
       * Autor:               Mic (ioBroker) | Mic-M (github)
       * Version:             1.1 (26 January 2020)
       * -----------------------------------------------
       *              executes the callback PRIOR to completing the state creation. Therefore, we use a setTimeout and counter. 
       * -----------------------------------------------
       * @param {string} where          Where to create the state: '0_userdata.0' or 'javascript.x'.
       * @param {boolean} force         Force state creation (overwrite), if state is existing.
       * @param {array} statesToCreate  State(s) to create. single array or array of arrays
       * @param {object} [callback]     Optional: a callback function -- This provided function will be executed after all states are created.
       */
      function createUserStates(where, force, statesToCreate, callback = undefined) {
       
          const WARN = false; // Only for 0_userdata.0: Throws warning in log, if state is already existing and force=false. Default is false, so no warning in log, if state exists.
          const LOG_DEBUG = false; // To debug this function, set to true
         function setObject() executes the callback 
          // before the state is actual created. Therefore, we use a setTimeout and counter as a workaround.
          const DELAY = 50; // Delay in milliseconds (ms). Increase this to 100, if it is not working.
      
          // Validate "where"
          if (where.endsWith('.')) where = where.slice(0, -1); // Remove trailing dot
          if ( (where.match(/^((javascript\.([1-9][0-9]|[0-9]))$|0_userdata\.0$)/) == null) ) {
              log('This script does not support to create states under [' + where + ']', 'error');
              return;
          }
      
          // Prepare "statesToCreate" since we also allow a single state to create
          if(!Array.isArray(statesToCreate[0])) statesToCreate = [statesToCreate]; // wrap into array, if just one array and not inside an array
      
          // Add "where" to STATES_TO_CREATE
          for (let i = 0; i < statesToCreate.length; i++) {
              let lpPath = statesToCreate[i][0].replace(/\.*\./g, '.'); // replace all multiple dots like '..', '...' with a single '.'
              lpPath = lpPath.replace(/^((javascript\.([1-9][0-9]|[0-9])\.)|0_userdata\.0\.)/,'') // remove any javascript.x. / 0_userdata.0. from beginning
              lpPath = where + '.' + lpPath; // add where to beginning of string
              statesToCreate[i][0] = lpPath;
          }
      
          if (where != '0_userdata.0') {
              // Create States under javascript.x
              let numStates = statesToCreate.length;
              statesToCreate.forEach(function(loopParam) {
                  if (LOG_DEBUG) log('[Debug] Now we are creating new state [' + loopParam[0] + ']');
                  let loopInit = (loopParam[1]['def'] == undefined) ? null : loopParam[1]['def']; // mimic same behavior as createState if no init value is provided
                  createState(loopParam[0], loopInit, force, loopParam[1], function() {
                      numStates--;
                      if (numStates === 0) {
                          if (LOG_DEBUG) log('[Debug] All states processed.');
                          if (typeof callback === 'function') { // execute if a function was provided to parameter callback
                              if (LOG_DEBUG) log('[Debug] Function to callback parameter was provided');
                              return callback();
                          } else {
                              return;
                          }
                      }
                  });
              });
          } else {
              // Create States under 0_userdata.0
              let numStates = statesToCreate.length;
              let counter = -1;
              statesToCreate.forEach(function(loopParam) {
                  counter += 1;
                  if (LOG_DEBUG) log ('[Debug] Currently processing following state: [' + loopParam[0] + ']');
                  if( ($(loopParam[0]).length > 0) && (existsState(loopParam[0])) ) {  State is existing.
                      if (WARN && !force) log('State [' + loopParam[0] + '] is already existing and will no longer be created.', 'warn');
                      if (!WARN && LOG_DEBUG) log('[Debug] State [' + loopParam[0] + '] is already existing. Option force (=overwrite) is set to [' + force + '].');
                      if(!force) {
                          // State exists and shall not be overwritten since force=false
                          // So, we do not proceed.
                          numStates--;
                          if (numStates === 0) {
                              if (LOG_DEBUG) log('[Debug] All states successfully processed!');
                              if (typeof callback === 'function') { // execute if a function was provided to parameter callback
                                  if (LOG_DEBUG) log('[Debug] An optional callback function was provided, which we are going to execute now.');
                                  return callback();
                              }
                          } else {
                              // We need to go out and continue with next element in loop.
                              return; // https://stackoverflow.com/questions/18452920/continue-in-cursor-foreach
                          }
                      } // if(!force)
                  }
      
                  // State is not existing or force = true, so we are continuing to create the state through setObject().
                  let obj = {};
                  obj.type = 'state';
                  obj.native = {};
                  obj.common = loopParam[1];
                  setObject(loopParam[0], obj, function (err) {
                      if (err) {
                          log('Cannot write object for state [' + loopParam[0] + ']: ' + err);
                      } else {
                          if (LOG_DEBUG) log('[Debug] Now we are creating new state [' + loopParam[0] + ']')
                          let init = null;
                          if(loopParam[1].def === undefined) {
                              if(loopParam[1].type === 'number') init = 0;
                              if(loopParam[1].type === 'boolean') init = false;
                              if(loopParam[1].type === 'string') init = '';
                          } else {
                              init = loopParam[1].def;
                          }
                          setTimeout(function() {
                              setState(loopParam[0], init, true, function() {
                                  if (LOG_DEBUG) log('[Debug] setState durchgeführt: ' + loopParam[0]);
                                  numStates--;
                                  if (numStates === 0) {
                                      if (LOG_DEBUG) log('[Debug] All states processed.');
                                      if (typeof callback === 'function') { // execute if a function was provided to parameter callback
                                          if (LOG_DEBUG) log('[Debug] Function to callback parameter was provided');
                                          return callback();
                                      }
                                  }
                              });
                          }, DELAY + (20 * counter) );
                      }
                  });
              });
          }
      }
      
      

      Codierknecht 2 Replies Last reply Reply Quote 0
      • Codierknecht
        Codierknecht Developer Most Active @rtwl last edited by

        @rtwl
        Die Datenpunkte werden als ReadOnly angelegt.

        finalStates.push([FINAL_STATE_PATH + TIMERS[i].state + '.' + STATE_DAYS_LEFT, {'name':'Days left', 'type':'number', 'unit':'d', 'min':0, 'max':9999, 'read':true, 'write':false, 'role':'value', 'def':0}]);                                                                    
        

        Das führt dann zu dem Fehler

        2023-02-12 21:05:00.103 - warn: javascript.0 (11896) Read-only state "0_userdata.0.VIS.Timer.Entkalken.daysLeft" has been written without ack-flag with value "59"
        

        Mach die angemeckerten Datenpunkte doch einfach beschreibbar.

        1 Reply Last reply Reply Quote 0
        • Codierknecht
          Codierknecht Developer Most Active @rtwl last edited by Codierknecht

          @rtwl sagte in Log Error aus Script: Read-only state ... written without...:

          PS: Keine Ahnung woher diese "... created this issue in" herkommt.

          Weil der Parser hier im Forum die URL's im Code findet.
          Schmeiß mal die entsprechenden Zeilen (in den Kommentaren) raus.

          rtwl 1 Reply Last reply Reply Quote 0
          • rtwl
            rtwl @Codierknecht last edited by

            @codierknecht
            Danke!
            Hab die bestehenden Datenpunkte sowie die entsprechenden Zeilen im Skript auf 'write':true gesetzt. Hoffe das passt so.
            Genauso hab ich die entsprechenden Links im Spoiler-Code entfernt.

            1 Reply Last reply Reply Quote 0
            • M
              MCU last edited by

              @rtwl
              Zeilen 268 - 276 müssten auch angepasst werden.
              Bei einigen steht noch: 'write':false

              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              468
              Online

              31.8k
              Users

              80.0k
              Topics

              1.3m
              Posts

              3
              5
              167
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo