#include #include #include #include #include #include "cc1101.h" #include "hcs200.h" void http_door_open(); void serial_door_open(); ESP8266WebServer http_service(80); CC1101 radio(D0 /* GDO0 */, D2 /* GDO2 */, D8 /* SS */); #define PIN_HCS200_ENABLE D3 #define PIN_HCS200_DATA D1 //#define HCS200_TEST HCS200 hcs200; const int ping_delay = 60000; long ping_last = 0; ping_option ping_opt; void setup() { Serial.begin(9600); pinMode(PIN_HCS200_ENABLE, OUTPUT); digitalWrite(PIN_HCS200_ENABLE, LOW); pinMode(PIN_HCS200_DATA, INPUT); if (!radio.setup()) Serial.println("Radio not found!"); else if (!radio.setISM(CC1101::FREQ_434MHZ)) Serial.println("Unable to set radio frequency"); else { Serial.println("Radio found"); (void)radio.idle(); } WiFiManager wifiManager; wifiManager.setConfigPortalTimeout(600); Serial.printf_P(PSTR("Setting up WiFi\n")); WiFi.hostname("door"); if (!wifiManager.autoConnect("a-door-able")) { Serial.printf_P(PSTR("Failed to connect and hit timeout\n")); delay(5000); ESP.restart(); } if (!MDNS.begin("door")) Serial.println("Error setting up MDNS responder!"); MDNS.addService("http", "tcp", 80); http_service.on("/", HTTP_GET, []() { http_service.send_P(200, PSTR("text/plain"), PSTR("I'm a-door-able")); }); http_service.on("/door/open", HTTP_PUT, http_door_open); http_service.on("/door/close", HTTP_GET, []() { http_service.send_P(200, PSTR("text/plain"), PSTR("OK")); }); http_service.on("/door/status", HTTP_GET, []() { http_service.send_P(200, PSTR("text/plain"), PSTR("CLOSED")); }); http_service.begin(); memset(&ping_opt, 0, sizeof(struct ping_option)); ping_opt.count = 1; ping_opt.ip = WiFi.localIP(); Serial.println("Started listening"); } void ICACHE_RAM_ATTR on_hcs200_isr() { hcs200.on_isr(digitalRead(PIN_HCS200_DATA) == HIGH); } bool hcs200_get_keycode(HCS200_Keycode &keycode) { #if !defined(HCS200_TEST) hcs200.reset(); attachInterrupt(digitalPinToInterrupt(PIN_HCS200_DATA), on_hcs200_isr, CHANGE); digitalWrite(PIN_HCS200_ENABLE, HIGH); uint8_t maxloop = 255; while(--maxloop) { if (hcs200.decode(keycode)) break; delay(1); yield(); } digitalWrite(PIN_HCS200_ENABLE, LOW); detachInterrupt(digitalPinToInterrupt(PIN_HCS200_DATA)); return (maxloop != 0); #else keycode.encrypted = 0xDEAD; keycode.serial = 0xC0DE; keycode.buttons = HCS200_Keycode::BM_S0; keycode.lowbat = false; return true; #endif } void http_door_open() { if (!radio.register_check()) { http_service.send_P(500, PSTR("text/plain"), PSTR("Radio error")); return; } HCS200_Keycode keycode; if (!hcs200_get_keycode(keycode)) { http_service.send_P(500, PSTR("text/plain"), PSTR("No data from HCS200")); return; } keycode.lowbat = false; Serial.print("Got keycode: "); keycode.print(Serial); if (http_service.hasArg("power")) { static const uint8_t patable_power_n30[8] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t patable_power_n20[8] = { 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t patable_power_n15[8] = { 0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t patable_power_n10[8] = { 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t patable_power_0[8] = { 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t patable_power_5[8] = { 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t patable_power_7[8] = { 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t patable_power_10[8] = { 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int power = http_service.arg("power").toInt(); if (power == -30) radio.setPatable(patable_power_n30); else if (power == -20) radio.setPatable(patable_power_n20); else if (power == -15) radio.setPatable(patable_power_n15); else if (power == -10) radio.setPatable(patable_power_n10); else if (power == 0) radio.setPatable(patable_power_0); else if (power == 5) radio.setPatable(patable_power_5); else if (power == 7) radio.setPatable(patable_power_7); else if (power == 10) radio.setPatable(patable_power_10); else { http_service.send_P(500, PSTR("text/plain"), PSTR("Unsupported power level")); return; } } if (!radio.transmit()) { http_service.send_P(500, PSTR("text/plain"), PSTR("Unable to enable radio transmit mode")); return; } if (http_service.hasArg("button1")) keycode.buttons = HCS200_Keycode::BM_S0; else if (http_service.hasArg("button2")) keycode.buttons = HCS200_Keycode::BM_S1; else if (http_service.hasArg("button3")) keycode.buttons = HCS200_Keycode::BM_S2; else if (http_service.hasArg("button4")) keycode.buttons = HCS200_Keycode::BM_S3; unsigned long count = constrain(http_service.arg("count").toInt(), 2, 400); for (unsigned int i = 0; i < count; i++) { keycode.send([&](int value) { radio.setGDO0(value); }); yield(); } (void)radio.idle(); Serial.println("Sending done"); http_service.send_P(200, PSTR("text/plain"), PSTR("OK")); } void serial_door_open(Print &stream) { if (!radio.register_check()) { stream.println("Radio error"); return; } HCS200_Keycode keycode; bool key_valid = hcs200_get_keycode(keycode); if (!key_valid) stream.println("No data from HCS200"); stream.print("HCS200 decoder state: "); hcs200.print_state(stream); if (!key_valid) return; stream.print("Got keycode: "); keycode.print(stream); if (!radio.transmit()) { stream.println("Unable to enable radio transmit mode"); return; } /* send twice */ keycode.send([&](int value) { radio.setGDO0(value); }); keycode.send([&](int value) { radio.setGDO0(value); }); (void)radio.idle(); stream.println("Sending done"); } void loop() { MDNS.update(); http_service.handleClient(); if (millis() - ping_last > ping_delay) { ping_start(&ping_opt); ping_last = millis(); } if (Serial.available() > 0) { while (Serial.read() >= 0) {} //serial_door_open(Serial); } delay(1); }