Now properly sends light state back to HA
This commit is contained in:
parent
ef7144ebc1
commit
26341e075a
@ -1,5 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "door_singleton.h"
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
|
||||||
#include "esphome.h"
|
#include "esphome.h"
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "hciemulator.h"
|
#include "hciemulator.h"
|
||||||
@ -14,22 +18,15 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace hoermann_door {
|
namespace hoermann_door {
|
||||||
|
|
||||||
HCIEmulator emulator;
|
|
||||||
TaskHandle_t modBusTask;
|
|
||||||
void modBusPolling(void *parameter);
|
void modBusPolling(void *parameter);
|
||||||
class HoermanDoor : public Component, public cover::Cover
|
class HoermanDoor : public Component, public cover::Cover
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HoermanDoor()
|
|
||||||
{
|
|
||||||
emulator;
|
|
||||||
}
|
|
||||||
|
|
||||||
cover::CoverTraits get_traits() override {
|
cover::CoverTraits get_traits() override {
|
||||||
auto traits = cover::CoverTraits();
|
auto traits = cover::CoverTraits();
|
||||||
traits.set_is_assumed_state(false);
|
traits.set_is_assumed_state(false);
|
||||||
traits.set_supports_position(true);
|
traits.set_supports_position(false);
|
||||||
traits.set_supports_tilt(false);
|
traits.set_supports_tilt(false);
|
||||||
traits.set_supports_stop(true);
|
traits.set_supports_stop(true);
|
||||||
traits.set_supports_toggle(true);
|
traits.set_supports_toggle(true);
|
||||||
@ -51,11 +48,11 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
if(pos == 1.0){
|
if(pos == 1.0){
|
||||||
emulator.openDoor();
|
HoermannSingleton::getInstance()->getEmulator()->openDoor();
|
||||||
manual = false;
|
manual = false;
|
||||||
}
|
}
|
||||||
else if(pos == 0.0){
|
else if(pos == 0.0){
|
||||||
emulator.closeDoor();
|
HoermannSingleton::getInstance()->getEmulator()->closeDoor();
|
||||||
manual = false;
|
manual = false;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -64,7 +61,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
if (call.get_stop()) {
|
if (call.get_stop()) {
|
||||||
emulator.stopDoor();
|
HoermannSingleton::getInstance()->getEmulator()->stopDoor();
|
||||||
}
|
}
|
||||||
//if(call.get_close()) {
|
//if(call.get_close()) {
|
||||||
//emulator.closeDoor();
|
//emulator.closeDoor();
|
||||||
@ -91,25 +88,7 @@ void modBusPolling(void *parameter)
|
|||||||
|
|
||||||
void setup() override
|
void setup() override
|
||||||
{
|
{
|
||||||
// setup modbus
|
HoermannSingleton::getInstance()->initializeEmulator();
|
||||||
RS485.begin(57600, SERIAL_8E1, 16, 17);
|
|
||||||
pinMode(TX_ON, OUTPUT);
|
|
||||||
digitalWrite(TX_ON, LOW);
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
modBusPolling, // Function to implement the task
|
|
||||||
"ModBusTask", // Name of the task
|
|
||||||
10000, // Stack size in words
|
|
||||||
NULL, // Task input parameter
|
|
||||||
// 1, // Priority of the task
|
|
||||||
configMAX_PRIORITIES - 1,
|
|
||||||
&modBusTask, // Task handle.
|
|
||||||
1 // Core where the task should run
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -130,7 +109,7 @@ void modBusPolling(void *parameter)
|
|||||||
u_int8_t pos = 255;
|
u_int8_t pos = 255;
|
||||||
void loop() override
|
void loop() override
|
||||||
{
|
{
|
||||||
u_int8_t position = emulator.getState().doorCurrentPosition;
|
u_int8_t position = HoermannSingleton::getInstance()->getEmulator()->getState().doorCurrentPosition;
|
||||||
if(pos != position){
|
if(pos != position){
|
||||||
this->position = (float) position / 200.0;
|
this->position = (float) position / 200.0;
|
||||||
this->publish_state();
|
this->publish_state();
|
||||||
@ -140,53 +119,9 @@ void modBusPolling(void *parameter)
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Custom binary output, for exposing binary states
|
|
||||||
class NbsLightOutput: public output::BinaryOutput, public Component {
|
|
||||||
public:
|
|
||||||
void setup() override {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_state(bool state) override {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lastState = false;
|
|
||||||
bool firstState = false;
|
|
||||||
void loop() override {
|
|
||||||
if(!emulator.getState().valid) false;
|
|
||||||
if(!firstState || emulator.getState().lampOn != lastState){
|
|
||||||
//ESP_LOGD("Test", "I have no idea");
|
|
||||||
lastState = emulator.getState().lampOn;
|
|
||||||
this->set_state(lastState);
|
|
||||||
firstState = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void turn_on() override {
|
|
||||||
if(!lastState) emulator.toggleLamp();
|
|
||||||
}
|
|
||||||
void turn_off() override {
|
|
||||||
if(lastState) emulator.toggleLamp();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
volatile unsigned long lastCall = 0;
|
|
||||||
volatile unsigned long maxPeriod = 0;
|
|
||||||
void modBusPolling(void *parameter)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (lastCall > 0)
|
|
||||||
{
|
|
||||||
maxPeriod = _max(micros() - lastCall, maxPeriod);
|
|
||||||
}
|
|
||||||
lastCall = micros();
|
|
||||||
emulator.poll();
|
|
||||||
vTaskDelay(1);
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace hoermann
|
} // namespace hoermann
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
79
external_components/hoermann_door/door_singleton.h
Normal file
79
external_components/hoermann_door/door_singleton.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "hciemulator.h"
|
||||||
|
//#include "cover.h"
|
||||||
|
|
||||||
|
#define RS485 Serial2
|
||||||
|
#define TX_ON 25
|
||||||
|
//#define configMAX_PRIORITIES 25
|
||||||
|
|
||||||
|
#define TAG "hoermann_door"
|
||||||
|
|
||||||
|
|
||||||
|
void modBusPolling(void *parameter);
|
||||||
|
|
||||||
|
class HoermannSingleton {
|
||||||
|
public:
|
||||||
|
HoermannSingleton() {
|
||||||
|
emulator;
|
||||||
|
}
|
||||||
|
static HoermannSingleton* instance_;
|
||||||
|
HCIEmulator emulator;
|
||||||
|
TaskHandle_t modBusTask;
|
||||||
|
bool hasBeenInitialized = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static HoermannSingleton* getInstance(){
|
||||||
|
if(instance_ == nullptr){
|
||||||
|
instance_ = new HoermannSingleton();
|
||||||
|
}
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeEmulator(){
|
||||||
|
if(hasBeenInitialized) return;
|
||||||
|
hasBeenInitialized = true;
|
||||||
|
RS485.begin(57600, SERIAL_8E1, 16, 17);
|
||||||
|
pinMode(TX_ON, OUTPUT);
|
||||||
|
digitalWrite(TX_ON, LOW);
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(
|
||||||
|
modBusPolling, // Function to implement the task
|
||||||
|
"ModBusTask", // Name of the task
|
||||||
|
10000, // Stack size in words
|
||||||
|
NULL, // Task input parameter
|
||||||
|
// 1, // Priority of the task
|
||||||
|
configMAX_PRIORITIES - 1,
|
||||||
|
&modBusTask, // Task handle.
|
||||||
|
1 // Core where the task should run
|
||||||
|
);
|
||||||
|
}
|
||||||
|
HCIEmulator *getEmulator(){
|
||||||
|
return &emulator;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HoermannSingleton* HoermannSingleton::instance_ = nullptr;
|
||||||
|
|
||||||
|
//DoorManager *DoorManager::getInstance()
|
||||||
|
|
||||||
|
|
||||||
|
volatile unsigned long lastCall = 0;
|
||||||
|
volatile unsigned long maxPeriod = 0;
|
||||||
|
void modBusPolling(void *parameter)
|
||||||
|
{
|
||||||
|
auto emulator = HoermannSingleton::getInstance()->getEmulator();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (lastCall > 0)
|
||||||
|
{
|
||||||
|
maxPeriod = _max(micros() - lastCall, maxPeriod);
|
||||||
|
}
|
||||||
|
lastCall = micros();
|
||||||
|
emulator->poll();
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
106
external_components/hoermann_door/light_component.h
Normal file
106
external_components/hoermann_door/light_component.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef USE_LIGHT
|
||||||
|
|
||||||
|
#include "esphome.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "hciemulator.h"
|
||||||
|
#include "door_singleton.h"
|
||||||
|
//#include "cover.h"
|
||||||
|
|
||||||
|
#define RS485 Serial2
|
||||||
|
#define TX_ON 25
|
||||||
|
//#define configMAX_PRIORITIES 25
|
||||||
|
|
||||||
|
#define TAG "hoermann_door"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace hoermann_door {
|
||||||
|
|
||||||
|
// Custom binary output, for exposing binary states
|
||||||
|
class NbsLightManager: public binary::BinaryLightOutput, public light::LightState {
|
||||||
|
protected:
|
||||||
|
HoermannSingleton *single;
|
||||||
|
public:
|
||||||
|
void setup() override {
|
||||||
|
//single = HoermannSingleton::getInstance();
|
||||||
|
//single->initializeGetInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lastState = false;
|
||||||
|
bool firstState = false;
|
||||||
|
void loop() override {
|
||||||
|
//if(!DoorManager.getEmulator().getState().valid) false;
|
||||||
|
//if(!firstState || DoorManager.getEmulator().getState().lampOn != lastState){
|
||||||
|
//ESP_LOGD("Test", "I have no idea");
|
||||||
|
// lastState = DoorManager.getEmulator().getState().lampOn;
|
||||||
|
// this->write_state(lastState);
|
||||||
|
|
||||||
|
// firstState = true;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Custom binary output, for exposing binary states
|
||||||
|
class NbsLightOutput: public output::BinaryOutput, public Component{
|
||||||
|
|
||||||
|
light::LightState *callback;
|
||||||
|
HoermannSingleton *single;
|
||||||
|
bool lastState = false;
|
||||||
|
bool firstState = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void write_state(bool state){
|
||||||
|
if(lastState != state){
|
||||||
|
single->getEmulator()->toggleLamp();
|
||||||
|
//lastState = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_state_callback(light::LightState *callback){
|
||||||
|
if(callback == nullptr) ESP_LOGW("Hoermann_door(Light)", "Got Nullable callback");
|
||||||
|
this->callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() override {
|
||||||
|
if(!single->getEmulator()->getState().valid) false;
|
||||||
|
if(firstState || single->getEmulator()->getState().lampOn != lastState){
|
||||||
|
//ESP_LOGD("Test", "I have no idea");
|
||||||
|
lastState = single->getEmulator()->getState().lampOn;
|
||||||
|
if(lastState == true){
|
||||||
|
ESP_LOGD("Hoermann_door(Light)", "Light State ON");
|
||||||
|
|
||||||
|
auto call = callback->make_call();
|
||||||
|
call.set_state(true);
|
||||||
|
call.perform();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESP_LOGD("Hoermann_door(Light)", "Light State OFF");
|
||||||
|
auto call = callback->make_call();
|
||||||
|
call.set_state(false);
|
||||||
|
call.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
firstState = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() override {
|
||||||
|
single = HoermannSingleton::getInstance();
|
||||||
|
single->initializeEmulator();
|
||||||
|
}
|
||||||
|
|
||||||
|
void turn_on() override {
|
||||||
|
this->write_state(true);
|
||||||
|
}
|
||||||
|
void turn_off() override {
|
||||||
|
this->write_state(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace hoermann
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
@ -1,18 +1,22 @@
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome import automation
|
from esphome.components import output, light
|
||||||
from esphome.components import output
|
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
hoermann_cover_ns = cg.esphome_ns.namespace('hoermann_door')
|
hoermann_cover_ns = cg.esphome_ns.namespace('hoermann_door')
|
||||||
HoermannCoverLight = hoermann_cover_ns.class_('NbsLightOutput', output.BinaryOutput, cg.Component)
|
HoermannCoverLight = hoermann_cover_ns.class_('NbsLightOutput', output.BinaryOutput, cg.Component)
|
||||||
|
CONF_STATE_CALLBACK = "state_callback"
|
||||||
|
|
||||||
CONFIG_SCHEMA = output.BINARY_OUTPUT_SCHEMA.extend({
|
CONFIG_SCHEMA = output.BINARY_OUTPUT_SCHEMA.extend({
|
||||||
cv.GenerateID(): cv.declare_id(HoermannCoverLight)
|
cv.GenerateID(CONF_ID): cv.declare_id(HoermannCoverLight),
|
||||||
|
cv.Required(CONF_STATE_CALLBACK): cv.use_id(light.LightState)
|
||||||
}).extend(cv.COMPONENT_SCHEMA)
|
}).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
yield cg.register_component(var, config)
|
yield cg.register_component(var, config)
|
||||||
yield output.register_output(var, config)
|
yield output.register_output(var, config)
|
||||||
|
|
||||||
|
callback = yield cg.get_variable(config[CONF_STATE_CALLBACK])
|
||||||
|
cg.add(var.set_state_callback(callback))
|
26
garage1.yaml
26
garage1.yaml
@ -9,19 +9,11 @@ esphome:
|
|||||||
libraries:
|
libraries:
|
||||||
- plerup/EspSoftwareSerial
|
- plerup/EspSoftwareSerial
|
||||||
|
|
||||||
# custom_component:
|
ota:
|
||||||
# - lambda: |-
|
password: !secret gd_passwd
|
||||||
# auto door = new HoermanDoor();
|
api:
|
||||||
# App.register_component(door);
|
encryption:
|
||||||
# return {door};
|
key: !secret gd_key
|
||||||
# components:
|
|
||||||
# - id: door_${garageSide}
|
|
||||||
# - lambda: |-
|
|
||||||
# auto light = new NbsLightOutput();
|
|
||||||
# App.register_component(light);
|
|
||||||
# return {light};
|
|
||||||
# components:
|
|
||||||
# - id: door_${garageSide}_lamp
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
ssid: !secret wifi_ssid
|
||||||
@ -39,18 +31,16 @@ external_components:
|
|||||||
cover:
|
cover:
|
||||||
- platform: hoermann_door
|
- platform: hoermann_door
|
||||||
name: door_${garageSide}
|
name: door_${garageSide}
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: binary
|
- platform: binary
|
||||||
name: door_${garageSide}_lamp
|
name: door_${garageSide}_lamp
|
||||||
|
id: lamp_id_${garageSide}
|
||||||
output: light_out
|
output: light_out
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- id: light_out
|
- id: light_out
|
||||||
platform: hoermann_door
|
platform: hoermann_door
|
||||||
|
state_callback: lamp_id_${garageSide}
|
||||||
|
|
||||||
|
|
||||||
ota:
|
|
||||||
password: !secret gd_passwd
|
|
||||||
api:
|
|
||||||
encryption:
|
|
||||||
key: !secret gd_key
|
|
Loading…
Reference in New Issue
Block a user