mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-07-09 13:31:41 +00:00
New api: log to MQTT. https://github.com/Koenkk/zigbee2mqtt/issues/3281
This commit is contained in:
@@ -3,6 +3,7 @@ const utils = require('../util/utils');
|
||||
const Extension = require('./extension');
|
||||
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
||||
const settings = require('../util/settings');
|
||||
const Transport = require('winston-transport');
|
||||
|
||||
const requestRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/request/(.*)`);
|
||||
|
||||
@@ -10,6 +11,7 @@ class Bridge extends Extension {
|
||||
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
|
||||
super(zigbee, mqtt, state, publishEntityState, eventBus);
|
||||
this.lastJoinedDeviceIeeeAddr = null;
|
||||
this.setupMQTTLogging();
|
||||
|
||||
this.requestLookup = {
|
||||
'device/options': this.deviceOptions.bind(this),
|
||||
@@ -39,6 +41,19 @@ class Bridge extends Extension {
|
||||
await this.publishGroups();
|
||||
}
|
||||
|
||||
setupMQTTLogging() {
|
||||
const mqtt = this.mqtt;
|
||||
class EventTransport extends Transport {
|
||||
log(info, callback) {
|
||||
const payload = JSON.stringify({message: info.message, level: info.level});
|
||||
mqtt.publish(`bridge/logging`, payload, {}, settings.get().mqtt.base_topic, true);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
logger.add(new EventTransport());
|
||||
}
|
||||
|
||||
async onMQTTMessage(topic, message) {
|
||||
const match = topic.match(requestRegex);
|
||||
if (match && this.requestLookup[match[1].toLowerCase()]) {
|
||||
|
||||
+8
-4
@@ -99,17 +99,21 @@ class MQTT extends events.EventEmitter {
|
||||
return this.client && !this.client.reconnecting;
|
||||
}
|
||||
|
||||
async publish(topic, payload, options, base=settings.get().mqtt.base_topic) {
|
||||
async publish(topic, payload, options, base=settings.get().mqtt.base_topic, skipLog=false) {
|
||||
topic = `${base}/${topic}`;
|
||||
options = {qos: 0, retain: false, ...options};
|
||||
|
||||
if (!this.isConnected()) {
|
||||
logger.error(`Not connected to MQTT server!`);
|
||||
logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
|
||||
if (!skipLog) {
|
||||
logger.error(`Not connected to MQTT server!`);
|
||||
logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`MQTT publish: topic '${topic}', payload '${payload}'`);
|
||||
if (!skipLog) {
|
||||
logger.info(`MQTT publish: topic '${topic}', payload '${payload}'`);
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.client.publish(topic, payload, options, () => resolve());
|
||||
|
||||
+29
-1
@@ -5,7 +5,6 @@ const MQTT = require('./stub/mqtt');
|
||||
const settings = require('../lib/util/settings');
|
||||
const Controller = require('../lib/controller');
|
||||
const flushPromises = () => new Promise(setImmediate);
|
||||
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
|
||||
const {coordinator, bulb, unsupported} = zigbeeHerdsman.devices;
|
||||
zigbeeHerdsman.returnDevices.push(coordinator.ieeeAddr);
|
||||
@@ -16,6 +15,7 @@ describe('Bridge', () => {
|
||||
let controller;
|
||||
|
||||
beforeEach(async () => {
|
||||
MQTT.mock.reconnecting = false;
|
||||
data.writeDefaultConfiguration();
|
||||
settings._reRead();
|
||||
settings.set(['advanced', 'legacy_api'], false);
|
||||
@@ -23,6 +23,7 @@ describe('Bridge', () => {
|
||||
data.writeDefaultState();
|
||||
logger.info.mockClear();
|
||||
logger.warn.mockClear();
|
||||
logger.setTransportsEnabled(false);
|
||||
MQTT.publish.mockClear();
|
||||
const device = zigbeeHerdsman.devices.bulb;
|
||||
device.removeFromDatabase.mockClear();
|
||||
@@ -51,7 +52,34 @@ describe('Bridge', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('Should log to MQTT', async () => {
|
||||
logger.setTransportsEnabled(true);
|
||||
MQTT.publish.mockClear();
|
||||
logger.info.mockClear();
|
||||
logger.info("this is a test");
|
||||
expect(MQTT.publish).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/logging',
|
||||
JSON.stringify({message: 'this is a test', level: 'info'}),
|
||||
{ retain: false, qos: 0 },
|
||||
expect.any(Function)
|
||||
);
|
||||
expect(logger.info).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Shouldnt log to MQTT when not connected', async () => {
|
||||
logger.setTransportsEnabled(true);
|
||||
MQTT.mock.reconnecting = true;
|
||||
MQTT.publish.mockClear();
|
||||
logger.info.mockClear();
|
||||
logger.error.mockClear();
|
||||
logger.info("this is a test");
|
||||
expect(MQTT.publish).toHaveBeenCalledTimes(0);
|
||||
expect(logger.info).toHaveBeenCalledTimes(1);
|
||||
expect(logger.error).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should publish devices on startup', async () => {
|
||||
logger.setTransportsEnabled(true);
|
||||
expect(MQTT.publish).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/groups',
|
||||
JSON.stringify([{"id":1,"friendly_name":"group_1","members":[]},{"id":15071,"friendly_name":"group_tradfri_remote","members":[]},{"id":99,"friendly_name":99,"members":[]},{"id":11,"friendly_name":"group_with_tradfri","members":[]},{"id":2,"friendly_name":"group_2","members":[]}]),
|
||||
|
||||
+17
-5
@@ -1,14 +1,26 @@
|
||||
let level = 'info';
|
||||
|
||||
const transports = [];
|
||||
|
||||
let transportsEnabled = false;
|
||||
const callTransports = (level, message) => {
|
||||
if (transportsEnabled) {
|
||||
for (const transport of transports) {
|
||||
transport.log({level, message}, () => {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mock = {
|
||||
info: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
info: jest.fn().mockImplementation((msg) => callTransports('info', msg)),
|
||||
warn: jest.fn().mockImplementation((msg) => callTransports('warn', msg)),
|
||||
error: jest.fn().mockImplementation((msg) => callTransports('error', msg)),
|
||||
debug: jest.fn().mockImplementation((msg) => callTransports('debug', msg)),
|
||||
cleanup: jest.fn(),
|
||||
add: (transport) => transports.push(transport),
|
||||
setLevel: (newLevel) => {level = newLevel},
|
||||
getLevel: () => level,
|
||||
setTransportsEnabled: (value) => {transportsEnabled = value},
|
||||
};
|
||||
|
||||
jest.mock('../../lib/util/logger', () => (mock));
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ const mock = {
|
||||
publish: jest.fn().mockImplementation((topic, payload, options, cb) => cb()),
|
||||
end: jest.fn(),
|
||||
subscribe: jest.fn(),
|
||||
reconnecting: false,
|
||||
on: (type, handler) => {
|
||||
if (type === 'connect') {
|
||||
handler();
|
||||
@@ -20,5 +21,5 @@ jest.mock('mqtt', () => {
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
events, ...mock, connect: mockConnect,
|
||||
events, ...mock, connect: mockConnect, mock,
|
||||
};
|
||||
Reference in New Issue
Block a user