Discovery
Scan for advertised device names in the format MOONSIDE-[Model Name]. For example, an S1 device advertises as MOONSIDE-S1.
A command reference for controlling moonside smart lighting products over Bluetooth LE. The current device API accepts plain ASCII commands on a write characteristic, so every example here is ready to copy into a BLE client.
Protocol Map
moonside devices expose a UART-style Bluetooth LE service. To control a lamp from a computer, phone, or embedded controller, use a BLE client, app, or library that can scan, connect, and write text to a GATT characteristic.
Scan for advertised device names in the format MOONSIDE-[Model Name]. For example, an S1 device advertises as MOONSIDE-S1.
Connect to service 6E400001-B5A3-F393-E0A9-E50E24DCCA9E. The device may update connection parameters after connect and resumes advertising on disconnect.
Write UTF-8/ASCII command strings to 6E400002-B5A3-F393-E0A9-E50E24DCCA9E. Read 6E400003-B5A3-F393-E0A9-E50E24DCCA9E for version|mac.
Quick Start
These are conceptual BLE operation steps, not shell commands. Use a BLE GUI tool such as nRF Connect or LightBlue, or write a small program with a Bluetooth library such as Python Bleak, Web Bluetooth, or your platform's native BLE APIs.
1. Scan for devices matching "MOONSIDE-*"
2. Connect to service 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
3. Write "LEDON" to 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
4. Write "BRIGH80" to set brightness
5. Write "COLOR255120000" to set RGB
6. Optional: read 6E400003-B5A3-F393-E0A9-E50E24DCCA9E -> "1.0|AA:BB:CC:DD:EE:FF"
Reference
These are the lighting commands accepted by the current device API when written as plain ASCII strings to the BLE write characteristic.
LEDON
LEDOFF
BRIGH80
COLOR255120000
THEME.THEME5.200,20,150,0,60,255,
MODEPIXEL
PIXEL,42,255000128,
BACKLED1,0,050050050,
BACKLED2,0,000050120,
BTN1 // brightness +10
BTN2 // brightness -10
BTN3 // toggle power
BTN4 // next saved mode
BTN5 // previous saved mode
Themes
Theme commands follow THEME.<CODE>.<params>. Parameters are comma-separated decimal color channels, usually grouped as RGB triplets. A trailing comma is used by the documented examples and is safest to include.
| Family | Code | Parameters | Example Command |
|---|---|---|---|
| Rainbow | RAINBOW1 | speed; current devices use a fixed animation timing. | THEME.RAINBOW1.20, |
| Rainbow | RAINBOW2 | speed; current devices use a fixed animation timing. | THEME.RAINBOW2.20, |
| Rainbow | RAINBOW3 | No color parameters. | THEME.RAINBOW3.0, |
| Fire | FIRE1 | No color parameters. | THEME.FIRE1.0, |
| Fire | FIRE2 | Four RGB colors: r1,g1,b1,...,r4,g4,b4. | THEME.FIRE2.0,0,0,255,0,0,0,0,255,255,255,255, |
| Static motion | THEME1 | Two RGB colors. | THEME.THEME1.255,80,0,0,120,255, |
| Static motion | THEME2 | Two RGB colors. | THEME.THEME2.255,80,0,0,120,255, |
| Static motion | THEME3 | Six RGB colors. | THEME.THEME3.0,0,200,0,100,200,100,0,200,200,0,0,200,0,100,120,200,0, |
| Static motion | THEME4 | Two RGB colors. | THEME.THEME4.255,80,0,0,120,255, |
| Static motion | THEME5 | Two RGB colors. | THEME.THEME5.200,20,150,0,60,255, |
| Color | COLORDROP1 | Two RGB colors. | THEME.COLORDROP1.255,0,80,0,120,255, |
| Gradient | GRADIENT1 | Two RGB colors. | THEME.GRADIENT1.255,80,0,0,120,255, |
| Gradient | GRADIENT2 | Three RGB colors. | THEME.GRADIENT2.255,80,0,0,120,255,255,255,255, |
| Gradient | GRADIENT3 | Two RGB colors. | THEME.GRADIENT3.255,80,0,0,120,255, |
| Twinkle | TWINKLE1 | Two RGB colors. | THEME.TWINKLE1.255,255,255,0,120,255, |
| Pulse | PULSING1 | Two RGB colors. | THEME.PULSING1.255,80,0,0,120,255, |
| Palette | PALETTE1 | Optional unused parameter; the device ignores it. | THEME.PALETTE1.0, |
| Palette | PALETTE2 | Six RGB colors. | THEME.PALETTE2.0,0,200,0,100,200,100,0,200,200,0,0,200,0,100,120,200,0, |
| Beat | BEAT1 | Three RGB colors. | THEME.BEAT1.255,0,0,0,255,0,0,0,255, |
| Beat | BEAT2 | Two RGB colors. | THEME.BEAT2.255,80,0,0,120,255, |
| Beat | BEAT3 | Three RGB colors. | THEME.BEAT3.255,0,0,0,255,0,0,0,255, |
| Wave | WAVE1 | Two RGB colors. | THEME.WAVE1.255,80,0,0,120,255, |
| Lava | LAVA1 | Three RGB colors. | THEME.LAVA1.255,60,0,180,0,0,255,180,40, |
| Music | M1 | Two RGB colors; reacts to the microphone input. | THEME.M1.255,140,0,255,0,128, |
| Music | M2 | Three RGB colors; reacts to the microphone input. | THEME.M2.255,0,0,0,255,0,0,0,255, |
| Music | M3 | Two RGB colors; reacts to the microphone input. | THEME.M3.255,140,0,255,0,128, |
| Music | M4 | Two RGB colors; reacts to the microphone input. | THEME.M4.255,140,0,255,0,128, |
| Music | M5 | Two RGB colors; reacts to the microphone input. | THEME.M5.255,140,0,255,0,128, |
| Music | M6 | Two RGB colors; reacts to the microphone input. | THEME.M6.255,140,0,255,0,128, |
| Music | M7 | Two RGB colors; reacts to the microphone input. | THEME.M7.255,140,0,255,0,128, |
| Music | M8 | Three RGB colors; reacts to the microphone input. | THEME.M8.255,0,0,0,255,0,0,0,255, |
| Music | M9 | Two RGB colors; reacts to the microphone input. | THEME.M9.255,140,0,255,0,128, |
| Music | M10 | Three RGB colors; reacts to the microphone input. | THEME.M10.255,0,0,0,255,0,0,0,255, |
| Music | M11 | Three RGB colors; reacts to the microphone input. | THEME.M11.255,0,0,0,255,0,0,0,255, |
| Music | M12 | Two RGB colors; reacts to the microphone input. | THEME.M12.255,140,0,255,0,128, |
Payloads
The parser uses string prefixes, fixed-width decimal fields, and comma-separated values. Send the text exactly as shown; do not hex-encode these commands before writing them.
| Pattern | Example | Parsed As | Notes |
|---|---|---|---|
| BRIGH<value> | BRIGH80 | substring(5).toInt() | Recommended brightness range is 10-100. Values outside that range may be accepted but are not guaranteed. |
| COLORRRRGGGBBB | COLOR255120000 | Red 5..8, green 8..11, blue 11..14. | Each color channel must be padded to three decimal digits, usually 000-255. |
| THEME.CODE.params | THEME.M9.255,140,0,255,0,128, | getValue(command, '.', 1) for code and index 2 for params. | Theme params are split by comma into RGB triplets. Include the trailing comma for consistency. |
| PIXEL,index,RRRGGGBBB, | PIXEL,42,255000128, | Comma index 1 is the LED number; comma index 2 is the 9-digit color. | Sets ledmode to pixel mode and stores this pixel color in preferences. |
| BACKLEDn,0,RRRGGGBBB, | BACKLED1,0,050050050, | Comma index 2 is the 9-digit color; the middle field is parsed but unused. | BACKLED1 updates pixels 0-15. BACKLED2 updates pixels 16-31. |
| LEDON / LEDOFF | LEDON | Exact string comparison. | Power on restores the previous saved mode; power off writes black to all LEDs. |
Builder
Pick a common command shape and copy the generated ASCII string into a BLE client write operation.
Generated ASCII command
LEDON
Device Model
The device stores lighting state locally. Power-on behavior restores the saved mode, brightness, and colors.
ledpower stores on/off. LEDON restores the saved mode; LEDOFF turns every LED black.
ledmode=1 is solid color, 2 is theme animation, and 3 is pixel mode.
The lamp supports 172 addressable LEDs. The BLE read characteristic returns version|mac, for example 1.0|AA:BB:CC:DD:EE:FF.
Diagnostics
The current public API does not emit BLE error codes or acknowledgements for lighting commands. Client apps should validate command strings before writing them.
| Condition | Firmware Behavior | Client Risk | Recommended Handling |
|---|---|---|---|
| Unknown command | The parser falls through without a response. | No explicit failure signal. | Whitelist the commands documented here before writing to BLE. |
| Malformed RGB value | Fixed substrings are converted with toInt(). | Missing digits may become zero or unintended color values. | Always pad RGB channels to three digits: 000-255. |
| Theme already running | Any BLE write sets LEDControlBreak so long-running effects can exit. | Rapid writes can interrupt animation transitions. | Queue writes on the client and wait for visible state changes when possible. |