mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-28 13:34:24 +00:00
Persist devices state across restarts. #249
This commit is contained in:
+2
-1
@@ -60,4 +60,5 @@ typings/
|
||||
# data
|
||||
data/database.db
|
||||
data/config.json
|
||||
data/log*.txt
|
||||
data/log*.txt
|
||||
data/state.json
|
||||
+11
-6
@@ -1,5 +1,6 @@
|
||||
const MQTT = require('./mqtt');
|
||||
const Zigbee = require('./zigbee');
|
||||
const State = require('./state');
|
||||
const logger = require('./util/logger');
|
||||
const settings = require('./util/settings');
|
||||
const zigbeeShepherdConverters = require('zigbee-shepherd-converters');
|
||||
@@ -32,7 +33,7 @@ class Controller {
|
||||
constructor() {
|
||||
this.zigbee = new Zigbee();
|
||||
this.mqtt = new MQTT();
|
||||
this.stateCache = {};
|
||||
this.state = new State();
|
||||
this.configured = [];
|
||||
this.handleZigbeeMessage = this.handleZigbeeMessage.bind(this);
|
||||
this.handleMQTTMessage = this.handleMQTTMessage.bind(this);
|
||||
@@ -99,8 +100,8 @@ class Controller {
|
||||
|
||||
sendAllCachedStates() {
|
||||
this.zigbee.getAllClients().forEach((device) => {
|
||||
if (this.stateCache.hasOwnProperty(device.ieeeAddr)) {
|
||||
this.mqttPublishDeviceState(device.ieeeAddr, this.stateCache[device.ieeeAddr], false);
|
||||
if (this.state.exists(device.ieeeAddr)) {
|
||||
this.mqttPublishDeviceState(device.ieeeAddr, this.state.get(device.ieeeAddr), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -152,6 +153,7 @@ class Controller {
|
||||
}
|
||||
|
||||
stop(callback) {
|
||||
this.state.save();
|
||||
this.mqtt.disconnect();
|
||||
this.pollTimer(false);
|
||||
this.softResetTimeout(false);
|
||||
@@ -393,6 +395,9 @@ class Controller {
|
||||
// Remove from configuration.yaml
|
||||
settings.removeDevice(deviceID);
|
||||
|
||||
// Remove from state
|
||||
this.state.remove(deviceID);
|
||||
|
||||
logger.info(`Successfully removed ${deviceID}`);
|
||||
this.mqtt.log('device_removed', message);
|
||||
};
|
||||
@@ -549,13 +554,13 @@ class Controller {
|
||||
mqttPublishDeviceState(deviceID, payload, cache) {
|
||||
if (cacheState) {
|
||||
// Add cached state to payload
|
||||
if (this.stateCache[deviceID]) {
|
||||
payload = objectAssignDeep.noMutate(this.stateCache[deviceID], payload);
|
||||
if (this.state.exists(deviceID)) {
|
||||
payload = objectAssignDeep.noMutate(this.state.get(deviceID), payload);
|
||||
}
|
||||
|
||||
// Update state cache with new state.
|
||||
if (cache) {
|
||||
this.stateCache[deviceID] = payload;
|
||||
this.state.set(deviceID, payload);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
const logger = require('./util/logger');
|
||||
const data = require('./util/data');
|
||||
const fs = require('fs');
|
||||
|
||||
const saveInterval = 1000 * 60 * 5; // 5 minutes
|
||||
|
||||
class State {
|
||||
constructor() {
|
||||
this.state = {};
|
||||
this.file = data.joinPath('state.json');
|
||||
this._load();
|
||||
|
||||
// Save the state on every interval
|
||||
this.timer = setInterval(() => this.save(), saveInterval);
|
||||
}
|
||||
|
||||
_load() {
|
||||
if (fs.existsSync(this.file)) {
|
||||
try {
|
||||
this.state = JSON.parse(fs.readFileSync(this.file, 'utf8'));
|
||||
logger.debug(`Loaded state from file ${this.file}`);
|
||||
} catch (e) {
|
||||
logger.debug(`Failed to load state from file ${this.file} (corrupt file?)`);
|
||||
}
|
||||
} else {
|
||||
logger.debug(`Can't load state from file ${this.file} (doesn't exsist)`);
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
logger.debug(`Saving state to file ${this.file}`);
|
||||
const json = JSON.stringify(this.state, null, 4);
|
||||
fs.writeFileSync(this.file, json, 'utf8');
|
||||
}
|
||||
|
||||
exists(ID) {
|
||||
return this.state.hasOwnProperty(ID);
|
||||
}
|
||||
|
||||
get(ID) {
|
||||
return this.state[ID];
|
||||
}
|
||||
|
||||
set(ID, state) {
|
||||
this.state[ID] = state;
|
||||
}
|
||||
|
||||
remove(ID) {
|
||||
if (this.exists(ID)) {
|
||||
delete this.state[ID];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = State;
|
||||
Reference in New Issue
Block a user