{"id":17972413,"url":"https://github.com/jnyjny/busylight","last_synced_at":"2025-05-15T11:03:23.055Z","repository":{"id":37205559,"uuid":"279200278","full_name":"JnyJny/busylight","owner":"JnyJny","description":"Control USB connected presence lights from multiple vendors via the command-line or web API.","archived":false,"fork":false,"pushed_at":"2025-03-05T15:32:20.000Z","size":41272,"stargazers_count":266,"open_issues_count":8,"forks_count":29,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-07T18:05:59.413Z","etag":null,"topics":["agile-innovative","blink1","blinklight","blynclight","busy-tag","busylight","busytag","embrava","fit-statusb","flag","kuando","luxafor","muteme","mutesync","presence-light","python","python3","status","status-light","thingm"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JnyJny.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-13T03:27:09.000Z","updated_at":"2025-04-06T20:14:41.000Z","dependencies_parsed_at":"2023-02-10T10:45:40.796Z","dependency_job_id":"9ffde210-9b79-46f3-818f-e0476aa2b258","html_url":"https://github.com/JnyJny/busylight","commit_stats":{"total_commits":1015,"total_committers":10,"mean_commits":101.5,"dds":0.1724137931034483,"last_synced_commit":"509af133fb3f810f2b4e65311fca3dd96cac955c"},"previous_names":[],"tags_count":126,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JnyJny%2Fbusylight","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JnyJny%2Fbusylight/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JnyJny%2Fbusylight/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JnyJny%2Fbusylight/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JnyJny","download_url":"https://codeload.github.com/JnyJny/busylight/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248960751,"owners_count":21189988,"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":["agile-innovative","blink1","blinklight","blynclight","busy-tag","busylight","busytag","embrava","fit-statusb","flag","kuando","luxafor","muteme","mutesync","presence-light","python","python3","status","status-light","thingm"],"created_at":"2024-10-29T16:14:54.001Z","updated_at":"2025-04-14T20:46:24.725Z","avatar_url":"https://github.com/JnyJny.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- USB HID API embrava blynclight agile innovative blinkstick kuando busylight omega alpha plantronics luxafor bluetooth bt flag mute orb thingM blink(1) muteme mutesync compulab fit-statusb --\u003e\n![BusyLight Project Logo][LOGO]\n\u003cbr\u003e\n![version][pypi-version]\n![monthly-downloads][monthly-downloads]\n![visits][visits]\n![supported python versions][python-versions] \n![license][license]\n![Code style: black][code-style-black]\n\u003cbr\u003e\n[![pytest-linux](https://github.com/JnyJny/busylight/actions/workflows/pytest-linux.yaml/badge.svg)](https://github.com/JnyJny/busylight/actions/workflows/pytest-linux.yaml)\n[![MacOS](https://github.com/JnyJny/busylight/actions/workflows/pytest-macos.yaml/badge.svg)](https://github.com/JnyJny/busylight/actions/workflows/pytest-macos.yaml)\n[![pytest-windows](https://github.com/JnyJny/busylight/actions/workflows/pytest-windows.yaml/badge.svg)](https://github.com/JnyJny/busylight/actions/workflows/pytest-windows.yaml)\n\u003cbr\u003e\n\n[BusyLight for Humans™][0] gives you control of USB attached LED\nlights from a variety of vendors. Lights can be controlled via\nthe command-line, using a HTTP API or imported directly into your own\nPython project.\n\n![All Supported Lights][DEMO]\nFlag\u003csup\u003e1\u003c/sup\u003e,\nBusylight Alpha\u003csup\u003e2\u003c/sup\u003e,\nStatus Indicator\u003csup\u003e3\u003c/sup\u003e,\nBlink(1)\u003csup\u003e4\u003c/sup\u003e,\nMute\u003csup\u003e5\u003c/sup\u003e,\nBlynclight\u003csup\u003e6\u003c/sup\u003e.\nOrb\u003csup\u003e7\u003c/sup\u003e,\nBusyLight Omega\u003csup\u003e8\u003c/sup\u003e,\nBlinkStick Square\u003csup\u003e9\u003c/sup\u003e,\nBlynclight Mini\u003csup\u003e10\u003c/sup\u003e,\nMuteMe Original\u003csup\u003e11\u003c/sup\u003e,\nfit-statUSB\u003csup\u003e12\u003c/sup\u003e,\nMuteSync\u003csup\u003e13\u003c/sup\u003e, \nBlynclight Plus\u003csup\u003e14\u003c/sup\u003e\n\n## Features\n- Control lights from the [command-line][HELP].\n- Control lights via a [Web API][WEBAPI].\n- Import `busylight` into your own Python project.\n- Supported on MacOS and Linux\n- Windows support is untested but there are reports that it is working.\n- Supports _ten_ vendors \u0026 seventeen devices:\n\n| **Vendor** | | | | |\n|------------:|---|---|---|---|\n| [**Agile Innovative**][2] | BlinkStick Square |\n| [**Busy Tag**][10] | Busy Tag |\n| [**Compulab**][8] | fit-statUSB |\n| [**Embrava**][3] | Blynclight | Blynclight Mini | Blynclight Plus |\n| [**Kuando**][4] | Busylight Alpha | BusyLight Omega |\n| [**Luxafor**][5] | Bluetooth | Flag | Mute | Orb |\n| [**Plantronics**][3] | Status Indicator |\n| [**MuteMe**][7] | MuteMe Original | Mute Mini |\n| [**MuteSync**][9] | MuteSync |\n| [**ThingM**][6] | Blink(1) |\n\nIf you have a USB light that's not on this list open an issue with:\n - the make and model device you want supported\n - where I can get one\n - any public hardware documentation you are aware of\n \nOr even better, open a pull request!\n\n### Gratitude\n\nThank you to [@todbot][todbot] and the very nice people at [ThingM][thingm] who\ngraciously and unexpectedly gifted me with two `blink(1) mk3` lights!\n\n## Basic Install\n\nInstalls only the command-line `busylight` tool and associated\nmodules.\n\n```console\n$ python3 -m pip install busylight-for-humans \n```\n\n## Web API Install\n\nInstalls `uvicorn` and `FastAPI` in addition to `busylight`:\n\n```console\n$ python3 -m pip install busylight-for-humans[webapi]\n```\n\n## Development Install\n\nI use the tool [poetry][poetry-docs] to manage various aspects of this project, including:\n- dependencies\n- pytest configuration\n- versioning\n- optional dependencies\n- virtual environment creation\n- building packages\n- publishing packages to PyPi\n\n```console\n$ python3 -m pip install poetry \n$ cd path/to/busylight\n$ poetry shell\n\u003cvenv\u003e $ poetry install -E webapi\n\u003cvenv\u003e $ which busylight\n\u003cvenv\u003e $ which busyserve\n```\n\nAfter installing into the virtual environment, the project is now available in editable mode.  Changes made in the source will be reflected in the runtime behavior when running in the poetry initiated shell.\n\n## Linux Post-Install Activities\n\nLinux controls access to USB devices via the [udev subsystem][UDEV]. By\ndefault it denies non-root users access to devices it doesn't\nrecognize. I've got you covered!\n\nYou'll need root access to configure the udev rules:\n\n```console\n$ busylight udev-rules -o 99-busylights.rules\n$ sudo cp 99-busylights.rules /etc/udev/rules.d\n$ sudo udevadm control -R\n$ # unplug/plug your light\n$ busylight on\n```\n\n## Command-Line Examples\n\n```console\n$ busylight on               # light turns on green\n$ busylight on red           # now it's shining a friendly red\n$ busylight on 0xff0000      # still red\n$ busylight on #00ff00       # now it's blue!\n$ busylight blink            # it's slowly blinking on and off with a red color\n$ busylight blink green fast # blinking faster green and off\n$ busylight --all on         # turn all lights on green\n$ busylight --all off        # turn all lights off\n```\n\n## HTTP API Examples\n\nFirst start the `busylight` API server using the `busyserv` command line interface:\n```console\n$ busyserve -D\nINFO:     Started server process [40064]\nINFO:     Waiting for application startup.\nINFO:     Application startup complete.\nINFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)\n...\n```\n\nThe API is fully documented and available via these URLs:\n\n- `https://localhost:8000/redoc`\n- `https://localhost:8000/docs`\n\n\nNow you can use the web API endpoints which return JSON payloads:\n\n```console\n  $ curl -s http://localhost:8000/lights/status | jq\n  ...\n  \n  $ curl -s http://localhost:8000/light/0/status | jq\n  ...\n  \n  $ curl -s http://localhost:8000/light/0/on | jq\n  {\n    \"light_id\": 0,\n    \"action\": \"on\",\n    \"color\": \"green\",\n    \"rgb\": [0, 128, 0]\n  }\n  \n  $ curl -s http://localhost:8000/light/0/off | jq\n  {\n    \"light_id\": 0,\n    \"action\": \"off\"\n  }\n  \n  $ curl -s http://localhost:8000/light/0/on?color=purple | jq\n  {\n    \"light_id\": 0,\n    \"action\": \"on\",\n    \"color\": \"purple\",\n    \"rgb\": [128, 0, 128]\n  }\n  \n  $ curl -s http://localhost:8000/lights/on | jq\n  {\n    \"light_id\": \"all\",\n    \"action\": \"on\",\n    \"color\": \"green\",\n    \"rgb\", [0, 128, 0]\n  }\n  \n  $ curl -s http://localhost:8000/lights/off | jq\n  {\n    \"light_id\": \"all\",\n    \"action\": \"off\"\n  }\n  \n  $ curl -s http://localhost:8000/lights/rainbow | jq\n  {\n    \"light_id\": \"all\",\n    \"action\": \"effect\",\n    \"name\": \"rainbow\"\n  }\n```\n\n### Authentication\nThe API can be secured with a simple username and password through\n[HTTP Basic Authentication][BASICAUTH]. To require authentication\nfor all API requests, set the `BUSYLIGHT_API_USER` and\n`BUSYLIGHT_API_PASS` environmental variables before running\n`busyserve`.\n\n\u003e :warning: **SECURITY WARNING**: HTTP Basic Auth sends usernames and passwords in *cleartext* (i.e., unencrypted). Use of SSL is highly recommended!\n\n## Code Examples\n\nAdding light support to your own python applications is easy!\n\n### Simple Case: Turn On a Single Light\n\nIn this example, we pick an Embrava Blynclight to activate with\nthe color white. Colors are specified as a three-tuple of integers\nthat range from 0 to 255 and represent red, green, and blue\nin that order.\n\n```python\nfrom busylight.lights.embrava import Blynclight\n\nlight = Blynclight.first_light()\n\nlight.on((255, 255, 255))\n\nlight.off()\n```\n\nNot sure what light you've got? No problem!\n\n```python\nfrom busylight.lights import Light\n\nlight = Light.first_light()\n\nlight.on((0xff, 0, 0xff))\n\nlight.off()\n```\n\n### Slightly More Complicated\n\nThe `busylight` package includes a manager class that's great for\nworking with multiple lights or lights that require a little\nmore direct intervention like the Kuando Busylight family.\n\n```python\nfrom busylight.manager import LightManager\nfrom busylight.effects import Effects\n\nmanager = LightManager()\nfor light in manager.lights:\n   print(light.name)\n   \nrainbow = Effects.for_name(\"spectrum\")(duty_cycle=0.05)\n\nmanager.apply_effect(rainbow)\n...\nmanager.off()\n```\n\n[0]: https://github.com/JnyJny/busylight\n\n\n\u003c!-- doc links --\u003e\n[2]: https://github.com/JnyJny/busylight/blob/master/docs/devices/agile_innovative.md\n[3]: https://github.com/JnyJny/busylight/blob/master/docs/devices/embrava.md\n[4]: https://github.com/JnyJny/busylight/blob/master/docs/devices/kuando.md\n[5]: https://github.com/JnyJny/busylight/blob/master/docs/devices/luxafor.md\n[6]: https://github.com/JnyJny/busylight/blob/master/docs/devices/thingm.md\n[7]: https://github.com/JnyJny/busylight/blob/master/docs/devices/muteme.md\n[8]: https://github.com/JnyJny/busylight/blob/master/docs/devices/compulab.md\n[9]: https://github.com/JnyJny/busylight/blob/master/docs/devices/mutesync.md\n[10]: https://github.com/JnyJny/busylight/blob/master/docs/devices/busytag.md\n\n[LOGO]: https://github.com/JnyJny/busylight/blob/master/docs/assets/BusyLightForHumans.png\n[HELP]: https://github.com/JnyJny/busylight/blob/master/docs/busylight.1.md\n[WEBAPI]: https://github.com/JnyJny/busylight/blob/master/docs/busylight_api.pdf\n\n\u003c!-- [DEMO]: demo/demo-updated.gif --\u003e\n[DEMO]: https://github.com/JnyJny/busylight/blob/master/docs/assets/HerdOfLights.png\n\n[BASICAUTH]: https://en.wikipedia.org/wiki/Basic_access_authentication\n[UDEV]: https://en.wikipedia.org/wiki/Udev\n\n[todbot]: https://github.com/todbot\n[thingm]: https://thingm.com\n\n\u003c!-- badges --\u003e\n\n[code-style-black]: https://img.shields.io/badge/code%20style-black-000000.svg\n[pypi-version]: https://img.shields.io/pypi/v/busylight-for-humans\n[python-versions]: https://img.shields.io/pypi/pyversions/busylight-for-humans\n[license]: https://img.shields.io/pypi/l/busylight-for-humans\n[dependencies]: https://img.shields.io/librariesio/github/JnyJny/busylight\n[monthly-downloads]: https://img.shields.io/pypi/dm/busylight-for-humans\n[poetry-docs]: https://python-poetry.org/docs/\n[visits]: https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2FJnyJny%2Fbusylight\u0026count_bg=%2379C83D\u0026title_bg=%23555555\u0026icon=\u0026icon_color=%23E7E7E7\u0026title=Visits\u0026edge_flat=false\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjnyjny%2Fbusylight","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjnyjny%2Fbusylight","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjnyjny%2Fbusylight/lists"}