Hi Forum,
Usecase:
I have a Garagedor Opener (Hörmann) installed with a PushButton (Open-Stop-Closed-Stop...) and a Wall mounted Button, photoelectric sensor and what not. An integration pushing just the button with the shelly is simple, however, i wanted defined states. Therfore i have installed a reed switch signaling me a closed door.
Currently i run a Shelly 1 having the logic buried in HomeAssistant/Node Red. With the new Plus 1 devices i tried to push down the logic to the Shelly, so this is what i came up with:
- Shelly 1 Plus
- Detached Mode
- Reed Switch on Input (ON== Closed)
- Relaid Connected to Door opener
- MQTT enabled
- HomeAssistant with MQTT, defining a Cover as:
Add in Homeasistant Config.yaml
cover:
- platform: mqtt
name: "Garagedoor"
unique_id: "MQTTGARAGE"
command_topic: "home-assistant/garage/set"
state_topic: "home-assistant/garage/state"
availability:
- topic: "home-assistant/garage/availability"
qos: 0
retain: true
payload_open: "OPEN"
payload_close: "CLOSE"
payload_stop: "STOP"
state_open: "open"
state_opening: "opening"
state_closed: "closed"
state_closing: "closing"
state_stopped: "stopped"
payload_available: "online"
payload_not_available: "offline"
optimistic: false
value_template: "{{ value.x }}"
Alles anzeigen
On the Shelly i run a script as:
let CONFIG = {
openTime: 25000, // Time to open the door in Milieconds
closeTime: 200000, // Time to open the door in Milieconds
relaisHoldTime: 700, // Time to push the door opener button in ms
mqttCommand: "home-assistant/garage/set", // Command Topic
mqttState: "home-assistant/garage/state", // state Topic
// mqttPoition : "home-assistant/garage/position", //poition topic
mqttAvailability: "home-assistant/garage/availability", // Availability Topic
debug: true
};
let STATES = {
open: "open",
opening: "opening",
closed: "closed",
closing: "closing",
stopped: "stopped",
available: "online",
not_available: "offline"
};
let COMMANDS = {
open: "OPEN",
close: "CLOSE",
stop: "STOP"
};
// Clobal Variable to keep trac of current state
let currentState = "";
let timerOpening = null;
let timerClosing = null;
// In case you would disregard the results of the call such an empty callback
// can be used
function stubCB(res, error_code, error_msg, ud) {};
// switche relais on
function triggerRelais() {
Shelly.call("switch.set", {
id: 0,
on: true
},
stubCB,
null);
// release after xxx milisec
Timer.set(CONFIG.relaisHoldTime, false, function() {
Shelly.call("switch.set", {
id: 0,
on: false
},
stubCB,
null);
}, null)
}
// so, door just closed up
function handleInputOn() {
if (CONFIG.debug) print("Contact ON - Door is closed ");
Timer.clear(timerOpening)
Timer.clear(timerClosing)
setCoverState(STATES.closed); // this is unvonditional: If the contact says closed, it is closed.
}
// so, door just startet opening
function handleInputOff() {
if (CONFIG.debug) print("Contact OFF - Door is opening ");
currentState = STATES.opening; // this is gueswork. it was closed before, so we assume it is opening.
setCoverState(STATES.opening); // set MQTT to opening
Timer.clear(timerOpening)
// assume after a while it is open
timerOpening = Timer.set(CONFIG.openTime, false, function() {
setCoverState(STATES.open);
}, null);
}
// Event handler to react on changes of the input sensor
Shelly.addEventHandler(
function(event, ud) {
if (CONFIG.debug) print("Event: " + JSON.stringify(event));
if (event.name === "input") {
if (event.info.state === true) handleInputOn(); //closed
if (event.info.state === false) handleInputOff(); //opening
}
},
null
);
// helper to send the new states
function setCoverState(newstate) {
if (CONFIG.debug) print("MQTT setting state: " + newstate);
MQTT.publish(CONFIG.mqttState, newstate, 0, false);
currentState = newstate; // remember it for later consistency checks
}
// so, lets subscribe to the MQTT command
MQTT.subscribe(
CONFIG.mqttCommand,
function(topic, message, ud) {
// add debug text
if (CONFIG.debug) print("MQTT Command Topic" + JSON.stringify(topic) + " Message: " + JSON.stringify(message));
if (message === COMMANDS.open) { // open command via MQTT recieved
if (currentState === STATES.closed ||
currentState === SSTATES.stopped ) { // we are closed right now
triggerRelais(); // so, push the button. Within seconds the contact will open
// and set the opening state + timer based open
}
} else if (message === COMMANDS.close) { // close command via MQTT
if (currentState === STATES.open ||
currentState === SSTATES.stopped) {
setCoverState(STATES.closing); // puh the button
triggerRelais(); // now the door should close
// Set a timer, to check if the door indeed closed
openTimer = Timer.set(CONFIG.closeTime, false, function() {
if (currentState !== STATES.closed) {
// ok. The dour should be closed, but it is not.
// now we could push and wait for 3 times to see if we can force it.
// or we just put the status to stopped.
setCoverState(STATES.stopped);
}
}, null);
}
} else if (message === COMMANDS.stop) {
triggerRelais();
setCoverState(STATES.stopped);
}
}, //EndOfEventhandler
null
);
// Anounce the devilce to be available now & every 10 minutes
MQTT.publish(CONFIG.mqttAvailability, STATES.available, 0, false);
Timer.set(10000, true, function() {
MQTT.publish(CONFIG.mqttAvailability, STATES.available, 0, false);
}, null);
// we are here in the startup run; so determin the current status and set the MQTT Accordingly
Shelly.call(
"input.getstatus", {
id: 0
},
function(result, error_code, error_message, user_data) {
if (error_code === 0) {
//{"state":true,"id":0}
if (result.state === true) { // if it is
setCoverState(STATES.closed);
} else {
setCoverState(STATES.open);
}
}
},
null
);
Alles anzeigen
i will see how it runs on a long run....
Any Feedback&Improvements are highly welcome
Gruß
Michael