Breadboard
docs
Example project · ESP32

Zigbee door sensor + smart button

A door/window sensor as a sealed product: the C6 inside runs esp-zigbee IAS-zone firmware, and the smart-button puck (the coordinator) forms the network it joins. The DIP switch across the contact terminals plays the door — flip it and the sensor reports a genuine zone-status change over the air (watch its serial tab and the 📡 Sniffer). Click the sensor for its live join + contact state.

The Zigbee door sensor + smart button circuit as rendered by the simulator

How it works

A wired door sensor is just a contact and a radio — and that’s exactly what this is. The sealed C6 inside runs esp-zigbee IAS-zone contact firmware: its GPIO4 input (with the internal pull-up) reads the two contact terminals, and the smart-button puck is the coordinator whose network it joins. The DIP switch across the terminals plays the door: closed = terminals shorted = contact made. Every change calls setClosed()/setOpen() in the firmware, which reports a genuine IAS zone-status change over the air.

What's on the bench

  • Battery
  • DIP Switch
  • Zigbee Contact Sensor
  • Zigbee Smart Button

How it's wired

  • Battery · posZigbee Smart Button · vcc
  • Battery · negZigbee Smart Button · gnd
  • Battery · posZigbee Contact Sensor · vcc
  • Battery · negZigbee Contact Sensor · gnd
  • Zigbee Contact Sensor · c1DIP Switch · a0
  • Zigbee Contact Sensor · c2DIP Switch · b0

The code

The exact Arduino C++ sketch(es) the bundled firmware was compiled from — shown in the simulator’s Code tab, where you can edit them and press Compile & upload to rebuild the board’s firmware.

// Zigbee contact sensor (door/window) — an IAS Zone end device.
//
// The contact input is GPIO4 with the internal pull-up: short it to GND
// (door CLOSED) or leave it open (door OPEN), exactly like the two screw
// terminals on a wired door-sensor. Every change reports a genuine IAS
// zone-status change to the coordinator over the air.

#include <Arduino.h>
#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"

#define ZIGBEE_CONTACT_ENDPOINT 10
const uint8_t contact = 4;  // GPIO4: LOW (shorted to GND) = closed

ZigbeeContactSwitch zbContact = ZigbeeContactSwitch(ZIGBEE_CONTACT_ENDPOINT);

void setup() {
  Serial.begin(115200);
  pinMode(contact, INPUT_PULLUP);

  zbContact.setManufacturerAndModel("Breadboard", "DoorSensor");
  Serial.println("Adding ZigbeeContactSwitch endpoint to Zigbee Core");
  Zigbee.addEndpoint(&zbContact);

  if (!Zigbee.begin()) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();
  }
  Serial.println("Connecting to network");
  while (!Zigbee.connected()) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();
  Serial.println("Joined. Contact reports armed (GPIO4: low = closed).");
}

void loop() {
  static int last = -1;
  int level = digitalRead(contact);
  if (level != last) {
    last = level;
    if (level == LOW) {
      zbContact.setClosed();
      Serial.println("DOOR CLOSED (contact made) - reported");
    } else {
      zbContact.setOpen();
      Serial.println("DOOR OPEN (contact broken) - reported");
    }
  }
  delay(100);
}

Try this

  • Wait for the sensor to join (its serial tab prints the dots, then "Joined").
  • Flip DIP switch 0 and watch DOOR OPEN / DOOR CLOSED print as each report transmits.
  • Click the sensor: the Inspector shows its live join state and contact position (the magnet bar slides).
  • Open the 📡 Sniffer to catch the IAS zone report frames.

Related projects