Now properly sends light state back to HA

This commit is contained in:
Nicolas Bachschwell 2024-04-29 13:49:12 +02:00
parent ef7144ebc1
commit 26341e075a
Signed by: NBSgamesAT
GPG Key ID: 2D73288FF7AEED2F
5 changed files with 214 additions and 100 deletions

View File

@ -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

View 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);
}

View 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

View File

@ -1,14 +1,15 @@
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)
@ -16,3 +17,6 @@ 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))

View File

@ -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