2019-09-09 10:48:09 -07:00
|
|
|
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
2019-10-25 10:42:47 -07:00
|
|
|
const equals = require('fast-deep-equal');
|
2019-03-16 12:07:34 -07:00
|
|
|
|
2018-10-02 12:15:12 -07:00
|
|
|
// Xiaomi uses 4151 and 4447 (lumi.plug) as manufacturer ID.
|
|
|
|
const xiaomiManufacturerID = [4151, 4447];
|
2019-02-01 11:04:49 -07:00
|
|
|
const ikeaTradfriManufacturerID = [4476];
|
2018-10-02 12:15:12 -07:00
|
|
|
|
2019-03-02 08:47:36 -07:00
|
|
|
// construct a local ISO8601 string (instead of UTC-based)
|
|
|
|
// Example:
|
|
|
|
// - ISO8601 (UTC) = 2019-03-01T15:32:45.941+0000
|
|
|
|
// - ISO8601 (local) = 2019-03-01T16:32:45.941+0100 (for timezone GMT+1)
|
|
|
|
function toLocalISOString(dDate) {
|
|
|
|
const tzOffset = -dDate.getTimezoneOffset();
|
|
|
|
const plusOrMinus = tzOffset >= 0 ? '+' : '-';
|
|
|
|
const pad = function(num) {
|
|
|
|
const norm = Math.floor(Math.abs(num));
|
|
|
|
return (norm < 10 ? '0' : '') + norm;
|
|
|
|
};
|
|
|
|
|
|
|
|
return dDate.getFullYear() +
|
|
|
|
'-' + pad(dDate.getMonth() + 1) +
|
|
|
|
'-' + pad(dDate.getDate()) +
|
|
|
|
'T' + pad(dDate.getHours()) +
|
|
|
|
':' + pad(dDate.getMinutes()) +
|
|
|
|
':' + pad(dDate.getSeconds()) +
|
|
|
|
plusOrMinus + pad(tzOffset / 60) +
|
|
|
|
':' + pad(tzOffset % 60);
|
|
|
|
}
|
|
|
|
|
2019-03-15 13:19:42 -07:00
|
|
|
const postfixes = [
|
2019-09-09 10:48:09 -07:00
|
|
|
'left', 'right', 'center', 'bottom_left', 'bottom_right', 'l1', 'l2', 'default',
|
2019-07-27 08:33:33 -07:00
|
|
|
'top_left', 'top_right', 'white', 'rgb', 'system', 'top', 'bottom', 'center_left', 'center_right',
|
2019-09-09 10:48:09 -07:00
|
|
|
'ep1', 'ep2',
|
2019-03-15 13:19:42 -07:00
|
|
|
];
|
|
|
|
|
2019-06-04 10:23:58 -07:00
|
|
|
function flatten(arr) {
|
|
|
|
return arr.reduce((flat, toFlatten) => {
|
|
|
|
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
|
|
|
|
}, []);
|
|
|
|
}
|
|
|
|
|
|
|
|
const forceEndDevice = flatten(
|
2019-09-09 10:48:09 -07:00
|
|
|
['QBKG03LM', 'QBKG04LM', 'ZNMS13LM', 'ZNMS12LM']
|
|
|
|
.map((model) => zigbeeHerdsmanConverters.devices.find((d) => d.model === model))
|
2019-06-04 10:23:58 -07:00
|
|
|
.map((mappedModel) => mappedModel.zigbeeModel));
|
|
|
|
|
2019-09-09 10:48:09 -07:00
|
|
|
async function getZigbee2mqttVersion() {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const git = require('git-last-commit');
|
|
|
|
const packageJSON = require('../../package.json');
|
|
|
|
const version = packageJSON.version;
|
|
|
|
|
|
|
|
git.getLastCommit((err, commit) => {
|
|
|
|
let commitHash = null;
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
try {
|
|
|
|
commitHash = require('../../.hash.json').hash;
|
|
|
|
} catch (error) {
|
|
|
|
commitHash = 'unknown';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
commitHash = commit.shortHash;
|
2019-03-17 12:04:51 -07:00
|
|
|
}
|
|
|
|
|
2019-09-09 10:48:09 -07:00
|
|
|
resolve({commitHash, version});
|
|
|
|
});
|
2019-03-17 12:04:51 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-06-17 12:28:27 -07:00
|
|
|
function formatDate(date, type, _default) {
|
|
|
|
let result;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case 'ISO_8601':
|
|
|
|
result = new Date(date).toISOString();
|
|
|
|
break;
|
|
|
|
case 'ISO_8601_local':
|
|
|
|
result = toLocalISOString(new Date(date));
|
|
|
|
break;
|
|
|
|
case 'epoch':
|
|
|
|
result = date;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = _default;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-09-09 10:48:09 -07:00
|
|
|
function objectHasProperties(object, properties) {
|
|
|
|
for (const property of properties) {
|
|
|
|
if (!object.hasOwnProperty(property)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-10-25 10:42:47 -07:00
|
|
|
function equalsPartial(object, expected) {
|
|
|
|
for (const [key, value] of Object.entries(expected)) {
|
|
|
|
if (!equals(object[key], value)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-10-02 12:15:12 -07:00
|
|
|
module.exports = {
|
|
|
|
millisecondsToSeconds: (milliseconds) => milliseconds / 1000,
|
|
|
|
secondsToMilliseconds: (seconds) => seconds * 1000,
|
2019-09-09 10:48:09 -07:00
|
|
|
getZigbee2mqttVersion,
|
|
|
|
objectHasProperties,
|
|
|
|
getPostfixes: () => postfixes,
|
2019-04-17 11:03:40 -07:00
|
|
|
isXiaomiDevice: (device) => {
|
2019-09-09 10:48:09 -07:00
|
|
|
return device.modelID !== 'lumi.router' && xiaomiManufacturerID.includes(device.manufacturerID) &&
|
|
|
|
(!device.manufacturerName || !device.manufacturerName.startsWith('Trust'));
|
2019-04-17 11:03:40 -07:00
|
|
|
},
|
2019-09-09 10:48:09 -07:00
|
|
|
isIkeaTradfriDevice: (device) => ikeaTradfriManufacturerID.includes(device.manufacturerID),
|
|
|
|
isRouter: (device) => device.type === 'Router' && !forceEndDevice.includes(device.modelID),
|
2019-03-24 06:38:08 -07:00
|
|
|
isBatteryPowered: (device) => device.powerSource && device.powerSource === 'Battery',
|
2019-06-17 12:28:27 -07:00
|
|
|
formatDate: (date, type, _default=null) => formatDate(date, type, _default),
|
2019-10-25 10:42:47 -07:00
|
|
|
equalsPartial,
|
2018-10-02 12:15:12 -07:00
|
|
|
};
|