State Storage

Sometimes you need to save the last state of a sensor, for example if you want to publish those again during startup or your sensor does not send all data in one telegram or frame. The storage uses JSON as its internal format because it’s used by Home Assistant on the MQTT side. It’s up to the protocol manager to use or not use the state storage, energy2mqtt does not enforce the usage.

You may find the relevant code in src/storage/mod.rs if you want to look into details.

Details

You should never export button, device triggers or a flag which may be used in automations which may retrigger during startup of Home Assistant or energy2mqtt. You may break a user’s system or home and raise unneeded alarms.

To use the state storage you may use it before you build up the meter reading which will be sent to MQTT by energy2mqtt. An example may look like this:

let proto_used = "example".to_string();

let mut meter_data = MeteringData::new().unwrap();
meter_data.meter_name = your_meter_unique_name.clone();
meter_data.protocol = DeviceProtocol::Example;
meter_data.id = get_id(proto_used.clone(), &dev_eui);

let mut perist = StoredData::load(proto_used.clone(),
                                    your_meter_unique_name.clone()).await;

/*
    Iterate over the keys that should be known for that meter
*/
for key in your_meters_known_keys.iter() {
    /*
        Your current frame does not contain the needed keys, ask the state storage.
        The persistence may return Null if the data is unknown.

        That is fine for Home Assistant, the sensor will switch to "unknown".
    */
    let value =  match current_values.contains_key(key) {
        true => current_values[key].clone(),
        false => perist.get_data(&key)
    }

    /* Update the persistence layer with the now active value */
    perist.set_data(&key, &value);
    meter_data.metered_values.insert(key.clone(), value);
}

/* Send the data */
let _ = sender.send(Transmission::Metering(meter_data)).await;
Details

There is no need to call save or anything, StoredData implements the Drop trait and will write the state as soon as the instance is destroyed. The user may change the file in the filesystem which will then be reread on load()