UNPKG

@flowfuse/flowfuse

Version:

An open source low-code development platform

113 lines (104 loc) 4.93 kB
const fp = require('fastify-plugin') const ACLManager = require('./aclManager') const { CommsClient } = require('./commsClient') const { DeviceCommsHandler } = require('./devices') const { InstanceCommsHandler } = require('./instances') const { PlatformAutomationHandler } = require('./platformAutomation.js') /** * This module represents the real-time comms component of the platform. * We depend on an external MQTT broker (mosquitto) and of the runtime configuration * to include the details needed to connect to it. * * This module handles * - Incoming device status messages * - Broker ACL requests * */ module.exports = fp(async function (app, _opts) { // Check the runtime configuration includes the minimum required configuration // to use the MQTT broker service if (app.config.broker && app.config.broker.url) { // Register the authentication routes the broker will be using await app.register(require('./authRoutes'), { prefix: '/api/comms/auth', logLevel: app.config.logging.http }) await app.register(require('./v2AuthRoutes'), { prefix: '/api/comms/v2', logLevel: app.config.logging.http }) // Ensure we have a BrokerClient object (auth details) for use by the platform await app.db.controllers.BrokerClient.ensurePlatformClient() // Create the platform's client for connecting to the broker const client = new CommsClient(app) // Create the handler for any device-related messages const deviceCommsHandler = DeviceCommsHandler(app, client) const instanceCommsHandler = InstanceCommsHandler(app, client) const platformAutomationHandler = PlatformAutomationHandler(app, client) // Not in the current release, but when we handle Launcher status // via MQTT, it will arrive here. Compare to the status/device handler in `devices.js` // client.on('status/project', (status) => { // // console.info(status) // }) // Setup the platform API for the comms component app.decorate('comms', { devices: deviceCommsHandler, instances: instanceCommsHandler, aclManager: ACLManager(app), platformAutomation: platformAutomationHandler, platform: { settings: { sync: function (key) { const msg = { key, srcId: client.platformId } client.publish('ff/v1/platform/sync', JSON.stringify(msg)) } }, housekeeper: { vote: function (vote) { const msg = { vote, id: client.platformId } client.publish('ff/v1/platform/leader', JSON.stringify(msg)) } } }, team: { notify: function (teamHash, reason, srcId) { if (!teamHash) return const msg = { reason: reason || null, srcId: srcId || null } client.publish(`ff/v1/${teamHash}/t/updated`, JSON.stringify(msg)) }, notifyMembership: function (teamHash, userHash, reason, srcId) { if (!teamHash || !userHash) return const msg = { reason: reason || null, srcId: srcId || null } client.publish(`ff/v1/${teamHash}/u/${userHash}/membership`, JSON.stringify(msg)) }, notifyDeviceState: function (teamHash, id, state) { if (!teamHash || !id) return client.publish(`ff/v1/${teamHash}/d/${id}/state`, JSON.stringify({ id, meta: { state } })) }, notifyInstanceState: function (teamHash, id, { state, versions } = {}) { if (!teamHash || !id) return const meta = { state } if (versions) meta.versions = versions client.publish(`ff/v1/${teamHash}/p/${id}/state`, JSON.stringify({ id, meta })) } } }) app.addHook('onReady', async () => { try { await client.init() } catch (err) { app.log.info('[comms] problem starting comms client:', err.toString()) } }) app.addHook('onClose', async (_) => { app.log.info('Comms shutdown') await deviceCommsHandler.stopLogWatcher() client.publish('ff/v1/platform/leader', JSON.stringify({ id: client.platformId, vote: -1 })) await client.disconnect() }) } else { app.log.warn('[comms] Broker not configured - comms unavailable') } }, { name: 'app.comms' })