A college bike-sharing system with a Raspberry Pi server, one ESP32 on every stand, and one ESP32 on every bike.
Raspberry PiRuns the Node.js backend, booking logic, OTP verification, MQTT coordination, alerts, and SQLite database.Stand ESP32One per stand. Reads keypad OTPs, shows LCD feedback, and talks to the Pi over MQTT.Bike ESP32One per bike. Sends live location, battery, and lock status to the Pi over MQTT.
cbss/stand/{standId}/otpcbss/stand/{standId}/status
cbss/stand/{standId}/result
cbss/bike/{bikeId}/locationcbss/bike/{bikeId}/status
cbss/bike/{bikeId}/command
1 Raspberry Piis the central server.1 ESP32 per standhandles OTP entry and local feedback.1 ESP32 per bikehandles GPS/live location and lock state.
The backend maps:
stand -> docked bikesbooking -> bikebike -> bike ESP topic id
So when a stand submits a correct OTP, the Raspberry Pi decides which bike at that stand should unlock and publishes the unlock command to that bike.
cd backend
npm install
node server.jsThe backend runs on:
Create a ThingSpeak channel with these fields:
field1: Bike IDfield2: Latitudefield3: Longitudefield4: Battery percentagefield5: Lock state code (0= unlocked,1= locked)field6: Bike status code (0= available,1= booked,2= in use,3= missing)field7: Alert code (0= none,1= tamper,2= out of bounds,3= low battery,4= OTP brute force,5= overdue user,6= overdue guard)field8: Stand ID (0when bike is not docked)
Run the backend with your ThingSpeak Write API Key:
THINGSPEAK_WRITE_API_KEY=YOUR_WRITE_API_KEY node server.jsOn Windows PowerShell:
$env:THINGSPEAK_WRITE_API_KEY="YOUR_WRITE_API_KEY"
node server.jsThe backend uploads to ThingSpeak only when THINGSPEAK_WRITE_API_KEY is set. It throttles updates to about 16 seconds by default to match ThingSpeak rate limits. You can override that with:
THINGSPEAK_MIN_INTERVAL_MS=20000 node server.jsSTAND-001-> topic id1STAND-002-> topic id2
BIKE-001-> topic id1BIKE-002-> topic id2BIKE-003-> topic id3BIKE-004-> topic id4
ADMIN001 / admin123STU001 / pass123STU002 / pass123
The simulator now matches the real hardware split:
python simulator.py stand --stand 1 --code 123456python simulator.py stand --stand 1 --brute-forcepython simulator.py bike --bike 1 --mode normalpython simulator.py bike --bike 1 --mode misbehavepython simulator.py bike --bike 1 --mode tamperPOST /bookingsPOST /stand/otpPOST /stand/statusPOST /bike/gpsPOST /bike/statusGET /system/topologyGET /admin/devices
- OTPs are still returned in the booking API for demo/testing.
- The stand ESP code expects a 16x2 I2C LCD and a 4x4 keypad.
- A real bike ESP sketch is available at
esp32_bike/bike_tracker/bike_tracker.inofor GPS-based telemetry. - Update the bike sketch Wi-Fi credentials, bike identity, GPS UART pins, and optional battery pin before flashing.