Learning Lab

A NodeMCU panic button with Telegram alerts and RF fallback — circuit, code, lessons

Posted 28 Apr 2026 Read ~14 min Tags electronics, esp8266, telegram Reply by email

I wanted a single tactile button that, when pressed, delivers a short message to a small group of people on Telegram — and keeps working when the office Wi-Fi quietly stops working, which it does. What follows is the build I settled on after three weekends of false starts.

Why bother

A friend asked. The counter at her clinic gets the occasional aggressive visitor, and the existing “solution” was “shout for help.” I’ve had a tray of NodeMCUs1 gathering dust since 2022, so this seemed like a useful excuse to use them.

note 1 — what’s a NodeMCU
ESP8266-based dev boards. Built-in Wi-Fi, a handful of GPIO, run on USB power. About ₹220 each in bulk.

The circuit

Two boards, talking by radio, with one on Wi-Fi as the primary path. Receiver lives near the back-office router; transmitter sits under the counter on its own 5V adapter.

Component list, for the curious or for future-me when I rebuild this on a Sunday and can’t remember which radio module worked:

Bill of materials, per unit
Part Notes Cost (₹)
NodeMCU v3 (ESP8266)Either CH340 or CP2102 driver works220
FS1000A 433 MHz pairCheap, lo-fi, surprisingly enough range with a 17 cm wire antenna90
12 mm tactile buttonRecess-mounted; pull-up on D235
5V/1A USB adaptor + cableOne per board160
Hammond-style enclosureMatte black; the button should look intentional240
Total per unit~745

The firmware

The transmitter does almost nothing on purpose. Debounce the button, fire the radio, fire Wi-Fi, sleep. The hardest part of writing this was resisting the urge to add features.2

Arduino · C++
// transmitter.ino — keep this file boring on purpose.

#include <ESP8266WiFi.h>
#include <RCSwitch.h>
#include "secrets.h"   // SSID, PSK, BOT_TOKEN, CHAT_ID

constexpr uint8_t PIN_BTN = D2;
constexpr uint8_t PIN_RF  = D5;
constexpr uint32_t RF_CODE = 0xA17C0DE;

RCSwitch rf;

void setup() {
  pinMode(PIN_BTN, INPUT_PULLUP);
  rf.enableTransmit(PIN_RF);
  rf.setRepeatTransmit(15);
  WiFi.begin(WIFI_SSID, WIFI_PSK);
}

void loop() {
  if (digitalRead(PIN_BTN) == LOW) {
    rf.send(RF_CODE, 32);            // fallback first
    notifyTelegram("PANIC at counter"); // then primary
    delay(2500);                       // crude debounce
  }
}

On the receiver, the only addition is that an RF packet with the matching code triggers the same Telegram path, which means a Wi-Fi outage on the transmitter side still gets a message out, as long as the receiver itself can reach the router.3

The hardest part of writing reliable hardware code is admitting that most of the failures are not interesting. They are wires, solder joints, and adapters from a market two years ago.

Lessons

Lesson 1 Range estimates on AliExpress are creative writing. The FS1000A claims 100 m line-of-sight. In a building with rebar in the walls, expect 25.
Lesson 2 Telegram’s Bot API is about as boring and reliable as an HTTP API gets, and that is exactly what you want here.
Caution If you put one of these on the production network, please give it its own VLAN. The ESP8266 stack has had enough CVEs over the years that I would not put it next to anything I cared about.

I will probably rebuild the receiver on an ESP32 the next time I touch it — not because the ESP8266 is bad, but because the ESP32 has dual-core scheduling that lets the radio task and the Wi-Fi task stop fighting each other for the radio bus. That fight is invisible until it isn’t.

Originally published at notebook · Prashant, Mohali Punjab, IN