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