Compare commits

..

1 Commits

Author SHA1 Message Date
iGoX 782db6f039 Migrate Stream Deck plugin into its own repository 2026-03-26 10:36:45 +01:00
15 changed files with 27 additions and 125 deletions
+9 -63
View File
@@ -165,7 +165,7 @@ class LedController:
async def stop(self): async def stop(self):
await self.sendCommand({"type": "off"}) await self.sendCommand({"type": "off"})
def getStatus(self): def get_state(self):
if self.blinking and self.blinkDuration > 0: if self.blinking and self.blinkDuration > 0:
elapsed = time.ticks_diff(time.ticks_ms(), self.blinkStart) / 1000 elapsed = time.ticks_diff(time.ticks_ms(), self.blinkStart) / 1000
remains = max(0.0, self.blinkDuration - elapsed) remains = max(0.0, self.blinkDuration - elapsed)
@@ -258,16 +258,7 @@ async def setColor(request):
await led.set_color((r, g, b), brightness) await led.set_color((r, g, b), brightness)
status = await led.get_status() status = await led.get_status()
state = led.getStatus() return {'status': status}
return {'status': state["status"],
'color': state["color"],
'brightness': state["brightness"],
'isblinking': state["isblinking"],
'blinkParameters': {
'frequency': state["frequency"],
'duration': state["duration"],
'remains': state["remains"]}
}
@app.get('/api/color') @app.get('/api/color')
@@ -279,16 +270,7 @@ async def getColor(request):
@app.get('/api/status') @app.get('/api/status')
async def getStatus(request): async def getStatus(request):
status = await led.get_status() status = await led.get_status()
state = led.getStatus() return {'status': status}
return {'status': state["status"],
'color': state["color"],
'brightness': state["brightness"],
'isblinking': state["isblinking"],
'blinkParameters': {
'frequency': state["frequency"],
'duration': state["duration"],
'remains': state["remains"]}
}
@app.route('/api/status/<status>', methods=['GET', 'POST']) @app.route('/api/status/<status>', methods=['GET', 'POST'])
@@ -299,16 +281,7 @@ async def setStatus(request, status):
return {'error': 'unknown status'}, 404 return {'error': 'unknown status'}, 404
status = await led.get_status() status = await led.get_status()
state = led.getStatus() return {'status': status}
return {'status': state["status"],
'color': state["color"],
'brightness': state["brightness"],
'isblinking': state["isblinking"],
'blinkParameters': {
'frequency': state["frequency"],
'duration': state["duration"],
'remains': state["remains"]}
}
@app.post('/api/blink') @app.post('/api/blink')
@@ -327,21 +300,12 @@ async def setBlink(request):
await led.blink(freq, duration) await led.blink(freq, duration)
state = led.getStatus() return {'status': 'blinking', 'frequency': freq, 'duration': duration}
return {'status': state["status"],
'color': state["color"],
'brightness': state["brightness"],
'isblinking': state["isblinking"],
'blinkParameters': {
'frequency': state["frequency"],
'duration': state["duration"],
'remains': state["remains"]}
}
@app.get('/api/blink') @app.get('/api/blink')
async def getBlinkStatus(request): async def getBlink(request):
state = led.getStatus() state = led.get_state()
return { return {
'isblinking': state["isblinking"], 'isblinking': state["isblinking"],
'frequency': state["frequency"], 'frequency': state["frequency"],
@@ -355,16 +319,7 @@ async def blinkStop(request):
await led.stop() await led.stop()
await led.set_status(led.previousStatus) await led.set_status(led.previousStatus)
status = await led.get_status() status = await led.get_status()
state = led.getStatus() return {'status': status}
return {'status': state["status"],
'color': state["color"],
'brightness': state["brightness"],
'isblinking': state["isblinking"],
'blinkParameters': {
'frequency': state["frequency"],
'duration': state["duration"],
'remains': state["remains"]}
}
@app.get('/api/debug') @app.get('/api/debug')
@@ -397,16 +352,7 @@ async def mutedeckWebhook(request):
else: else:
await led.set_status('available') await led.set_status('available')
state = led.getStatus() return {'status': led.status}
return {'status': state["status"],
'color': state["color"],
'brightness': state["brightness"],
'isblinking': state["isblinking"],
'blinkParameters': {
'frequency': state["frequency"],
'duration': state["duration"],
'remains': state["remains"]}
}
@app.post('/shutdown') @app.post('/shutdown')
+18 -62
View File
@@ -20,13 +20,9 @@ A cheap, simple to build, nice looking and portable DIY **Busy Light**.
It comes with a with a simplistic but neat **Web UI** and a simple (but hopefully convenient) **Rest API**. It comes with a with a simplistic but neat **Web UI** and a simple (but hopefully convenient) **Rest API**.
| Controlled by Stream Deck with REST API | Light roll | | Controlled by Stream Deck with REST API | Light roll |
| ------------------------------------------------------------- | ------------------------------------------------- | | --- | --- |
| ![busylight and stream deck](resources/images/busylight.jpg) | ![busylight roll](resources/images/busylight.gif) | | ![busylight and stream deck](img/busylight.jpg) | ![busylight roll](img/busylight.gif) |
---
![show case](resources/videos/busylight-showoff.webp)
# Web UI # Web UI
@@ -37,25 +33,23 @@ You can try to reach the web UI @ <http://igox-busylight.local>.
| What an neat UI ! 😄 | | What an neat UI ! 😄 |
| --- | | --- |
| ![Web UI](resources/images/web-ui.png) | | ![Web UI](img/web-ui.png) |
# BusyLight Buddy companion app # BusyLight Buddy companion app
[BusyLight Buddy](https://code.igox.org/iGoX/busylight-buddy) is a free, open-source multiplatform companion app to control your BusyLight from your phone or computer — no browser needed. [BusyLight Buddy](https://code.igox.org/iGoX/busylight-buddy) is a free, open-source multiplatform companion app to control your BusyLight from your phone or computer — no browser needed.
Available for **Android**, **macOS** and **Windows**. Available for **iOS**, **iPadOS**, **Android**, **macOS**, and **Windows**.
It features quick status presets, a custom color picker with saveable presets, a brightness slider, and background polling to keep the UI in sync with the device. It features quick status presets, a custom color picker with saveable presets, a brightness slider, and background polling to keep the UI in sync with the device.
![busylight-buddy-screenshot](resources/images/buddy-ios-screenshot-main.png)
# Stream Deck plug-in # Stream Deck plug-in
You can download the Stream Deck plugin to control your BusyLight: You can download a Stream Deck plugin to control your BusyLight:
[![marketplace button](resources/images/streamdeck-plugin-get-it-on-marketplace.svg)](https://marketplace.elgato.com/product/igox-busylight-7448a0be-6dd6-4711-ba0d-86c52b9075b9) [![marketplace button](img/streamdeck-plugin-get-it-on-marketplace.svg)](https://marketplace.elgato.com/product/igox-busylight-7448a0be-6dd6-4711-ba0d-86c52b9075b9)
Or directly from **[busyLight-streamdeck-pluing](https://code.igox.org/iGoX/busylight-streamdeck-plugin)** repository. Or directly from [BusyLight Stream Deck pluing](https://code.igox.org/iGoX/busylight-streamdeck-plugin) repository.
# BusyLight API # BusyLight API
@@ -73,8 +67,8 @@ Or directly from **[busyLight-streamdeck-pluing](https://code.igox.org/iGoX/busy
| /api/status/busy | POST / GET | n/a | Set the BusyLight in `busy` mode. Red color. Return a `status` object. | | /api/status/busy | POST / GET | n/a | Set the BusyLight in `busy` mode. Red color. Return a `status` object. |
| /api/status/off | POST / GET | n/a | Shutdown the BusyLight. Return a `status` object. | | /api/status/off | POST / GET | n/a | Shutdown the BusyLight. Return a `status` object. |
| /api/status | GET | n/a | Retreive the current BusyLight status. Return a `status` object. | | /api/status | GET | n/a | Retreive the current BusyLight status. Return a `status` object. |
| /api/blink | POST | `blinkParam` JSON object | Make the BusyLight blink. Preserves current color, status and brightness. Return a `status` object. | | /api/blink | POST | `blink` JSON object | Make the BusyLight blink. Preserves current color, status and brightness. Return a `status` object. |
| /api/blink | GET | n/a | Retrieve the current BusyLight blink status. Return a `blinkStatus` object. | | /api/blink | GET | n/a | Retrieve the current BusyLight blink status. Return a `blink` object. |
| /api/blink/stop | POST | n/a | Stop the BusyLight blinking and restore previous state. Return a `status` object. | | /api/blink/stop | POST | n/a | Stop the BusyLight blinking and restore previous state. Return a `status` object. |
| /api/debug | GET | n/a | Retreive the full BusyLight status. | | /api/debug | GET | n/a | Retreive the full BusyLight status. |
@@ -106,19 +100,7 @@ Or directly from **[busyLight-streamdeck-pluing](https://code.igox.org/iGoX/busy
`brightness`: LED brightness | float | [0.0 .. 1.0] `brightness`: LED brightness | float | [0.0 .. 1.0]
### `blinkParam` object ### `blink` object
```json
{
"frequency": 2,
"duration": 5.0,
```
`frequency`: blink frequency | integer | Hz
`duration`: total blink duration | float | seconds | 0 = endless
### `blinkStatus` object
```json ```json
{ {
@@ -138,37 +120,11 @@ Or directly from **[busyLight-streamdeck-pluing](https://code.igox.org/iGoX/busy
```json ```json
{ {
"status": "<STATUS>", "status": "<STATUS>"
"color": {
"r": 255,
"g": 0,
"b": 110
},
"brightness": 0.1
"isBlinkning": false,
"blinkParameters": {
"frequency": 2,
"duration": 5.0,
"remains": 3.2
}
} }
``` ```
`<STATUS>` : `on` | `off` | `available` | `away` | `busy` | `colored` `<STATUS>` : `on` | `off` | `available` | `away` | `busy` | `colored` | `blinking`
`color`:
- `r`: RED color | integer | [0 .. 255]
- `g`: GREEN color | integer | [0 .. 255]
- `b`: BLUE color | integer | [0 .. 255]
`brightness`: LED brightness (optional) | float | [0.0 .. 1.0]
`isblinking`: whether the BusyLight is currently blinking | boolean
`blinkParameters`
- `frequency`: blink frequency | integer | Hz
- `duration`: total blink duration | float | seconds | 0 = endless
- `remains`: remaining blink time | float | seconds | 0 if endless
# MuteDeck integration # MuteDeck integration
@@ -183,7 +139,7 @@ It will automatically switch to the BusyLight in:
| MuteDeck Configuration | | MuteDeck Configuration |
| --- | | --- |
| ![MuteDeck config](resources/images/mutedeck-webhook-conf.png) | | ![MuteDeck config](img/mutedeck-webhook-conf.png) |
# Electronic parts # Electronic parts
@@ -202,7 +158,7 @@ It will automatically switch to the BusyLight in:
| Tools > Manage plug-ins | lib selection | | Tools > Manage plug-ins | lib selection |
| --- | --- | | --- | --- |
| ![lib-menu](resources/images/lib-menu.png) | ![lib-install](resources/images/lib-install.png) | | ![lib-menu](img/lib-menu.png) | ![lib-install](img/lib-install.png) |
> ⚠️ **Compatibility note:** MicroPython v1.27 is **not compatible** with Microdot due to breaking changes in the underlying ESP-IDF v5.5. Use MicroPython **v1.24.1** with Microdot **v2.0.6**. > ⚠️ **Compatibility note:** MicroPython v1.27 is **not compatible** with Microdot due to breaking changes in the underlying ESP-IDF v5.5. Use MicroPython **v1.24.1** with Microdot **v2.0.6**.
@@ -210,7 +166,7 @@ It will automatically switch to the BusyLight in:
**(4)** Copy the content of [ESP32](ESP32) folder with the modified `boot.py` file to the root of your ESP32 file system. Again, can easily be done using [Thonny](https://thonny.org): **(4)** Copy the content of [ESP32](ESP32) folder with the modified `boot.py` file to the root of your ESP32 file system. Again, can easily be done using [Thonny](https://thonny.org):
![file-copy](resources/images/file-copy.png) ![file-copy](img/file-copy.png)
**Done!** **Done!**
@@ -222,7 +178,7 @@ All the required 3D files (STLs and f3d project) to 3D print the enclosure are a
# Wiring / Soldering # Wiring / Soldering
![wiring-soldering](resources/images/wiring-soldering.png) ![wiring-soldering](img/wiring-soldering.png)
You can see a final assembly image [here](3D-files-to-print/README.md). You can see a final assembly image [here](3D-files-to-print/README.md).
@@ -238,7 +194,7 @@ You can see a final assembly image [here](3D-files-to-print/README.md).
## Microdot ## Microdot
<https://microdot.readthedocs.io> <https://microdot.readthedocs.io/en/latest/index.html>
## JSColor ## JSColor

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 195 KiB

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB