mqtt: always send globally, always retain, thermostat und windowContact completed
This commit is contained in:
50
dist/MaxThermostat.js
vendored
Normal file
50
dist/MaxThermostat.js
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const MqttDispatcher_1 = require("./MqttDispatcher");
|
||||||
|
const AHomematicItem_1 = require("./AHomematicItem");
|
||||||
|
// import { SwitchExport, ExportType } from './Export'
|
||||||
|
const WINDOW_OPEN_TEMPERATURE = 4.5;
|
||||||
|
class MaxThermostat extends AHomematicItem_1.AHomematicItem {
|
||||||
|
// Thermostat: homegear/instance1/set/3/1/SET_TEMPERATURE
|
||||||
|
constructor(floor, room, item, label, hmId, windowContacts) {
|
||||||
|
super(floor, room, item, label, hmId);
|
||||||
|
this.temperatureTopic = `${this.topicFirstPart}/temperature`;
|
||||||
|
this.temperatureFeedbackTopic = `${this.topicFirstPart}/temperature/feedback`;
|
||||||
|
this.deviceFeedbackTopic = `${this.deviceTopicPre}/1/SET_TEMPERATURE`;
|
||||||
|
this.actionTopic = `${this.actionTopicPre}/1/SET_TEMPERATURE`;
|
||||||
|
this.subscribeTopics = [
|
||||||
|
this.temperatureTopic,
|
||||||
|
this.deviceFeedbackTopic
|
||||||
|
];
|
||||||
|
this.windowOpen = false;
|
||||||
|
this.windowContactMap = {};
|
||||||
|
windowContacts.forEach((windowContact) => {
|
||||||
|
this.subscribeTopics.push(windowContact.getStateFeedbackTopic());
|
||||||
|
this.windowContactMap[windowContact.getStateFeedbackTopic()] = { windowContact: windowContact, state: 'unknown' };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
processMessage(topic, payload) {
|
||||||
|
if ((topic == this.temperatureTopic) || (topic == this.deviceFeedbackTopic)) {
|
||||||
|
this.temperature = parseFloat(payload);
|
||||||
|
}
|
||||||
|
else if (topic in this.windowContactMap) {
|
||||||
|
this.windowContactMap[topic].state = payload;
|
||||||
|
this.windowOpen = false;
|
||||||
|
Object.values(this.windowContactMap).forEach((w) => {
|
||||||
|
if (w.state == 'OPEN') {
|
||||||
|
this.windowOpen = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!this.windowOpen) {
|
||||||
|
MqttDispatcher_1.mqttHandler.send(this.temperatureFeedbackTopic, `${this.temperature}`);
|
||||||
|
MqttDispatcher_1.mqttHandler.send(this.actionTopic, `${this.temperature}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MqttDispatcher_1.mqttHandler.send(this.temperatureFeedbackTopic, `${WINDOW_OPEN_TEMPERATURE}`);
|
||||||
|
MqttDispatcher_1.mqttHandler.send(this.actionTopic, `${WINDOW_OPEN_TEMPERATURE}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.MaxThermostat = MaxThermostat;
|
||||||
|
//# sourceMappingURL=MaxThermostat.js.map
|
26
dist/MaxWindowContact.js
vendored
Normal file
26
dist/MaxWindowContact.js
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const MqttDispatcher_1 = require("./MqttDispatcher");
|
||||||
|
const AHomematicItem_1 = require("./AHomematicItem");
|
||||||
|
// import { SwitchExport, ExportType } from './Export'
|
||||||
|
class MaxWindowContact extends AHomematicItem_1.AHomematicItem {
|
||||||
|
getStateFeedbackTopic() {
|
||||||
|
return this.stateFeedbackTopic;
|
||||||
|
}
|
||||||
|
constructor(floor, room, item, label, hmId) {
|
||||||
|
super(floor, room, item, label, hmId);
|
||||||
|
this.stateTopic = `${this.topicFirstPart}/state`;
|
||||||
|
this.stateFeedbackTopic = `${this.topicFirstPart}/state/feedback`;
|
||||||
|
this.deviceFeedbackTopic = `${this.deviceTopicPre}/1/STATE`;
|
||||||
|
this.subscribeTopics = [
|
||||||
|
this.stateTopic,
|
||||||
|
this.deviceFeedbackTopic
|
||||||
|
];
|
||||||
|
}
|
||||||
|
processMessage(topic, payload) {
|
||||||
|
this.state = payload;
|
||||||
|
MqttDispatcher_1.mqttHandler.send(this.stateFeedbackTopic, this.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.MaxWindowContact = MaxWindowContact;
|
||||||
|
//# sourceMappingURL=MaxWindowContact.js.map
|
22
dist/MqttDispatcher.js
vendored
22
dist/MqttDispatcher.js
vendored
@ -70,18 +70,18 @@ class MqttHandler {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
send(topic, payload, internalFirst = false) {
|
send(topic, payload, internalFirst = false) {
|
||||||
let sent = false;
|
//let sent = false
|
||||||
if (internalFirst) {
|
//if (internalFirst) {
|
||||||
logger.info(`Try internal sending: ${topic}`);
|
// logger.info(`Try internal sending: ${topic}`)
|
||||||
sent = this.processMessage(topic, payload);
|
// sent = this.processMessage(topic, payload)
|
||||||
}
|
//}
|
||||||
if (!sent) {
|
//if (! sent) {
|
||||||
logger.info(`External sending required: ${topic}`);
|
logger.info(`External sending required: ${topic}`);
|
||||||
this.mqttClient.publish(topic, payload);
|
let options = { retain: true, qos: 0 };
|
||||||
}
|
this.mqttClient.publish(topic, payload, options);
|
||||||
else {
|
//} else {
|
||||||
logger.info(`Internally delivered: ${topic}`);
|
// logger.info(`Internally delivered: ${topic}`)
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.mqttHandler = new MqttHandler();
|
exports.mqttHandler = new MqttHandler();
|
||||||
|
44
dist/UrlSwitchItem.js
vendored
Normal file
44
dist/UrlSwitchItem.js
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const MqttDispatcher_1 = require("./MqttDispatcher");
|
||||||
|
const AItem_1 = require("./AItem");
|
||||||
|
const Export_1 = require("./Export");
|
||||||
|
const http = require("http");
|
||||||
|
class UrlSwitchItem extends AItem_1.AItem {
|
||||||
|
getStateTopic() {
|
||||||
|
return this.stateTopic;
|
||||||
|
}
|
||||||
|
getStateFeedbackTopic() {
|
||||||
|
return this.stateFeedbackTopic;
|
||||||
|
}
|
||||||
|
constructor(floor, room, item, label, onUrl, offUrl, type = 'bulb') {
|
||||||
|
super(floor, room, item, label);
|
||||||
|
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.onUrl = onUrl;
|
||||||
|
this.offUrl = offUrl;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
exportItem() {
|
||||||
|
return Export_1.SwitchExport(this.itemId, this.label, this.stateTopic, this.stateFeedbackTopic, this.type);
|
||||||
|
}
|
||||||
|
processMessage(topic, payload) {
|
||||||
|
this.state = payload;
|
||||||
|
MqttDispatcher_1.mqttHandler.send(this.stateFeedbackTopic, this.state);
|
||||||
|
if (this.state != this.oldState) {
|
||||||
|
if (this.state == 'ON') {
|
||||||
|
http.get(this.onUrl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
http.get(this.offUrl);
|
||||||
|
}
|
||||||
|
this.oldState = this.state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.UrlSwitchItem = UrlSwitchItem;
|
||||||
|
//# sourceMappingURL=UrlSwitchItem.js.map
|
8
dist/main.js
vendored
8
dist/main.js
vendored
@ -13,6 +13,8 @@ const HomematicSwitchItem_1 = require("./HomematicSwitchItem");
|
|||||||
const Forwarder_1 = require("./Forwarder");
|
const Forwarder_1 = require("./Forwarder");
|
||||||
const Scene_1 = require("./Scene");
|
const Scene_1 = require("./Scene");
|
||||||
const MaxEcoSwitch_1 = require("./MaxEcoSwitch");
|
const MaxEcoSwitch_1 = require("./MaxEcoSwitch");
|
||||||
|
const MaxThermostat_1 = require("./MaxThermostat");
|
||||||
|
const MaxWindowContact_1 = require("./MaxWindowContact");
|
||||||
logger.info("Dispatcher starting");
|
logger.info("Dispatcher starting");
|
||||||
let allLabeledItems = new Array();
|
let allLabeledItems = new Array();
|
||||||
// Anna -----------------------------------------------------------------------------------------------------
|
// Anna -----------------------------------------------------------------------------------------------------
|
||||||
@ -154,6 +156,12 @@ let testForwarder = new Forwarder_1.Forwarder('Gnd', 'Hallway', 'TestForwarder',
|
|||||||
testForwarder.start();
|
testForwarder.start();
|
||||||
let testScene = new Scene_1.LightScene('Gnd', 'Hallway', 'TestScene', 'TestScene', [aquariumLight, annaBedLight], [matthiasStandLights, matthiasBedLight]);
|
let testScene = new Scene_1.LightScene('Gnd', 'Hallway', 'TestScene', 'TestScene', [aquariumLight, annaBedLight], [matthiasStandLights, matthiasBedLight]);
|
||||||
testScene.start();
|
testScene.start();
|
||||||
|
let windowContact1 = new MaxWindowContact_1.MaxWindowContact('Gnd', 'Bathroom', 'WindowContact1', 'Fenster Bad unten', 2);
|
||||||
|
windowContact1.start();
|
||||||
|
let windowContact2 = new MaxWindowContact_1.MaxWindowContact('Gnd', 'Bathroom', 'WindowContact2', 'Fenster Bad unten', 20);
|
||||||
|
windowContact2.start();
|
||||||
|
let thermostat1 = new MaxThermostat_1.MaxThermostat('Gnd', 'Bathroom', 'Thermostat', 'Thermostat Bad unten', 3, [windowContact1, windowContact2]);
|
||||||
|
thermostat1.start();
|
||||||
// ----------------------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------------------
|
||||||
// Homekit export
|
// Homekit export
|
||||||
let homekitObject = {};
|
let homekitObject = {};
|
||||||
|
@ -7,14 +7,18 @@ import { MaxWindowContact } from './MaxWindowContact';
|
|||||||
const WINDOW_OPEN_TEMPERATURE = 4.5
|
const WINDOW_OPEN_TEMPERATURE = 4.5
|
||||||
|
|
||||||
|
|
||||||
|
type WindowContactHolder = {
|
||||||
|
windowContact : MaxWindowContact
|
||||||
|
state : string
|
||||||
|
}
|
||||||
|
|
||||||
export class MaxThermostat extends AHomematicItem {
|
export class MaxThermostat extends AHomematicItem {
|
||||||
private actionTopic: string
|
private actionTopic: string
|
||||||
private deviceFeedbackTopic: string
|
private deviceFeedbackTopic: string
|
||||||
private temperatureFeedbackTopic: string
|
private temperatureFeedbackTopic: string
|
||||||
private temperatureTopic: string
|
private temperatureTopic: string
|
||||||
private temperature: number
|
private temperature: number
|
||||||
private windowContacts: MaxWindowContact[]
|
private windowContactMap: { [key:string]: WindowContactHolder }
|
||||||
private windowContactTopics: string[]
|
|
||||||
private windowOpen: boolean
|
private windowOpen: boolean
|
||||||
// Thermostat: homegear/instance1/set/3/1/SET_TEMPERATURE
|
// Thermostat: homegear/instance1/set/3/1/SET_TEMPERATURE
|
||||||
|
|
||||||
@ -28,33 +32,35 @@ export class MaxThermostat extends AHomematicItem {
|
|||||||
this.temperatureTopic,
|
this.temperatureTopic,
|
||||||
this.deviceFeedbackTopic
|
this.deviceFeedbackTopic
|
||||||
]
|
]
|
||||||
this.windowContacts = windowContacts
|
|
||||||
this.windowOpen = false
|
this.windowOpen = false
|
||||||
this.windowContactTopics = []
|
this.windowContactMap = {}
|
||||||
this.windowContacts.forEach((windowContact) => {
|
windowContacts.forEach((windowContact) => {
|
||||||
this.subscribeTopics.push(windowContact.getStateFeedbackTopic())
|
this.subscribeTopics.push(windowContact.getStateFeedbackTopic())
|
||||||
this.windowContactTopics.push(windowContact.getStateFeedbackTopic())
|
this.windowContactMap[windowContact.getStateFeedbackTopic()] = { windowContact: windowContact, state: 'unknown' }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
processMessage(topic: string, payload: string) : void {
|
processMessage(topic: string, payload: string) : void {
|
||||||
if (topic == this.temperatureTopic) {
|
if ((topic == this.temperatureTopic) || (topic == this.deviceFeedbackTopic)) {
|
||||||
this.temperature = parseFloat(payload)
|
this.temperature = parseFloat(payload)
|
||||||
|
} else if (topic in this.windowContactMap) {
|
||||||
|
this.windowContactMap[topic].state = payload
|
||||||
|
this.windowOpen = false
|
||||||
|
Object.values(this.windowContactMap).forEach((w) => {
|
||||||
|
if (w.state == 'OPEN') {
|
||||||
|
this.windowOpen = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! this.windowOpen) {
|
||||||
mqttHandler.send(this.temperatureFeedbackTopic, `${this.temperature}`)
|
mqttHandler.send(this.temperatureFeedbackTopic, `${this.temperature}`)
|
||||||
mqttHandler.send(this.actionTopic, `${this.temperature}`)
|
mqttHandler.send(this.actionTopic, `${this.temperature}`)
|
||||||
} else if (topic == this.deviceFeedbackTopic) {
|
|
||||||
this.temperature = parseFloat(payload)
|
|
||||||
mqttHandler.send(this.temperatureFeedbackTopic, `${this.temperature}`)
|
|
||||||
} else if (this.windowContactTopics.indexOf(topic) >= 0) {
|
|
||||||
if (payload == 'CLOSED') {
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
mqttHandler.send(this.temperatureFeedbackTopic, `${WINDOW_OPEN_TEMPERATURE}`)
|
||||||
|
mqttHandler.send(this.actionTopic, `${WINDOW_OPEN_TEMPERATURE}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ import * as logger from './log'
|
|||||||
import * as Mqtt from 'mqtt'
|
import * as Mqtt from 'mqtt'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as config from './config'
|
import * as config from './config'
|
||||||
|
import { IClientPublishOptions } from 'mqtt';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -97,7 +98,8 @@ class MqttHandler {
|
|||||||
//}
|
//}
|
||||||
//if (! sent) {
|
//if (! sent) {
|
||||||
logger.info(`External sending required: ${topic}`)
|
logger.info(`External sending required: ${topic}`)
|
||||||
this.mqttClient.publish(topic, payload)
|
let options : IClientPublishOptions = { retain: true, qos: 0 }
|
||||||
|
this.mqttClient.publish(topic, payload, options)
|
||||||
//} else {
|
//} else {
|
||||||
// logger.info(`Internally delivered: ${topic}`)
|
// logger.info(`Internally delivered: ${topic}`)
|
||||||
//}
|
//}
|
||||||
|
11
src/main.ts
11
src/main.ts
@ -15,6 +15,8 @@ import { HomematicSwitchItem } from './HomematicSwitchItem'
|
|||||||
import { Forwarder } from './Forwarder'
|
import { Forwarder } from './Forwarder'
|
||||||
import { LightScene } from './Scene'
|
import { LightScene } from './Scene'
|
||||||
import { MaxEcoSwitch } from './MaxEcoSwitch'
|
import { MaxEcoSwitch } from './MaxEcoSwitch'
|
||||||
|
import { MaxThermostat } from './MaxThermostat'
|
||||||
|
import { MaxWindowContact } from './MaxWindowContact'
|
||||||
|
|
||||||
|
|
||||||
logger.info("Dispatcher starting")
|
logger.info("Dispatcher starting")
|
||||||
@ -211,6 +213,15 @@ let testScene = new LightScene('Gnd', 'Hallway', 'TestScene', 'TestScene',
|
|||||||
testScene.start()
|
testScene.start()
|
||||||
|
|
||||||
|
|
||||||
|
let windowContact1 = new MaxWindowContact('Gnd', 'Bathroom', 'WindowContact1', 'Fenster Bad unten', 2)
|
||||||
|
windowContact1.start()
|
||||||
|
let windowContact2 = new MaxWindowContact('Gnd', 'Bathroom', 'WindowContact2', 'Fenster Bad unten', 20)
|
||||||
|
windowContact2.start()
|
||||||
|
|
||||||
|
let thermostat1 = new MaxThermostat('Gnd', 'Bathroom', 'Thermostat', 'Thermostat Bad unten', 3, [windowContact1, windowContact2])
|
||||||
|
thermostat1.start()
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------------------
|
||||||
// Homekit export
|
// Homekit export
|
||||||
let homekitObject : { [key:string]:{} } = {}
|
let homekitObject : { [key:string]:{} } = {}
|
||||||
|
Reference in New Issue
Block a user