Persistent in-memory variables

Openremote default configuration suffers the illness of cheap Chinese devices — it forgets almost everything after power on/off cycle. This article describes how to preserve in-memory variables. If you want to save your in memory variables with rules presented here, please follow these guidelines:

  • A name of in-memory variable, which should be preserved between restarts, must begin with capital string “GV”, for example “GVRememberThis”;
  • This in-memory variable should have command ‘status’;
  • Sensor associated with this command should have exactly the same name — in our example “GVRememberThis”;
  • The sensor should be of type ‘custom’.

When you follow these guidelines and add following rules in the designer then Openremote controller will miraculously remember all “GV” started in-memory variables. GV stays for Global Variable.

package org.openremote.controller.protocol.preserve;
import java.io.*;
import org.openremote.controller.protocol.Event;
global org.openremote.controller.statuscache.CommandFacade execute;

function void _WriteToFile(String fn, Object o){
  String vl = o.toString();
  PrintWriter writer = new PrintWriter(fn+".txt", "UTF-8");
  try{
    writer.println(vl);
  } finally {
    writer.close();
  }
}

function String _ReadFromFile(String fn, String dft){
  String result = dft;
  try{
    BufferedReader fr = new BufferedReader(new InputStreamReader(new FileInputStream(fn+".txt"), "UTF-8"));
    try{
      result = fr.readLine();
    } finally {
      fr.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
  return(result);
}

rule "Store values"
timer(int: 1s)                                                                                             
when
  Event($s:source matches "^GV.*", $v:value!="status")
then
  _WriteToFile($s, $v);
end

rule "Init values"
  salience 100
when
(OR
  Event($s:source matches "^GV.*", value=="")
  Event($s:source matches "^GV.*", value=="status")
)
then
  execute.command($s, _ReadFromFile($s, "-"));
end

You can either use these rules in designer or save it separately in your controller’s subdirectory [path to the controller]/webapps/controller/rules/. The second solution has an advantage that these rules will always be available — even if there are no rules in the designer or rules are with errors. It should be a part of the standard Openremote distribution if you ask me 😉

13 thoughts on “Persistent in-memory variables

  1. Hi i want to use your script because it looks very usefull and should indeed be in by default. But i put the script in.

    can you just send me a screenshot on how i should create the custom sensor? and how i should create rules for that custom sensor?

    just 2 lines and a screenshot and i will get the picture i hope 🙂

  2. problem is that i am using a KNX status command.
    that status command i want to use for the custom sensor.

    also in the file i see N/A instead of the value.

    but i am very sure we can solve this issue. Hope that it works with KNX (which i think is also an in-memory variabele)

    thx again for the quick reply. It is because of Guys like you that the opensource community can grow and exist.

    • You don’t need persistence for a KNX sensor. This technique is applicable only to in-memory virtual commands, which are in fact memory locations which get reset after power-on cycle.

      • if i now reset my openremote machine, then the openremote will do a lot of read commands to my knx bus. so if i write a 0 to these values he stops reading the values. that is why i want to keep them stored as well.
        now each time i reboot i need to write all the values on the bus again.

        • In this case you need a different solution – initialise values after system reboot. This can be achieved with a rule. Suppose that you want to write ‘0’ 10 seconds after system reboot. The following rule does it:

          rule “Init 10s after system start”
          timer(int: 10s)
          then
          execute.command(“KNX write command”, “0”);
          end

          • OK.

            that is feasable. But can i directy set the value of a sensor?

            for example like this?

            rule “Init 10s after system start”
            timer(int: 10s)
            then
            Event(source == “Fasttel relais 3”).setvalue(“off”);
            end

  3. Unfortunately, the value of a sensor cannot be set directly unless you have a command which does it. A little misleading is the fact that with in-memory virtual command you can indeed set a value with the same command which is used for reading. However, this is not usually true for other protocols.

  4. package org.openremote.controller.model.event
    global org.openremote.controller.statuscache.CommandFacade execute;
    global org.openremote.controller.statuscache.SwitchFacade switches;
    global org.openremote.controller.statuscache.LevelFacade levels;
    import java.util.concurrent.TimeUnit;
    import org.openremote.controller.protocol.*;

    rule “init” when
    timer (int: 10s)
    then
    execute.command( “voordeur on/off (OFF)” );
    end

    give me this error:

    [ERR 102] Line 9:12 mismatched input ’10’ expecting ‘identifier’ in rule “init” in pattern timer

  5. no the problem gets even worse.

    first of all the action does not work at startup but this is now not the real issue anymore.

    the real issue is that if i execute all the commands to write the values to the bus he keeps reading them.
    So if openremote writes to the bus he does not listen at the same time to that values.

    • This seems to be rather a KNX problem and not persistent in-memory virtual commands (in-memory virtual commands are different protocol than KNX). You should describe what you are trying to do at http://www.openremote.org forums, as myself I’m not an expert with KNX.

Leave a Reply