{"id":21040548,"url":"https://github.com/pixelspark/pwlp","last_synced_at":"2025-06-28T09:35:15.582Z","repository":{"id":46094039,"uuid":"398774058","full_name":"pixelspark/pwlp","owner":"pixelspark","description":"Control LED strips wirelessly by sending them short animation programs","archived":false,"fork":false,"pushed_at":"2021-08-22T10:55:50.000Z","size":180,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-19T15:58:34.583Z","etag":null,"topics":["led-strips","rgb","wasm"],"latest_commit_sha":null,"homepage":"https://pixelspark.nl/2021/over-engineering-an-rgb-led-strip-controller-lets-write-a-custom-programming-language-and-instruction-set","language":"Rust","has_issues":false,"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/pixelspark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-22T10:40:18.000Z","updated_at":"2023-06-25T17:40:56.000Z","dependencies_parsed_at":"2022-07-19T01:02:16.520Z","dependency_job_id":null,"html_url":"https://github.com/pixelspark/pwlp","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelspark%2Fpwlp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelspark%2Fpwlp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelspark%2Fpwlp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelspark%2Fpwlp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pixelspark","download_url":"https://codeload.github.com/pixelspark/pwlp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254377449,"owners_count":22061140,"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":["led-strips","rgb","wasm"],"created_at":"2024-11-19T13:47:07.960Z","updated_at":"2025-05-15T16:33:21.488Z","avatar_url":"https://github.com/pixelspark.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pixelspark Wireless Led Protocol (PWLP) server\n\n## Building\n\n### Regular build\n````sh\ncargo build\n````\n\n### For Raspberry Pi\n````sh\ncargo build --target=arm-unknown-linux-musleabi --features=raspberrypi \n````\n\nTo streamline building and uploading to a Raspberry Pi, use [build_pi.sh](./build_pi.sh). Add the following to your SSH \nconfig file (~/.ssh/config):\n\n````\nHost rpi\n\tHostName raspberrypi.local\n\tUser pi\n\tIdentityFile ~/.ssh/id_rsa\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n````\n\nAfter adding your SSH public key (`~/.ssh/id_rsa.pub`) to `~/.ssh/authorized_keys` on the Pi, you will be able to upload \nwithout using a password. If you don't have an SSH key yet, run `ssh-keygen`.\n\n### WASM\n\n````sh\ncargo install wasm-pack\nwasm-pack build --target=web --release -- --no-default-features --features=wasm\n````\n\nSee [index.html](./index.html) for a usage example. To test:\n\n````sh\nnpm install -g http-server\nhttp-server\n````\n\n### Programs\n\nThe binaries will include several default programs as binaries; these are in the [src/programs](./src/programs) folder\nand can be rebuilt using `./generate_programs.sh`:\n\n* `off.{txt, bin}`: the program that is sent to strips to turn off\n* `default_serve.{txt, bin}`: the default program served when no other program is specified in settings/command line\n\n## Usage\n\n````\n# Compile a script\ncargo run -- compile test/random.txt test/random.bin\n\n# Test run a script\ncat test/random.txt | cargo run -- run\n\n# Serve programs to devices (configure using config.toml)\ncargo run -- serve\n\n# Run a client (configure using config.toml)\ncargo run -- client\n\n# Run a program\ncargo run -- run --binary test/clock.bin\n\n# Run a program on an actual strip with 100 LEDs (SPI bus 0 SS 0) on a Raspberry\ncargo run -- run --binary --hardware -l 100 test/clock.bin\n\n# Run a program on an actual strip with 100 LEDs connected to SPI bus 1 slave select 1 on a Raspberry\ncargo run -- run --binary --hardware --bus 1 --ss 1 -l 100 test/clock.bin\n````\n\n## Protocol\n\nThe PLWP protocol devices a message format as well as an instruction architecture. Scripts are compiled to this architecture and transmitted using the message format to the devices, who will execute them.\n\nFor more information see [protocol.md](https://git.pixelspark.nl/pixelspark/espled/src/branch/master/Protocol.md).\n\n## Script language\n\nExample scripts can be found in the [test](./test/) folder. \n\n### Statements\n\nConsecutive statements are separated by \";\". Supported constructs:\n\n* `if(comparison) { statements }`\n* `loop { statements }`: loops `statements` forever\n* `for(var=expression) { statements }`: counts `var` down from `expression` to 1 (inclusive), e.g. `for(n=5)` will loop with n=5, 4, 3, 2, 1.\n* Comments and whitespace:\n  * `/* may span multiple lines */`\n  * `// single line` (should end in `\\n`)\n  * `\\r`, `\\n`, `\\t` and ` ` are whitespace\n* Special commands:\n  * `yield`\n* User commands:\n  * `get_pixel(index)`: gets the current value for a pixel (may not be blitted yet); formatted as 0x00BBGGRR\n  * `set_pixel(i, r, g, b)`: set pixel at index `i` to color `(r, g, b)`\n  * `random(max)`: return a random number between zero and `max`, inclusive\n  * `get_length`: returns the length of the strip\n  * `get_precise_time`: returns a monotonic time in milliseconds. In deterministic mode, uses the number of instructions to return an approximate time.\n  * `get_wall_time`: returns the number of seconds elapsed since the Unix epoch time (possibly wrapping around in the future!).\n* Compiler intrinsics:\n  * `rgb(r, g, b)` translates to `(r \u0026 0xFF) | (g \u0026 0xFF) \u003c\u003c 8 | (b \u0026 0xFF) \u003c\u003c 16`\n  * `red(c)` translates to `c \u0026 0xFF`\n  * `green(c)` translates to `(c \u003e\u003e 8) \u0026 0xFF`\n  * `blue(c)` translates to `(c \u003e\u003e 16) \u0026 0xFF`\n\n### Expressions\n\nSupported operators:\n\n* Arithmetic: `a+b`, `a/b`, `a*b`, `a-b`, `a%b`\n* Binary: `a|b`, `a\u0026b`, `a^b` (XOR)\n* Unary: `!a`\n* Comparison: `a==b`, `a!=b`, `a\u003cb`, `a\u003eb`, `a\u003c=b`, `a\u003e=b`\n\n## API\n\n### GET `/`\n\nGet server status. Can be used for health checking.\n\n````json\n{}\n````\n\n### GET `/devices`\n\nReturns a list of devices currently or previously connected.\n\n````json\n{\n  \"devices\": {\n    \"aa-bb-cc-dd-ee-ff\": {\n      \"address\": \"1.2.3.4:5678\",\n      \"program\": [10, 11, 12, ...]\n    }\n  }\n}\n````\n\n### GET `/devices/\u003cmac\u003e`\n\nReturns information on a specific device\n\n````json\n{\n  \"address\": \"1.2.3.4:5678\",\n  \"program\": [10, 11, 12, ...]\n}\n````\n\n### GET `/devices/\u003cmac\u003e/\u003cprogram_name\u003e`\n\nSend a built-in program to the device. Built-in program names:\n\n* [`off`](./src/programs/off.txt)\n* [`default`](./src/programs/default_serve.txt)\n\n````json\n{}\n````\n\n## License\n\n[MIT](./LICENSE.txt)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelspark%2Fpwlp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpixelspark%2Fpwlp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelspark%2Fpwlp/lists"}