@things-factory/integration-base 9.0.0-beta.7 → 9.0.0-beta.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/engine/analyzer/analyze-integration.js +1 -1
- package/dist-server/engine/analyzer/analyze-integration.js.map +1 -1
- package/dist-server/engine/connection-manager.js +1 -8
- package/dist-server/engine/connection-manager.js.map +1 -1
- package/dist-server/engine/index.d.ts +2 -2
- package/dist-server/engine/index.js +2 -2
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/engine/task/mqtt-publish.js +29 -6
- package/dist-server/engine/task/mqtt-publish.js.map +1 -1
- package/dist-server/engine/task/mqtt-subscribe.d.ts +84 -0
- package/dist-server/engine/task/mqtt-subscribe.js +199 -79
- package/dist-server/engine/task/mqtt-subscribe.js.map +1 -1
- package/dist-server/index.d.ts +6 -6
- package/dist-server/index.js +10 -10
- package/dist-server/index.js.map +1 -1
- package/dist-server/routes.js +8 -7
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/connection/connection-mutation.d.ts +3 -1
- package/dist-server/service/connection/connection-mutation.js +17 -5
- package/dist-server/service/connection/connection-mutation.js.map +1 -1
- package/dist-server/service/connection/connection-query.js +3 -0
- package/dist-server/service/connection/connection-query.js.map +1 -1
- package/dist-server/service/connection/connection-type.d.ts +14 -3
- package/dist-server/service/connection/connection-type.js +26 -15
- package/dist-server/service/connection/connection-type.js.map +1 -1
- package/dist-server/service/scenario/scenario-query.js +1 -1
- package/dist-server/service/scenario/scenario-query.js.map +1 -1
- package/dist-server/service/scenario-instance/scenario-instance-type.js +1 -8
- package/dist-server/service/scenario-instance/scenario-instance-type.js.map +1 -1
- package/dist-server/service/step/step-type.d.ts +11 -3
- package/dist-server/service/step/step-type.js +24 -5
- package/dist-server/service/step/step-type.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/translations/en.json +4 -1
- package/translations/ja.json +4 -1
- package/translations/ko.json +4 -1
- package/translations/ms.json +4 -1
- package/translations/zh.json +4 -1
@@ -63,7 +63,7 @@ async function analyzeIntegration(domain) {
|
|
63
63
|
scenarios.forEach(scenario => {
|
64
64
|
const tags = (0, uniq_1.default)(scenario.steps
|
65
65
|
.filter(step => !step.connection && step.task == 'publish')
|
66
|
-
.map(step => { var _a; return (_a =
|
66
|
+
.map(step => { var _a; return (_a = step.params) === null || _a === void 0 ? void 0 : _a.tag; })
|
67
67
|
.filter(Boolean));
|
68
68
|
for (const tag of tags) {
|
69
69
|
if (tagNames.includes(tag)) {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"analyze-integration.js","sourceRoot":"","sources":["../../../server/engine/analyzer/analyze-integration.ts"],"names":[],"mappings":"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
|
1
|
+
{"version":3,"file":"analyze-integration.js","sourceRoot":"","sources":["../../../server/engine/analyzer/analyze-integration.ts"],"names":[],"mappings":"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","sourcesContent":["import uniq from 'lodash/uniq'\n\nimport { Domain, getRepository } from '@things-factory/shell'\nimport { Scenario } from '../../service/scenario/scenario'\nimport { Connection } from '../../service/connection/connection-type'\n\nexport async function analyzeIntegration(domain: Domain) {\n const tagNames = []\n\n const model = {\n nodes: [],\n relationships: []\n }\n\n var id = 0\n\n const scenarios = await getRepository(Scenario).find({\n where: { domain: { id: domain.id } },\n relations: ['steps']\n })\n\n const connections = await getRepository(Connection).find({\n where: { domain: { id: domain.id } }\n })\n\n model.nodes = model.nodes.concat(\n scenarios.map(scenario => {\n return {\n id: scenario.id,\n labels: ['Scenario'],\n text: scenario.name,\n icon: 'settings',\n properties: {\n name: scenario.name,\n description: scenario.description\n }\n }\n })\n )\n\n model.nodes = model.nodes.concat(\n connections.map(connection => {\n return {\n id: connection.id,\n labels: ['Connection'],\n text: connection.name,\n icon: 'link',\n properties: {\n name: connection.name,\n description: connection.description\n }\n }\n })\n )\n\n scenarios.forEach(scenario => {\n const connectionNames = uniq(scenario.steps.map(step => step.connection).filter(Boolean))\n const connectionList = connectionNames\n .map(connectionName => connections.find(connection => connection.name == connectionName))\n .filter(Boolean)\n\n const relationships = connectionList.map(connection => {\n return {\n id: ++id,\n type: 'using',\n startNode: scenario.id,\n endNode: connection.id,\n properties: {}\n }\n })\n\n model.relationships = model.relationships.concat(relationships)\n })\n\n scenarios.forEach(scenario => {\n const tags = uniq(\n scenario.steps\n .filter(step => !step.connection && step.task == 'publish')\n .map(step => step.params?.tag)\n .filter(Boolean)\n )\n\n for (const tag of tags) {\n if (tagNames.includes(tag)) {\n continue\n }\n\n model.nodes.push({\n id: `tag-${tag}`,\n labels: ['Tag'],\n text: tag,\n icon: 'label',\n properties: {\n tag\n }\n })\n\n tagNames.push(tag)\n }\n\n const relationships = tags.map(tag => {\n return {\n id: ++id,\n type: 'publish',\n startNode: scenario.id,\n endNode: `tag-${tag}`,\n properties: {}\n }\n })\n\n model.relationships = model.relationships.concat(relationships)\n })\n\n return model\n}\n"]}
|
@@ -34,14 +34,7 @@ class ConnectionManager {
|
|
34
34
|
where: { active: true },
|
35
35
|
relations: ['domain', 'edge', 'creator', 'updater']
|
36
36
|
})).map(connection => {
|
37
|
-
|
38
|
-
try {
|
39
|
-
params = JSON.parse(connection.params || '{}');
|
40
|
-
}
|
41
|
-
catch (ex) {
|
42
|
-
ConnectionManager.logger.error(`connection '${connection.name}' params should be JSON format`, ex);
|
43
|
-
}
|
44
|
-
return Object.assign(Object.assign({}, connection), { params });
|
37
|
+
return Object.assign(Object.assign({}, connection), { params: connection.params || {} });
|
45
38
|
});
|
46
39
|
ConnectionManager.logger.info('Initializing ConnectionManager...');
|
47
40
|
return await Promise.all([...Object.keys(ConnectionManager.connectors), 'proxy-connector'].map(type => {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"connection-manager.js","sourceRoot":"","sources":["../../server/engine/connection-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\nimport { createLogger, format, transports } from 'winston'\n\nimport { Domain, getRepository, pubsub, PubSubLogTransport } from '@things-factory/shell'\n\nimport { Connection, ConnectionStatus } from '../service'\nimport { Connector } from './types'\nimport { ProxyConnector } from './connector/proxy-connector'\n\nconst { combine, splat, printf, errors } = format\nconst debug = require('debug')('things-factory:integration-base:connections')\n\nfunction getSystemTimeZone() {\n try {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone\n if (!timeZone) {\n throw new Error('Unable to resolve timeZone')\n }\n return timeZone\n } catch (e) {\n console.warn('Failed to get system timeZone, falling back to UTC.', e)\n return 'UTC'\n }\n}\n\nconst SYSTEM_TZ = getSystemTimeZone()\nconst systemTimestamp = format((info, opts: { tz?: string }) => {\n if (opts.tz) info.timestamp = moment().tz(opts.tz).format()\n return info\n})\n\nexport class ConnectionManager {\n private static connectors: { [propName: string]: Connector } = {}\n private static connections: { [domainId: string]: { [name: string]: any } } = {}\n private static entities = {}\n private static logFormat = printf(({ level, message, timestamp, stack }) => {\n return `${timestamp} ${level}: ${stack || message}`\n })\n\n public static logger = createLogger({\n format: combine(errors({ stack: true }), systemTimestamp({ tz: SYSTEM_TZ }), splat(), ConnectionManager.logFormat),\n transports: [\n new (transports as any).DailyRotateFile({\n filename: `logs/connections-%DATE%.log`,\n datePattern: 'YYYY-MM-DD-HH',\n zippedArchive: false,\n maxSize: '20m',\n maxFiles: '14d',\n level: 'info'\n }),\n new PubSubLogTransport({\n topic: 'connection-log'\n })\n ]\n })\n\n static async ready() {\n const CONNECTIONS = (\n await getRepository(Connection).find({\n where: { active: true },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n ).map(connection => {\n var params = {}\n try {\n params = JSON.parse(connection.params || '{}')\n } catch (ex) {\n ConnectionManager.logger.error(`connection '${connection.name}' params should be JSON format`, ex)\n }\n\n return {\n ...connection,\n params\n }\n })\n\n ConnectionManager.logger.info('Initializing ConnectionManager...')\n\n return await Promise.all(\n [...Object.keys(ConnectionManager.connectors), 'proxy-connector'].map(type => {\n const connector = type == 'proxy-connector' ? ProxyConnector.instance : ConnectionManager.getConnector(type)\n\n ConnectionManager.logger.info(`Connector '${type}' started to ready`)\n\n return connector\n .ready(\n CONNECTIONS.filter(connection => {\n if (type == 'proxy-connector') {\n return !!connection.edge\n } else {\n return !connection.edge && connection.type == type\n }\n }) as any\n )\n .catch(error => {\n ConnectionManager.logger.error(error)\n })\n .then(() => {\n ConnectionManager.logger.info(`All connector for '${type}' ready`)\n })\n })\n ).then(() => {\n ConnectionManager.logger.info('ConnectionManager initialization done:')\n Object.keys(ConnectionManager.connections).forEach(key => {\n var connections = ConnectionManager.connections[key]\n ConnectionManager.logger.info('For domain(%s) : %s', key, JSON.stringify(Object.keys(connections)))\n })\n })\n }\n\n static registerConnector(type: string, connector: Connector) {\n ConnectionManager.connectors[type] = connector\n }\n\n static getConnector(type: string): Connector {\n return ConnectionManager.connectors[type]\n }\n\n static getConnectors(): { [connectorName: string]: Connector } {\n return {\n ...ConnectionManager.connectors\n }\n }\n\n static unregisterConnector(type: string) {\n delete ConnectionManager.connectors[type]\n }\n\n static getConnections() {\n return ConnectionManager.connections\n }\n\n static getEntities() {\n return ConnectionManager.entities\n }\n\n static getConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n return ConnectionManager.connections[domain.id]?.[name]\n }\n\n static getConnectionInstanceByName(domain: Domain, name: string) {\n const connections = ConnectionManager.connections[domain.id]\n const connection = connections?.[name]\n\n if (!connection) {\n throw `The connection with the given name(${name}) cannot be found`\n }\n\n return connection\n }\n\n static getConnectionInstanceEntityByName(domain: Domain, name: string): any {\n const connection = ConnectionManager.entities[domain.id]?.[name]\n if (connection) {\n return connection\n }\n\n if (domain.parentId) {\n return ConnectionManager.entities[domain.id]?.[name]\n }\n }\n\n static getConnectionInstances(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.connections[domain.id]\n const parentConnections = domain.parentId && ConnectionManager.connections[domain.parentId]\n\n return {\n ...parentConnections,\n ...connections\n }\n }\n\n static getConnectionInstanceEntities(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.entities[domain.id]\n\n return {\n ...connections\n }\n }\n\n static addConnectionInstance(connection: Connection, instance: any) {\n const { domain, name } = connection\n\n var connections = ConnectionManager.connections[domain.id]\n if (!connections) {\n connections = ConnectionManager.connections[domain.id] = {}\n }\n\n var entities = ConnectionManager.entities[domain.id]\n if (!entities) {\n entities = ConnectionManager.entities[domain.id] = {}\n }\n\n connections[name] = instance\n entities[name] = connection\n\n ConnectionManager.publishState(connection, ConnectionStatus.CONNECTED)\n debug('add-connection', domain.subdomain, name)\n }\n\n static removeConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n var connections = ConnectionManager.connections[domain.id]\n var entities = ConnectionManager.entities[domain.id]\n\n var instance = connections?.[name]\n\n if (!connections || !instance) {\n debug('remove-connection', `'${name}' connection not found in domain '${domain.subdomain}'`)\n return\n }\n\n delete connections[name]\n delete entities[name]\n\n ConnectionManager.publishState(connection, ConnectionStatus.DISCONNECTED)\n debug('remove-connection', `'${name}' connection is removed from domain '${domain.subdomain}'`)\n\n return instance\n }\n\n private static async publishState(connection: Connection, state) {\n const { domain, id, name, description, type, edge } = connection\n\n pubsub.publish('connection-state', {\n connectionState: {\n domain,\n id,\n name,\n description,\n type,\n edge,\n state,\n timestamp: new Date()\n }\n })\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"connection-manager.js","sourceRoot":"","sources":["../../server/engine/connection-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\nimport { createLogger, format, transports } from 'winston'\n\nimport { Domain, getRepository, pubsub, PubSubLogTransport } from '@things-factory/shell'\n\nimport { Connection, ConnectionStatus } from '../service'\nimport { Connector } from './types'\nimport { ProxyConnector } from './connector/proxy-connector'\n\nconst { combine, splat, printf, errors } = format\nconst debug = require('debug')('things-factory:integration-base:connections')\n\nfunction getSystemTimeZone() {\n try {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone\n if (!timeZone) {\n throw new Error('Unable to resolve timeZone')\n }\n return timeZone\n } catch (e) {\n console.warn('Failed to get system timeZone, falling back to UTC.', e)\n return 'UTC'\n }\n}\n\nconst SYSTEM_TZ = getSystemTimeZone()\nconst systemTimestamp = format((info, opts: { tz?: string }) => {\n if (opts.tz) info.timestamp = moment().tz(opts.tz).format()\n return info\n})\n\nexport class ConnectionManager {\n private static connectors: { [propName: string]: Connector } = {}\n private static connections: { [domainId: string]: { [name: string]: any } } = {}\n private static entities = {}\n private static logFormat = printf(({ level, message, timestamp, stack }) => {\n return `${timestamp} ${level}: ${stack || message}`\n })\n\n public static logger = createLogger({\n format: combine(errors({ stack: true }), systemTimestamp({ tz: SYSTEM_TZ }), splat(), ConnectionManager.logFormat),\n transports: [\n new (transports as any).DailyRotateFile({\n filename: `logs/connections-%DATE%.log`,\n datePattern: 'YYYY-MM-DD-HH',\n zippedArchive: false,\n maxSize: '20m',\n maxFiles: '14d',\n level: 'info'\n }),\n new PubSubLogTransport({\n topic: 'connection-log'\n })\n ]\n })\n\n static async ready() {\n const CONNECTIONS = (\n await getRepository(Connection).find({\n where: { active: true },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n ).map(connection => {\n return {\n ...connection,\n params: connection.params || {}\n }\n })\n\n ConnectionManager.logger.info('Initializing ConnectionManager...')\n\n return await Promise.all(\n [...Object.keys(ConnectionManager.connectors), 'proxy-connector'].map(type => {\n const connector = type == 'proxy-connector' ? ProxyConnector.instance : ConnectionManager.getConnector(type)\n\n ConnectionManager.logger.info(`Connector '${type}' started to ready`)\n\n return connector\n .ready(\n CONNECTIONS.filter(connection => {\n if (type == 'proxy-connector') {\n return !!connection.edge\n } else {\n return !connection.edge && connection.type == type\n }\n }) as any\n )\n .catch(error => {\n ConnectionManager.logger.error(error)\n })\n .then(() => {\n ConnectionManager.logger.info(`All connector for '${type}' ready`)\n })\n })\n ).then(() => {\n ConnectionManager.logger.info('ConnectionManager initialization done:')\n Object.keys(ConnectionManager.connections).forEach(key => {\n var connections = ConnectionManager.connections[key]\n ConnectionManager.logger.info('For domain(%s) : %s', key, JSON.stringify(Object.keys(connections)))\n })\n })\n }\n\n static registerConnector(type: string, connector: Connector) {\n ConnectionManager.connectors[type] = connector\n }\n\n static getConnector(type: string): Connector {\n return ConnectionManager.connectors[type]\n }\n\n static getConnectors(): { [connectorName: string]: Connector } {\n return {\n ...ConnectionManager.connectors\n }\n }\n\n static unregisterConnector(type: string) {\n delete ConnectionManager.connectors[type]\n }\n\n static getConnections() {\n return ConnectionManager.connections\n }\n\n static getEntities() {\n return ConnectionManager.entities\n }\n\n static getConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n return ConnectionManager.connections[domain.id]?.[name]\n }\n\n static getConnectionInstanceByName(domain: Domain, name: string) {\n const connections = ConnectionManager.connections[domain.id]\n const connection = connections?.[name]\n\n if (!connection) {\n throw `The connection with the given name(${name}) cannot be found`\n }\n\n return connection\n }\n\n static getConnectionInstanceEntityByName(domain: Domain, name: string): any {\n const connection = ConnectionManager.entities[domain.id]?.[name]\n if (connection) {\n return connection\n }\n\n if (domain.parentId) {\n return ConnectionManager.entities[domain.id]?.[name]\n }\n }\n\n static getConnectionInstances(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.connections[domain.id]\n const parentConnections = domain.parentId && ConnectionManager.connections[domain.parentId]\n\n return {\n ...parentConnections,\n ...connections\n }\n }\n\n static getConnectionInstanceEntities(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.entities[domain.id]\n\n return {\n ...connections\n }\n }\n\n static addConnectionInstance(connection: Connection, instance: any) {\n const { domain, name } = connection\n\n var connections = ConnectionManager.connections[domain.id]\n if (!connections) {\n connections = ConnectionManager.connections[domain.id] = {}\n }\n\n var entities = ConnectionManager.entities[domain.id]\n if (!entities) {\n entities = ConnectionManager.entities[domain.id] = {}\n }\n\n connections[name] = instance\n entities[name] = connection\n\n ConnectionManager.publishState(connection, ConnectionStatus.CONNECTED)\n debug('add-connection', domain.subdomain, name)\n }\n\n static removeConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n var connections = ConnectionManager.connections[domain.id]\n var entities = ConnectionManager.entities[domain.id]\n\n var instance = connections?.[name]\n\n if (!connections || !instance) {\n debug('remove-connection', `'${name}' connection not found in domain '${domain.subdomain}'`)\n return\n }\n\n delete connections[name]\n delete entities[name]\n\n ConnectionManager.publishState(connection, ConnectionStatus.DISCONNECTED)\n debug('remove-connection', `'${name}' connection is removed from domain '${domain.subdomain}'`)\n\n return instance\n }\n\n private static async publishState(connection: Connection, state) {\n const { domain, id, name, description, type, edge } = connection\n\n pubsub.publish('connection-state', {\n connectionState: {\n domain,\n id,\n name,\n description,\n type,\n edge,\n state,\n timestamp: new Date()\n }\n })\n }\n}\n"]}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const tslib_1 = require("tslib");
|
4
|
-
require("./connector");
|
5
|
-
require("./task");
|
4
|
+
require("./connector/index.js");
|
5
|
+
require("./task/index.js");
|
6
6
|
tslib_1.__exportStar(require("./connection-manager"), exports);
|
7
7
|
tslib_1.__exportStar(require("./scenario-engine"), exports);
|
8
8
|
tslib_1.__exportStar(require("./task-registry"), exports);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/engine/index.ts"],"names":[],"mappings":";;;AAAA,
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/engine/index.ts"],"names":[],"mappings":";;;AAAA,gCAA6B;AAC7B,2BAAwB;AAExB,+DAAoC;AACpC,4DAAiC;AACjC,0DAA+B;AAC/B,yEAA8C;AAC9C,wDAA6B;AAC7B,0DAA+B","sourcesContent":["import './connector/index.js'\nimport './task/index.js'\n\nexport * from './connection-manager'\nexport * from './scenario-engine'\nexport * from './task-registry'\nexport * from './analyzer/analyze-integration'\nexport * from './edge-client'\nexport * from './resource-pool'\n\nexport { Connector, Context, TaskHandler } from './types'\n"]}
|
@@ -1,18 +1,24 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const utils_1 = require("@things-factory/utils");
|
4
|
-
const
|
5
|
-
const
|
4
|
+
const task_registry_js_1 = require("../task-registry.js");
|
5
|
+
const connection_manager_js_1 = require("../connection-manager.js");
|
6
6
|
async function MqttPublish(step, { logger, data, domain }) {
|
7
|
-
var { connection: connectionName, params: { topic, accessor } } = step;
|
8
|
-
const { client } =
|
7
|
+
var { connection: connectionName, params: { topic, accessor, dataFormat = 'json' } } = step;
|
8
|
+
const { client } = connection_manager_js_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
|
9
9
|
if (!client) {
|
10
10
|
throw Error(`connection is not found : ${connectionName}`);
|
11
11
|
}
|
12
12
|
if (!topic || !accessor) {
|
13
13
|
throw Error(`topic and accessor should be defined: : topic - '${topic}', accessor - '${accessor}'`);
|
14
14
|
}
|
15
|
-
var message =
|
15
|
+
var message = (0, utils_1.access)(accessor, data);
|
16
|
+
if (dataFormat === 'text') {
|
17
|
+
message = String(message);
|
18
|
+
}
|
19
|
+
else {
|
20
|
+
message = JSON.stringify(message);
|
21
|
+
}
|
16
22
|
await client.publish(topic, message);
|
17
23
|
return {
|
18
24
|
data: message
|
@@ -28,8 +34,25 @@ MqttPublish.parameterSpec = [
|
|
28
34
|
type: 'scenario-step-input',
|
29
35
|
name: 'accessor',
|
30
36
|
label: 'accessor'
|
37
|
+
},
|
38
|
+
{
|
39
|
+
type: 'select',
|
40
|
+
label: 'data-format',
|
41
|
+
name: 'dataFormat',
|
42
|
+
property: {
|
43
|
+
options: [
|
44
|
+
{
|
45
|
+
display: 'Plain Text',
|
46
|
+
value: 'text'
|
47
|
+
},
|
48
|
+
{
|
49
|
+
display: 'JSON',
|
50
|
+
value: 'json'
|
51
|
+
}
|
52
|
+
]
|
53
|
+
}
|
31
54
|
}
|
32
55
|
];
|
33
56
|
MqttPublish.help = 'integration/task/mqtt-publish';
|
34
|
-
|
57
|
+
task_registry_js_1.TaskRegistry.registerTaskHandler('mqtt-publish', MqttPublish);
|
35
58
|
//# sourceMappingURL=mqtt-publish.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"mqtt-publish.js","sourceRoot":"","sources":["../../../server/engine/task/mqtt-publish.ts"],"names":[],"mappings":";;AAAA,iDAA8C;AAC9C,
|
1
|
+
{"version":3,"file":"mqtt-publish.js","sourceRoot":"","sources":["../../../server/engine/task/mqtt-publish.ts"],"names":[],"mappings":";;AAAA,iDAA8C;AAC9C,0DAAkD;AAClD,oEAA4D;AAI5D,KAAK,UAAU,WAAW,CAAC,IAAe,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW;IAC3E,IAAI,EACF,UAAU,EAAE,cAAc,EAC1B,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,EAAE,EACjD,GAAG,IAAI,CAAA;IAER,MAAM,EAAE,MAAM,EAAE,GAAG,yCAAiB,CAAC,2BAA2B,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACxF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,CAAC,6BAA6B,cAAc,EAAE,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,oDAAoD,KAAK,kBAAkB,QAAQ,GAAG,CAAC,CAAA;IACrG,CAAC;IAED,IAAI,OAAO,GAAG,IAAA,cAAM,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAEpC,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;IAC3B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC;IAED,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAEpC,OAAO;QACL,IAAI,EAAE,OAAO;KACd,CAAA;AACH,CAAC;AAED,WAAW,CAAC,aAAa,GAAG;IAC1B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;KACf;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KAClB;IACD;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP;oBACE,OAAO,EAAE,YAAY;oBACrB,KAAK,EAAE,MAAM;iBACd;gBACD;oBACE,OAAO,EAAE,MAAM;oBACf,KAAK,EAAE,MAAM;iBACd;aACF;SACF;KACF;CACF,CAAA;AAED,WAAW,CAAC,IAAI,GAAG,+BAA+B,CAAA;AAElD,+BAAY,CAAC,mBAAmB,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA","sourcesContent":["import { access } from '@things-factory/utils'\nimport { TaskRegistry } from '../task-registry.js'\nimport { ConnectionManager } from '../connection-manager.js'\nimport { InputStep } from '../../service/step/step-type.js'\nimport { Context } from '../types.js'\n\nasync function MqttPublish(step: InputStep, { logger, data, domain }: Context) {\n var {\n connection: connectionName,\n params: { topic, accessor, dataFormat = 'json' }\n } = step\n\n const { client } = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n if (!client) {\n throw Error(`connection is not found : ${connectionName}`)\n }\n\n if (!topic || !accessor) {\n throw Error(`topic and accessor should be defined: : topic - '${topic}', accessor - '${accessor}'`)\n }\n\n var message = access(accessor, data)\n\n if (dataFormat === 'text') {\n message = String(message)\n } else {\n message = JSON.stringify(message)\n }\n\n await client.publish(topic, message)\n\n return {\n data: message\n }\n}\n\nMqttPublish.parameterSpec = [\n {\n type: 'string',\n name: 'topic',\n label: 'topic'\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n },\n {\n type: 'select',\n label: 'data-format',\n name: 'dataFormat',\n property: {\n options: [\n {\n display: 'Plain Text',\n value: 'text'\n },\n {\n display: 'JSON',\n value: 'json'\n }\n ]\n }\n }\n]\n\nMqttPublish.help = 'integration/task/mqtt-publish'\n\nTaskRegistry.registerTaskHandler('mqtt-publish', MqttPublish)\n"]}
|
@@ -1 +1,85 @@
|
|
1
|
+
/**
|
2
|
+
* MQTT Subscribe Task
|
3
|
+
* ====================
|
4
|
+
*
|
5
|
+
* Pull-Based Message Consumption on MQTT:
|
6
|
+
* ---------------------------------------
|
7
|
+
* While MQTT is inherently a push-based protocol, this task implements a controlled,
|
8
|
+
* pull-style message consumption model. A message is only processed when the task is
|
9
|
+
* explicitly invoked (i.e., the consumer actively pulls one message at a time).
|
10
|
+
* This enables fine-grained control over message flow and avoids unintended buffering.
|
11
|
+
*
|
12
|
+
* Overview:
|
13
|
+
* ---------
|
14
|
+
* This task connects to a specified MQTT broker and subscribes to a given topic.
|
15
|
+
* It waits for a single message to arrive, resolves the result, and then removes
|
16
|
+
* its internal message handler. It is designed to be reentrant — each execution
|
17
|
+
* of this task handles exactly one message.
|
18
|
+
*
|
19
|
+
* This model is useful for applications where message processing must happen
|
20
|
+
* sequentially or be synchronized with external state (e.g., workflows or state machines).
|
21
|
+
*
|
22
|
+
* Key Features:
|
23
|
+
* -------------
|
24
|
+
* - One-message-per-invocation: each task call resolves with a single message.
|
25
|
+
* - Stateless message flow: the system does not queue or buffer messages locally.
|
26
|
+
* - Supports automatic re-subscription on reconnect, improving robustness in unstable networks.
|
27
|
+
* - Uses broker-level guarantees (QoS, retain) for durability and delivery control.
|
28
|
+
* - Supports multiple data formats (JSON, plain text) and adjustable QoS levels.
|
29
|
+
*
|
30
|
+
* MQTT Reconnection Handling:
|
31
|
+
* ---------------------------
|
32
|
+
* The task listens for 'connect' events on the MQTT client. When the client reconnects
|
33
|
+
* (e.g., after a dropped network), it automatically re-subscribes to all previously
|
34
|
+
* tracked topics. This ensures consistent behavior even in long-running systems or
|
35
|
+
* unstable network environments.
|
36
|
+
*
|
37
|
+
* If a disconnect occurs while a task is waiting for a message, the Promise remains
|
38
|
+
* pending until a message is received after reconnection, or until manually cleaned up
|
39
|
+
* via the task closure mechanism.
|
40
|
+
*
|
41
|
+
* How It Works:
|
42
|
+
* -------------
|
43
|
+
* 1. Retrieve an MQTT client using a named connection.
|
44
|
+
* 2. Subscribe to the specified topic (only once per topic per workflow).
|
45
|
+
* 3. Register a one-time message handler for the topic.
|
46
|
+
* 4. When a message is received:
|
47
|
+
* - It is parsed into the requested data format.
|
48
|
+
* - The task resolves with the parsed message.
|
49
|
+
* - The handler is immediately removed.
|
50
|
+
* 5. Re-subscribe to all topics upon reconnect.
|
51
|
+
* 6. Clean up all resources (subscription, handler, resolver) on task termination.
|
52
|
+
*
|
53
|
+
* Assumptions:
|
54
|
+
* ------------
|
55
|
+
* - Broker reliability is enforced via QoS ≥ 1 and/or retained messages.
|
56
|
+
* - Message loss may occur if a message arrives before re-invocation, unless the broker retains it.
|
57
|
+
* - The task caller is responsible for repeated invocations to consume additional messages.
|
58
|
+
* - MQTT clients are externally managed and assumed to reconnect automatically.
|
59
|
+
*
|
60
|
+
* Parameters:
|
61
|
+
* -----------
|
62
|
+
* - topic (string): MQTT topic to subscribe to.
|
63
|
+
* - dataFormat ('json' | 'text'): Describes how to parse the incoming message payload.
|
64
|
+
* - qos (0 | 1 | 2): Quality of Service level for the subscription (default: 1).
|
65
|
+
*
|
66
|
+
* Returns:
|
67
|
+
* --------
|
68
|
+
* - A Promise that resolves with the first received message:
|
69
|
+
* { data: any }
|
70
|
+
* - If the task is terminated before receiving a message:
|
71
|
+
* { data: null, terminated: true }
|
72
|
+
*
|
73
|
+
* Example:
|
74
|
+
* --------
|
75
|
+
* await MqttSubscribe({
|
76
|
+
* connection: 'my-mqtt',
|
77
|
+
* params: {
|
78
|
+
* topic: 'sensor/temperature',
|
79
|
+
* dataFormat: 'json',
|
80
|
+
* qos: 1
|
81
|
+
* },
|
82
|
+
* name: 'readTemperature'
|
83
|
+
* }, context)
|
84
|
+
*/
|
1
85
|
export {};
|
@@ -1,89 +1,200 @@
|
|
1
1
|
"use strict";
|
2
|
+
/**
|
3
|
+
* MQTT Subscribe Task
|
4
|
+
* ====================
|
5
|
+
*
|
6
|
+
* Pull-Based Message Consumption on MQTT:
|
7
|
+
* ---------------------------------------
|
8
|
+
* While MQTT is inherently a push-based protocol, this task implements a controlled,
|
9
|
+
* pull-style message consumption model. A message is only processed when the task is
|
10
|
+
* explicitly invoked (i.e., the consumer actively pulls one message at a time).
|
11
|
+
* This enables fine-grained control over message flow and avoids unintended buffering.
|
12
|
+
*
|
13
|
+
* Overview:
|
14
|
+
* ---------
|
15
|
+
* This task connects to a specified MQTT broker and subscribes to a given topic.
|
16
|
+
* It waits for a single message to arrive, resolves the result, and then removes
|
17
|
+
* its internal message handler. It is designed to be reentrant — each execution
|
18
|
+
* of this task handles exactly one message.
|
19
|
+
*
|
20
|
+
* This model is useful for applications where message processing must happen
|
21
|
+
* sequentially or be synchronized with external state (e.g., workflows or state machines).
|
22
|
+
*
|
23
|
+
* Key Features:
|
24
|
+
* -------------
|
25
|
+
* - One-message-per-invocation: each task call resolves with a single message.
|
26
|
+
* - Stateless message flow: the system does not queue or buffer messages locally.
|
27
|
+
* - Supports automatic re-subscription on reconnect, improving robustness in unstable networks.
|
28
|
+
* - Uses broker-level guarantees (QoS, retain) for durability and delivery control.
|
29
|
+
* - Supports multiple data formats (JSON, plain text) and adjustable QoS levels.
|
30
|
+
*
|
31
|
+
* MQTT Reconnection Handling:
|
32
|
+
* ---------------------------
|
33
|
+
* The task listens for 'connect' events on the MQTT client. When the client reconnects
|
34
|
+
* (e.g., after a dropped network), it automatically re-subscribes to all previously
|
35
|
+
* tracked topics. This ensures consistent behavior even in long-running systems or
|
36
|
+
* unstable network environments.
|
37
|
+
*
|
38
|
+
* If a disconnect occurs while a task is waiting for a message, the Promise remains
|
39
|
+
* pending until a message is received after reconnection, or until manually cleaned up
|
40
|
+
* via the task closure mechanism.
|
41
|
+
*
|
42
|
+
* How It Works:
|
43
|
+
* -------------
|
44
|
+
* 1. Retrieve an MQTT client using a named connection.
|
45
|
+
* 2. Subscribe to the specified topic (only once per topic per workflow).
|
46
|
+
* 3. Register a one-time message handler for the topic.
|
47
|
+
* 4. When a message is received:
|
48
|
+
* - It is parsed into the requested data format.
|
49
|
+
* - The task resolves with the parsed message.
|
50
|
+
* - The handler is immediately removed.
|
51
|
+
* 5. Re-subscribe to all topics upon reconnect.
|
52
|
+
* 6. Clean up all resources (subscription, handler, resolver) on task termination.
|
53
|
+
*
|
54
|
+
* Assumptions:
|
55
|
+
* ------------
|
56
|
+
* - Broker reliability is enforced via QoS ≥ 1 and/or retained messages.
|
57
|
+
* - Message loss may occur if a message arrives before re-invocation, unless the broker retains it.
|
58
|
+
* - The task caller is responsible for repeated invocations to consume additional messages.
|
59
|
+
* - MQTT clients are externally managed and assumed to reconnect automatically.
|
60
|
+
*
|
61
|
+
* Parameters:
|
62
|
+
* -----------
|
63
|
+
* - topic (string): MQTT topic to subscribe to.
|
64
|
+
* - dataFormat ('json' | 'text'): Describes how to parse the incoming message payload.
|
65
|
+
* - qos (0 | 1 | 2): Quality of Service level for the subscription (default: 1).
|
66
|
+
*
|
67
|
+
* Returns:
|
68
|
+
* --------
|
69
|
+
* - A Promise that resolves with the first received message:
|
70
|
+
* { data: any }
|
71
|
+
* - If the task is terminated before receiving a message:
|
72
|
+
* { data: null, terminated: true }
|
73
|
+
*
|
74
|
+
* Example:
|
75
|
+
* --------
|
76
|
+
* await MqttSubscribe({
|
77
|
+
* connection: 'my-mqtt',
|
78
|
+
* params: {
|
79
|
+
* topic: 'sensor/temperature',
|
80
|
+
* dataFormat: 'json',
|
81
|
+
* qos: 1
|
82
|
+
* },
|
83
|
+
* name: 'readTemperature'
|
84
|
+
* }, context)
|
85
|
+
*/
|
2
86
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const
|
4
|
-
const
|
5
|
-
const task_registry_1 = require("../task-registry");
|
6
|
-
const connection_manager_1 = require("../connection-manager");
|
7
|
-
const utils_1 = require("@things-factory/utils");
|
87
|
+
const task_registry_js_1 = require("../task-registry.js");
|
88
|
+
const connection_manager_js_1 = require("../connection-manager.js");
|
8
89
|
function convertDataFormat(data, format) {
|
9
|
-
if (format
|
10
|
-
|
90
|
+
if (format === 'json') {
|
91
|
+
try {
|
92
|
+
return JSON.parse(data);
|
93
|
+
}
|
94
|
+
catch (e) {
|
95
|
+
console.error('JSON parse error:', e.message);
|
96
|
+
return data.toString();
|
97
|
+
}
|
11
98
|
}
|
12
99
|
else {
|
13
100
|
return data.toString();
|
14
101
|
}
|
15
102
|
}
|
16
103
|
async function MqttSubscribe(step, context) {
|
17
|
-
|
18
|
-
const {
|
19
|
-
|
20
|
-
|
104
|
+
var _a, _b, _c;
|
105
|
+
const { connection: connectionName, params: { topic, dataFormat, qos = 1 }, name: stepName } = step;
|
106
|
+
const { domain, logger, closures } = context;
|
107
|
+
const { client } = connection_manager_js_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
|
108
|
+
if (!client)
|
109
|
+
throw new Error(`connection not found: ${connectionName}`);
|
110
|
+
if (!topic)
|
111
|
+
throw new Error(`Missing topic for connection: ${connectionName}`);
|
112
|
+
const subscriberId = `${domain}_${connectionName}_${topic}_${stepName}`;
|
113
|
+
(_a = context.__mqtt_subscriptions) !== null && _a !== void 0 ? _a : (context.__mqtt_subscriptions = new Set());
|
114
|
+
(_b = context.__mqtt_resolvers) !== null && _b !== void 0 ? _b : (context.__mqtt_resolvers = new Map());
|
115
|
+
(_c = context.__mqtt_handlers) !== null && _c !== void 0 ? _c : (context.__mqtt_handlers = new Map());
|
116
|
+
// Setup MQTT client reconnect/resubscribe handlers only once
|
117
|
+
if (!context.__mqtt_event_hooked) {
|
118
|
+
client.on('connect', async () => {
|
119
|
+
logger.info('[MQTT] Reconnected. Resubscribing to topics...');
|
120
|
+
for (const t of context.__mqtt_subscriptions) {
|
121
|
+
try {
|
122
|
+
await client.subscribe(t, { qos });
|
123
|
+
logger.info(`[MQTT] Resubscribed to topic: ${t}`);
|
124
|
+
}
|
125
|
+
catch (e) {
|
126
|
+
logger.error(`[MQTT] Failed to resubscribe to topic ${t}: ${e.message}`);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
});
|
130
|
+
client.on('offline', () => {
|
131
|
+
logger.warn('[MQTT] Client offline');
|
132
|
+
});
|
133
|
+
client.on('close', () => {
|
134
|
+
logger.warn('[MQTT] Connection closed');
|
135
|
+
});
|
136
|
+
client.on('error', err => {
|
137
|
+
logger.error(`[MQTT] Error: ${err.message}`);
|
138
|
+
});
|
139
|
+
context.__mqtt_event_hooked = true;
|
21
140
|
}
|
22
|
-
|
23
|
-
if (!topic) {
|
24
|
-
|
141
|
+
// Subscribe if not already done
|
142
|
+
if (!context.__mqtt_subscriptions.has(topic)) {
|
143
|
+
await client.subscribe(topic, { qos });
|
144
|
+
context.__mqtt_subscriptions.add(topic);
|
145
|
+
logger.info(`Subscribed to topic: ${topic} (QoS: ${qos})`);
|
25
146
|
}
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
147
|
+
// Remove previous handler for this step
|
148
|
+
if (context.__mqtt_handlers.has(subscriberId)) {
|
149
|
+
const removeHandler = context.__mqtt_handlers.get(subscriberId);
|
150
|
+
removeHandler === null || removeHandler === void 0 ? void 0 : removeHandler();
|
151
|
+
context.__mqtt_handlers.delete(subscriberId);
|
152
|
+
}
|
153
|
+
return new Promise(resolve => {
|
154
|
+
context.__mqtt_resolvers.set(subscriberId, resolve);
|
155
|
+
const messageHandler = (messageTopic, message) => {
|
156
|
+
if (messageTopic !== topic)
|
157
|
+
return;
|
158
|
+
const converted = convertDataFormat(message, dataFormat);
|
159
|
+
const resolver = context.__mqtt_resolvers.get(subscriberId);
|
160
|
+
if (resolver) {
|
161
|
+
context.__mqtt_resolvers.delete(subscriberId);
|
162
|
+
resolver({ data: converted });
|
163
|
+
client.removeListener('message', messageHandler);
|
164
|
+
context.__mqtt_handlers.delete(subscriberId);
|
41
165
|
}
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
166
|
+
};
|
167
|
+
client.on('message', messageHandler);
|
168
|
+
context.__mqtt_handlers.set(subscriberId, () => {
|
169
|
+
client.removeListener('message', messageHandler);
|
170
|
+
});
|
171
|
+
closures.push(async () => {
|
172
|
+
var _a, _b, _c;
|
173
|
+
try {
|
174
|
+
if ((_a = context.__mqtt_subscriptions) === null || _a === void 0 ? void 0 : _a.has(topic)) {
|
175
|
+
await client.unsubscribe(topic);
|
176
|
+
context.__mqtt_subscriptions.delete(topic);
|
177
|
+
logger.info(`Unsubscribed from topic: ${topic}`);
|
50
178
|
}
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
return {
|
56
|
-
topic,
|
57
|
-
message
|
58
|
-
};
|
59
|
-
};
|
60
|
-
broker.on('message', async (messageTopic, message) => {
|
61
|
-
if (topic !== messageTopic) {
|
62
|
-
return;
|
179
|
+
if ((_b = context.__mqtt_handlers) === null || _b === void 0 ? void 0 : _b.has(subscriberId)) {
|
180
|
+
const remove = context.__mqtt_handlers.get(subscriberId);
|
181
|
+
remove === null || remove === void 0 ? void 0 : remove();
|
182
|
+
context.__mqtt_handlers.delete(subscriberId);
|
63
183
|
}
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
closures.push(async () => {
|
69
|
-
try {
|
70
|
-
broker && (await broker.end());
|
71
|
-
logger.info(`mqtt-connector connection(${connectionName}:${uri}) is disconnected`);
|
72
|
-
}
|
73
|
-
catch (e) {
|
74
|
-
logger.error(e);
|
184
|
+
if ((_c = context.__mqtt_resolvers) === null || _c === void 0 ? void 0 : _c.has(subscriberId)) {
|
185
|
+
const resolver = context.__mqtt_resolvers.get(subscriberId);
|
186
|
+
resolver === null || resolver === void 0 ? void 0 : resolver({ data: null, terminated: true });
|
187
|
+
context.__mqtt_resolvers.delete(subscriberId);
|
75
188
|
}
|
76
|
-
}
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
}
|
81
|
-
|
82
|
-
|
83
|
-
return {
|
84
|
-
data: message
|
85
|
-
};
|
189
|
+
}
|
190
|
+
catch (e) {
|
191
|
+
logger.error(`MQTT cleanup error: ${e.message}`);
|
192
|
+
}
|
193
|
+
});
|
194
|
+
logger.info(`Waiting for MQTT message on topic: ${topic}`);
|
195
|
+
});
|
86
196
|
}
|
197
|
+
// Task parameter definitions for UI or DSL support
|
87
198
|
MqttSubscribe.parameterSpec = [
|
88
199
|
{
|
89
200
|
type: 'string',
|
@@ -96,18 +207,27 @@ MqttSubscribe.parameterSpec = [
|
|
96
207
|
name: 'dataFormat',
|
97
208
|
property: {
|
98
209
|
options: [
|
99
|
-
{
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
210
|
+
{ display: '', value: undefined },
|
211
|
+
{ display: 'Plain Text', value: 'text' },
|
212
|
+
{ display: 'JSON', value: 'json' }
|
213
|
+
]
|
214
|
+
}
|
215
|
+
},
|
216
|
+
{
|
217
|
+
type: 'select',
|
218
|
+
label: 'QoS',
|
219
|
+
name: 'qos',
|
220
|
+
property: {
|
221
|
+
options: [
|
222
|
+
{ display: '', value: undefined },
|
223
|
+
{ display: '0 (at most once)', value: 0 },
|
224
|
+
{ display: '1 (at least once)', value: 1 },
|
225
|
+
{ display: '2 (exactly once)', value: 2 }
|
107
226
|
]
|
108
227
|
}
|
109
228
|
}
|
110
229
|
];
|
111
230
|
MqttSubscribe.help = 'integration/task/mqtt-subscribe';
|
112
|
-
|
231
|
+
// Register task with runtime registry
|
232
|
+
task_registry_js_1.TaskRegistry.registerTaskHandler('mqtt-subscribe', MqttSubscribe);
|
113
233
|
//# sourceMappingURL=mqtt-subscribe.js.map
|