mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add support for wl-134 (#3569)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -254,6 +254,7 @@ esphome/components/wake_on_lan/* @willwill2will54 | ||||
| esphome/components/web_server_base/* @OttoWinter | ||||
| esphome/components/whirlpool/* @glmnet | ||||
| esphome/components/whynter/* @aeonsablaze | ||||
| esphome/components/wl_134/* @hobbypunk90 | ||||
| esphome/components/xiaomi_lywsd03mmc/* @ahpohl | ||||
| esphome/components/xiaomi_mhoc303/* @drug123 | ||||
| esphome/components/xiaomi_mhoc401/* @vevsvevs | ||||
|   | ||||
							
								
								
									
										0
									
								
								esphome/components/wl_134/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/wl_134/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										31
									
								
								esphome/components/wl_134/text_sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								esphome/components/wl_134/text_sensor.py
									
									
									
									
									
										Normal 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) | ||||
							
								
								
									
										111
									
								
								esphome/components/wl_134/wl_134.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								esphome/components/wl_134/wl_134.cpp
									
									
									
									
									
										Normal 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 | ||||
							
								
								
									
										63
									
								
								esphome/components/wl_134/wl_134.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								esphome/components/wl_134/wl_134.h
									
									
									
									
									
										Normal 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 | ||||
		Reference in New Issue
	
	Block a user