mirror of
https://github.com/esphome/esphome.git
synced 2024-11-15 11:38:11 +01:00
WIP
This commit is contained in:
parent
9e4b7f954d
commit
4be0ac2d65
6 changed files with 172 additions and 81 deletions
5
esphome/.gitignore
vendored
Normal file
5
esphome/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Gitignore settings for ESPHome
|
||||
# This is an example and may include too much for your use-case.
|
||||
# You can modify this file to suit your needs.
|
||||
/.esphome/
|
||||
/secrets.yaml
|
|
@ -55,55 +55,46 @@ struct {
|
|||
} __attribute__((packed)) espnow_frame_format_t;
|
||||
#endif
|
||||
|
||||
ESPNowPacket::ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t app_id)
|
||||
: mac64(mac64), size(size), app_id(app_id), retrys(0) {
|
||||
if (this->mac64 == 0)
|
||||
this->mac64 = ESPNOW_BROADCAST_ADDR;
|
||||
this->is_broadcast = this->mac64 == ESPNOW_BROADCAST_ADDR;
|
||||
|
||||
this->ref_id = 0;
|
||||
|
||||
this->size = std::min(MAX_ESPNOW_DATA_SIZE, size);
|
||||
std::memcpy(&this->data, (uint8_t *) data, this->size);
|
||||
ESPNowPacket::ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) : ESPNowPacket() {
|
||||
if (this->peer() == {0})
|
||||
this->peer(ESPNOW_BROADCAST_ADDR);
|
||||
this->is_broadcast = memcpr(&this->peer(), &ESPNOW_BROADCAST_ADDR, 6);
|
||||
this->protocol(protocol);
|
||||
this->content_->get_data().std::memcpy(&this->data, (uint8_t *) data, this->size);
|
||||
|
||||
this->data[this->size + 1] = 0;
|
||||
this->recalc();
|
||||
this->info("create");
|
||||
}
|
||||
|
||||
inline void ESPNowPacket::info(std::string place) {
|
||||
void ESPNowPacket::info(std::string place) {
|
||||
ESP_LOGVV(TAG, "%s: M:%s A:0x%06x R:0x%02x C:0x%04x S:%02x", place.c_str(), this->to_str().c_str(), this->app_id,
|
||||
this->ref_id, this->random, this->size);
|
||||
}
|
||||
|
||||
bool ESPNowPacket::is_valid() {
|
||||
uint16_t crc = this->crc16;
|
||||
recalc();
|
||||
bool valid = (std::memcmp(&header, &TRANSPORT_HEADER, 3) == 0);
|
||||
valid &= (this->app_id != 0);
|
||||
valid &= (this->crc16 == crc);
|
||||
uint16_t crc = this->crc();
|
||||
this->calc_crc();
|
||||
bool valid = (std::memcmp(this->header(), &TRANSPORT_HEADER, 3) == 0);
|
||||
valid &= (this->protocol() != 0);
|
||||
valid &= (this->crc() == crc);
|
||||
if (!valid) {
|
||||
ESP_LOGV("Packet", "Invalid H:%02x%02x%02x A:%06x R:%02x C:%04x ipv. %04x, %d&%d&%d=%d\n", this->header[0],
|
||||
this->header[1], this->header[2], this->app_id, this->ref_id, crc, this->crc16,
|
||||
std::memcmp(&header, &TRANSPORT_HEADER, 3) == 0, (this->app_id != 0), (this->crc16 == crc), valid);
|
||||
ESP_LOGV("Packet", "Invalid H:%02x%02x%02x A:%06x R:%02x C:%04x ipv. %04x\n", this->header()[0], this->header()[1],
|
||||
this->header()[2], this->protocol(), this->packet_id(), crc, this->crc());
|
||||
}
|
||||
|
||||
this->crc16 = crc;
|
||||
this->crc(crc);
|
||||
return valid;
|
||||
}
|
||||
|
||||
void ESPNowProtocol::setup() { parent_->register_protocol(this); }
|
||||
|
||||
bool ESPNowProtocol::write(uint64_t mac_address, const uint8_t *data, uint8_t len) {
|
||||
ESPNowPacket packet(mac_address, data, len, this->get_app_id());
|
||||
ESPNowPacket packet(mac_address, data, len, this->get_protocol_id());
|
||||
return this->parent_->write(packet);
|
||||
}
|
||||
bool ESPNowProtocol::write(uint64_t mac_address, std::vector<uint8_t> &data) {
|
||||
ESPNowPacket packet(mac_address, (uint8_t *) data.data(), (uint8_t) data.size(), this->get_app_id());
|
||||
ESPNowPacket packet(mac_address, (uint8_t *) data.data(), (uint8_t) data.size(), this->get_protocol_id());
|
||||
return this->parent_->write(packet);
|
||||
}
|
||||
bool ESPNowProtocol::write(ESPNowPacket packet) {
|
||||
packet.app_id = this->get_app_id();
|
||||
packet.protocol(this->get_protocol_id());
|
||||
packet.ref_id = this->get_next_ref_id();
|
||||
packet.recalc();
|
||||
return this->parent_->write(packet);
|
||||
|
@ -239,7 +230,6 @@ esp_err_t ESPNowComponent::del_peer(uint64_t addr) {
|
|||
ESPNowDefaultProtocol *ESPNowComponent::get_default_protocol() {
|
||||
if (this->protocols_[ESPNOW_DEFAULT_APP_ID] == nullptr) {
|
||||
ESPNowDefaultProtocol *tmp = new ESPNowDefaultProtocol();
|
||||
this->protocols_[ESPNOW_DEFAULT_APP_ID] = tmp;
|
||||
this->register_protocol(tmp);
|
||||
}
|
||||
return (ESPNowDefaultProtocol *) this->protocols_[ESPNOW_DEFAULT_APP_ID];
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace espnow {
|
|||
|
||||
typedef uint8_t espnow_addr_t[6];
|
||||
|
||||
static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF;
|
||||
static const espnow_addr_t ESPNOW_BROADCAST_ADDR = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
static espnow_addr_t ESPNOW_ADDR_SELF = {0};
|
||||
|
||||
static const uint8_t ESPNOW_DATA_HEADER = 0x00;
|
||||
|
@ -62,70 +62,76 @@ class ESPNowPacket {
|
|||
public:
|
||||
ESPNowPacket() ESPHOME_ALWAYS_INLINE { this->content_.put_uint24(TRANSPORT_HEADER); }
|
||||
// Create packet to be send.
|
||||
ESPNowPacket(espnow_addr_t mac64, const uint8_t *data, uint8_t size, uint32_t app_id);
|
||||
ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size, uint32_t app_id);
|
||||
|
||||
// Load received packet's.
|
||||
ESPNowPacket(espnow_addr_t mac64, const uint8_t *data, uint8_t size);
|
||||
ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size);
|
||||
|
||||
void info(std::string place);
|
||||
inline void info(std::string place);
|
||||
|
||||
uint8_T *peer() { return this->peer_; }
|
||||
void peer(espnow_addr_t mac_addres) { std::memcpy(&this->peer_, &mac_addres, 6); }
|
||||
|
||||
uint8_T size() { return this->content_; }
|
||||
uint8_T size() {
|
||||
if (this->content_->get_used() <= 10) {
|
||||
return 0;
|
||||
}
|
||||
return this->content_->get_used();
|
||||
}
|
||||
}
|
||||
|
||||
bool broadcast(){return this->is_broadcast_};
|
||||
void broadcast(bool state) { this->is_broadcast_ = state; }
|
||||
void broadcast(bool state) { this->is_broadcast_ = state; }
|
||||
|
||||
uint32_t timestamp() { return this->timestamp_; };
|
||||
void timestamp(uint32_t timestamp) { this->timestamp_ = timestamp; };
|
||||
uint32_t timestamp() { return this->timestamp_; };
|
||||
void timestamp(uint32_t timestamp) { this->timestamp_ = timestamp; };
|
||||
|
||||
uint32_t protocol() {
|
||||
uint32_t protocol() {
|
||||
this->content_->set_position(ESPNOW_DATA_PROTOCOL);
|
||||
return this->content_->get_uint24();
|
||||
}
|
||||
void protocol(uint32_t protocol) {
|
||||
}
|
||||
void protocol(uint32_t protocol) {
|
||||
this->content_->set_position(ESPNOW_DATA_PROTOCOL);
|
||||
this->content_->put_uint24(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t packet_id() {
|
||||
uint8_t packet_id() {
|
||||
this->content_->set_position(ESPNOW_DATA_PACKET);
|
||||
return this->content_->get_uint8();
|
||||
}
|
||||
void packet_id(uint8_t packet_id) {
|
||||
}
|
||||
void packet_id(uint8_t packet_id) {
|
||||
this->content_->set_position(ESPNOW_DATA_PACKET);
|
||||
this->content_->put_uint8(packet_id);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t crc() {
|
||||
uint16_t crc() {
|
||||
this->content_->set_position(ESPNOW_DATA_CRC);
|
||||
return this->content_->get_uint16();
|
||||
}
|
||||
void crc(uint16_t crc) {
|
||||
}
|
||||
void crc(uint16_t crc) {
|
||||
this->content_->set_position(ESPNOW_DATA_CRC);
|
||||
this->content_->put_uint16(crc);
|
||||
}
|
||||
}
|
||||
|
||||
ByteBuffer *content() {
|
||||
ByteBuffer *content() {
|
||||
this->content_.set_position(ESPNOW_DATA_CONTENT + this->size_);
|
||||
return &this->content_;
|
||||
}
|
||||
}
|
||||
|
||||
void retry() {
|
||||
void retry() {
|
||||
if (this->retrys_ < 7) {
|
||||
this->retrys_ = this->retrys_ + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void calc_crc() {
|
||||
void calc_crc() {
|
||||
this->crc(0);
|
||||
this->crc(esp_crc16_le(this->packet(), this->dataptr(), 10 + size()));
|
||||
}
|
||||
}
|
||||
|
||||
bool is_valid();
|
||||
bool is_valid();
|
||||
|
||||
uint8_t *dataptr() { return this->content_->get_data()->data(); }
|
||||
uint8_t *dataptr() { return this->content_->get_data()->data(); }
|
||||
};
|
||||
|
||||
class ESPNowComponent;
|
||||
|
@ -136,13 +142,11 @@ class ESPNowProtocol : public Parented<ESPNowComponent> {
|
|||
public:
|
||||
ESPNowProtocol(){};
|
||||
|
||||
void setup();
|
||||
|
||||
virtual void on_receive(ESPNowPacket packet){};
|
||||
virtual void on_sent(ESPNowPacket packet, bool status){};
|
||||
virtual void on_new_peer(ESPNowPacket packet){};
|
||||
|
||||
virtual uint32_t get_app_id() = 0;
|
||||
virtual uint32_t get_protocol_id() = 0;
|
||||
uint8_t get_next_ref_id() { return next_ref_id_++; }
|
||||
|
||||
bool write(uint64_t mac_address, const uint8_t *data, uint8_t len);
|
||||
|
@ -159,7 +163,7 @@ class ESPNowDefaultProtocol : public ESPNowProtocol {
|
|||
void on_sent(ESPNowPacket packet, bool status) override { this->on_sent_.call(packet, status); };
|
||||
void on_new_peer(ESPNowPacket packet) override { this->on_new_peer_.call(packet); };
|
||||
|
||||
uint32_t get_app_id() override { return ESPNOW_DEFAULT_APP_ID; };
|
||||
uint32_t get_protocol_id() override { return ESPNOW_DEFAULT_APP_ID; };
|
||||
|
||||
void add_on_sent_callback(std::function<void(ESPNowPacket, bool status)> &&callback) {
|
||||
this->on_sent_.add(std::move(callback));
|
||||
|
@ -206,7 +210,7 @@ class ESPNowComponent : public Component {
|
|||
|
||||
void register_protocol(ESPNowProtocol *protocol) {
|
||||
protocol->set_parent(this);
|
||||
this->protocols_[protocol->get_app_id()] = protocol;
|
||||
this->protocols_[protocol->get_protocol_id()] = protocol;
|
||||
}
|
||||
|
||||
esp_err_t add_peer(uint64_t addr);
|
||||
|
|
|
@ -80,7 +80,9 @@ void ByteBuffer::flip() {
|
|||
/// Getters
|
||||
uint8_t ByteBuffer::get_uint8() {
|
||||
assert(this->get_remaining() >= 1);
|
||||
return this->data_[this->position_++];
|
||||
this->position_++;
|
||||
this->update_used_();
|
||||
return this->data_[this->position_];
|
||||
}
|
||||
uint64_t ByteBuffer::get_uint(size_t length) {
|
||||
assert(this->get_remaining() >= length);
|
||||
|
@ -98,6 +100,7 @@ uint64_t ByteBuffer::get_uint(size_t length) {
|
|||
value |= this->data_[this->position_++];
|
||||
}
|
||||
}
|
||||
this->update_used_();
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -126,13 +129,22 @@ std::vector<uint8_t> ByteBuffer::get_vector(size_t length) {
|
|||
assert(this->get_remaining() >= length);
|
||||
auto start = this->data_.begin() + this->position_;
|
||||
this->position_ += length;
|
||||
this->update_used_();
|
||||
return {start, start + length};
|
||||
}
|
||||
void ByteBuffer::get_data(const uint8_t *data, size_t length) {
|
||||
assert(this->get_remaining() >= length);
|
||||
auto start = this->data_.begin() + this->position_;
|
||||
copy(start, start + length, data);
|
||||
this->position_ += length;
|
||||
this->update_used_();
|
||||
}
|
||||
|
||||
/// Putters
|
||||
void ByteBuffer::put_uint8(uint8_t value) {
|
||||
assert(this->get_remaining() >= 1);
|
||||
this->data_[this->position_++] = value;
|
||||
this->update_used_();
|
||||
}
|
||||
|
||||
void ByteBuffer::put_uint(uint64_t value, size_t length) {
|
||||
|
@ -150,6 +162,7 @@ void ByteBuffer::put_uint(uint64_t value, size_t length) {
|
|||
value >>= 8;
|
||||
}
|
||||
}
|
||||
this->update_used_();
|
||||
}
|
||||
void ByteBuffer::put_float(float value) {
|
||||
static_assert(sizeof(float) == sizeof(uint32_t), "Float sizes other than 32 bit not supported");
|
||||
|
@ -169,5 +182,13 @@ void ByteBuffer::put_vector(const std::vector<uint8_t> &value) {
|
|||
assert(this->get_remaining() >= value.size());
|
||||
std::copy(value.begin(), value.end(), this->data_.begin() + this->position_);
|
||||
this->position_ += value.size();
|
||||
this->update_used_();
|
||||
}
|
||||
void ByteBuffer::put_array(const uint8_t *data, size_t size) {
|
||||
assert(this->get_remaining() >= size);
|
||||
std::copy(data[0], data[size], this->data_.begin() + this->position_);
|
||||
this->position_ += size;
|
||||
this->update_used_();
|
||||
}
|
||||
|
||||
} // namespace esphome
|
||||
|
|
|
@ -92,6 +92,7 @@ class ByteBuffer {
|
|||
bool get_bool() { return this->get_uint8(); }
|
||||
// Get vector of bytes, increment by length
|
||||
std::vector<uint8_t> get_vector(size_t length);
|
||||
void get_data(const uint8_t *data, size_t length);
|
||||
|
||||
// Put values into the buffer, increment the position accordingly
|
||||
// put any integral value, length represents the number of bytes
|
||||
|
@ -112,11 +113,13 @@ class ByteBuffer {
|
|||
void put_double(double value);
|
||||
void put_bool(bool value) { this->put_uint8(value); }
|
||||
void put_vector(const std::vector<uint8_t> &value);
|
||||
void put_array(const uint8_t *data, size_t size);
|
||||
|
||||
inline size_t get_capacity() const { return this->data_.size(); }
|
||||
inline size_t get_position() const { return this->position_; }
|
||||
inline size_t get_limit() const { return this->limit_; }
|
||||
inline size_t get_remaining() const { return this->get_limit() - this->get_position(); }
|
||||
inline size_t get_used() const { return this->used_; }
|
||||
inline Endian get_endianness() const { return this->endianness_; }
|
||||
inline void mark() { this->mark_ = this->position_; }
|
||||
inline void big_endian() { this->endianness_ = BIG; }
|
||||
|
@ -131,14 +134,21 @@ class ByteBuffer {
|
|||
std::vector<uint8_t> get_data() { return this->data_; };
|
||||
void rewind() { this->position_ = 0; }
|
||||
void reset() { this->position_ = this->mark_; }
|
||||
void resize() { this->used_ = this->position_; }
|
||||
|
||||
protected:
|
||||
ByteBuffer(std::vector<uint8_t> const &data) : data_(data), limit_(data.size()) {}
|
||||
void update_used_() {
|
||||
if (this->used_ < this->position_) {
|
||||
this->resize();
|
||||
}
|
||||
}
|
||||
std::vector<uint8_t> data_;
|
||||
Endian endianness_{LITTLE};
|
||||
size_t position_{0};
|
||||
size_t mark_{0};
|
||||
size_t limit_{0};
|
||||
size_t used_{0};
|
||||
};
|
||||
|
||||
} // namespace esphome
|
||||
|
|
61
esphome/test.yaml
Normal file
61
esphome/test.yaml
Normal file
|
@ -0,0 +1,61 @@
|
|||
# These substitutions allow the end user to override certain values
|
||||
substitutions:
|
||||
name: "lum-iot-test"
|
||||
friendly_name: "Project Template"
|
||||
|
||||
#xternal_components:
|
||||
# - source: github://pr#7141
|
||||
# components: [ espnow ]
|
||||
# refresh: 1 sec
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
wifi:
|
||||
|
||||
esphome:
|
||||
name: "${name}"
|
||||
# Friendly names are used where appropriate in Home Assistant
|
||||
friendly_name: "${friendly_name}"
|
||||
# Automatically add the mac address to the name
|
||||
# so you can use a single firmware for all devices
|
||||
name_add_mac_suffix: false
|
||||
|
||||
# This will allow for (future) project identification,
|
||||
# configuration and updates.
|
||||
project:
|
||||
name: esphome.project-template
|
||||
version: "1.0"
|
||||
|
||||
# To be able to get logs from the device via serial and api.
|
||||
logger:
|
||||
|
||||
# API is a requirement of the dashboard import.
|
||||
api:
|
||||
|
||||
# OTA is required for Over-the-Air updating
|
||||
ota:
|
||||
platform: esphome
|
||||
|
||||
# Sets up Bluetooth LE (Only on ESP32) to allow the user
|
||||
# to provision wifi credentials to the device.
|
||||
esp32_improv:
|
||||
authorizer: none
|
||||
|
||||
espnow:
|
||||
auto_add_peer: true
|
||||
peers:
|
||||
- FF:FF:FF:FF:FF:FF
|
||||
on_receive:
|
||||
- logger.log:
|
||||
format: "Received: %s RSSI: %d"
|
||||
args: [it->data().data(), it->rssi()]
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin: GPIO39
|
||||
name: Button
|
||||
on_click:
|
||||
- espnow.send: "hallo everyone"
|
Loading…
Reference in a new issue