Trial this

This commit is contained in:
Daniël Koek 2024-02-20 16:17:56 +00:00
parent 113ed8d48f
commit 4c0772a8f1
8 changed files with 105 additions and 187 deletions

View file

@ -4,31 +4,21 @@ from esphome import pins
from esphome.components import sensor, text_sensor, uart
from esphome.const import *
DEPENDENCIES = ["uart"]
MULTI_CONF = True
lora_ns = cg.esphome_ns.namespace("lora")
Lora = lora_ns.class_("Lora", cg.Component, uart.UARTDevice)
DEPENDENCIES = ["uart"]
AUTO_LOAD = ["uart", "sensor", "text_sensor"]
LoraGPIOPin = lora_ns.class_("LoraGPIOPin", cg.GPIOPin)
CONF_PIN_AUX = "pin_aux"
CONF_PIN_M0 = "pin_m0"
CONF_PIN_M1 = "pin_m1"
CONF_LORA_MESSAGE = "lora_message"
CONF_LORA_RSSI = "lora_rssi"
CONF_LORA = "lora"
CONFIG_SCHEMA = (
cv.Schema(
{
# if you send gps locations over lora, this will be able to read it
cv.Optional(CONF_LATITUDE): sensor.sensor_schema(
unit_of_measurement=UNIT_DEGREES,
accuracy_decimals=6,
),
# if you send gps locations over lora, this will be able to read it
cv.Optional(CONF_LONGITUDE): sensor.sensor_schema(
unit_of_measurement=UNIT_DEGREES,
accuracy_decimals=6,
),
cv.GenerateID(): cv.declare_id(Lora),
# for communication to let us know that we can receive data
cv.Required(CONF_PIN_AUX): pins.gpio_input_pin_schema,
@ -54,6 +44,27 @@ CONFIG_SCHEMA = (
)
def validate_mode(value):
if not (value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be output")
return value
Lora_PIN_SCHEMA = pins.gpio_base_schema(
LoraGPIOPin,
cv.int_range(min=0, max=17),
modes=[CONF_OUTPUT],
mode_validator=validate_mode,
invertable=True,
).extend(
{
cv.Required(CONF_LORA): cv.use_id(Lora),
}
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
@ -74,3 +85,17 @@ async def to_code(config):
if CONF_LORA_RSSI in config:
sens = await sensor.new_sensor(config[CONF_LORA_RSSI])
cg.add(var.set_rssi_sensor(sens))
@pins.PIN_SCHEMA_REGISTRY.register(CONF_LORA, Lora_PIN_SCHEMA)
async def lora_pin_to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_LORA])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var

View file

@ -124,7 +124,10 @@ void Lora::dump_config() {
LOG_PIN("M0 Pin:", this->pin_m0);
LOG_PIN("M1 Pin:", this->pin_m1);
};
void Lora::digital_write(uint8_t pin, bool value) {
std::string message = str_snprintf("%02x%02x", 12, pin, value);
sendMessage(message);
}
bool Lora::sendMessage(std::string message) {
uint8_t size = message.length();
char messageFixed[size];

View file

@ -33,8 +33,12 @@ class Lora : public PollingComponent, public uart::UARTDevice {
void loop() override;
void dump_config() override;
// local
void set_latitude_sensor(sensor::Sensor *latitude_sensor) { latitude_sensor_ = latitude_sensor; }
void set_longitude_sensor(sensor::Sensor *longitude_sensor) { longitude_sensor_ = longitude_sensor; }
/// Helper function to read the value of a pin.
bool digital_read(uint8_t pin);
/// Helper function to write the value of a pin.
void digital_write(uint8_t pin, bool value);
/// Helper function to set the pin mode of a pin.
void pin_mode(uint8_t pin, gpio::Flags flags);
void set_message_sensor(text_sensor::TextSensor *s) { message_text_sensor = s; }
void set_rssi_sensor(sensor::Sensor *s) { rssi_sensor = s; }
void set_pin_aux(GPIOPin *s) { pin_aux = s; }
@ -54,8 +58,6 @@ class Lora : public PollingComponent, public uart::UARTDevice {
float latitude_ = -1;
float longitude_ = -1;
std::string raw_message_;
sensor::Sensor *latitude_sensor_{nullptr};
sensor::Sensor *longitude_sensor_{nullptr};
text_sensor::TextSensor *message_text_sensor{nullptr};
sensor::Sensor *rssi_sensor{nullptr};
GPIOPin *pin_aux{nullptr};

View file

@ -0,0 +1,22 @@
#include "lora_pin.h"
#include "esphome/core/log.h"
namespace esphome {
namespace lora {
static const char *const TAG = "lora.pin";
void LoraGPIOPin::setup() { pin_mode(flags_); }
void LoraGPIOPin::pin_mode(gpio::Flags flags) {
if (flags != gpio::FLAG_OUTPUT) {
ESP_LOGD(TAG, "Output only supported");
}
}
bool LoraGPIOPin::digital_read() { return false; }
void LoraGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
std::string LoraGPIOPin::dump_summary() const {
char buffer[32];
snprintf(buffer, sizeof(buffer), "%u via Lora", pin_);
return buffer;
}
} // namespace lora
} // namespace esphome

View file

@ -0,0 +1,33 @@
#pragma once
#include "esphome/core/component.h"
#include "./lora.h"
#include <cinttypes>
#include <vector>
namespace esphome {
namespace lora {
class LoraGPIOPin : public GPIOPin {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
std::string dump_summary() const override;
void set_parent(Lora *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags) { flags_ = flags; }
protected:
Lora *parent_;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
} // namespace lora
} // namespace esphome

View file

@ -1,71 +0,0 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import switch, uart
from esphome.const import CONF_DATA, CONF_SEND_EVERY
from esphome.core import HexInt
from .. import lora_ns
def validate_raw_data(value):
if isinstance(value, str):
return value.encode("utf-8")
if isinstance(value, str):
return value
if isinstance(value, list):
return cv.Schema([cv.hex_uint8_t])(value)
raise cv.Invalid(
"data must either be a string wrapped in quotes or a list of bytes"
)
DEPENDENCIES = ["uart"]
LoraSwitch = lora_ns.class_("LoraSwitch", switch.Switch, uart.UARTDevice, cg.Component)
CONF_TURN_OFF = "turn_off"
CONF_TURN_ON = "turn_on"
CONFIG_SCHEMA = (
switch.switch_schema(LoraSwitch, block_inverted=True)
.extend(
{
cv.Required(CONF_DATA): cv.Any(
validate_raw_data,
cv.Schema(
{
cv.Optional(CONF_TURN_OFF): validate_raw_data,
cv.Optional(CONF_TURN_ON): validate_raw_data,
}
),
),
cv.Optional(CONF_SEND_EVERY): cv.positive_time_period_milliseconds,
},
)
.extend(uart.UART_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
)
async def to_code(config):
var = await switch.new_switch(config)
await cg.register_component(var, config)
await uart.register_uart_device(var, config)
data = config[CONF_DATA]
if isinstance(data, dict):
if data_on := data.get(CONF_TURN_ON):
if isinstance(data_on, bytes):
data_on = [HexInt(x) for x in data_on]
cg.add(var.set_data_on(data_on))
if data_off := data.get(CONF_TURN_OFF):
if isinstance(data_off, bytes):
data_off = [HexInt(x) for x in data_off]
cg.add(var.set_data_off(data_off))
else:
data = config[CONF_DATA]
if isinstance(data, bytes):
data = [HexInt(x) for x in data]
cg.add(var.set_data_on(data))
cg.add(var.set_single_state(True))
if CONF_SEND_EVERY in config:
cg.add(var.set_send_every(config[CONF_SEND_EVERY]))

View file

@ -1,61 +0,0 @@
#include "lora_switch.h"
#include "esphome/core/log.h"
namespace esphome {
namespace lora {
static const char *const TAG = "lora.switch";
void LoraSwitch::loop() {
if (this->send_every_) {
const uint32_t now = millis();
if (now - this->last_transmission_ > this->send_every_) {
this->write_command_(this->state);
this->last_transmission_ = now;
}
}
}
void LoraSwitch::write_command_(bool state) {
if (state && !this->data_on_.empty()) {
ESP_LOGD(TAG, "'%s': Sending on data...", this->get_name().c_str());
this->write_array(this->data_on_.data(), this->data_on_.size());
}
if (!state && !this->data_off_.empty()) {
ESP_LOGD(TAG, "'%s': Sending off data...", this->get_name().c_str());
this->write_array(this->data_off_.data(), this->data_off_.size());
}
}
void LoraSwitch::write_state(bool state) {
if (!this->single_state_) {
this->publish_state(state);
this->write_command_(state);
this->last_transmission_ = millis();
return;
}
if (!state) {
this->publish_state(false);
return;
}
this->publish_state(true);
this->write_command_(true);
if (this->send_every_ == 0) {
this->publish_state(false);
} else {
this->last_transmission_ = millis();
}
}
void LoraSwitch::dump_config() {
LOG_SWITCH("", "UART Switch", this);
if (this->send_every_) {
ESP_LOGCONFIG(TAG, " Send Every: %" PRIu32, this->send_every_);
}
}
} // namespace lora
} // namespace esphome

View file

@ -1,35 +0,0 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/uart/uart.h"
#include "esphome/components/switch/switch.h"
#include <cinttypes>
#include <vector>
namespace esphome {
namespace lora {
class LoraSwitch : public switch_::Switch, public uart::UARTDevice, public Component {
public:
void loop() override;
void set_data_on(const std::vector<uint8_t> &data) { this->data_on_ = data; }
void set_data_off(const std::vector<uint8_t> &data) { this->data_off_ = data; }
void set_send_every(uint32_t send_every) { this->send_every_ = send_every; }
void set_single_state(bool single) { this->single_state_ = single; }
void dump_config() override;
protected:
void write_command_(bool state);
void write_state(bool state) override;
std::vector<uint8_t> data_on_;
std::vector<uint8_t> data_off_;
bool single_state_{false};
uint32_t send_every_;
uint32_t last_transmission_;
};
} // namespace lora
} // namespace esphome