Pixel Streaming SKY only

LaMetric SKY devices support the LaMetric Streaming Protocol (LMSP) for pushing real-time RGB888 frames over UDP at up to 30 FPS. All three streaming services target the Light entity of a SKY device.

SKY only UDP RGB888 API v2.3.0

How it works

  1. Read canvas dimensions — check the Light entity's state attributes (canvas_pixel or canvas_triangle) to find the correct canvas size for your device and chosen render mode.
  2. Start a stream — call start_stream. The service returns a session_id and the device enters streaming state.
  3. Send frames — call send_stream_data repeatedly, up to 30 FPS, passing the session_id and raw RGB888 pixel data.
  4. Stop the stream — call stop_stream. The device returns to its normal app display immediately.
SKY only All three services return an error when called on non-SKY devices. The Light entity is only created for SKY models in the first place — see Light entity.

Light entity stream attributes

The Light entity always exposes the current stream state and canvas dimensions as extra state attributes, updated on every coordinator poll:

Attribute Description
stream_status Current stream status, e.g. stopped or receiving.
canvas_pixel Object with width and height for pixel render mode (e.g. {"width": 24, "height": 8}).
canvas_triangle Object with width and height for triangle render mode (typically twice the pixel dimensions).

Use these attributes to determine the correct rgb_data length (width × height triplets) before sending frames.

start_stream

PUT /api/v2/device/stream/start API 2.3.0+

Starts an LMSP streaming session and configures the canvas rendering parameters. Returns a session_id which must be passed to every subsequent send_stream_data call.

Fields

Field Required Type Description
config yes object Canvas configuration object. See the canvas config table below.

canvas config object

Field Required Values Description
canvas.fill_type yes
scale tile
How to fill the physical display when content is smaller than the screen:
  • scale — stretch the canvas to fill the display.
  • tile — tile the canvas to fill the display.
canvas.render_mode yes
pixel triangle
Determines the addressable pixel unit:
  • pixel — each logical pixel maps to one square LED. Best for images and text.
  • triangle — each logical pixel maps to one triangular LED (addressing individual triangles). Best for abstract effects. The canvas is larger in this mode (roughly 2× in each dimension).
canvas.post_process.type no
none effect
Post-processing applied on top of the streamed content. none displays content as-is.
canvas.post_process.params no object Effect parameters. Only used when type = effect. See fading_pixels effect.

fading_pixels effect

Currently the only available post-process effect. It adds a fade-in/fade-out animation on top of the raw pixel content.

Parameter Type Range Description
effect_params.smooth boolean true — pixels appear gradually; false — pixels appear instantly.
effect_params.pixel_fill float 0.0 – 1.0 Fill area percentage. 1.0 = pixels fill 100 % of the LED area.
effect_params.fade_speed float 0.0 – 1.0 Brightness delta added per render cycle. Larger value = faster fade.
effect_params.pixel_base float 0.0 – 1.0 Base (minimum) pixel brightness. 0.0 = fully off; 1.0 = full brightness.

Service response

The service returns the session_id needed for all subsequent send_stream_data calls:

{
  "session_id": "a2891aa891ab4f8e8a1a16eb319b00f3"
}

Example: basic pixel mode

service: lametric_hass_local.start_stream
target:
  entity_id: light.lametric_sky_light
data:
  config:
    canvas:
      fill_type: scale
      render_mode: pixel
      post_process:
        type: none

Example: pixel mode with fading effect

service: lametric_hass_local.start_stream
target:
  entity_id: light.lametric_sky_light
data:
  config:
    canvas:
      fill_type: scale
      render_mode: pixel
      post_process:
        type: effect
        params:
          effect_type: fading_pixels
          effect_params:
            smooth: true
            pixel_fill: 1.0
            fade_speed: 0.005
            pixel_base: 0.05

send_stream_data

Sends one RGB888 frame to an active LMSP stream session. The service fetches the current stream state itself on every call (to get the UDP port and validate the session), so you only need to supply the session_id and the pixel data.

No HTTP call Unlike all other services, send_stream_data does not call an HTTP API endpoint. It sends a raw UDP datagram directly to the device's streaming port.

Fields

Field Required Type Description
session_id yes string The session_id returned by start_stream.
rgb_data yes list of [R, G, B] triplets One [R, G, B] triplet per pixel, ordered left-to-right top-to-bottom. Each channel is an integer 0–255. The number of triplets must match canvas_width × canvas_height — read these from the Light entity's stream attributes.

Example

service: lametric_hass_local.send_stream_data
target:
  entity_id: light.lametric_sky_light
data:
  session_id: "{{ session_id }}"
  rgb_data: "[[255,0,0],[255,0,0],[0,255,0],[0,0,255],...]"
Automation tip Store the session_id returned by start_stream in a template variable or input_text entity, then pass it to send_stream_data in a loop or repeat action.

stop_stream

PUT /api/v2/device/stream/stop API 2.3.0+

Stops the active streaming session. The device returns to its normal app display immediately. The service takes no additional fields beyond the entity target.

service: lametric_hass_local.stop_stream
target:
  entity_id: light.lametric_sky_light

API response

{
  "success": {
    "data": {
      "status": "stopped"
    },
    "path": "api/v2/device/stream/stop"
  }
}

LMSP UDP packet format

This section describes the low-level wire format used by the integration when sending frames. It is provided for debugging and advanced use-cases. Full reference: LaMetric Streaming API.

Byte order All multi-byte integer fields use little-endian byte order.

Packet header (28 bytes fixed)

Offset Size (bytes) Field Value / Notes
0 4 Protocol name ASCII lmsp = 0x6c 0x6d 0x73 0x70
4 2 Version 0x01 0x00 (version 1, little-endian)
6 16 Session ID UUID bytes from start_stream response (no dashes, raw 16 bytes). Packets with a mismatched session ID are silently discarded by the device.
22 1 Content encoding 0x00 = RAW, 0x01 = PNG, 0x02 = JPEG, 0x03 = GIF. The integration always uses 0x00 (RAW RGB888).
23 1 Reserved 0x00
24 1 Canvas area count Number of canvas areas in this packet. The integration always sends 0x01 (one area per packet).
25 1 Reserved 0x00

Canvas area descriptor (8 bytes per area)

Offset Size (bytes) Field Value
26 2 X offset 0–canvas_width; usually 0x00 0x00
28 2 Y offset 0–canvas_height; usually 0x00 0x00
30 2 Width Canvas width in pixels (e.g. 0x18 0x00 for 24)
32 2 Height Canvas height in pixels (e.g. 0x08 0x00 for 8)
34 2 Data length width × height × 3 bytes (RGB888). For a 24×8 canvas: 576 bytes = 0x40 0x02

Pixel data

Immediately after the area descriptor: width × height RGB888 triplets, ordered left-to-right, top-to-bottom. Each triplet is three bytes: R, G, B.

Total packet size

26 (header) + 10 (area descriptor) + width × height × 3 (pixel data)

For a 24×8 pixel canvas: 26 + 10 + 576 = 612 bytes

Annotated example (24×8, all red)

6c 6d 73 70       // "lmsp"
01 00             // version 1
a2 89 1a a8 91 ab 4f 8e
8a 1a 16 eb 31 9b 00 f3  // session_id (16 bytes)
00                // RAW encoding
00                // reserved
01                // 1 canvas area
00                // reserved
00 00             // x = 0
00 00             // y = 0
18 00             // width = 24
08 00             // height = 8
40 02             // data length = 576
ff 00 00  ff 00 00  ff 00 00  ...  // 192 red pixels (24*8)

Full LMSP reference: LaMetric Streaming API.