Box IO for Arduino and ESP32
Box IO is a self-hosted IoT server. An Arduino or ESP32 talks to your Linux machine over virtual pins. You watch and control those pins from a web dashboard or from Android, iPhone, and Windows apps. The same sketch can send email, send an SMS, and pulse a pin on the board when a connection drops.
What Box IO can do
virtualWrite. Buttons and sliders come back through BOX_WRITE.BoxIO.email from the sketch.
SMSSave Twilio in Settings, then call BoxIO.sms from the sketch.
Linux Docker serverInstall Docker on Ubuntu, start the containers, and open the dashboard.
License$30 for one year, a 30-day trial, and a public address for each virtual pin.
ForumRead problems and feature requests. Sign in to post one.
Arduino functionsTimers, the virtualWrite cap, poll interval, BOX_WRITE, and setProperty.
Ping watchdogThe Arduino checks a host and pulses one of its own GPIO pins if that connection drops.
Arduino boards it works with
Copy the BoxIO library into Documents/Arduino/libraries/BoxIO and restart the Arduino IDE. Examples are under File → Examples → BoxIO, including PingWatchdog.
- ESP32 over Wi-Fi. Include
BoxIOEsp32.h. The sketches on this site use that header. - ESP32-S3 with a W5500 Ethernet chip. Use the Arduino Ethernet library over SPI. Generic Dev Module cores often do not define
ETH_PHY_W5500, soETH.hcannot drive that chip. - Teensy 4.1. Use the onboard Ethernet jack with QNEthernet by Shawn Silverman. Open File → Examples → BoxIO → Teensy41. The host in the sketch is the LAN address of the Box IO computer. The Arduino Ethernet library is for a W5500 shield and does not drive this PHY.
- SAM, SAMD, MegaAVR, and classic AVR. Any of those boards works when it can open a
WiFiClientorEthernetClientto the server.
The dashboard is http://localhost. The device hub the sketch uses is http://localhost:5923 (HTTP, not HTTPS).
Email and SMS
Both messages leave through the Box IO server. The sketch does not hold the SMTP password or the Twilio token. Those stay in admin Settings. Email and SMS are not counted in the 30 virtualWrite messages per second.
- Send email with
BoxIO.email(to, subject, body)after SMTP is saved. - Send an SMS with
BoxIO.sms(to, body)after Twilio is saved. The dashboard still runs if you skip Twilio.
Connect a board
Do this once on the Ubuntu Box IO machine. Each command is on the Docker install page.
- Open the dashboard and sign in as admin. Create a device key. Copy the
bx_...value intoBOXIO_AUTHin the sketch. Do not commit that key to git. - Create a project and assign that device key to the project.
- Open the project, turn on Edit, add widgets, set each virtual pin, then Save layout. A widget that was never saved disappears on refresh.
- Open Live to use buttons, sliders, and the input box. Edit mode does not send those clicks.
- Flash the sketch with the same host, port
5923, and device key.BoxIO.run()must stay inloop().
Rules that apply to every widget
- The virtual pin on the widget is the number in the sketch. Pin
6isV6. Macros exist forV0throughV31. Higher pins are just numbers:BoxIO.virtualWrite(40, 1). - Buttons, sliders, the input box, and a read/write grid send data to
BOX_WRITE. That table listens on pins 0 through 31. Use those pins for anything the dashboard must deliver to the sketch. - The ping watchdog is different. Its number is an Arduino GPIO, not a virtual pin, and the board toggles that pin itself.
- A non-empty
setPropertyfrom the sketch replaces the dashboard value for that property. Editing the same property on the dashboard writes it back and holds it until the sketch sends that property again. - Colors are
#plus six hex digits. Meter color stops are0:#2ee0c5;60:#f5b942;85:#ff5d73. Grid color rules are0-25:#2ee0c5:all;35-100:#ff5d73:0,1. - Leave Device on “Project device” unless that one widget should talk to a different device key.
virtualWriteis capped at 30 messages per second unless the sketch callsBoxIO.setMaxSendsPerSecondorBoxIO.setMaxSendsPerMinute. Extra writes keep the latest value per pin and go out on a laterBoxIO.run().BoxIO.setTimer(1000, myFunction)calls that function every 1000 milliseconds.BoxIO.run()runs the timers. The Arduino functions page shows how to add, stop, and size those timers.
Widgets
Questions
What Arduino boards work with Box IO?
ESP32 boards over Wi-Fi, an ESP32-S3 with a W5500 Ethernet chip, and SAM, SAMD, MegaAVR, and classic AVR boards that can open a WiFiClient or EthernetClient. The board talks to the Box IO server on HTTP port 5923.
How does an Arduino send email with Box IO?
An admin saves SMTP settings on the Box IO server. The sketch then calls BoxIO.email with the address, subject, and message. The board does not store the mail password.
How does an Arduino send an SMS with Box IO?
An admin saves a Twilio account SID, auth token, and from number. The sketch calls BoxIO.sms with the destination number and the message. Twilio is optional. The dashboard works without it.
How do I install the Box IO server on Linux?
On Ubuntu 24.04, install Docker, clone the Box IO repository, create a JWT secret, and run docker compose up --build -d from the server folder. The Docker page lists each command.
Where does the Box IO ping watchdog run?
On the Arduino. BoxIO.run checks the site from the board and pulses one of that board's GPIO pins if the connection drops. The dashboard stores the settings and shows the status.
How do I run a function on a timer in a Box IO sketch?
Call BoxIO.setTimer with a millisecond interval and a function, then keep BoxIO.run in loop. deleteTimer stops one timer. The Arduino functions page lists the other sketch calls, including the virtualWrite rate cap and setPollInterval.
How does a web page read a Box IO virtual pin?
With a valid license on the Docker server, open https://your-server/public/ then the device key, then /V and the pin number. The page returns JSON. Add .txt for the raw value. The address only reads that pin.
How much does a Box IO license cost?
A license is $30 for one year. A new account can start one 30-day trial. Auto-renew charges $30 again each year. The Docker server hides pin values when the license is missing or expired.