Merge branch 'dev' into master

This commit is contained in:
Koen Kanters
2018-08-24 23:59:39 +02:00
committed by GitHub
17 changed files with 4741 additions and 1598 deletions
+7 -5
View File
@@ -4,14 +4,16 @@
},
"extends": ["eslint:recommended", "google"],
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
},
"ecmaVersion": 6,
"sourceType": "module"
},
"rules": {
"require-jsdoc": "off",
"indent": ["error", 4],
"max-len": ["error", { "code": 120 }]
}
"max-len": ["error", { "code": 120 }],
"mocha/no-exclusive-tests": "error"
},
"plugins": [
"mocha"
]
}
+11
View File
@@ -0,0 +1,11 @@
Unsupported device
First check: https://github.com/Koenkk/zigbee2mqtt/wiki/How-to-support-new-devices
Bug report
- First make sure your on the latest version of zigbee2mqtt.
- Make sure you are running the latest CC253X firmware from https://github.com/koenkk/z-stack-firmware.
- Provide a clear description of the problem.
- If applicable, provide steps how to reproduce the problem.
- Provide a log with `log_level` set to `debug`, see https://github.com/Koenkk/zigbee2mqtt/wiki/Configuration
- DON'T copy logs directly here, post a link to https://hastebin.com/ or https://pastebin.com/.
+3 -1
View File
@@ -60,4 +60,6 @@ typings/
# data
data/database.db
data/config.json
data/log*.txt
data/log*.txt
data/state.json
data/log
+3 -2
View File
@@ -11,11 +11,12 @@ node_js:
install:
- npm install
script:
before_script:
- npm test
- npm run verify-homeassistant-mapping
- npm run eslint
after_success:
script:
- ".travis/docker.sh"
- ".travis/wiki.sh"
- ".travis/trigger-downstream.sh"
+1 -1
View File
@@ -17,7 +17,7 @@ build_and_push() {
# Only update Docker images for:
# - dev branch
# - version release
if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ ! -z ${TRAVIS_TAG+x} ]
if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ ! -z ${TRAVIS_TAG+x} ] && [ ! "$TRAVIS_TAG" = "" ]
then
echo "Updating docker images for master branch!"
login
+3 -3
View File
@@ -20,11 +20,11 @@ function travis_trigger() {
"https://api.travis-ci.org/repo/${org}%2F${repo}/requests"
}
# Only trigger downstream if on master branch and not pull request
if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]
# Only trigger downstream if on dev branch and not pull request
if [ "$TRAVIS_BRANCH" = "dev" -a "$TRAVIS_PULL_REQUEST" = "false" ]
then
echo "Triggering build of downstream projects!"
travis_trigger "danielwelch" "hassio-zigbee2mqtt" "master"
else
echo "Not triggering build of downstream projects, triggered by pull request or not on master branch"
echo "Not triggering build of downstream projects, triggered by pull request or not on dev branch"
fi
+62 -10
View File
@@ -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);
@@ -159,7 +161,11 @@ class Controller {
}
configureDevice(device) {
let friendlyName = 'unknown';
const ieeeAddr = device.ieeeAddr;
if (settings.getDevice(ieeeAddr)) {
friendlyName = settings.getDevice(ieeeAddr).friendly_name;
}
if (ieeeAddr && device.modelId && !this.configured.includes(ieeeAddr)) {
const mappedModel = zigbeeShepherdConverters.findByZigbeeModel(device.modelId);
@@ -167,9 +173,9 @@ class Controller {
if (mappedModel && mappedModel.configure) {
mappedModel.configure(ieeeAddr, this.zigbee.shepherd, this.zigbee.getCoordinator(), (ok, msg) => {
if (ok) {
logger.info(`Succesfully configured ${ieeeAddr}`);
logger.info(`Succesfully configured ${friendlyName} ${ieeeAddr}`);
} else {
logger.error(`Failed to configure ${ieeeAddr}`);
logger.error(`Failed to configure ${friendlyName} ${ieeeAddr}`);
}
});
}
@@ -282,10 +288,14 @@ class Controller {
if (!converters.length) {
if (cid) {
logger.warn(
`No converter available for '${mappedModel.model}' with cid '${cid}' and type '${message.type}'`
`No converter available for '${mappedModel.model}' with cid '${cid}', ` +
`type '${message.type}' and data '${JSON.stringify(message.data)}'`
);
} else if (cmdId) {
logger.warn(`No converter available for '${mappedModel.model}' with cmd '${cmdId}'`);
logger.warn(
`No converter available for '${mappedModel.model}' with cmd '${cmdId}' ` +
`and data '${JSON.stringify(message.data)}'`
);
}
logger.warn(`Please see: https://github.com/Koenkk/zigbee2mqtt/wiki/How-to-support-new-devices.`);
@@ -308,6 +318,11 @@ class Controller {
}
});
// Add device linkquality.
if (message.linkquality) {
payload.linkquality = message.linkquality;
}
this.mqttPublishDeviceState(device.ieeeAddr, payload, cache);
};
@@ -384,6 +399,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);
};
@@ -400,6 +418,40 @@ class Controller {
} else {
cleanup();
}
} else if (option === 'rename') {
const invalid = `Invalid rename message format expected {old: 'friendly_name', new: 'new_name} ` +
`got ${message.toString()}`;
let json = null;
try {
json = JSON.parse(message.toString());
} catch (e) {
logger.error(invalid);
return;
}
// Validate message
if (!json.new || !json.old) {
logger.error(invalid);
return;
}
if (settings.changeFriendlyName(json.old, json.new)) {
logger.info(`Successfully renamed - ${json.old} to ${json.new} `);
} else {
logger.error(`Failed to renamed - ${json.old} to ${json.new}`);
return;
}
// Homeassistant rediscover
if (settings.get().homeassistant) {
const ID = settings.getIDByFriendlyName(json.new);
const device = this.zigbee.getDevice(ID);
const mappedModel = zigbeeShepherdConverters.findByZigbeeModel(device.modelId);
if (mappedModel) {
homeassistant.discover(device.ieeeAddr, mappedModel.model, this.mqtt, true);
}
}
} else {
logger.warn(`Cannot handle MQTT config option '${option}' with message '${message}'`);
}
@@ -506,13 +558,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);
}
}
+37 -20
View File
@@ -123,9 +123,9 @@ const configurations = {
type: 'sensor',
object_id: 'action',
discovery_payload: {
icon: 'mdi:cube',
icon: 'mdi:gesture-double-tap',
value_template: '{{ value_json.action }}',
json_attributes: ['battery', 'voltage', 'angle', 'side', 'from_side', 'to_side'],
json_attributes: ['battery', 'voltage', 'angle', 'side', 'from_side', 'to_side', 'brightness'],
force_update: true,
},
},
@@ -193,28 +193,21 @@ const configurations = {
command_topic: true,
},
},
'switch_left': {
};
const switchWithPostfix = (postfix) => {
return {
type: 'switch',
object_id: 'switch_left',
object_id: `switch_${postfix}`,
discovery_payload: {
payload_off: 'OFF',
payload_on: 'ON',
value_template: '{{ value_json.state_left }}',
value_template: `{{ value_json.state_${postfix} }}`,
command_topic: true,
command_topic_prefix: 'left',
command_topic_prefix: postfix,
json_attributes: [`button_${postfix}`],
},
},
'switch_right': {
type: 'switch',
object_id: 'switch_right',
discovery_payload: {
payload_off: 'OFF',
payload_on: 'ON',
value_template: '{{ value_json.state_right }}',
command_topic: true,
command_topic_prefix: 'right',
},
},
};
};
// Map homeassitant configurations to devices.
@@ -225,7 +218,7 @@ const mapping = {
'WXKG03LM': [configurations.sensor_click],
'WXKG02LM': [configurations.sensor_click],
'QBKG04LM': [configurations.switch],
'QBKG03LM': [configurations.switch_left, configurations.switch_right],
'QBKG03LM': [switchWithPostfix('left'), switchWithPostfix('right')],
'WSDCGQ01LM': [configurations.sensor_temperature, configurations.sensor_humidity],
'WSDCGQ11LM': [configurations.sensor_temperature, configurations.sensor_humidity, configurations.sensor_pressure],
'RTCGQ01LM': [configurations.binary_sensor_occupancy],
@@ -242,6 +235,7 @@ const mapping = {
'LED1537R6': [configurations.light_brightness_colortemp],
'LED1650R5': [configurations.light_brightness],
'LED1536G5': [configurations.light_brightness_colortemp],
'7299760PH': [configurations.light_brightness_xy],
'7146060PH': [configurations.light_brightness_colortemp_xy],
'F7C033': [configurations.light_brightness],
'JTYJ-GD-01LM/BW': [configurations.binary_sensor_smoke],
@@ -282,7 +276,7 @@ const mapping = {
'SL 110 W': [configurations.light_brightness],
'AA68199': [configurations.light_brightness_colortemp],
'QBKG11LM': [configurations.switch, configurations.sensor_power],
'QBKG12LM': [configurations.switch_left, configurations.switch_right, configurations.sensor_power],
'QBKG12LM': [switchWithPostfix('left'), switchWithPostfix('right'), configurations.sensor_power],
'K2RGBW01': [configurations.light_brightness_colortemp_xy],
'9290011370': [configurations.light_brightness],
'DNCKATSW001': [configurations.switch],
@@ -290,6 +284,29 @@ const mapping = {
'NL08-0800': [configurations.light_brightness],
'915005106701': [configurations.light_brightness_colortemp_xy],
'AB32840': [configurations.light_brightness_colortemp],
'8718696485880': [configurations.light_brightness_colortemp_xy],
'8718696598283': [configurations.light_brightness_colortemp],
'73693': [configurations.light_brightness_colortemp_xy],
'324131092621': [configurations.sensor_action],
'GL-C-008': [configurations.light_brightness_colortemp_xy],
'STSS-MULT-001': [configurations.binary_sensor_contact],
'E11-G23': [configurations.light_brightness],
'AC03845': [configurations.light_brightness_colortemp_xy],
'AC03641': [configurations.light_brightness],
'FB56+ZSW05HG1.2': [configurations.switch],
'72922-A': [configurations.switch],
'AC03642': [configurations.light_brightness_colortemp],
'DNCKATSW002': [switchWithPostfix('left'), switchWithPostfix('right')],
'DNCKATSW003': [switchWithPostfix('left'), switchWithPostfix('right'), switchWithPostfix('center')],
'DNCKATSW004': [
switchWithPostfix('bottom_left'), switchWithPostfix('bottom_right'),
switchWithPostfix('top_left'), switchWithPostfix('top_right'),
],
'BY 165': [configurations.light_brightness],
'ZLED-2709': [configurations.light_brightness],
'8718696548738': [configurations.light_brightness_colortemp],
'4052899926110': [configurations.light_brightness_colortemp_xy],
'Z01-CIA19NAE26': [configurations.light_brightness],
};
// A map of all discoverd devices
+24 -3
View File
@@ -12,12 +12,29 @@ class MQTT {
const mqttSettings = settings.get().mqtt;
logger.info(`Connecting to MQTT server at ${mqttSettings.server}`);
const options = {};
const options = {
will: {
topic: this.prefixTopic('bridge/state'),
payload: 'offline',
retain: true,
},
};
if (mqttSettings.user && mqttSettings.password) {
options.username = mqttSettings.user;
options.password = mqttSettings.password;
}
if (mqttSettings.client_id) {
logger.debug(`Using MQTT client ID: '${mqttSettings.client_id}'`);
options.clientId = mqttSettings.client_id;
}
if (mqttSettings.hasOwnProperty('reject_unauthorized') && !mqttSettings.reject_unauthorized) {
logger.debug(`MQTT reject_unauthorized set false, ignoring certificate warnings.`);
options.rejectUnauthorized = false;
}
this.client = mqtt.connect(mqttSettings.server, options);
// Register callbacks.
@@ -63,8 +80,7 @@ class MQTT {
}
publish(topic, payload, options, callback, baseTopic) {
baseTopic = baseTopic ? baseTopic : settings.get().mqtt.base_topic;
topic = `${baseTopic}/${topic}`;
topic = this.prefixTopic(topic, baseTopic);
if (!this.client || this.client.reconnecting) {
logger.error(`Not connected to MQTT server!`);
@@ -76,6 +92,11 @@ class MQTT {
this.client.publish(topic, payload, options, callback);
}
prefixTopic(topic, baseTopic) {
baseTopic = baseTopic ? baseTopic : settings.get().mqtt.base_topic;
return `${baseTopic}/${topic}`;
}
log(type, message) {
const payload = {type: type, message: message};
this.publish('bridge/log', JSON.stringify(payload), {retain: false});
+55
View File
@@ -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;
+1
View File
@@ -11,4 +11,5 @@ if (process.env.ZIGBEE2MQTT_DATA) {
module.exports = {
joinPath: (file) => path.join(dataPath, file),
getPath: () => dataPath,
};
+46 -14
View File
@@ -1,37 +1,69 @@
const winston = require('winston');
const moment = require('moment');
const data = require('./data');
const settings = require('./settings');
const path = require('path');
const fs = require('fs');
const fx = require('mkdir-recursive');
const rimraf = require('rimraf');
let logLevel = '';
// Determine the log level.
let level = winston.level.info;
if (process.env.DEBUG) {
logLevel = 'debug';
level = 'debug';
} else if (settings.get().advanced && settings.get().advanced.log_level) {
logLevel = settings.get().advanced.log_level;
} else {
logLevel = winston.level.info;
level = settings.get().advanced.log_level;
}
// Directoy to log to
let rootDirectory = path.join(data.getPath(), 'log');
if (settings.get().advanced && settings.get().advanced.log_directory) {
rootDirectory = settings.get().advanced.log_directory;
}
// Add start time to directory.
const directory = path.join(rootDirectory, moment(Date.now()).format('YYYY-MM-DD.HH:mm:ss'));
// Make sure that log directoy exsists
fx.mkdirSync(directory);
// Create logger
const logger = new (winston.Logger)({
transports: [
new (winston.transports.File)({
filename: data.joinPath('log.txt'),
filename: path.join(directory, 'log.txt'),
json: false,
level: logLevel,
maxFiles: 3,
maxsize: 10000000, // 10MB
level: level,
maxFiles: 3, // Max 3 files per run.
maxsize: 10000000, // 10MB // Only if Filename is static!
timestamp: () => new Date().toLocaleString(),
}),
new (winston.transports.Console)({
timestamp: () => new Date().toLocaleString(),
formatter: function(options) {
return options.timestamp() + ' ' +
winston.config.colorize(options.level, options.level.toUpperCase()) + ' ' +
(options.message ? options.message : '') +
(options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' );
return winston.config.colorize(options.level, ' zigbee2mqtt:' + options.level.toLowerCase()) + ' ' +
options.timestamp() + ' ' + (options.message ? options.message : '') +
(options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' );
},
}),
],
});
logger.transports.console.level = logLevel;
logger.info(`Logging to directory: '${directory}'`);
logger.transports.console.level = level;
// Cleanup any old log directory.
let directories = fs.readdirSync(rootDirectory).map((d) => {
d = path.join(rootDirectory, d);
return {path: d, birth: fs.statSync(d).birthtimeMs};
});
directories.sort((a, b) => b.birth - a.birth);
directories = directories.slice(10, directories.length);
directories.forEach((dir) => {
logger.debug(`Removing old log directory '${dir.path}'`);
rimraf.sync(dir.path);
});
module.exports = logger;
+13
View File
@@ -44,6 +44,18 @@ function getIDByFriendlyName(friendlyName) {
);
}
function changeFriendlyName(old, new_) {
const ID = getIDByFriendlyName(old);
if (!ID) {
return false;
}
settings.devices[ID].friendly_name = new_;
writeRead();
return true;
}
module.exports = {
get: () => settings,
write: () => write(),
@@ -51,4 +63,5 @@ module.exports = {
addDevice: (id) => addDevice(id),
removeDevice: (id) => removeDevice(id),
getIDByFriendlyName: (friendlyName) => getIDByFriendlyName(friendlyName),
changeFriendlyName: (old, new_) => changeFriendlyName(old, new_),
};
+29 -5
View File
@@ -13,7 +13,7 @@ const shepherdSettings = {
},
dbPath: data.joinPath('database.db'),
sp: {
baudrate: advancedSettings && advancedSettings.baudrate ? advancedSettings.baudrate : 115200,
baudRate: advancedSettings && advancedSettings.baudrate ? advancedSettings.baudrate : 115200,
rtscts: advancedSettings && (typeof(advancedSettings.rtscts) === 'boolean') ? advancedSettings.rtscts : true,
},
};
@@ -47,13 +47,13 @@ class Zigbee {
);
callback(error);
} else {
logger.info('zigbee-shepherd started');
this._logStartupInfo();
callback(null);
}
});
}, 60 * 1000);
} else {
logger.info('zigbee-shepherd started');
this._logStartupInfo();
callback(null);
}
});
@@ -66,6 +66,12 @@ class Zigbee {
this.onMessage = onMessage;
}
_logStartupInfo() {
logger.info('zigbee-shepherd started');
logger.info(`Coordinator firmware version: '${this.shepherd.info().firmware.revision}'`);
logger.debug(`zigbee-shepherd info: ${JSON.stringify(this.shepherd.info())}`);
}
softReset(callback) {
this.shepherd.reset('soft', callback);
}
@@ -94,6 +100,11 @@ class Zigbee {
}
});
// Check if we have to turn of the led
if (settings.get().serial.disable_led) {
this.shepherd.controller.request('UTIL', 'ledControl', {ledid: 3, mode: 0});
}
logger.info('zigbee-shepherd ready');
}
@@ -143,11 +154,16 @@ class Zigbee {
}
ping(deviceID) {
let friendlyName = 'unknown';
const device = this.shepherd._findDevByAddr(deviceID);
const ieeeAddr = device.ieeeAddr;
if (settings.getDevice(ieeeAddr)) {
friendlyName = settings.getDevice(ieeeAddr).friendly_name;
}
if (device) {
// Note: checkOnline has the callback argument but does not call callback
logger.debug(`Check online ${deviceID}`);
logger.debug(`Check online ${friendlyName} ${deviceID}`);
this.shepherd.controller.checkOnline(device);
}
}
@@ -175,7 +191,15 @@ class Zigbee {
}
logger.info(`Zigbee publish to '${deviceID}', ${cid} - ${cmd} - ${JSON.stringify(zclData)} - ${ep}`);
device.functional(cid, cmd, zclData, callback);
device.functional(cid, cmd, zclData, (error) => {
if (error) {
logger.error(
`Zigbee publish to '${deviceID}', ${cid} - ${cmd} - ${JSON.stringify(zclData)} - ${ep} ` +
`failed with error ${error}`);
}
callback(error);
});
}
read(deviceID, cid, attr, ep, callback) {
+4399 -1521
View File
File diff suppressed because it is too large Load Diff
+24 -13
View File
@@ -1,6 +1,6 @@
{
"name": "zigbee2mqtt",
"version": "0.1.0",
"version": "0.1.3",
"description": "Zigbee to MQTT bridge using zigbee-shepherd",
"main": "index.js",
"repository": {
@@ -17,10 +17,12 @@
"cc2531"
],
"scripts": {
"start": "node index.js",
"coverage": "nyc --all report --reporter=text mocha --recursive --timeout=3000",
"docgen": "node support/docgen.js",
"verify-homeassistant-mapping": "node support/verify-homeassistant-mapping.js",
"eslint": "node_modules/.bin/eslint ."
"eslint": "node_modules/.bin/eslint .",
"start": "node index.js",
"test": "mocha --recursive",
"verify-homeassistant-mapping": "node support/verify-homeassistant-mapping.js"
},
"author": "Koen Kanters",
"license": "GPL-3.0",
@@ -29,18 +31,27 @@
},
"homepage": "https://github.com/Koenkk/zigbee2mqtt/wiki",
"dependencies": {
"object-assign-deep": "*",
"mqtt": "*",
"winston": "2.4.2",
"zigbee-shepherd": "git+https://github.com/Koenkk/zigbee-shepherd.git",
"zigbee-shepherd-converters": "*",
"json2yaml": "*",
"zcl-packet": "git+https://github.com/Koenkk/zcl-packet.git",
"git-last-commit": "*",
"js-yaml": "*",
"git-last-commit": "*"
"json2yaml": "*",
"mkdir-recursive": "*",
"moment": "*",
"mqtt": "*",
"object-assign-deep": "*",
"rimraf": "*",
"winston": "2.4.2",
"zcl-packet": "git+https://github.com/Koenkk/zcl-packet.git#b7d5b4478a88cd3fc65328c6dc94572c277c7d3e",
"zigbee-shepherd": "git+https://github.com/Koenkk/zigbee-shepherd.git#7673fc5a285dc93d2e466bc2aa7134220e1fb134",
"zigbee-shepherd-converters": "*"
},
"devDependencies": {
"chai": "*",
"chai-spies": "*",
"eslint": "*",
"eslint-config-google": "*"
"eslint-config-google": "*",
"eslint-plugin-mocha": "*",
"mocha": "*",
"nyc": "*",
"proxyquire": "*"
}
}
+23
View File
@@ -0,0 +1,23 @@
/* global describe, it */
const chai = require('chai');
const proxyquire = require('proxyquire').noPreserveCache();
const data = () => proxyquire('../lib/util/data.js', {});
const path = require('path');
describe('Data', () => {
describe('Get path', () => {
it('Should return correct path', () => {
const expected = path.normalize(path.join(__dirname, '..', 'data'));
const actual = data().getPath();
chai.assert.strictEqual(actual, expected);
});
it('Should return correct path when ZIGBEE2MQTT_DATA set', () => {
const expected = path.join('var', 'zigbee2mqtt');
process.env.ZIGBEE2MQTT_DATA = expected;
const actual = data().getPath();
chai.assert.strictEqual(actual, expected);
});
});
});