ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
wiegand.cpp
Go to the documentation of this file.
1#include "wiegand.h"
2#include <cinttypes>
4#include "esphome/core/log.h"
5
6namespace esphome {
7namespace wiegand {
8
9static const char *const TAG = "wiegand";
10static const char *const KEYS = "0123456789*#";
11
12void IRAM_ATTR HOT WiegandStore::d0_gpio_intr(WiegandStore *arg) {
13 if (arg->d0.digital_read())
14 return;
15 arg->count++; // NOLINT(clang-diagnostic-deprecated-volatile)
16 arg->value <<= 1;
17 arg->last_bit_time = millis();
18 arg->done = false;
19}
20
21void IRAM_ATTR HOT WiegandStore::d1_gpio_intr(WiegandStore *arg) {
22 if (arg->d1.digital_read())
23 return;
24 arg->count++; // NOLINT(clang-diagnostic-deprecated-volatile)
25 arg->value = (arg->value << 1) | 1;
26 arg->last_bit_time = millis();
27 arg->done = false;
28}
29
38
39bool check_eparity(uint64_t value, int start, int length) {
40 int parity = 0;
41 uint64_t mask = 1LL << start;
42 for (int i = 0; i < length; i++, mask <<= 1) {
43 if (value & mask)
44 parity++;
45 }
46 return !(parity & 1);
47}
48
49bool check_oparity(uint64_t value, int start, int length) {
50 int parity = 0;
51 uint64_t mask = 1LL << start;
52 for (int i = 0; i < length; i++, mask <<= 1) {
53 if (value & mask)
54 parity++;
55 }
56 return parity & 1;
57}
58
60 if (this->store_.done)
61 return;
62 if (millis() - this->store_.last_bit_time < 100)
63 return;
64 uint8_t count = this->store_.count;
65 uint64_t value = this->store_.value;
66 this->store_.count = 0;
67 this->store_.value = 0;
68 this->store_.done = true;
69 ESP_LOGV(TAG, "received %d-bit value: %llx", count, value);
70 for (auto *trigger : this->raw_triggers_)
71 trigger->trigger(count, value);
72 if (count == 26) {
73 char tag_buf[12]; // max 8 digits for 24-bit value + null
74 buf_append_printf(tag_buf, sizeof(tag_buf), 0, "%" PRIu32, static_cast<uint32_t>((value >> 1) & 0xffffff));
75 ESP_LOGD(TAG, "received 26-bit tag: %s", tag_buf);
76 if (!check_eparity(value, 13, 13) || !check_oparity(value, 0, 13)) {
77 ESP_LOGW(TAG, "invalid parity");
78 return;
79 }
80 for (auto *trigger : this->tag_triggers_)
81 trigger->trigger(tag_buf);
82 } else if (count == 34) {
83 char tag_buf[12]; // max 10 digits for 32-bit value + null
84 buf_append_printf(tag_buf, sizeof(tag_buf), 0, "%" PRIu32, static_cast<uint32_t>((value >> 1) & 0xffffffff));
85 ESP_LOGD(TAG, "received 34-bit tag: %s", tag_buf);
86 if (!check_eparity(value, 17, 17) || !check_oparity(value, 0, 17)) {
87 ESP_LOGW(TAG, "invalid parity");
88 return;
89 }
90 for (auto *trigger : this->tag_triggers_)
91 trigger->trigger(tag_buf);
92 } else if (count == 37) {
93 char tag_buf[12]; // max 11 digits for 35-bit value + null
94 buf_append_printf(tag_buf, sizeof(tag_buf), 0, "%" PRIu64, static_cast<uint64_t>((value >> 1) & 0x7ffffffff));
95 ESP_LOGD(TAG, "received 37-bit tag: %s", tag_buf);
96 if (!check_eparity(value, 18, 19) || !check_oparity(value, 0, 19)) {
97 ESP_LOGW(TAG, "invalid parity");
98 return;
99 }
100 for (auto *trigger : this->tag_triggers_)
101 trigger->trigger(tag_buf);
102 } else if (count == 4) {
103 for (auto *trigger : this->key_triggers_)
104 trigger->trigger(value);
105 if (value < 12) {
106 uint8_t key = KEYS[value];
107 this->send_key_(key);
108 }
109 } else if (count == 8) {
110 if ((value ^ 0xf0) >> 4 == (value & 0xf)) {
111 value &= 0xf;
112 for (auto *trigger : this->key_triggers_)
113 trigger->trigger(value);
114 if (value < 12) {
115 uint8_t key = KEYS[value];
116 this->send_key_(key);
117 }
118 }
119 } else {
120 ESP_LOGD(TAG, "received unknown %d-bit value: %llx", count, value);
121 }
122}
123
125 ESP_LOGCONFIG(TAG, "Wiegand reader:");
126 LOG_PIN(" D0 pin: ", this->d0_pin_);
127 LOG_PIN(" D1 pin: ", this->d1_pin_);
128}
129
130} // namespace wiegand
131} // namespace esphome
virtual void setup()=0
void attach_interrupt(void(*func)(T *), T *arg, gpio::InterruptType type) const
Definition gpio.h:107
virtual ISRInternalGPIOPin to_isr() const =0
InternalGPIOPin * d1_pin_
Definition wiegand.h:46
void loop() override
Definition wiegand.cpp:59
void dump_config() override
Definition wiegand.cpp:124
std::vector< WiegandKeyTrigger * > key_triggers_
Definition wiegand.h:50
InternalGPIOPin * d0_pin_
Definition wiegand.h:45
void setup() override
Definition wiegand.cpp:30
std::vector< WiegandTagTrigger * > tag_triggers_
Definition wiegand.h:48
std::vector< WiegandRawTrigger * > raw_triggers_
Definition wiegand.h:49
WiegandStore store_
Definition wiegand.h:47
@ INTERRUPT_FALLING_EDGE
Definition gpio.h:51
bool check_eparity(uint64_t value, int start, int length)
Definition wiegand.cpp:39
bool check_oparity(uint64_t value, int start, int length)
Definition wiegand.cpp:49
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:25
ISRInternalGPIOPin d0
Definition wiegand.h:14
static void d0_gpio_intr(WiegandStore *arg)
Definition wiegand.cpp:12
static void d1_gpio_intr(WiegandStore *arg)
Definition wiegand.cpp:21
ISRInternalGPIOPin d1
Definition wiegand.h:15
volatile uint64_t value
Definition wiegand.h:16
volatile uint8_t count
Definition wiegand.h:19
volatile uint32_t last_bit_time
Definition wiegand.h:17
uint16_t length
Definition tt21100.cpp:0