Smart Indoor Security System
Smart Indoor Security System is a runnable microcontroller simulation example on SensBench — open the wired circuit, inspect the code, and compile real firmware in your browser, no install needed. Last updated Aug 14, 2026.
FREE SIMULATOR EXAMPLE · INTERMEDIATE
Smart Indoor Security System
This example runs an indoor security system on the ESP32 — motion sensing, an arm/trigger/latch alarm state machine, and alert outputs. The entry-level alarm pattern with the logic spelled out.
| Board | ESP32 DevKit (Xtensa LX6, 240 MHz) |
|---|---|
| Difficulty | intermediate |
| Category | communication |
| Libraries | None — just the Arduino core |
| Runs in | Sensbench browser simulator — free, no account |

The exact circuit you get when you open this example — already wired, ready to run.
The sketch
# main.py
import machine, utime, network, urequests, ujson
# ─── Favoriot Credentials ───────────────────────
API_KEY = '..'
USERNAME = ''
DEVICE_ID = 'SmartSecurityr'+USERNAME
URL = 'https://apiv2.favoriot.com/v2/streams'
#import machine, utime, network, urequests, ujson
# ─── WiFi Credentials ───────────────────────────
SSID = 'SENSBENCH-GUEST'
PASSWORD = ''
# ─── Pin Setup ──────────────────────────────────
pir = machine.Pin(14, machine.Pin.IN)
ROW_PINS = [19, 18, 5, 17]
COL_PINS = [16, 4, 2, 15]
KEYS = [
['1','2','3','A'],
['4','5','6','B'],
['7','8','9','C'],
['*','0','#','D']
]
rows = [machine.Pin(p, machine.Pin.OUT) for p in ROW_PINS]
cols = [machine.Pin(p, machine.Pin.IN, machine.Pin.PULL_DOWN) for p in COL_PINS]
# ─── Settings ───────────────────────────────────
CORRECT_PASSWORD = '1234'
TIMEOUT_MS = 30000
# ─── WiFi Connect ───────────────────────────────
def connect_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
print('Connecting to WiFi', end='')
for _ in range(20):
if wlan.isconnected():
break
print('.', end='')
utime.sleep(0.5)
if wlan.isconnected():
print(' Connected! IP:', wlan.ifconfig()[0])
else:
print(' WiFi Failed - running without Favoriot')
# ─── Keypad ─────────────────────────────────────
def get_key():
for r, row in enumerate(rows):
row.value(1)
for c, col in enumerate(cols):
if col.value() == 1:
row.value(0)
# Wait for button release
while col.value() == 1:
utime.sleep_ms(10)
utime.sleep_ms(50)
return KEYS[r][c]
row.value(0)
return None
# ─── Favoriot ───────────────────────────────────
def send_to_favoriot(event, status, access):
print('>>> FAVORIOT | event:', event, '| status:', status, '| access:', access)
wlan = network.WLAN(network.STA_IF)
if not wlan.isconnected():
print('No WiFi - skipping Favoriot')
return
try:
headers = {
'Content-Type': 'application/json',
'apikey': API_KEY,
'username': USERNAME
}
body = ujson.dumps({
'device_developer_id': DEVICE_ID,
'data': {
'event': event,
'status': status,
'access': str(access)
}
})
r = urequests.post(URL, headers=headers, data=body)
print('Favoriot Response:', r.status_code)
r.close()
except Exception as e:
print('Favoriot Error:', e)
# ─── Main ───────────────────────────────────────
connect_wifi()
print('System Ready - Waiting for motion...')
while True:
if pir.value() == 1:
print('Motion Detected!')
send_to_favoriot('MOTION_DETECTED', 'WAITING', 0)
entered = ''
start = utime.ticks_ms()
while utime.ticks_diff(utime.ticks_ms(), start) < TIMEOUT_MS:
key = get_key()
if key:
if key == '#':
if entered == CORRECT_PASSWORD:
print('Access Granted!')
send_to_favoriot('ACCESS_GRANTED', 'SAFE', 1)
else:
print('Wrong Password!')
send_to_favoriot('WRONG_PASSWORD', 'ALARM', 0)
break
elif key == '*':
entered = ''
print('Cleared')
else:
entered += key
print('*', end='')
else:
print('Timeout - Alarm!')
send_to_favoriot('TIMEOUT_ALARM', 'ALARM', 0)
utime.sleep_ms(100)
How it works
The firmware runs an alarm state machine over its sensor inputs: armed mode watches for triggers, a trigger latches the alarm, and the alert output fires until reset. The serial log records every state transition, making the system’s behavior auditable.
The arming flow is the security logic: a grace period after arming lets the user leave, the trigger path latches so a passing intruder cannot silence the alarm by leaving, and the reset is deliberate. These details are what make it a security system rather than a motion indicator.
Before you build it for real
A hobby alarm is not a security product — no tamper detection, no backup power, no redundant paths; the example teaches the logic, not the certification. The PIR’s false triggers are the real-world enemy: pets, curtains and HVAC airflow all trigger the sensor, and the alarm’s usefulness depends on threshold tuning and placement. And the latch must survive power loss — a security system that disarms itself when the power blips is not securing anything.
Get the parts
Related examples
FAQ
What sensors make up the system?
Motion (PIR) is the primary trigger, with door contacts or sound sensors as the usual companions. The firmware monitors the inputs, applies the alarm logic, and raises alerts — the layered detection model of every entry-level alarm system.
How does the alarm logic work?
State machine: disarmed, armed, triggered. The system only alarms when armed, and a trigger latches the alarm state until reset — the arm-trigger-latch cycle that distinguishes an alarm from a motion light.