A full project suite for Homebridge + Arduino/ESP with a PHP/MySQL server, admin dashboard, user dashboard, token-per-project API, and a dynamic Homebridge platform plugin using JSON per virtual pin.
plugin/→ npm packagehomebridge-arduino-esp-platformserver/→ Apache/PHP/MySQL web app + HTTP/HTTPS JSON APIserver/sql/schema.sql→ database schema + first admin accountserver/apache/arduino-esp.conf→ Apache vhost example
- One user account can own multiple projects.
- Every project gets a server-generated token.
- The token is used by Arduino/ESP and by the Homebridge plugin to read/write JSON per
VPin. - API endpoints:
GET /TOKEN/get/V0GET /TOKEN/update/V0?value={...}POST /TOKEN/update/V0withvalue={...}
- The plugin adds required characteristics and selected optional characteristics by probing the HAP service definition at runtime.
- For irrigation systems, the plugin creates the Valve services first, then links them to the IrrigationSystem service with
addLinkedService(). - Valve defaults include:
Is Configured = 1Service Label Index = 1..NSet Durationfrom configRemaining Duration = 0Valve Typefrom config
- The plugin polls the server and updates HomeKit when the server-side JSON changes.
- If a VPin does not exist yet, the plugin seeds a full JSON object once using the generated required/optional characteristic set.
{
"Name": "light",
"On": "0",
"Brightness": "55",
"Hue": "0",
"Saturation": "0",
"Color Temperature": "0"
}{
"platform": "Arduino_ESP_Platform",
"name": "Arduino ESP Platform",
"serverurl": "http://IP-SERVER:8181",
"pollerseconds": 1,
"devices": [
{
"name": "Garden Controller",
"token": "REPLACE_WITH_PROJECT_TOKEN",
"deviceId": 1,
"manufacturer": "Domi",
"accessories": [
{
"model": "ESP-Light",
"name": "Patio Light",
"pinnumber": 0,
"typeOf": "OUTLET",
"characteristics": {
"Name": true,
"OutletInUse": true
}
},
{
"model": "ESP-Irrigation",
"name": "Front Yard",
"pinnumber": 3,
"typeOf": "IRRIGATION_SYSTEM",
"characteristics": {
"Name": true,
"RemainingDuration": true,
"StatusFault": true
},
"valves": [
{
"valveName": "Zone 1",
"valvePinNumber": 4,
"valveType": 1,
"valveSetDuration": 120,
"characteristics": {
"Name": true,
"RemainingDuration": true,
"SetDuration": true,
"IsConfigured": true,
"ServiceLabelIndex": true,
"StatusFault": true
}
},
{
"valveName": "Zone 2",
"valvePinNumber": 5,
"valveType": 1,
"valveSetDuration": 120,
"characteristics": {
"Name": true,
"RemainingDuration": true,
"SetDuration": true,
"IsConfigured": true,
"ServiceLabelIndex": true,
"StatusFault": true
}
}
]
}
]
}
],
"debug": false,
"_bridge": {
"username": "0E:8D:EE:31:65:DA",
"port": 33823,
"name": "Arduino Esp Platform",
"model": "ESP",
"manufacturer": "Domi",
"firmwareRevision": "1.0"
}
}Place plugin/ in its own git repository or directly in your Homebridge plugin development folder.
This plugin intentionally uses no external runtime dependency and relies on Node 20+ built-in fetch.
npm install -g homebridge-arduino-esp-platformThen configure it from Homebridge UI using the included config.schema.json.
- Apache 2.4+
- PHP 8.1+
- MySQL / MariaDB
mod_rewriteenabled
Copy arduino-esp-server to your Apache document root, for example:
/var/www/arduino-esp-serverImport:
mysql -u root -p < arduino-esp-server/sql/schema.sqlCopy:
cp arduino-esp-server/src/config.sample.php arduino-esp-server/src/config.phpEdit the database credentials and base URL.
Copy arduino-esp-server/apache/arduino-esp.conf to /etc/apache2/sites-available/arduino-esp.conf
Create a symbolic link sudo ln -s /etc/apache2/sites-available/arduino-esp.conf /etc/apache2/sites-enabled/arduino-esp.conf
sudo nano /etc/apache2/ports.conf
Add this line :
Listen 8181
For example, the file should become:
Listen 80 Listen 8181
Listen 443 Listen 443- Login page:
/ - Admin page:
/admin.php - User dashboard:
/dashboard.php
Created by schema.sql:
- Username:
admin - Password:
ChangeMe123!
Change it immediately after first login.
curl "http://IP-SERVER:8181/YOUR_TOKEN/update/V0?value={"Name":"Light","On":"1"}"curl "http://IP-SERVER:8181/YOUR_TOKEN/get/V0"curl -X POST "http://IP-SERVER:8181/YOUR_TOKEN/update/V0" \
-d 'value={"Name":"Light","On":"1"}'- The plugin keeps JSON keys aligned with the HomeKit characteristic display names.
- Missing values are auto-filled with defaults in memory.
- Unsupported complex HAP formats such as
tlv8are added to the service when available, but the generic JSON bridge only binds simple primitive formats automatically. - This keeps the code centralized and avoids scattered per-characteristic logic.