node-red-contrib-deconz
Version:
deCONZ connectivity nodes for node-red
150 lines (134 loc) • 4.21 kB
JavaScript
const Query = require("./Query");
const Utils = require("./Utils");
class DeviceList {
constructor() {
this.domains = ["groups", "lights", "sensors"];
this.devices = {};
this.all_group_real_id = undefined;
for (const resource of this.domains)
this.devices[resource] = {
ById: {},
ByUniqueID: {},
};
}
parse(data, onNewDevice = undefined) {
//TODO find a better way than recreate all object from scratch each time
let newDevices = {};
for (const resourceName of this.domains) {
if (data[resourceName] === undefined) continue;
newDevices[resourceName] = {
ById: {},
ByUniqueID: {},
};
for (const [id, device] of Object.entries(data[resourceName])) {
device.device_type = resourceName;
device.device_id = Number(id);
let idPath = this.getIDPathByDevice(device, true);
let uniquePath = this.getUniqueIDPathByDevice(device, true);
device.device_path = uniquePath || idPath;
Utils.convertLightsValues(device);
if (idPath) newDevices[resourceName].ById[device.device_id] = device;
if (uniquePath)
newDevices[resourceName].ByUniqueID[device.uniqueid] = device;
if (
this.getDeviceByPath(device.device_path) === undefined &&
typeof onNewDevice === "function"
) {
onNewDevice(device);
}
}
}
this.devices = newDevices;
}
getDeviceByPath(path) {
let parts = path.split("/");
let resourceName = parts.shift();
let domain = parts.shift();
if (resourceName === "uniqueid") return this.getDeviceByUniqueID(domain);
let sub_path = parts.join("/");
switch (domain) {
case "device_id":
return this.devices[resourceName].ById[sub_path];
case "uniqueid":
return this.devices[resourceName].ByUniqueID[sub_path];
}
}
/**
* Get the device from his unique ID.
* Warning, some devices have the same uniqueID.
* @param uniqueID
* @returns device
*/
getDeviceByUniqueID(uniqueID) {
for (const domain of Object.values(this.devices)) {
let found = domain.ByUniqueID[uniqueID];
if (found) return found;
}
}
/**
* Get the device from his domain and his ID.
* @param domain string {'groups', 'lights', 'sensors'}
* @param deviceID string
* @returns device
*/
getDeviceByDomainID(domain, deviceID) {
return this.domains.includes(domain)
? this.devices[domain].ById[deviceID]
: undefined;
}
createQuery(device) {
return { device_path: this.getPathByDevice(device) };
}
getAllDevices() {
return this.getDevicesByQuery("all");
}
getDevicesByQuery(queryParams, options = {}) {
let opt = {
includeNotMatched: options.includeNotMatched || false,
extractValue: options.extractValue,
};
let query = new Query(queryParams);
let result = {
matched: [],
rejected: [],
};
for (const domain of Object.values(this.devices)) {
for (const device of Object.values(domain.ById)) {
let value = opt.extractValue ? device[opt.extractValue] : device;
if (query.match(device)) {
result.matched.push(value);
} else {
result.rejected.push(value);
}
}
}
return result;
}
getPathByDevice(device, includeDeviceType = true) {
return (
this.getUniqueIDPathByDevice(device, includeDeviceType) ||
this.getIDPathByDevice(device, includeDeviceType)
);
}
getIDPathByDevice(device, includeDeviceType = true) {
let path = "";
if (includeDeviceType) path += device.device_type + "/";
path += "device_id/" + device.device_id;
return path;
}
getUniqueIDPathByDevice(device, includeDeviceType = true) {
if (device.uniqueid === undefined) return;
let path = "";
if (includeDeviceType) path += device.device_type + "/";
path += "uniqueid/" + device.uniqueid;
return path;
}
get count() {
let result = 0;
for (const resource of this.domains) {
result += Object.keys(this.devices[resource].ById).length;
}
return result;
}
}
module.exports = DeviceList;