Programmatically created array data not saved to InfluxDB

Hi,
Running OpenHabian4 + InfluxDB on a Raspberry Pi 4. I am daily fetching electricity spot data from Entso-E, Sometimes Entso-E can be down and then I can’t get control data for my heat pump.

To cope with this situation I mad a rule with manually typed control data for the heat pump that can be run at those situations that Entso_E is down. It works perfectly but is a little bit awkward to use because you have to type in the points array data and run the rule when needed. Then code here below,

influx = require('/etc/openhab/scripts/kotikolo/influx.js');

points = [
  { "datetime": "2024-02-09T22:00:00Z", "value": 0 },
  { "datetime": "2024-02-09T23:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T00:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T01:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T02:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T03:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T04:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T05:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T06:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T07:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T08:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T09:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T10:00:00Z", "value": 1 },
  { "datetime": "2024-02-10T11:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T12:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T13:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T14:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T15:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T16:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T17:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T18:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T19:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T20:00:00Z", "value": 0 },
  { "datetime": "2024-02-10T21:00:00Z", "value": 0 }
  
]

influx.writePoints('heatpump_control', points); 

In order to make a better approach I made a new rule with preset control data that is run every day just before the Entso-E data fetch is run. If the Entso-E fetch succeeds the this preset data is overwritten by control data based on the electricity spot prices. My problem is that I can’t figure out why the control data created programatically in the points array variable isn’t savet to the InfluxDB. No error messages are shown and if i log the contents of the points array to the console the data is correct. Here is the rule code,

influx = require('/etc/openhab/scripts/kotikolo/influx.js');   

// Set the date to todays date and time 22:00:00
date = new Date(); 
date.setDate(date.getDate() + 1); 
date.setHours(1); 
date.setMinutes(0); 
date.setSeconds(0); 
date.setMilliseconds(0);

points = [];

createPointsArrayData();

// Write the actual control data to the points array
function createPointsArrayData() {
for (let h = -2; h < 22; h++) {
  startString = '{ "datetime": "';
  if (h < -1) {
    endString = '", "value": 0 }'
  } else if (h > -2 && h < 6) {
    endString = '", "value": 1 }'
  } else  if ((h >= 6 && h < 21)) {
            endString = '", "value": 0 }'
        } else {
            endString = '", "value": 0 }'
        }  
        newHour = 2 + h;
        d = new Date(date.setHours(newHour)).toISOString().replace(".000Z", "Z");
        newString = startString + d + endString;
        let data = newString;
        points.push(data);
    }
}

influx.writePoints('heatpump_control', points);

The messages that comes from the influx.js script are exactly the same with both rules,

  • influx.js: Preparing to write 24 points to the database for heatpump_control
  • influx.js: Points successfully saved for measurement heatpump_control

It is a total mystery to me why both rules seems to work correctly only the first with hardcoded points array data actually saves data to the InfluxDB.

What do you see in the logs on the OH side?

Is this Nashorn JS or JS Scripting or run outside of a rule entirely?

Because the records are JSON formatted, you can build up JS Objects and then use JSON.stringify() to get the String instead of building up the String manually. That will make cleaner code and avoid subtle errors like missing commas and the like.

If you are using JS Scripting you can use the Influx node module.

If this is in a rule, it might be easier to do the DateTime stuff using the built in time.

influx = require('/etc/openhab/scripts/kotikolo/influx.js');   

// Set the date to todays date and time 22:00:00
var date = time.toZDT('00:00'); // today at midnight

points = [];

createPointsArrayData();

// Write the actual control data to the points array
function createPointsArrayData() {
  for (let h = -2; h < 22; h++) {
    let record = null;
    if (h < -1) {
      record = { "value" : 0 };
    } else if (h > -2 && h < 6) {
      record = { "value" : 1 };
    } else  if ((h >= 6 && h < 21)) {
      record = { "value" : 0  };
    } else {
      record = { "value" : 0 };
    }
    newHour = 2 + h;
    d = d.withHour(newHour).toLocalDateTime().toString() + 'Z';
    record.push( "datetime" : d );
        points.push(data);
    }
}

influx.writePoints('heatpump_control', points.map(record => JSON.stringify(record)));

The above assumes JS Scripting and not Nashorn which doesn’t support () => notation for anonymous functions and time.toZDT() comes from the JS Scripting helper library.

Would let you do this nicely using time series, once it’s merged.

After trying out your code suggestions and searching the web I finally came up with the working solution below. I also added code for my water heater.

influx = require('/etc/openhab/scripts/kotikolo/influx.js');

// Set the date to todays date and time 00:00:00
date = new Date(); 
date.setDate(date.getDate() + 2); 
date.setHours(0); 
date.setMinutes(0); 
date.setSeconds(0); 
date.setMilliseconds(0);

//console.log(date);

pointsHp = [];
pointsWh = [];

createPointsArrayDataHp();
createPointsArrayDataWh();

// Write the actual control data to the points array for the heatpump (control value = 1 between 01 - 07)
function createPointsArrayDataHp() {
for (let h = -2; h < 22; h++) {
  startString = '{"datetime": ';
  if (h < -1) {
    endString = ', "value": 0}';
  } else if (h > -2 && h < 5) {
    endString = ', "value": 1}';
  } else  if ((h >= 5 && h < 21)) {
    endString = ', "value": 0}';
  } else {
    endString = ', "value": 0}';
  }  
  newHour = 2 + h;
  d = new Date(date.setHours(newHour)).toISOString().replace(".000Z", "Z");
  newString = startString + '"' + d + '"' + endString;
  data = newString;
  eval('var obj='+newString);
  pointsHp.push(obj);
  
  }
}

// Write the control points to InfluxDB
influx.writePoints('heatpump_control', pointsHp);



// Write the actual control data to the points array for the water (control value = 1 between 03 - 05)
function createPointsArrayDataWh() {
for (let h = -2; h < 22; h++) {
  startString = '{"datetime": ';
  if (h < -1) {
    endString = ', "value": 0}';
  } else if (h > 0 && h < 3) {
    endString = ', "value": 1}';
  } else  if ((h >= 3 && h < 21)) {
    endString = ', "value": 0}';
  } else {
    endString = ', "value": 0}';
  }  
  newHour = 2 + h;
  d = new Date(date.setHours(newHour)).toISOString().replace(".000Z", "Z");
  newString = startString + '"' + d + '"' + endString;
  data = newString;
  eval('var obj='+newString);
  pointsWh.push(obj);
  
  }
}

// Write the control points to InfluxDB
influx.writePoints('waterheater_control', pointsWh);