What are storedValues (seen in Blocky) and where is it stored?

Hello all,

I’m using RRD4J as persistence layer.
My main issue is that I have exactly one Time (the WakeupTime) that is always lost after reboot. Yes I read the manual and I know this might not work because RRD4J can only store numbers.

Is there any other way how I can store and retrieve this information?
I found “storedValues” in the new Version of Blocky but I did not found any manual about it.

this.storedValues[‘key’] = ‘value’;

image

Could this be solution?

BR
/Franz

That stores the value of the variable from one run of the rule to the next. The only way to save and restore a value across an OH reboot is through persistence. If rrd4j doesn’t save the types you need, look into MapDB.

Hey thanks Rich,

that MapDB works relly well!
Sooner or later i guess i need to get into this .persist file.

BR
/Franz

Hi @rlkoshak ,

I’ve played arround a but with that storedvalue.

But I already fail at the start.
In this snipplet I wanted to check if it’s already set and if not then set it. (Inital Start state after restart).

logger.info(('Nextbulb start :' + String(this.storedValues['NextBulb'])));
if ((this.storedValues['NextBulb']) == null) {
  this.storedValues['NextBulb'] = '1';
  logger.info(('Nextbulb : set to ' + String(this.storedValues['NextBulb'])));
}
logger.info(('Nextbulb  after:' + String(this.storedValues['NextBulb'])));

But the output is always:
(Looks like it’s always undefined).
Did I missunderstood this feature?

2021-12-22 14:28:22.685 [INFO ] [org.openhab.rule.FadeColors         ] - Nextbulb start :undefined
2021-12-22 14:28:22.761 [INFO ] [org.openhab.rule.FadeColors         ] - Nextbulb : set to 1
2021-12-22 14:28:22.765 [INFO ] [org.openhab.rule.FadeColors         ] - Nextbulb  after:1

image

The “if stored value “NextBulb” = null” . To start, the value will be undefined because it doesn’t exist. Nothing in this rule actually sets it to null so the if statement should never run. But the logs are showing that it did run so I don’t know what’s going on.

The proper way though would be to test if it equals undefined and initialize it then.

Accessing an uninitialized stored value should throw an exception:

21:16:10.625 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID '4b9f2cd9ba' failed: TypeError: Cannot read property "Testdummy " from undefined in <eval> at line number 20

grafik

log output:

21:28:12.162 [ERROR] [org.openhab.rule.4b9f2cd9ba          ] - Testdummy:undefined

"undefined" isn’t the same things as undefined.

That error implies that this.storedValues doesn’t exist, which shouldn’t be the case because as soon as you us a store value it should create that dict. When you query for a key that doesn’t exist in a dict, you get back undefined, not an error.

I would want to see the JS code backing that Blockly to understand more about what’s happening.

Sure. I was just trying to replicate @FranzS’ log output that doesn’t make sense to me.

It depends:

Create a new rule:

grafik

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
logger.error(('Test124: ' + String(this.storedValues['Test124'])));

Result:

22:26:35.396 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID '8fc7061bec' failed: TypeError: Cannot read property "Test124" from undefined in <eval> at line number 4

openHABian / openHAB 3.2.0-SNAPSHOT - Build #2630

Add a ‘store value’

grafik

if (typeof this.storedValues === 'undefined') {
  this.storedValues = [];
}

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);


this.storedValues['B'] = 'A';
logger.error(('Test124: ' + String(this.storedValues['Test124'])));

Result:

22:40:11.542 [ERROR] [org.openhab.rule.8fc7061bec ] - Test124: undefined

Well yes, you never saved the value.

store value will put the value into this.storedValues. stored values will pull the value from this.storedValues. You can’t pull a value before you’ve stored it.

And the code that creates this.storedValues in the first place doesn’t get added to the rule until you have a store value block. It doesn’t make sense to create it if you are not storing anything in it. And it doesn’t make sense to query values from it if you never store any values in it in the first place.

I would hope this is something that can be made clear in the docs.

But if you for example, store a value “Test123” ad then try to retrieve "Test456" you will get back undefined`, not an error.

At the very least, it would be bad coding style.

Well, Blockly is an additional abstraction layer that has a number of pitfalls in store for users that don’t/aren’t able to read the source code. IMHO we will see a lot of posts with complaints about Blockly scripts that ‘don’t work as expected’. And yes, the answer is: good docs.

Right? and then the question begs… what is the point
Original post in this thread shows it is entirely possible to create scripts that, at best, don’t work

It’s always going to be possible to create scripts that don’t work. Blocky isn’t going to change that. And even if things were changed in this instance so that instead of an error it returns undefined, it makes no sense what do ever to try to read a cake from this.storedStates when no babies are ever stored there ever.

It’s not just bad coding practice, it doesn’t make any sense.

Bl9ckly does a lot to make the coding easier but it is still coding. It can’t protect you from all the potential pitfalls and illogical things you might try to do, like trying to read variables that are never created.

Rich and I have always been on the path to try to make it as fail safe as possible during design and implementation but there is some limit to do so.

Instead of complaining I would rather ask you, how we can improve it? What would you expect the blocks to behave like? Would a block help with which it is possible to check if key has already been set at all?

Rich and I have always been on the path to try to make it as fail safe as possible during design and implementation but there is some limit to do so.

Instead of complaining I would rather ask ourselves, how we can improve it? What would one expect the blocks to behave like?

So would a block help with which it is possible to check if key has already been set at all?

I have implemented the following block for you which would be available from 3.3 M1

The result in this case is “firstValue”.

Note the following

  • The values are persisted as a part of the instance of the rule
  • Modifying the rule during development creates a new instance which means the value is reset.
  • Restarting openHAB creates a new rule instance which also means the value is reset
  • In most cases both situations are negligible for many rules.

Does that help?

I have also written the section about that in the Blockly Reference. Do you mind checking that section if it is clear and comprehensive enough?

Hi @stefan.hoehn ,

thanks for that update.
To be honest I’m far away from complaining, I’m still on the level to understand how works at all :slight_smile:

BR
/Franz

2 Likes

Thank you very much for your enormous efforts to bring Blockly to OH!

Wouldn’t it be sufficient to prepend the JavaScript code with

if (typeof this.storedValues === 'undefined') {
  this.storedValues = [];
}

in order to keep the ScriptActionHandler happy (see What are storedValues (seen in Blocky) and where is it stored? - #8 by Ap15e) even if someone tries to access a key that has no value?

The problem isn’t accessing a key with no values. The problem is a user trying to access a variable from the store without having stored anything in the store at all.

To my mind, that’s a different thing entirely and having a different error when that happens is a good thing.

It’s the difference between asking for a value that doesn’t exist now but may exist later and a rule where no value will ever exist because the rule doesn’t make logical sense.