📦 Archived documentation: r1 (committed 2026-07-24) View current documentation →

Non-Volatile Setpoint Storage

Available on: Flexs Q5C Flexs Q5M

Persists operator setpoints and a users table in battery-backed memory with nv.get()/nv.set() — merging saved values over code defaults so newly added setpoints keep their defaults, and splitting the 4 kB between two objects with a byte offset.

let sp = {
  dialer: 0,

  p101Hrs: 0,
  p102Hrs: 0,
  p301Hrs: 0,
  p302Hrs: 0,

  p101Mode: 2,
  p102Mode: 2,
  p301Mode: 2,
  p302Mode: 2,

  // booster process
  millionGallonResPumpCall1: 85,
  millionGallonResPumpCall2: 80,
  millionGallonResFull: 95,

  clearwellLow: 50,
  clearwellResume: 60,
  boosterPumpSpeed: 57,
  boosterMinPumpFlow: 88 // per pump running 100% speed
};

let users = {}; // Blank users list.

let cfg = {
  load: function(){
    let ssp = nv.get(); // load from non-volatile memory; no offset argument = position 0
    if(ssp){            // nv.get() returns undefined if no valid string is detected
                        // (this can happen if the memory backup battery goes dead)
      let nsp = JSON.parse(ssp); // parse the saved setpoint string as a JSON object
      for(let key in nsp){ sp[key] = nsp[key]; }
      // Merging key-by-key (instead of sp = nsp) means setpoints added to the
      // code later keep their defaults when an older saved config is loaded.
    } else {
      print("Loaded Default Setpoints");
      cfg.save();
    }

    let u = nv.get(2048); // load the users object at a 2 kB offset —
                          // 4 kB total, so we split it in half
    if(u){
      users = JSON.parse(u); // parse the users string for our user authentication
    }
  },
  save: function(){
    nv.set(string(sp));
    nv.set(string(users), 2048);
  },
};

cfg.load(); // run at the beginning of the script, after setpoint and user declarations

cfg.save(); // run whenever setpoints or users are changed