Add support for wl-134 (#3569)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Marcel Hoppe 2022-10-19 02:44:26 +02:00 committed by GitHub
parent 06ac4980ba
commit 4ac72d7d08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 206 additions and 0 deletions

View file

@ -254,6 +254,7 @@ esphome/components/wake_on_lan/* @willwill2will54
esphome/components/web_server_base/* @OttoWinter esphome/components/web_server_base/* @OttoWinter
esphome/components/whirlpool/* @glmnet esphome/components/whirlpool/* @glmnet
esphome/components/whynter/* @aeonsablaze esphome/components/whynter/* @aeonsablaze
esphome/components/wl_134/* @hobbypunk90
esphome/components/xiaomi_lywsd03mmc/* @ahpohl esphome/components/xiaomi_lywsd03mmc/* @ahpohl
esphome/components/xiaomi_mhoc303/* @drug123 esphome/components/xiaomi_mhoc303/* @drug123
esphome/components/xiaomi_mhoc401/* @vevsvevs esphome/components/xiaomi_mhoc401/* @vevsvevs

View file

View file

@ -0,0 +1,31 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import text_sensor, uart
from esphome.const import (
ICON_FINGERPRINT,
)
CODEOWNERS = ["@hobbypunk90"]
DEPENDENCIES = ["uart"]
CONF_RESET = "reset"
wl134_ns = cg.esphome_ns.namespace("wl_134")
Wl134Component = wl134_ns.class_(
"Wl134Component", text_sensor.TextSensor, cg.Component, uart.UARTDevice
)
CONFIG_SCHEMA = (
text_sensor.text_sensor_schema(
Wl134Component,
icon=ICON_FINGERPRINT,
)
.extend({cv.Optional(CONF_RESET, default=False): cv.boolean})
.extend(uart.UART_DEVICE_SCHEMA)
)
async def to_code(config):
var = await text_sensor.new_text_sensor(config)
await cg.register_component(var, config)
cg.add(var.set_do_reset(config[CONF_RESET]))
await uart.register_uart_device(var, config)

View file

@ -0,0 +1,111 @@
#include "wl_134.h"
#include "esphome/core/log.h"
namespace esphome {
namespace wl_134 {
static const char *const TAG = "wl_134.sensor";
static const uint8_t ASCII_CR = 0x0D;
static const uint8_t ASCII_NBSP = 0xFF;
static const int MAX_DATA_LENGTH_BYTES = 6;
void Wl134Component::setup() { this->publish_state(""); }
void Wl134Component::loop() {
while (this->available() >= RFID134_PACKET_SIZE) {
Wl134Component::Rfid134Error error = this->read_packet_();
if (error != RFID134_ERROR_NONE) {
ESP_LOGW(TAG, "Error: %d", error);
}
}
}
Wl134Component::Rfid134Error Wl134Component::read_packet_() {
uint8_t packet[RFID134_PACKET_SIZE];
packet[RFID134_PACKET_START_CODE] = this->read();
// check for the first byte being the packet start code
if (packet[RFID134_PACKET_START_CODE] != 0x02) {
// just out of sync, ignore until we are synced up
return RFID134_ERROR_NONE;
}
if (!this->read_array(&(packet[RFID134_PACKET_ID]), RFID134_PACKET_SIZE - 1)) {
return RFID134_ERROR_PACKET_SIZE;
}
if (packet[RFID134_PACKET_END_CODE] != 0x03) {
return RFID134_ERROR_PACKET_END_CODE_MISSMATCH;
}
// calculate checksum
uint8_t checksum = 0;
for (uint8_t i = RFID134_PACKET_ID; i < RFID134_PACKET_CHECKSUM; i++) {
checksum = checksum ^ packet[i];
}
// test checksum
if (checksum != packet[RFID134_PACKET_CHECKSUM]) {
return RFID134_ERROR_PACKET_CHECKSUM;
}
if (static_cast<uint8_t>(~checksum) != static_cast<uint8_t>(packet[RFID134_PACKET_CHECKSUM_INVERT])) {
return RFID134_ERROR_PACKET_CHECKSUM_INVERT;
}
Rfid134Reading reading;
// convert packet into the reading struct
reading.id = this->hex_lsb_ascii_to_uint64_(&(packet[RFID134_PACKET_ID]), RFID134_PACKET_COUNTRY - RFID134_PACKET_ID);
reading.country = this->hex_lsb_ascii_to_uint64_(&(packet[RFID134_PACKET_COUNTRY]),
RFID134_PACKET_DATA_FLAG - RFID134_PACKET_COUNTRY);
reading.isData = packet[RFID134_PACKET_DATA_FLAG] == '1';
reading.isAnimal = packet[RFID134_PACKET_ANIMAL_FLAG] == '1';
reading.reserved0 = this->hex_lsb_ascii_to_uint64_(&(packet[RFID134_PACKET_RESERVED0]),
RFID134_PACKET_RESERVED1 - RFID134_PACKET_RESERVED0);
reading.reserved1 = this->hex_lsb_ascii_to_uint64_(&(packet[RFID134_PACKET_RESERVED1]),
RFID134_PACKET_CHECKSUM - RFID134_PACKET_RESERVED1);
ESP_LOGV(TAG, "Tag id: %012lld", reading.id);
ESP_LOGV(TAG, "Country: %03d", reading.country);
ESP_LOGV(TAG, "isData: %s", reading.isData ? "true" : "false");
ESP_LOGV(TAG, "isAnimal: %s", reading.isAnimal ? "true" : "false");
ESP_LOGV(TAG, "Reserved0: %d", reading.reserved0);
ESP_LOGV(TAG, "Reserved1: %d", reading.reserved1);
char buf[20];
sprintf(buf, "%03d%012lld", reading.country, reading.id);
this->publish_state(buf);
if (this->do_reset_) {
this->set_timeout(1000, [this]() { this->publish_state(""); });
}
return RFID134_ERROR_NONE;
}
uint64_t Wl134Component::hex_lsb_ascii_to_uint64_(const uint8_t *text, uint8_t text_size) {
uint64_t value = 0;
uint8_t i = text_size;
do {
i--;
uint8_t digit = text[i];
if (digit >= 'A') {
digit = digit - 'A' + 10;
} else {
digit = digit - '0';
}
value = (value << 4) + digit;
} while (i != 0);
return value;
}
void Wl134Component::dump_config() {
ESP_LOGCONFIG(TAG, "WL-134 Sensor:");
LOG_TEXT_SENSOR("", "Tag", this);
// As specified in the sensor's data sheet
this->check_uart_settings(9600, 1, esphome::uart::UART_CONFIG_PARITY_NONE, 8);
}
} // namespace wl_134
} // namespace esphome

View file

@ -0,0 +1,63 @@
#pragma once
#include <string>
#include "esphome/core/component.h"
#include "esphome/components/text_sensor/text_sensor.h"
#include "esphome/components/uart/uart.h"
namespace esphome {
namespace wl_134 {
class Wl134Component : public text_sensor::TextSensor, public Component, public uart::UARTDevice {
public:
enum Rfid134Error {
RFID134_ERROR_NONE,
// from library
RFID134_ERROR_PACKET_SIZE = 0x81,
RFID134_ERROR_PACKET_END_CODE_MISSMATCH,
RFID134_ERROR_PACKET_CHECKSUM,
RFID134_ERROR_PACKET_CHECKSUM_INVERT
};
struct Rfid134Reading {
uint16_t country;
uint64_t id;
bool isData;
bool isAnimal;
uint16_t reserved0;
uint32_t reserved1;
};
// Nothing really public.
// ========== INTERNAL METHODS ==========
void setup() override;
void loop() override;
void dump_config() override;
void set_do_reset(bool do_reset) { this->do_reset_ = do_reset; }
private:
enum DfMp3Packet {
RFID134_PACKET_START_CODE,
RFID134_PACKET_ID = 1,
RFID134_PACKET_COUNTRY = 11,
RFID134_PACKET_DATA_FLAG = 15,
RFID134_PACKET_ANIMAL_FLAG = 16,
RFID134_PACKET_RESERVED0 = 17,
RFID134_PACKET_RESERVED1 = 21,
RFID134_PACKET_CHECKSUM = 27,
RFID134_PACKET_CHECKSUM_INVERT = 28,
RFID134_PACKET_END_CODE = 29,
RFID134_PACKET_SIZE
};
bool do_reset_;
Rfid134Error read_packet_();
uint64_t hex_lsb_ascii_to_uint64_(const uint8_t *text, uint8_t text_size);
};
} // namespace wl_134
} // namespace esphome