Advertisement
Guest User

Untitled

a guest
Jan 27th, 2020
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.97 KB | None | 0 0
  1. esphome:
  2. name: node_keypad_garage_front
  3. platform: ESP32
  4. board: nodemcu-32s
  5. includes:
  6. - wiegand_device.h
  7.  
  8. wifi:
  9. ssid: !secret ssid
  10. password: !secret psw
  11. ap:
  12. ssid: "Node Em P2 X Fallback Hotspot"
  13. password: !secret psw
  14.  
  15. captive_portal:
  16. logger:
  17. api:
  18. ota:
  19.  
  20.  
  21. text_sensor:
  22. - platform: custom
  23. lambda: |-
  24. auto wiegand = new WiegandReader(36, 37, "");
  25. App.register_component(wiegand);
  26. return {wiegand};
  27.  
  28. text_sensors:
  29. name: "wiegand"
  30.  
  31.  
  32.  
  33.  
  34. #include "esphome.h"
  35.  
  36. /**
  37. * Wiegand Reader Custom Device
  38. *
  39. * Copied from https://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino
  40. * Implemented by Greg Doerr (https://github.com/gdoerr)
  41. *
  42. * In my example, hooked to an Olimex ESP32-POE device connected to a Retekess H1EM-W
  43. * Wiegand keypad. This device calls a service on Home Assistant when a code is available
  44. *
  45. * Samples key presses every 200ms and stores the key in a string until:
  46. * [1] - the user presses a '#' which sends the code immediately
  47. * [2] - the user presses nothing for 2,000ms (inter-digit timer) which then sends the code
  48. * [3] - the user presses a '*' which sends the '*' immediately
  49. */
  50. class WiegandReader : public PollingComponent, public TextSensor {
  51.  
  52. public:
  53. WiegandReader(int pinD0, int pinD1, std::string serviceName)
  54. : PollingComponent(200),
  55. pinD0(pinD0), pinD1(pinD1),
  56. serviceName(serviceName) {
  57. }
  58.  
  59. /**
  60. * Initial setup
  61. */
  62. void setup() override {
  63. _lastWiegand = 0;
  64. _cardTempHigh = 0;
  65. _cardTemp = 0;
  66. _code = 0;
  67. _wiegandType = 0;
  68. _bitCount = 0;
  69.  
  70. // Configure the input pins
  71. pinMode(pinD0, INPUT);
  72. pinMode(pinD1, INPUT);
  73.  
  74. // Attach the interrupts
  75. attachInterrupt(digitalPinToInterrupt(pinD0), ReadD0, FALLING); // Hardware interrupt - high to low pulse
  76. attachInterrupt(digitalPinToInterrupt(pinD1), ReadD1, FALLING); // Hardware interrupt - high to low pulse
  77. }
  78.  
  79. void update() override {
  80. // See if we have a valid code
  81. noInterrupts();
  82. bool rc = DoWiegandConversion();
  83. interrupts();
  84.  
  85. if(rc) {
  86. if(_code < 10) {
  87. // We have a digit, make it ASCII for convenience
  88. keyCodes += (_code + 0x30);
  89. } else if(_code == 11) {
  90. // The user pressed '#', send the accumulated code and reset for the next string
  91. callHAService(keyCodes);
  92. keyCodes = "";
  93. } else if(_code == 10) {
  94. // The user pressed '*', clear the code and send the asterisk
  95. callHAService("*");
  96. keyCodes = "";
  97. }
  98. // Capture the last time we received a code
  99. lastCode = millis();
  100. } else {
  101. if(keyCodes.length() > 0) {
  102. // We have a keyCode, see if the interdigit timer expired
  103. if(millis() - lastCode > 2000) {
  104. // The interdigit timer expired, send the code and reset for the next string
  105. callHAService(keyCodes);
  106. keyCodes = "";
  107. }
  108. }
  109. }
  110. }
  111.  
  112. private:
  113. static volatile unsigned long _cardTempHigh;
  114. static volatile unsigned long _cardTemp;
  115. static volatile unsigned long _lastWiegand;
  116. static volatile int _bitCount;
  117. static int _wiegandType;
  118. static unsigned long _code;
  119.  
  120. unsigned long lastCode = 0;
  121. std::string keyCodes = "";
  122.  
  123. int pinD0;
  124. int pinD1;
  125. std::string serviceName;
  126.  
  127. /**
  128. * Calls a Home Assistant service with the key code
  129. * @param keyCode
  130. */
  131. void callHAService(std::string keyCode) {
  132. publish_state(keyCode);
  133. }
  134.  
  135. /**
  136. * D0 Interrupt Handler
  137. */
  138. static void ReadD0() {
  139. _bitCount++; // Increment bit count for Interrupt connected to D0
  140. if(_bitCount > 31) { // If bit count more than 31, process high bits
  141. _cardTempHigh |= ((0x80000000 & _cardTemp)>>31); // shift value to high bits
  142. _cardTempHigh <<= 1;
  143. _cardTemp <<=1;
  144. } else
  145. _cardTemp <<= 1; // D0 represent binary 0, so just left shift card data
  146.  
  147. _lastWiegand = millis(); // Keep track of last wiegand bit received
  148. }
  149.  
  150. /**
  151. * D1 Interrupt Handler
  152. */
  153. static void ReadD1() {
  154. _bitCount ++; // Increment bit count for Interrupt connected to D1
  155.  
  156. if(_bitCount > 31) { // If bit count more than 31, process high bits
  157. _cardTempHigh |= ((0x80000000 & _cardTemp)>>31); // shift value to high bits
  158. _cardTempHigh <<= 1;
  159. _cardTemp |= 1;
  160. _cardTemp <<=1;
  161. } else {
  162. _cardTemp |= 1; // D1 represent binary 1, so OR card data with 1 then
  163. _cardTemp <<= 1; // left shift card data
  164. }
  165. _lastWiegand = millis(); // Keep track of last wiegand bit received
  166. }
  167.  
  168. /**
  169. * Extract the Card ID from the received bit stream
  170. * @param codehigh
  171. * @param codelow
  172. * @param bitlength
  173. * @return
  174. */
  175. unsigned long getCardId(volatile unsigned long *codehigh, volatile unsigned long *codelow, char bitlength) {
  176. if (bitlength==26) // EM tag
  177. return (*codelow & 0x1FFFFFE) >>1;
  178.  
  179. if (bitlength==34) // Mifare
  180. {
  181. *codehigh = *codehigh & 0x03; // only need the 2 LSB of the codehigh
  182. *codehigh <<= 30; // shift 2 LSB to MSB
  183. *codelow >>=1;
  184. return *codehigh | *codelow;
  185. }
  186. return *codelow; // EM tag or Mifare without parity bits
  187. }
  188.  
  189. /**
  190. * Convert the received bitstream
  191. * @return
  192. */
  193. bool DoWiegandConversion () {
  194. unsigned long cardID;
  195. unsigned long sysTick = millis();
  196.  
  197. if ((sysTick - _lastWiegand) > 25) // if no more signal coming through after 25ms
  198. {
  199. if ((_bitCount==24) || (_bitCount==26) || (_bitCount==32) || (_bitCount==34) || (_bitCount==8) || (_bitCount==4)) { // bitCount for keypress=4 or 8, Wiegand 26=24 or 26, Wiegand 34=32 or 34
  200. _cardTemp >>= 1; // shift right 1 bit to get back the real value - interrupt done 1 left shift in advance
  201. if (_bitCount>32) // bit count more than 32 bits, shift high bits right to make adjustment
  202. _cardTempHigh >>= 1;
  203.  
  204. if (_bitCount==8) { // keypress wiegand with integrity
  205. // 8-bit Wiegand keyboard data, high nibble is the "NOT" of low nibble
  206. // eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001
  207. char highNibble = (_cardTemp & 0xf0) >>4;
  208. char lowNibble = (_cardTemp & 0x0f);
  209. _wiegandType=_bitCount;
  210. _bitCount=0;
  211. _cardTemp=0;
  212. _cardTempHigh=0;
  213.  
  214. if (lowNibble == (~highNibble & 0x0f)) { // check if low nibble matches the "NOT" of high nibble.
  215. _code = (int)lowNibble;
  216. return true;
  217. } else {
  218. _lastWiegand=sysTick;
  219. _bitCount=0;
  220. _cardTemp=0;
  221. _cardTempHigh=0;
  222. return false;
  223. }
  224.  
  225. // TODO: Handle validation failure case!
  226. } else if (4 == _bitCount) {
  227. // 4-bit Wiegand codes have no data integrity check so we just
  228. // read the LOW nibble.
  229. _code = (int)(_cardTemp & 0x0000000F);
  230.  
  231. _wiegandType = _bitCount;
  232. _bitCount = 0;
  233. _cardTemp = 0;
  234. _cardTempHigh = 0;
  235.  
  236. return true;
  237. } else { // wiegand 26 or wiegand 34
  238. cardID = getCardId (&_cardTempHigh, &_cardTemp, _bitCount);
  239. _wiegandType=_bitCount;
  240. _bitCount=0;
  241. _cardTemp=0;
  242. _cardTempHigh=0;
  243. _code=cardID;
  244. return true;
  245. }
  246. } else {
  247. // well time over 25 ms and bitCount !=8 , !=26, !=34 , must be noise or nothing then.
  248. _lastWiegand=sysTick;
  249. _bitCount=0;
  250. _cardTemp=0;
  251. _cardTempHigh=0;
  252. return false;
  253. }
  254. } else
  255. return false;
  256. }
  257. };
  258.  
  259. volatile unsigned long WiegandReader::_cardTempHigh = 0;
  260. volatile unsigned long WiegandReader::_cardTemp = 0;
  261. volatile unsigned long WiegandReader::_lastWiegand = 0;
  262. volatile int WiegandReader::_bitCount = 0;
  263. unsigned long WiegandReader::_code = 0;
  264. int WiegandReader::_wiegandType = 0;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement