typescriptifying

This commit is contained in:
Wolfgang Hottgenroth
2018-01-09 16:36:14 +01:00
parent 9e39d74084
commit 8d85314fc9
21 changed files with 372 additions and 182 deletions

View File

@ -1,5 +1,5 @@
{
"brokerUrl": "mqtt://172.16.2.15:1883",
"brokerUrl": "mqtt://127.0.0.1:1883",
"brokerUser": "",
"brokerPass": "",
"brokerCa": "",

View File

@ -1,7 +1,7 @@
let AItem = require('./AItem')
class AHomematicItem extends AItem {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const AItem_1 = require("./AItem");
class AHomematicItem extends AItem_1.AItem {
constructor(floor, room, item, hmId) {
super(floor, room, item);
this.hmId = hmId;
@ -10,6 +10,5 @@ class AHomematicItem extends AItem {
this.deviceTopicPre = `${this.homegearTopicPre}/plain/${this.hmId}`;
}
}
module.exports = AHomematicItem;
exports.AHomematicItem = AHomematicItem;
//# sourceMappingURL=AHomematicItem.js.map

View File

@ -1,7 +1,7 @@
let mqtt = require('./mqttHandler');
let logger = require('./log');
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const logger = require("./log");
const MqttDispatcher_1 = require("./MqttDispatcher");
class AItem {
constructor(floor, room, item) {
this.floor = floor;
@ -10,14 +10,12 @@ class AItem {
this.itemId = `${this.floor}.${this.room}.${this.item}`;
this.topicFirstPart = `dispatcher_ng/items/${this.floor}/${this.room}/${this.item}`;
}
start() {
mqtt.register(this.subscribeTopics, (topic, payload) => {
logger.info(`item ${this.itemId}: ${topic}, ${payload}`)
MqttDispatcher_1.mqttHandler.register(this.subscribeTopics, (topic, payload) => {
logger.info(`item ${this.itemId}: ${topic}, ${payload}`);
this.processMessage(topic, payload);
});
}
}
module.exports = AItem;
exports.AItem = AItem;
//# sourceMappingURL=AItem.js.map

View File

@ -1,20 +1,18 @@
let AItem = require('./AItem')
let logger = require('./log')
let mqtt = require('./mqttHandler');
class DimmerAdaptor extends AItem {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const AItem_1 = require("./AItem");
const MqttDispatcher_1 = require("./MqttDispatcher");
class DimmerAdaptor extends AItem_1.AItem {
constructor(floor, room, item) {
super(floor, room, item);
this.actionStateTopic = `${this.topicFirstPart}/state`;
this.actionBrightTopic = `${this.topicFirstPart}/bright`;
this.inTopic = `${this.topicFirstPart}/dimmerIn`;
this.subscribeTopics = [ this.inTopic ];
this.subscribeTopics = [this.inTopic];
this.state = 'OFF';
this.bright = 100;
this.brightDirection = -1;
}
processMessage(topic, payload) {
switch (topic) {
case this.inTopic:
@ -22,10 +20,11 @@ class DimmerAdaptor extends AItem {
case 'SHORT':
if (this.state == 'OFF') {
this.state = 'ON';
} else {
}
else {
this.state = 'OFF';
}
mqtt.send(this.actionStateTopic, this.state, true);
MqttDispatcher_1.mqttHandler.send(this.actionStateTopic, this.state, true);
break;
case 'LONG_HOLD':
this.bright += (5 * this.brightDirection);
@ -35,17 +34,15 @@ class DimmerAdaptor extends AItem {
if (this.bright < 0) {
this.bright = 0;
}
mqtt.send(this.actionBrightTopic, this.bright, true);
MqttDispatcher_1.mqttHandler.send(this.actionBrightTopic, this.bright.toString(), true);
break;
case 'LONG_END':
this.brightDirection = this.brightDirection * -1;
break;
}
}
break;
}
}
}
module.exports = DimmerAdaptor;
exports.DimmerAdaptor = DimmerAdaptor;
//# sourceMappingURL=DimmerAdaptor.js.map

53
dist/HomematicFourButtonThing.js vendored Normal file
View File

@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const logger = require("./log");
const MqttDispatcher_1 = require("./MqttDispatcher");
const AHomematicItem_1 = require("./AHomematicItem");
class HomematicFourButtonSingleItem {
constructor(actionTopic) {
this.actionTopic = actionTopic;
}
processMessage(topic, payload) {
switch (topic) {
case 'PRESS_SHORT':
MqttDispatcher_1.mqttHandler.send(this.actionTopic, 'SHORT', true);
break;
case 'PRESS_LONG':
case 'PRESS_CONT':
MqttDispatcher_1.mqttHandler.send(this.actionTopic, 'LONG_HOLD', true);
break;
case 'PRESS_LONG_RELEASE':
MqttDispatcher_1.mqttHandler.send(this.actionTopic, 'LONG_END', true);
break;
default:
logger.warn(`HM4BSI: no handling available for ${topic}`);
break;
}
}
}
exports.HomematicFourButtonSingleItem = HomematicFourButtonSingleItem;
class HomematicFourButtonThing extends AHomematicItem_1.AHomematicItem {
constructor(floor, room, item, hmId, itemObjs) {
super(floor, room, item, hmId);
this.itemObjs = itemObjs;
if (this.itemObjs.length != 4) {
throw new Error('itemObjs for HomematicFourButtonThing must have four elements');
}
this.subscribeTopics = [
`${this.deviceTopicPre}/#`
];
}
processMessage(topic, payload) {
logger.info(`HM4B: ${topic}, ${payload}`);
let buttonRelatedPart = topic.substring(this.deviceTopicPre.length + 1);
let buttonIdx = parseInt(buttonRelatedPart.substring(0, buttonRelatedPart.indexOf('/')));
if (buttonIdx >= 1 && buttonIdx <= 4) {
this.itemObjs[buttonIdx - 1].processMessage(buttonRelatedPart.substring(buttonRelatedPart.indexOf('/') + 1), payload);
}
else {
logger.warn(`HM4B: no handling available for ${topic}`);
}
}
}
exports.HomematicFourButtonThing = HomematicFourButtonThing;
//# sourceMappingURL=HomematicFourButtonThing.js.map

View File

@ -1,9 +1,8 @@
let logger = require('./log');
let mqtt = require('./mqttHandler');
let AItem = require('./AItem');
class M433SwitchItem extends AItem {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const MqttDispatcher_1 = require("./MqttDispatcher");
const AItem_1 = require("./AItem");
class M433SwitchItem extends AItem_1.AItem {
constructor(floor, room, item, onCode, offCode) {
super(floor, room, item);
this.stateTopic = `${this.topicFirstPart}/state`;
@ -15,20 +14,19 @@ class M433SwitchItem extends AItem {
this.onCode = onCode;
this.offCode = offCode;
}
processMessage(topic, payload) {
this.state = payload;
mqtt.send(this.stateFeedbackTopic, this.state);
if (this.state != this.oldState) {
MqttDispatcher_1.mqttHandler.send(this.stateFeedbackTopic, this.state);
if (this.state != this.oldState) {
if (this.state == 'ON') {
mqtt.send(this.actionTopic, this.onCode);
} else {
mqtt.send(this.actionTopic, this.offCode);
MqttDispatcher_1.mqttHandler.send(this.actionTopic, this.onCode);
}
else {
MqttDispatcher_1.mqttHandler.send(this.actionTopic, this.offCode);
}
this.oldState = this.state;
}
}
}
module.exports = M433SwitchItem;
exports.M433SwitchItem = M433SwitchItem;
//# sourceMappingURL=M433SwitchItem.js.map

View File

@ -17,15 +17,16 @@ class MqttHandler {
this.mqttOptions.rejectUnauthorized = true;
}
this.topicHandlers = [];
logger.info("MqttHandler constructed");
}
register(topics, cb) {
topics.forEach((topic) => {
this.topicHandlers.push({ topic: topic, callback: cb });
logger.info(`additional callback registered for ${topic}`);
logger.info(`Callback registered for ${topic}`);
});
}
exec() {
logger.info(`connecting to ${this.mqttBrokerUrl}`);
logger.info(`Connecting to ${this.mqttBrokerUrl}`);
this.mqttClient = Mqtt.connect(this.mqttBrokerUrl, this.mqttOptions);
this.mqttClient.on('error', (err) => {
logger.error(`Error in mqttHandler: ${err}`);
@ -37,12 +38,12 @@ class MqttHandler {
this.mqttClient.subscribe(topicHandler.topic);
logger.info(`${topicHandler.topic} subscribed`);
});
logger.info('mqtt connection established');
logger.info('MQTT connection established');
});
this.mqttClient.on('message', (topic, payload, packet) => {
if (!packet.retain) {
let payloadStr = payload.toString('UTF-8');
logger.info(`message received on topic ${topic}: ${payload}`);
logger.info(`Message received on topic ${topic}: ${payload}`);
this.processMessage(topic, payloadStr);
}
});

3
dist/config.js vendored
View File

@ -2,7 +2,6 @@
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const cmdargs = require("command-line-args");
const logger = require("./log");
const OPTION_DEFINITIONS = [
{ name: 'verbose', alias: 'v', type: Boolean },
{ name: 'config', alias: 'c', type: String, defaultValue: '~/dispatcher_ng.conf' }
@ -10,7 +9,7 @@ const OPTION_DEFINITIONS = [
function readConfig() {
let options = cmdargs(OPTION_DEFINITIONS);
exports.dict = JSON.parse(fs.readFileSync(options.config, "utf8"));
logger.info(JSON.stringify(exports.dict));
}
exports.readConfig = readConfig;
readConfig();
//# sourceMappingURL=config.js.map

34
dist/main.js vendored
View File

@ -1,18 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const logger = require("./log");
const config = require("./config");
// import { mqttHandler } from './MqttDispatcher'
config.readConfig();
class Dispatcher {
constructor() {
logger.info("Dispatcher starting");
}
exec() {
logger.info("Hello world");
// mqttHandler.exec()
}
}
const dispatcher = new Dispatcher();
dispatcher.exec();
const MqttDispatcher_1 = require("./MqttDispatcher");
const M433SwitchItem_1 = require("./M433SwitchItem");
const HomematicFourButtonThing_1 = require("./HomematicFourButtonThing");
const DimmerAdaptor_1 = require("./DimmerAdaptor");
logger.info("Dispatcher starting");
let aquariumLight = new M433SwitchItem_1.M433SwitchItem('1st', 'Anna', 'AquariumLight', '14665044 24 1', '14665041 24 1');
aquariumLight.start();
let deskLight = new M433SwitchItem_1.M433SwitchItem('Gnd', 'Hallway', 'DeskLight', '83221 24 1', '83220 24 1');
deskLight.start();
let testFourButton = new HomematicFourButtonThing_1.HomematicFourButtonThing('Gnd', 'Hallway', 'TestButton', 9, [
new HomematicFourButtonThing_1.HomematicFourButtonSingleItem('dispatcher_ng/items/Gnd/Hallway/Testlight/dimmerIn'),
new HomematicFourButtonThing_1.HomematicFourButtonSingleItem('dispatcher_ng/items/Gnd/Hallway/DeskLight/timerIn'),
new HomematicFourButtonThing_1.HomematicFourButtonSingleItem('test/button/3'),
new HomematicFourButtonThing_1.HomematicFourButtonSingleItem('test/button/4')
]);
testFourButton.start();
let testDimmerAdaptor = new DimmerAdaptor_1.DimmerAdaptor('Gnd', 'Hallway', 'Testlight');
testDimmerAdaptor.start();
MqttDispatcher_1.mqttHandler.exec();
logger.info("Dispatcher running");
//# sourceMappingURL=main.js.map

40
package-lock.json generated
View File

@ -71,7 +71,7 @@
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
"integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg="
},
"balanced-match": {
"version": "1.0.0",
@ -169,7 +169,7 @@
"duplexify": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz",
"integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==",
"integrity": "sha1-ThUWvmiDi8kKSZlPCzmm5ZYL780=",
"requires": {
"end-of-stream": "1.4.0",
"inherits": "2.0.3",
@ -222,7 +222,7 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
@ -291,7 +291,7 @@
"is-absolute": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
"integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
"integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=",
"requires": {
"is-relative": "1.0.0",
"is-windows": "1.0.1"
@ -318,7 +318,7 @@
"is-relative": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
"integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
"integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=",
"requires": {
"is-unc-path": "1.0.0"
}
@ -326,7 +326,7 @@
"is-unc-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
"integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
"integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=",
"requires": {
"unc-path-regex": "0.1.2"
}
@ -367,7 +367,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"requires": {
"brace-expansion": "1.1.8"
}
@ -380,12 +380,12 @@
"moment": {
"version": "2.20.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
"integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
"integrity": "sha1-1usaRsvMFKKy+UNBEsH/iQfzE/0="
},
"mqtt": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-2.15.0.tgz",
"integrity": "sha512-Lanijk1/Olf9frbAFJi3L38h7SOw5nUQfdywVSIRqBAYdItsyFdflaz+Kk77ajY/O3yOwTfO/V6qC85i/OhodQ==",
"integrity": "sha1-ZL0nt7dbIvqVlProPHHNraQL1GA=",
"requires": {
"commist": "1.0.0",
"concat-stream": "1.6.0",
@ -405,7 +405,7 @@
"mqtt-packet": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-5.4.0.tgz",
"integrity": "sha512-ziN7uVysLdn7fYbOhEaKOhcZC3yIRTTakY4TFd2w+UvZIx9dPr8NCqbBYoC4WYDlzWHTn5EqR5x20pC+K24Ymg==",
"integrity": "sha1-OHEEwGqmj7ufgVnQxyLdXD5F3yI=",
"requires": {
"bl": "1.2.1",
"inherits": "2.0.3",
@ -452,7 +452,7 @@
"pump": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-2.0.0.tgz",
"integrity": "sha512-6MYypjOvtiXhBSTOD0Zs5eNjCGfnqi5mPsCsW+dgKTxrZzQMZQNpBo3XRkLx7id753f3EeyHLBqzqqUymIolgw==",
"integrity": "sha1-eUbaHI1iKwmOLOstNHZYJHCCnJ0=",
"requires": {
"end-of-stream": "1.4.0",
"once": "1.4.0"
@ -471,7 +471,7 @@
"pump": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
"integrity": "sha1-Xf6DEcM7v2/BgmH580cCxHwIqVQ=",
"requires": {
"end-of-stream": "1.4.0",
"once": "1.4.0"
@ -482,7 +482,7 @@
"readable-stream": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
"integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
@ -506,12 +506,12 @@
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
"integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
},
"simple-node-logger": {
"version": "0.93.33",
"resolved": "https://registry.npmjs.org/simple-node-logger/-/simple-node-logger-0.93.33.tgz",
"integrity": "sha512-ppFuaDeacR1Vu+cP17kwOWQsx5C1vbIRa54qm5WgZBzQ5eBue/GWsDd4sr++ITnWZIoIOvjx5kEm5AhP7IqU+Q==",
"integrity": "sha1-Le2/GMQMwsdB3/3rpwLpeKXG5uc=",
"requires": {
"lodash": "4.17.4",
"moment": "2.20.1"
@ -520,7 +520,7 @@
"split2": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz",
"integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==",
"integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=",
"requires": {
"through2": "2.0.3"
}
@ -533,7 +533,7 @@
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
"requires": {
"safe-buffer": "5.1.1"
}
@ -611,7 +611,7 @@
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
"integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw="
},
"unc-path-regex": {
"version": "0.1.2",
@ -635,7 +635,7 @@
"websocket-stream": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.1.1.tgz",
"integrity": "sha512-ypQ50zVCnikSvJcRFWaZh7xeCufSje5+mbJRq3mdvdNx+06TD98C+bQsSKc7FkI6y1PVuNbzkenGywxlFiQeUQ==",
"integrity": "sha1-aNI5Fs31NonP9z4hP6IXjbzqYWk=",
"requires": {
"duplexify": "3.5.1",
"inherits": "2.0.3",
@ -653,7 +653,7 @@
"ws": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
"integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=",
"requires": {
"async-limiter": "1.0.0",
"safe-buffer": "5.1.1",

17
src/AHomematicItem.ts Normal file
View File

@ -0,0 +1,17 @@
import { AItem } from './AItem'
export abstract class AHomematicItem extends AItem {
protected deviceTopicPre: string;
protected actionTopicPre: string;
protected homegearTopicPre: string;
protected hmId: number;
constructor(floor: string, room: string, item: string, hmId: number) {
super(floor, room, item);
this.hmId = hmId;
this.homegearTopicPre = 'homegear/instance1';
this.actionTopicPre = `${this.homegearTopicPre}/set/${this.hmId}`;
this.deviceTopicPre = `${this.homegearTopicPre}/plain/${this.hmId}`;
}
}

31
src/AItem.ts Normal file
View File

@ -0,0 +1,31 @@
import * as logger from './log'
import { mqttHandler } from './MqttDispatcher'
export abstract class AItem {
protected topicFirstPart: string;
private itemId: string;
private item: string;
private room: string;
private floor: string
protected subscribeTopics: string[]
constructor(floor: string, room: string, item: string) {
this.floor = floor
this.room = room
this.item = item
this.itemId = `${this.floor}.${this.room}.${this.item}`
this.topicFirstPart = `dispatcher_ng/items/${this.floor}/${this.room}/${this.item}`
}
abstract processMessage(topic: string, payload: string) : void
start() : void {
mqttHandler.register(this.subscribeTopics, (topic: string, payload: string) : void => {
logger.info(`item ${this.itemId}: ${topic}, ${payload}`)
this.processMessage(topic, payload)
})
}
}

56
src/DimmerAdaptor.ts Normal file
View File

@ -0,0 +1,56 @@
import { AItem } from './AItem'
import * as logger from './log'
import { mqttHandler } from './MqttDispatcher'
export class DimmerAdaptor extends AItem {
private brightDirection: number
private bright: number
private state: string
private inTopic: string
private actionBrightTopic: string
private actionStateTopic: string
constructor(floor: string, room: string, item: string) {
super(floor, room, item)
this.actionStateTopic = `${this.topicFirstPart}/state`
this.actionBrightTopic = `${this.topicFirstPart}/bright`
this.inTopic = `${this.topicFirstPart}/dimmerIn`
this.subscribeTopics = [ this.inTopic ]
this.state = 'OFF'
this.bright = 100
this.brightDirection = -1
}
processMessage(topic: string, payload: string) {
switch (topic) {
case this.inTopic:
switch (payload) {
case 'SHORT':
if (this.state == 'OFF') {
this.state = 'ON'
} else {
this.state = 'OFF'
}
mqttHandler.send(this.actionStateTopic, this.state, true)
break
case 'LONG_HOLD':
this.bright += (5 * this.brightDirection)
if (this.bright > 100) {
this.bright = 100
}
if (this.bright < 0) {
this.bright = 0
}
mqttHandler.send(this.actionBrightTopic, this.bright.toString(), true)
break
case 'LONG_END':
this.brightDirection = this.brightDirection * -1
break
}
break
}
}
}

View File

@ -1,31 +0,0 @@
let logger = require('./log');
let mqtt = require('./mqttHandler');
class HomematicFourButtonSingleItem {
constructor(name, actionTopic) {
this.name = name;
this.actionTopic = actionTopic;
}
processMessage(topic, payload) {
switch(topic) {
case 'PRESS_SHORT':
mqtt.send(this.actionTopic, 'SHORT', true);
break;
case 'PRESS_LONG':
case 'PRESS_CONT':
mqtt.send(this.actionTopic, 'LONG_HOLD', true);
break;
case 'PRESS_LONG_RELEASE':
mqtt.send(this.actionTopic, 'LONG_END', true);
break;
default:
logger.warn(`HM4BSI: no handling available for ${topic}`);
break;
}
}
}
module.exports = HomematicFourButtonSingleItem;

View File

@ -1,31 +0,0 @@
let logger = require('./log');
let mqtt = require('./mqttHandler');
let AHomematicItem = require('./AHomematicItem')
class HomematicFourButtonThing extends AHomematicItem {
constructor(floor, room, item, hmId, itemObjs) {
super(floor, room, item, hmId);
this.itemObjs = itemObjs;
if (this.itemObjs.length != 4) {
throw new Error('itemObjs for HomematicFourButtonThing must have four elements');
}
this.subscribeTopics = [
`${this.deviceTopicPre}/#`
];
}
processMessage(topic, payload) {
logger.info(`HM4B: ${topic}, ${payload}`);
let buttonRelatedPart = topic.substring(this.deviceTopicPre.length+1);
let buttonIdx = parseInt(buttonRelatedPart.substring(0, buttonRelatedPart.indexOf('/')));
if (buttonIdx >= 1 && buttonIdx <= 4) {
this.itemObjs[buttonIdx-1].processMessage(buttonRelatedPart.substring(buttonRelatedPart.indexOf('/')+1), payload);
} else {
logger.warn(`HM4B: no handling available for ${topic}`);
}
}
}
module.exports = HomematicFourButtonThing;

View File

@ -0,0 +1,58 @@
import * as logger from './log'
import { mqttHandler } from './MqttDispatcher'
import { AHomematicItem } from './AHomematicItem'
export class HomematicFourButtonSingleItem {
private actionTopic: string
constructor(actionTopic: string) {
this.actionTopic = actionTopic
}
processMessage(topic: string, payload: string) {
switch(topic) {
case 'PRESS_SHORT':
mqttHandler.send(this.actionTopic, 'SHORT', true)
break
case 'PRESS_LONG':
case 'PRESS_CONT':
mqttHandler.send(this.actionTopic, 'LONG_HOLD', true)
break
case 'PRESS_LONG_RELEASE':
mqttHandler.send(this.actionTopic, 'LONG_END', true)
break
default:
logger.warn(`HM4BSI: no handling available for ${topic}`)
break
}
}
}
export class HomematicFourButtonThing extends AHomematicItem {
private itemObjs: HomematicFourButtonSingleItem[]
constructor(floor: string, room: string, item: string, hmId: number, itemObjs: HomematicFourButtonSingleItem[]) {
super(floor, room, item, hmId)
this.itemObjs = itemObjs
if (this.itemObjs.length != 4) {
throw new Error('itemObjs for HomematicFourButtonThing must have four elements')
}
this.subscribeTopics = [
`${this.deviceTopicPre}/#`
]
}
processMessage(topic: string, payload: string) {
logger.info(`HM4B: ${topic}, ${payload}`)
let buttonRelatedPart = topic.substring(this.deviceTopicPre.length+1)
let buttonIdx = parseInt(buttonRelatedPart.substring(0, buttonRelatedPart.indexOf('/')))
if (buttonIdx >= 1 && buttonIdx <= 4) {
this.itemObjs[buttonIdx-1].processMessage(buttonRelatedPart.substring(buttonRelatedPart.indexOf('/')+1), payload)
} else {
logger.warn(`HM4B: no handling available for ${topic}`)
}
}
}

40
src/M433SwitchItem.ts Normal file
View File

@ -0,0 +1,40 @@
import * as logger from './log'
import { mqttHandler } from './MqttDispatcher'
import { AItem } from './AItem'
export class M433SwitchItem extends AItem {
private offCode: string
private onCode: string
private oldState: string|undefined
private state: string
private actionTopic: string
private stateFeedbackTopic: string
private stateTopic: string
constructor(floor: string, room: string, item: string, onCode: string, offCode: string) {
super(floor, room, item)
this.stateTopic = `${this.topicFirstPart}/state`
this.subscribeTopics = [this.stateTopic]
this.stateFeedbackTopic = `${this.topicFirstPart}/state/feedback`
this.actionTopic = 'IoT/Mqtt433Gateway/Message'
this.state = 'OFF'
this.oldState = undefined
this.onCode = onCode
this.offCode = offCode
}
processMessage(topic: string, payload: string) {
this.state = payload;
mqttHandler.send(this.stateFeedbackTopic, this.state);
if (this.state != this.oldState) {
if (this.state == 'ON') {
mqttHandler.send(this.actionTopic, this.onCode);
} else {
mqttHandler.send(this.actionTopic, this.offCode);
}
this.oldState = this.state;
}
}
}

View File

@ -32,17 +32,19 @@ class MqttHandler {
}
this.topicHandlers = []
logger.info("MqttHandler constructed")
}
register(topics: string[], cb: TopicCallbackFunc) : void {
topics.forEach((topic) => {
this.topicHandlers.push({topic: topic, callback: cb})
logger.info(`additional callback registered for ${topic}`)
logger.info(`Callback registered for ${topic}`)
})
}
exec() : void {
logger.info(`connecting to ${this.mqttBrokerUrl}`)
logger.info(`Connecting to ${this.mqttBrokerUrl}`)
this.mqttClient = Mqtt.connect(this.mqttBrokerUrl, this.mqttOptions)
this.mqttClient.on('error', (err) => {
@ -55,12 +57,12 @@ class MqttHandler {
this.mqttClient.subscribe(topicHandler.topic)
logger.info(`${topicHandler.topic} subscribed`)
})
logger.info('mqtt connection established')
logger.info('MQTT connection established')
})
this.mqttClient.on('message', (topic: string, payload: Buffer, packet : Mqtt.IPublishPacket): void => {
if (! packet.retain) {
let payloadStr : string = payload.toString('UTF-8')
logger.info(`message received on topic ${topic}: ${payload}`)
logger.info(`Message received on topic ${topic}: ${payload}`)
this.processMessage(topic, payloadStr)
}
})

View File

@ -1,6 +1,5 @@
import * as fs from 'fs'
import * as cmdargs from 'command-line-args'
import * as logger from './log'
@ -15,5 +14,6 @@ export let dict : any
export function readConfig() {
let options = cmdargs(OPTION_DEFINITIONS)
dict = JSON.parse(fs.readFileSync(options.config, "utf8"))
logger.info(JSON.stringify(dict))
}
readConfig()

View File

@ -1,9 +0,0 @@
const SimpleNodeLogger = require('simple-node-logger');
let opts = {
logFilePath:'mylogfile.log',
timestampFormat:'YYYY-MM-DD HH:mm:ss.SSS'
};
let log = SimpleNodeLogger.createSimpleLogger(opts);
module.exports = log

View File

@ -1,28 +1,34 @@
import * as logger from './log'
import * as config from './config'
import * as logger from './log'
import { mqttHandler } from './MqttDispatcher'
// import { mqttHandler } from './MqttDispatcher'
import { M433SwitchItem } from './M433SwitchItem'
import { HomematicFourButtonThing, HomematicFourButtonSingleItem } from './HomematicFourButtonThing'
import { DimmerAdaptor } from './DimmerAdaptor'
config.readConfig()
logger.info("Dispatcher starting")
let aquariumLight = new M433SwitchItem('1st', 'Anna', 'AquariumLight', '14665044 24 1', '14665041 24 1');
aquariumLight.start();
let deskLight = new M433SwitchItem('Gnd', 'Hallway', 'DeskLight', '83221 24 1', '83220 24 1');
deskLight.start();
class Dispatcher {
constructor() {
logger.info("Dispatcher starting")
}
let testFourButton = new HomematicFourButtonThing('Gnd', 'Hallway', 'TestButton', 9, [
new HomematicFourButtonSingleItem('dispatcher_ng/items/Gnd/Hallway/Testlight/dimmerIn'),
new HomematicFourButtonSingleItem('dispatcher_ng/items/Gnd/Hallway/DeskLight/timerIn'),
new HomematicFourButtonSingleItem('test/button/3'),
new HomematicFourButtonSingleItem('test/button/4')
]);
testFourButton.start();
exec() : void {
logger.info("Hello world")
let testDimmerAdaptor = new DimmerAdaptor('Gnd', 'Hallway', 'Testlight');
testDimmerAdaptor.start();
// mqttHandler.exec()
}
}
const dispatcher = new Dispatcher()
dispatcher.exec()
mqttHandler.exec()
logger.info("Dispatcher running")