From f9f509c619185742192d2c27d28146f2ce56d749 Mon Sep 17 00:00:00 2001
From: Fabrice Bellamy <12b@distrilab.fr>
Date: Wed, 28 Jan 2026 17:57:15 +0100
Subject: [PATCH] copy code from my personal git repo
---
.gitignore | 4 +
README.md | 100 +++++-
bibotron.ino | 455 ++++++++++++++++++++++++++++
doc/ESP32-S3-ETH-Schematic.pdf | Bin 0 -> 862163 bytes
doc/ESP32-S3-ETH-pinout.jpg | Bin 0 -> 293948 bytes
doc/bibotron-button-closed.png | Bin 0 -> 18705 bytes
doc/bibotron-button-opened.png | Bin 0 -> 18891 bytes
doc/bibotron-home-page.png | Bin 0 -> 49557 bytes
doc/bibotron-prototype-bottom.jpg | Bin 0 -> 209951 bytes
doc/bibotron-prototype-top.jpg | Bin 0 -> 215527 bytes
doc/bibotron_20251106.jpg | Bin 0 -> 75833 bytes
doc/pictures.md | 8 +
secrets.h.example | 44 +++
tests/button_empty.json | 1 +
tests/button_force_off.json | 1 +
tests/button_force_on.json | 1 +
tests/leds_3_values.json | 1 +
tests/leds_64_values.json | 70 +++++
tests/leds_all-off.json | 70 +++++
tests/leds_invalid_index_1.json | 1 +
tests/leds_invalid_index_2.json | 1 +
tests/leds_invalid_index_3.json | 1 +
tests/leds_invalid_index_4.json | 1 +
tests/leds_missing_values.json | 1 +
tests/leds_out_of_range_values.json | 1 +
tests/send_one_request.sh | 10 +
tests/send_test_requests.sh | 12 +
tests/test-env.sh.example | 5 +
28 files changed, 787 insertions(+), 1 deletion(-)
create mode 100644 .gitignore
create mode 100644 bibotron.ino
create mode 100644 doc/ESP32-S3-ETH-Schematic.pdf
create mode 100644 doc/ESP32-S3-ETH-pinout.jpg
create mode 100644 doc/bibotron-button-closed.png
create mode 100644 doc/bibotron-button-opened.png
create mode 100644 doc/bibotron-home-page.png
create mode 100644 doc/bibotron-prototype-bottom.jpg
create mode 100644 doc/bibotron-prototype-top.jpg
create mode 100644 doc/bibotron_20251106.jpg
create mode 100644 doc/pictures.md
create mode 100644 secrets.h.example
create mode 100644 tests/button_empty.json
create mode 100644 tests/button_force_off.json
create mode 100644 tests/button_force_on.json
create mode 100644 tests/leds_3_values.json
create mode 100644 tests/leds_64_values.json
create mode 100644 tests/leds_all-off.json
create mode 100644 tests/leds_invalid_index_1.json
create mode 100644 tests/leds_invalid_index_2.json
create mode 100644 tests/leds_invalid_index_3.json
create mode 100644 tests/leds_invalid_index_4.json
create mode 100644 tests/leds_missing_values.json
create mode 100644 tests/leds_out_of_range_values.json
create mode 100755 tests/send_one_request.sh
create mode 100755 tests/send_test_requests.sh
create mode 100644 tests/test-env.sh.example
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6dcd462
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+secrets.h
+tests/test-env.sh
+build/**
+test/**
diff --git a/README.md b/README.md
index ca7b54b..12e87df 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,100 @@
-# bibotron
+# The Bib O'Tron project
+A proof of concept for replacing the raspberry pi that is managing the bib button by an ESP32 microcontroller.
+## Features
+- Read the status of the bib button using a digital input
+- Display the state of the bib button using a trafic lights
+- Implement a HTTP server to serve :
+ - A basic home page with some links
+ - A bib button status page, that is meant to be included in the future static version of the [bib web site](https://lebib.org/)
+ - CSS/images are not hosted locally (links to the [bib web site](https://www.lebib.org/))
+ - A web OTA page to update the firmware through the network
+ - A REST API to force the button state remotely
+- Periodically pings a remote host and displays an error code on the RGB LED in case of failure (blinking orange color)
+- Connects to the network through an RJ45 ethernet interface
+- Implements Multicast DNS so that its IP address can be found through the bibotron.local name
+- Can be powered by USB-C, using a 5V power supply connected to screw terminals or though the ethernet cable if the optional POE module is installed.
+
+## Hardware
+The microcontroller board used is a [Waveshare ESP32-S3-ETH](https://www.waveshare.com/wiki/ESP32-S3-ETH).
+The RGB LED is a WS2812
+
+## /!\ Warning /!\
+This board, doesn't have any protection between the USB 5V line and the POE 5V line. you MUST remove the POE module and/or disconnect the ethernet cable before plugging-in a USB cable, or else the proverbial magic smoke will be released!!!
+(potentially on your computer side)
+
+## Pictures
+check [the pictures](doc/pictures.md) in the doc directory
+
+## License
+[Creative Commons Zero v1.0 Universal](https://creativecommons.org/public-domain/cc0/)
+
+
+## User guide
+### Changing the bibutton state physically from Le Bib
+Juste operate the switch that is next to the traffic lighs.
+**ToDo :** add a picture of the switch
+
+### Changing the bibutton state remotely
+In case the person who last closed Le Bib has forgotten to switch the bibutton state to the closed position, or if the physical switch is broken, it is possible to call a remote API to force the button state.
+This can be done from the command line with curl as below :
+- To force the bibutton to the closed state :
+ ```
+ curl -i -u "${bibutton_user}:${bibutton_password}" --request POST --data "{forceState:0}" --header "Content-Type: application/json" ${TARGET}
+ ```
+- To force the bibutton to the opened state :
+ ```
+ curl -i -u "${bibutton_user}:${bibutton_password}" --request POST --data "{forceState:0}" --header "Content-Type: application/json" ${TARGET}
+ ```
+
+**ToDo :** The user and password to use need to be stored in the password manager used by Le Bib
+
+While the bibutton state is being remotely forced to a diffent state than the physical switch state, the red and green traffic lights will be both illuminated at the same time.
+As soon as the the physical switch is changed to the same state as the remotely forced state, or the state is remotly forced back to the same state as the physical switch, the "remotly forced" mode will be canceled, and only the red or green light will be on, according the physical switch state.
+
+### Traffic lights
+Depending on the bibutton state, the traffic lights will be illuminated as follow :
+- Red color (upper light) when the bibutton is closed,
+- Green color (bottom light) when button is opened, Solid )
+- Orange color (middle light) when the network is down (the last ping to the reverse proxy failed)
+- Both Green and Red color at the same time when the bibutton state has been remotely forced to a diffent state than the physical switch
+
+### LED light strip
+This is work in progress.
+
+The light strip currently displays the count of requests received to read the bibutton state since the last boot of the microntroller, as a 64 bits binary number.
+And there is an effect with sliding LED from the right side to the left side, each time a new request is processed.
+It is also possible to change the LEDs through a REST API, that is only accessible from the local network. Check the scripts in the test directory to learn more.
+But note that the request count is frequently displayed to the LED strip, which will overwrite the least significant bits of whatever has been set through the API. Also the slifing effect will overwrite everything each time a request is processed.
+
+The LED strip behavior is not functionally usefull for the Bibutton feature. You can hack it any way you want.
+
+## Developer guide
+The project is developed using the Arduino IDE and the following libraries :
+- FastLED, to drive the addressable RGB LEDs
+- EthernetESP32, to drive the SPI ethernet chip (W5500) of the ESP32-S3-ETH
+- ESPping, to periodically check network connectivity
+- ElegantOTA light, to updade the firmware through the network
+- ArduinoJson, to parse json in the rest api handlers
+
+Additionally to these libraries, the esp32 boards package must be installed in Arduino IDE.
+Then in the `Tools` menu, select :
+- `Board` > `esp32` > `ESP32-S3-Box`
+- `Partition scheme` > `16 MB Flash`
+- `USB mode" > `Hardware CDC and JTAG`
+- `Programmer` > `esptools`
+- `Port` > the tty port of the board (if programming through USB)
+
+Before building the souce code, you need to add in your working copy the secret.h file that contains the sensitive information that we not want to publish in the this git repository
+**ToDo :** The secret.h needs to be stored in the password manager used by Le Bib
+If your are building the source code for a different site than Le Bib, you can create your own secret.h based on secret.h.example
+
+To update the firmware through Web OTA, first create the binary using the menu `Sketch` > `Export compiled Binary`.
+Then :
+- In your web browser, go to http://bibotron.local/update (or use the local IP address if the MDNS resolution of bibotron.local is not working : 10.13.12.40)
+- **ToDo :** The user and password to use need to be stored in the password manager used by Le Bib
+- In `OTA Mode` select firmware
+- Click on `Select file` and select the file `bibotron.ino.bin` that should have been generated somewhere under the project build folder (do not used any of the other .bin files that have been generated).
+- Wait for the upload to complete.
+- The ESP32 should automatically restart after the upgrade. (The LEDs and traffic lights will turn off for a while during the reset)
+- Check on www.lebib.org that the bibutton state is correctly displayed
diff --git a/bibotron.ino b/bibotron.ino
new file mode 100644
index 0000000..dfd4ce7
--- /dev/null
+++ b/bibotron.ino
@@ -0,0 +1,455 @@
+// SPDX-License-Identifier: CC0-1.0
+// Copyright © Fabrice Bellamy 2026
+
+/*
+ * The Bib O'Tron project
+ * A proof of concept for replacing the raspberry pi that is managing the bib button by an ESP32 microcontroller.
+ *
+ * license : Creative Commons Zero v1.0 Universal
+ * original source code and documentation : https://git.interhacker.space/12b/bibotron
+ */
+
+// Include some libraries
+#include
I am Bib O'Tron!
Master of buttons and lights.
+15uk
z3exmIllMd5e5sV{6Dns?lbjA&&P*J_0KTxn&&UxU>O5BI*~mD8o!(2qmux%)5>O3i
z1yNpA33l3>&;sT{)u($dyx>4@=2LZ#hl=SVqqXzJ(dhFs)LfrCT%yfepb=Ti*~DUw
zLNFKs22zmDa+7-umll*0q>w474S}AXd)f51-}<0`JVPMA7t5_nBb;p)dM8>XE#0T9
zrbaqh7PyHk952BBCDRVCwydNp$l_{WSc`IV)u3cpA$8Opoi3+?)kH5&=KVv_zaL;5
z^1Zt~dzra*eKnvex$-n*{E*EX4^*;9h71BwtZ|6E9w+_4EDpi>i$U#FsWTY#yihWp
zCOmB)sn4l^u^cf)>qNIbMciPXvgqoEG5e>=Rco5C6^03_Or_x oSqXeZySh;fn)DbxpmkF_}a*t+acDjSo7i9Agp7
zI*hVd3y<_XSLfT>A+NCMPYzmL&>wahLz}n>_NnVDG9X4;1EOh u%Kr?|+qIH5RHLp*&j|DHm?1z2(@>YPo&8Z$t
zb2sh5ev(83$xwXfCM1zMx`L_9o&deVM6+Fdq&mj@p^6^AG$M~4Q}De~Bl=u@H+3cM
zh>xTbj>*n>4A&8 RiKZz>N>9URMJHB+;V1*}i`-Y(R2&d8o_+q9|N?l*;8Rq}`@97?Rs%T>ySV
z=PN*AFesB+uWsSqIZ7fgi{JNL_m!H9Bn&W4`t%gQ7K)lbGFDFQRIHuKhI-^}-
zK9+itGKjf+*2JS!;3`zmuv04lr!kZTX52)eeA(gr$QG;B7y?Y#>-=)DeA!qpM<1$5
zO3T
0d0%KuicbUn(@@VW
z$e1>=8(=7WkQCbTObm1fsV54?*Lz`nr_Zd4YsZy1V;*cL{=xHRty1E@&mT$}D{&6N
z4>3||3wzVV`oOSaWlWIsO8h^=TEg#a_Q9vV+jo
zV-saM1Ez|9NH=5K*{n%oR{K1Yn+;gXOAT}{^|&p*+ba{aQJm0dh)OLR>w{BT5js_L
z@AoqaU!0abX%AcoYteE=`1Gt>D3RToLgba7yJE3c5{3|qCpOs%HL#?Z1Hei2;9i`f
zOhHfZ27l8ED!u{W3`dNSA8Rl`l^X