import * as mqtt from 'mqtt' let mqttClient: mqtt.MqttClient function startServer(): Promise { return new Promise(async resolve => { mqttClient = await connectMqtt() generateData(mqttClient) resolve(mqttClient) }) } function connectMqtt(): Promise { return new Promise(resolve => { const client = mqtt.connect('mqtt://127.0.0.1:1883', { username: 'thomas', password: 'bierbier', }) client.once('connect', () => { resolve(client) }) }) } function temperature(base = 18, sineCoefficient = 2, offset = 0, speed = 1) { const temp = base + Math.sin((Date.now() * speed) / 1000 / 5 + offset) * sineCoefficient + Math.random() return String(Math.round(temp * 100) / 100) } export function stopUpdates() { for (const interval of intervals) { clearInterval(interval) } intervals = [] } export function stop() { stopUpdates() try { mqttClient && mqttClient.end() } catch { // ignore } } let intervals: any = [] function generateData(client: mqtt.MqttClient) { client.publish('livingroom/lamp/state', 'on', { retain: true, qos: 0 }) client.publish('livingroom/lamp/brightness', '128', { retain: true, qos: 0 }) client.publish('livingroom/thermostat/targetTemperature', '20°C', { retain: true, qos: 0, }) intervals.push(setInterval(() => client.publish('livingroom/temperature', temperature()), 1000)) intervals.push(setInterval(() => client.publish('livingroom/humidity', temperature(60, -2, 0)), 1000)) client.publish('livingroom/lamp-1/state', 'on', { retain: true, qos: 0 }) client.publish('livingroom/lamp-1/brightness', '48', { retain: true, qos: 0, }) client.publish('livingroom/lamp-2/state', 'off', { retain: true, qos: 0 }) client.publish('livingroom/lamp-2/brightness', '48', { retain: true, qos: 0, }) client.publish('kitchen/lamp/state', 'off', { retain: true, qos: 0 }) client.subscribe('kitchen/lamp/set') client.on('message', (topic, payload) => { if (topic === 'kitchen/lamp/set') { setTimeout( () => client.publish('kitchen/lamp/state', payload, { retain: true, qos: 0, }), 500 ) } }) const coffeeMaker = { heater: 'on', temperature: 92.5, waterLevel: 0.5, update: new Date(), } intervals.push( setInterval(() => { const newTemp = parseFloat(temperature(90.3, -5, 0, 3)) coffeeMaker.heater = newTemp > coffeeMaker.temperature ? 'on' : 'off' coffeeMaker.temperature = newTemp client.publish('kitchen/coffee_maker', JSON.stringify(coffeeMaker), { retain: true, qos: 2 }) }, 1500) ) intervals.push(setInterval(() => client.publish('kitchen/temperature', temperature()), 1500)) intervals.push(setInterval(() => client.publish('kitchen/humidity', temperature(60, -5, 0)), 1800)) client.publish('garden/pump/state', 'off', { retain: true, qos: 0 }) client.publish('garden/water/level', '70%', { retain: true, qos: 0 }) client.publish('garden/lamps/state', 'off', { retain: true, qos: 0 }) client.publish('garden/lamps/state', 'off', { retain: true, qos: 0 }) client.publish('zigbee2mqtt/bridge/state', 'online', { retain: true, qos: 0, }) client.publish('ble2mqtt/bridge/state', 'online', { retain: true, qos: 0 }) // Used for demonstrating "clean up" client.publish('test 123', 'Hello world', { retain: true, qos: 0 }) client.publish('hello', 'sunshine', { retain: true, qos: 0 }) // Just stuff client.publish('01-80-C2-00-00-0F/LWT', 'offline', { retain: true, qos: 0 }) intervals.push( setInterval(() => { client.publish('3d-printer/OctoPrint/temperature/bed', '{"_timestamp":1548589083,"actual":25.9,"target":0}') client.publish('3d-printer/OctoPrint/temperature/tool0', '{"_timestamp":1548589093,"actual":26.4,"target":0}') }, 3333) ) let state = true intervals.push( setInterval(() => { state = !state const js = { tags: { entityId: 33512, entityType: 'person', host: 'd44ad81e10f9', server: 'http://localhost/dataActuality', status: state ? 'live' : 'inactive', }, timestamp: Date.now(), } client.publish('actuality/showcase', JSON.stringify(js), { retain: true, qos: 0, }) }, 2102) ) } export default startServer