loxone2mqtt
Version:
Gateway for Loxone™ miniserver to communicate with mqtt broker
144 lines (128 loc) • 4.63 kB
JavaScript
const util = require('util');
const events = require('events');
const unidecode = require('unidecode');
var Adaptor = function (structure) {
this.structure = structure;
this.room2name = {};
this.cat2name = {};
this.path2control = {};
this.controlid2path = {};
this.stateuuid2path = {};
this._build_rooms();
this._build_cats();
this._build_paths();
this._register_events();
};
util.inherits(Adaptor, events.EventEmitter);
Adaptor.prototype.set_value_for_uuid = function (uuid, value) {
this.structure.set_value_for_uuid(uuid, value);
};
Adaptor.prototype.get_command_from_topic = function (topic, data) {
var pathGroups = topic.match('^(.+)/cmd$');
if (!pathGroups) {
return {};
}
var control = this.path2control[pathGroups[1]];
if (!control) {
return {};
}
return {
'uuidAction': control.uuidAction,
'command': data
};
};
Adaptor.prototype.abort = function () {
this.structure.removeAllListeners();
this.structure = undefined;
this.removeAllListeners();
};
Adaptor.prototype._build_rooms = function () {
Object.keys(this.structure.rooms.items).forEach(function (key) {
var room = this.structure.rooms.items[key];
var name = this._normalize_name(room.name);
this.room2name[room.uuid] = name;
}, this);
};
Adaptor.prototype._build_cats = function () {
Object.keys(this.structure.categories.items).forEach(function (key) {
var cat = this.structure.categories.items[key];
var name = this._normalize_name(cat.name);
this.cat2name[cat.uuid] = name;
}, this);
};
Adaptor.prototype._build_paths = function () {
Object.keys(this.structure.controls.items).forEach(function (key) {
var control = this.structure.controls.items[key];
this._add_control(control);
if (control.subControls !== undefined) {
Object.keys(control.subControls.items).forEach(function (subKey) {
this._add_control(control.subControls.items[subKey], control.room, control.category);
}, this);
}
}, this);
this.controlid2path[this.structure.globalStates.id] = 'miniserver/global';
this.path2control['miniserver/global'] = this.structure.globalStates;
Object.keys(this.structure.globalStates).forEach(function (key) {
this.stateuuid2path[this.structure.globalStates[key].uuid] = 'miniserver/global/raw_state/' + key;
}, this);
};
Adaptor.prototype._register_events = function () {
var that = this;
Object.keys(this.path2control).forEach(function (path) {
this.path2control[path].on('state_update', function (control) {
if (that.controlid2path[control.id] !== undefined) {
var value;
if (control.states) {
if (control.states.items) {
if (control.states.items['active']) {
value = control.states.items['active'].value;
} else if (control.states.items.actual) {
value = control.states.items['actual'].value;
} else if (control.states.items.activeScene) {
value = control.states.items['activeScene'].value;
} else if (control.states.items.value) {
value = control.states.items['value'].value;
} else if (control.states.items.position) {
value = control.states.items['position'].value;
} else {
// value = control.states.items;
}
}
} else {
// value = control.states;
}
var data = {
val: value,
ts: Math.floor(new Date() / 1000),
raw: control.get_state()
};
that.emit('for_mqtt', that.controlid2path[control.id], JSON.stringify(data));
} else {
throw new Error('Invalid control! - path');
}
});
}, this);
};
Adaptor.prototype._add_control = function (control, defaultRoom, defaultCategory) {
var name = this._normalize_name(control.name);
var room = this.room2name[control.room];
if (room === undefined) {
room = this.room2name[defaultRoom];
}
var category = this.cat2name[control.category];
if (category === undefined) {
category = this.cat2name[defaultCategory];
}
var path = room + '/' + category + '/' + name;
this.path2control[path] = control;
this.controlid2path[control.id] = path;
if (control.states !== undefined) {
Object.keys(control.states.items).forEach(function (stateKey) {
this.stateuuid2path[control.states.items[stateKey].uuid] = path + '/raw_state/' + stateKey;
}, this);
}
};
Adaptor.prototype._normalize_name = function (name) {
return unidecode('' + name).replace(/\s+/g, '_').toLowerCase();
};
module.exports = Adaptor;