initial
This commit is contained in:
commit
dad740e620
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
*.map
|
57
dist/log.js
vendored
Normal file
57
dist/log.js
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const chalk = require("chalk");
|
||||||
|
const moment = require("moment");
|
||||||
|
var Level;
|
||||||
|
(function (Level) {
|
||||||
|
Level[Level["All"] = 0] = "All";
|
||||||
|
Level[Level["NoDebug"] = 1] = "NoDebug";
|
||||||
|
Level[Level["NoDebugNoInfo"] = 2] = "NoDebugNoInfo";
|
||||||
|
Level[Level["NoDebugNoInfoNoWarning"] = 3] = "NoDebugNoInfoNoWarning";
|
||||||
|
})(Level || (Level = {}));
|
||||||
|
var level = Level.NoDebug;
|
||||||
|
function timestamp() {
|
||||||
|
return moment().format('HH:mm:ss.SSS');
|
||||||
|
}
|
||||||
|
function setLevel(value) {
|
||||||
|
switch (value) {
|
||||||
|
case 'info':
|
||||||
|
level = Level.NoDebug;
|
||||||
|
break;
|
||||||
|
case 'warn':
|
||||||
|
level = Level.NoDebugNoInfo;
|
||||||
|
break;
|
||||||
|
case 'error':
|
||||||
|
level = Level.NoDebugNoInfoNoWarning;
|
||||||
|
break;
|
||||||
|
default: level = Level.All;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.setLevel = setLevel;
|
||||||
|
function info(message) {
|
||||||
|
if (level < Level.NoDebugNoInfo) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.cyan('[ II ]')} ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.info = info;
|
||||||
|
function warn(message) {
|
||||||
|
if (level < Level.NoDebugNoInfoNoWarning) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.yellow('[ WW ]')} ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.warn = warn;
|
||||||
|
function error(message) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.red('[ EE ]')} ${message}`);
|
||||||
|
}
|
||||||
|
exports.error = error;
|
||||||
|
function success(message) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.green('[ OK ]')} ${message}`);
|
||||||
|
}
|
||||||
|
exports.success = success;
|
||||||
|
function debug(message) {
|
||||||
|
if (level < Level.NoDebug) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.magenta('[ DB ]')} ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.debug = debug;
|
||||||
|
//# sourceMappingURL=log.js.map
|
18
dist/main.js
vendored
Normal file
18
dist/main.js
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const log = require("./log");
|
||||||
|
const MqttClient = require("./mqttclient");
|
||||||
|
class Dispatcher {
|
||||||
|
constructor() {
|
||||||
|
this._mqttClient = new MqttClient.MqttClient();
|
||||||
|
this._mqttClient.register('IoT/test', null);
|
||||||
|
this._mqttClient.register('IoT/Device/#', null);
|
||||||
|
}
|
||||||
|
exec() {
|
||||||
|
log.info("Dispatcher starting");
|
||||||
|
this._mqttClient.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const dispatcher = new Dispatcher();
|
||||||
|
dispatcher.exec();
|
||||||
|
//# sourceMappingURL=main.js.map
|
60
dist/mqttclient.js
vendored
Normal file
60
dist/mqttclient.js
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const Mqtt = require("mqtt");
|
||||||
|
const log = require("./log");
|
||||||
|
const MQTT_BROKER_DEFAULT_URL = "mqtt://localhost";
|
||||||
|
class MqttClient {
|
||||||
|
constructor(mqttBrokerUrl) {
|
||||||
|
this._mqttBrokerUrl = (mqttBrokerUrl) ? mqttBrokerUrl : MQTT_BROKER_DEFAULT_URL;
|
||||||
|
this._topicHandlers = [];
|
||||||
|
}
|
||||||
|
register(topic, callback) {
|
||||||
|
this._topicHandlers.push({ topic, callback });
|
||||||
|
log.info(`handler registered for topic ${topic}`);
|
||||||
|
}
|
||||||
|
exec() {
|
||||||
|
this._mqttClient = Mqtt.connect(this._mqttBrokerUrl);
|
||||||
|
this._mqttClient.on('error', log.error);
|
||||||
|
this._mqttClient.on('connect', () => {
|
||||||
|
log.info("connected to mqtt broker");
|
||||||
|
for (let topicHandler of this._topicHandlers) {
|
||||||
|
this._mqttClient.subscribe(topicHandler.topic);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._mqttClient.on('message', (topic, payload) => {
|
||||||
|
log.info(`message received, topic ${topic}, payload ${payload}`);
|
||||||
|
for (let topicHandler of this._topicHandlers) {
|
||||||
|
if (this.topicMatch(topicHandler.topic, topic)) {
|
||||||
|
log.info(`received topic ${topic} matches registered topic ${topicHandler.topic}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
topicMatch(registeredTopic, receivedTopic) {
|
||||||
|
let registeredTopicFields = registeredTopic.split('/');
|
||||||
|
let receivedTopicFields = receivedTopic.split('/');
|
||||||
|
for (let field in registeredTopicFields) {
|
||||||
|
let regField = registeredTopicFields[field];
|
||||||
|
let recvField = receivedTopicFields[field];
|
||||||
|
log.info(`recv: ${recvField}, reg: ${regField}`);
|
||||||
|
if (regField === "#") {
|
||||||
|
log.info('true');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (regField != recvField && regField != "+") {
|
||||||
|
log.info('false');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (registeredTopicFields.length == receivedTopicFields.length) {
|
||||||
|
log.info('true');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.info('false');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.MqttClient = MqttClient;
|
||||||
|
//# sourceMappingURL=mqttclient.js.map
|
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "dispatcher",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "dist/main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "tsc -p ./",
|
||||||
|
"debug": "npm run build && node dist/main.js --loglevel debug",
|
||||||
|
"start": "node dist/main.js"
|
||||||
|
},
|
||||||
|
"author": "Wolfgang Hottgenroth <woho@hottis.de>",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/chalk": "^0.4.31",
|
||||||
|
"@types/mqtt": "0.0.34",
|
||||||
|
"@types/node": "^8.0.14",
|
||||||
|
"typescript": "^2.4.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^2.0.1",
|
||||||
|
"moment": "^2.18.1",
|
||||||
|
"mqtt": "^2.9.2"
|
||||||
|
}
|
||||||
|
}
|
50
src/log.ts
Normal file
50
src/log.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import * as chalk from 'chalk'
|
||||||
|
import * as moment from 'moment'
|
||||||
|
|
||||||
|
enum Level {
|
||||||
|
All,
|
||||||
|
NoDebug,
|
||||||
|
NoDebugNoInfo,
|
||||||
|
NoDebugNoInfoNoWarning
|
||||||
|
}
|
||||||
|
|
||||||
|
var level = Level.NoDebug
|
||||||
|
|
||||||
|
function timestamp(): string {
|
||||||
|
return moment().format('HH:mm:ss.SSS')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setLevel(value: string): void {
|
||||||
|
switch (value) {
|
||||||
|
case 'info': level = Level.NoDebug; break
|
||||||
|
case 'warn': level = Level.NoDebugNoInfo; break
|
||||||
|
case 'error': level = Level.NoDebugNoInfoNoWarning; break
|
||||||
|
default: level = Level.All
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function info(message: string): void {
|
||||||
|
if (level < Level.NoDebugNoInfo) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.cyan('[ II ]')} ${message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function warn(message: string): void {
|
||||||
|
if (level < Level.NoDebugNoInfoNoWarning) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.yellow('[ WW ]')} ${message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function error(message: string): void {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.red('[ EE ]')} ${message}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function success(message: string): void {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.green('[ OK ]')} ${message}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debug(message: string): void {
|
||||||
|
if (level < Level.NoDebug) {
|
||||||
|
console.log(`${timestamp()} ${chalk.bold.magenta('[ DB ]')} ${message}`)
|
||||||
|
}
|
||||||
|
}
|
27
src/main.ts
Normal file
27
src/main.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import * as log from './log'
|
||||||
|
import * as MqttClient from './mqttclient'
|
||||||
|
|
||||||
|
class Dispatcher {
|
||||||
|
private _mqttClient: MqttClient.MqttClient
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._mqttClient = new MqttClient.MqttClient()
|
||||||
|
|
||||||
|
this._mqttClient.register('IoT/test', null)
|
||||||
|
this._mqttClient.register('IoT/Device/#', null)
|
||||||
|
}
|
||||||
|
|
||||||
|
exec() : void {
|
||||||
|
log.info("Dispatcher starting")
|
||||||
|
|
||||||
|
this._mqttClient.exec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const dispatcher = new Dispatcher()
|
||||||
|
dispatcher.exec()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
71
src/mqttclient.ts
Normal file
71
src/mqttclient.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import * as Mqtt from 'mqtt'
|
||||||
|
import * as log from './log'
|
||||||
|
|
||||||
|
const MQTT_BROKER_DEFAULT_URL : string = "mqtt://localhost"
|
||||||
|
|
||||||
|
type TopicHandlerCallback = (message: Buffer) => void
|
||||||
|
|
||||||
|
type TopicHandler = {
|
||||||
|
topic: string,
|
||||||
|
callback: TopicHandlerCallback|null
|
||||||
|
}
|
||||||
|
export class MqttClient {
|
||||||
|
private _mqttClient: Mqtt.Client
|
||||||
|
private _mqttBrokerUrl: string
|
||||||
|
private _topicHandlers: TopicHandler[]
|
||||||
|
|
||||||
|
constructor(mqttBrokerUrl? : string) {
|
||||||
|
this._mqttBrokerUrl = (mqttBrokerUrl) ? mqttBrokerUrl : MQTT_BROKER_DEFAULT_URL
|
||||||
|
this._topicHandlers = []
|
||||||
|
}
|
||||||
|
|
||||||
|
register(topic: string, callback: TopicHandlerCallback|null) : void {
|
||||||
|
this._topicHandlers.push({topic, callback})
|
||||||
|
log.info(`handler registered for topic ${topic}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
exec() : void {
|
||||||
|
this._mqttClient = Mqtt.connect(this._mqttBrokerUrl)
|
||||||
|
this._mqttClient.on('error', log.error)
|
||||||
|
this._mqttClient.on('connect', (): void => {
|
||||||
|
log.info("connected to mqtt broker")
|
||||||
|
for (let topicHandler of this._topicHandlers) {
|
||||||
|
this._mqttClient.subscribe(topicHandler.topic)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this._mqttClient.on('message', (topic: string, payload: Buffer): void => {
|
||||||
|
log.info(`message received, topic ${topic}, payload ${payload}`)
|
||||||
|
for (let topicHandler of this._topicHandlers) {
|
||||||
|
if (this.topicMatch(topicHandler.topic, topic)) {
|
||||||
|
log.info(`received topic ${topic} matches registered topic ${topicHandler.topic}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private topicMatch(registeredTopic: string, receivedTopic: string) : boolean {
|
||||||
|
let registeredTopicFields = registeredTopic.split('/')
|
||||||
|
let receivedTopicFields = receivedTopic.split('/')
|
||||||
|
for (let field in registeredTopicFields) {
|
||||||
|
let regField = registeredTopicFields[field]
|
||||||
|
let recvField = receivedTopicFields[field]
|
||||||
|
log.info(`recv: ${recvField}, reg: ${regField}`)
|
||||||
|
if (regField === "#") {
|
||||||
|
log.info('true')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (regField != recvField && regField != "+") {
|
||||||
|
log.info('false')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (registeredTopicFields.length == receivedTopicFields.length) {
|
||||||
|
log.info('true')
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
log.info('false')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"lib": ["es2015"],
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noEmitOnError": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"typeRoots": [
|
||||||
|
"node_modules/@types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.*"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"dist",
|
||||||
|
"proto",
|
||||||
|
"kernel"
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user