{"id":17124266,"url":"https://github.com/hipsterbrown/on-air-light","last_synced_at":"2025-06-20T16:12:06.398Z","repository":{"id":41117100,"uuid":"451247082","full_name":"HipsterBrown/on-air-light","owner":"HipsterBrown","description":"An offline-first IoT on-air light for video meetings, using ESP32 \u0026 JS","archived":false,"fork":false,"pushed_at":"2022-03-29T00:39:08.000Z","size":6794,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-20T16:11:27.522Z","etag":null,"topics":["esp32","iot","moddable","offline-first"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HipsterBrown.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-23T22:29:06.000Z","updated_at":"2023-09-02T10:10:31.000Z","dependencies_parsed_at":"2022-08-27T04:11:09.359Z","dependency_job_id":null,"html_url":"https://github.com/HipsterBrown/on-air-light","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/HipsterBrown/on-air-light","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HipsterBrown%2Fon-air-light","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HipsterBrown%2Fon-air-light/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HipsterBrown%2Fon-air-light/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HipsterBrown%2Fon-air-light/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HipsterBrown","download_url":"https://codeload.github.com/HipsterBrown/on-air-light/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HipsterBrown%2Fon-air-light/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260976921,"owners_count":23091528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp32","iot","moddable","offline-first"],"created_at":"2024-10-14T18:42:16.193Z","updated_at":"2025-06-20T16:12:01.380Z","avatar_url":"https://github.com/HipsterBrown.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# On-Air Light\n\nAn offline-first IoT project on-air light for video meetings, using [ESP32](https://www.espressif.com/en/products/devkits/esp32-devkitc) \u0026 JavaScript with [Moddable XS](https://www.moddable.com/).\n\n_While the materials demonstrate using an ESP32 development board, it is possible using an [ESP8266](https://www.adafruit.com/product/3046) with the same code (updated pins probably required) since Moddable runs on both platforms._\n\n## Materials\n\n- [ESP32](https://www.espressif.com/en/products/devkits/esp32-devkitc)\n- [Breadboard](https://www.adafruit.com/product/64)\n- [2 tri-color LEDs](https://www.adafruit.com/product/159)\n- [male/male jumper wires](https://www.adafruit.com/product/759)\n- slim USB battery pack\n- Box (I used an [Adabox](https://www.adafruit.com/adabox/) container) \n\n## Wiring Diagram\n\n![breadboard wiring](./docs/images/On-Air-LIght.png)\n\n## Setup\n\nThe dev environment was bootstrapped and managed using [`xs-dev`](https://github.com/HipsterBrown/xs-dev); however, that is not required if you want to go through the [Moddable set up instructions](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/Moddable%20SDK%20-%20Getting%20Started.md) manually or has been done previously.\n\nAfter cloning this project repo, the `ssid` and `password` config fields in the `manifest.json` to match your WiFi details. The project does not require any Internet access (i.e. \"offline-first\"), just a shared network for local Web UI and HTTP API control.\n\nAfter wiring the hardware materials together to match the documented diagram, the code can be uploaded to the board.\n\nUsing `xs-dev`:\n\n```\nxs-dev run --device esp32\n```\n\nUsing [`mcconfig`](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/tools/tools.md#mcconfig):\n\n```\nmcconfig -d -m -p esp32\n```\n\nOnce the LEDs are green for 3 seconds, the web UI should be available at `http://on-air.local/`.\n\n![web interface](./docs/images/web-ui.png)\n\nThere are some HTTP API endpoints for checking and controlling the light outside of the web UI:\n\n- `GET /api/state`: returns the current color if the light is on, otherwise returns `[1023, 1023, 1023]` as \"off\"\n- `POST /api/toggle`: toggles the state of the light, using the last used color if the light is off\n- `POST /api/color`: expects a `color` field in the body to set the color of the light, returns 204 status code if successful\n\n\n## Deployed Project\n\nExternal box:\n![external box](./docs/images/external-box.jpg)\n\nInternal layout:\n![internal box](./docs/images/internal-box.jpg)\n\nBreadboard wiring:\n![close up of breadboard wiring](./docs/images/internal-zoom.jpg)\n\n## Computer Camera event daemon\n\nRun using [`pm2`](https://pm2.keymetrics.io/docs/usage/quick-start/) to control long running process:\n\n```\npm2 start daemon/index.mjs --name on-air\n```\n\nThe script (`daemon/index.mjs`) watches the standard output stream from [`log stream`](https://developer.apple.com/documentation/os/logging) on MacOS for Camera events that include \"turn off\" and \"turn off\" messages. When it sees one of those messages, it will make a POST request to the `/api/toggle` endpoint at the `http://on-air.local` host. If it cannot reach `on-air.local`, it will log the error and continue watching the log output.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhipsterbrown%2Fon-air-light","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhipsterbrown%2Fon-air-light","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhipsterbrown%2Fon-air-light/lists"}