← 返回 Skills 市场
xander887

Bloomin8

作者 xander887 · GitHub ↗ · v2.2.5 · MIT-0
cross-platform ✓ 安全检测通过
221
总下载
0
收藏
0
当前安装
10
版本数
在 OpenClaw 中安装
/install bloomin8
功能描述
Push images or markdown to a Bloomin8 e-ink photo frame via cloud API (async) or local BLE+LAN (instant). Scan nearby devices, check status, track delivery,...
使用说明 (SKILL.md)

Bloomin8 E-ink Device Control

Control Bloomin8 e-ink photo frame devices. Two modes available:

  • Local BLE + LAN (local, instant) — scan, wake, and upload directly over the local network; image displays immediately.
  • Cloud API (remote, async) — push content via REST API; device displays on next scheduled wake.

Image sourcing: This skill handles delivery only. To create images, combine with any available tool — e.g. Puppeteer (HTML → screenshot), AI image generation, or scripted chart rendering — then pass the resulting file or URL to the push/upload commands below.

Mode selection: Prefer local mode when available, but always confirm with the user before performing BLE scans or probing local network hosts. Suggested flow:

  1. Ask the user which mode they prefer (local or cloud), or propose one based on context.
  2. If local mode: before scanning, inform the user (e.g. "I'll scan for nearby BLE devices — OK?"). Only proceed with explicit approval.
  3. If you have a device IP (from prior info, cache, or user-provided), verify reachability (curl http://\x3Cip>/whistle) before uploading. Inform the user of the IP being probed.
  4. Only fall back to cloud API when local is impossible (no BLE hardware, device out of range, IP unreachable after BLE wake).
  5. Explicit user intent overrides: "push" / "schedule" → cloud; "upload" / "display now" → local.

Device Identity Across Modes

Both modes use the same device name as the primary identifier. When a user says a device name (e.g. "Living Room"):

  • Cloud API → match to env var BLOOMIN8_TOKEN_LIVING_ROOM (uppercase, non-alphanumeric → _)
  • Local BLE → match via --name "Living Room" (case-insensitive partial match)

The device name is set by the user in the Bloomin8 app and is consistent across BLE advertisement (local_name) and cloud (device.name). The BLE info command also returns the full device serial (sn) which matches the cloud device_id embedded in the API token — but in practice, name matching is sufficient and preferred.


Mode 1: Cloud API (Remote, Async)

Self-Discovery

On first use, fetch the full API documentation (no auth needed). Cache the result — it rarely changes:

web_fetch https://einkshot-349134901638.us-central1.run.app/open-api/help

This returns all endpoints, parameters, and response fields as structured JSON. If anything below conflicts with the live docs, trust the live docs.

Authentication

Token is device-bound. Generated in the Bloomin8 app: Devices tab → device card → ⋮ menu → API Token.

  • Env var naming: BLOOMIN8_TOKEN_\x3CDEVICE_NAME> (uppercase, non-alphanumeric → _)
    • e.g. BLOOMIN8_TOKEN_LIVING_ROOM, BLOOMIN8_TOKEN_KIDS_BEDROOM
  • When user mentions a device by name, match it to the corresponding env var
  • If only one BLOOMIN8_TOKEN_* exists, confirm with the user before using it (e.g. "I found token BLOOMIN8_TOKEN_KITCHEN — shall I use it?")
  • Pass as: Authorization: Bearer $BLOOMIN8_TOKEN_\x3CNAME>
  • Generating a new token invalidates the previous one for that device
  • Token can be generated/revoked regardless of whether remote push is enabled

API base URL: https://einkshot-349134901638.us-central1.run.app

Capabilities

  • GET /open-api/help — full API docs (no auth)
  • GET /open-api/device/status — screen dimensions, orientation, interval, pending status (includes remote_image_on and pending_image.remote_image_id when pending)
  • POST /open-api/push — push image (URL / file upload / markdown). Requires remote_image_on = true. Last-wins: only the latest pending image will be displayed.
  • DELETE /open-api/push — cancel the current pending image. Requires remote_image_on = true.
  • GET /open-api/push/history — delivery history with status filter
  • PUT /open-api/device/interval — change wake frequency (10m / 1h / 3h / 6h). Requires remote_image_on = true.

Recommended Workflow

  1. GET /open-api/device/status — get screen dimensions, orientation, and estimated_push_time. Always do this before pushing to know the target size.
  2. Prepare image matching the device's width × height and orientation.
  3. POST /open-api/push — push via one of the three modes (see examples below). Last-wins: only the latest push will be displayed.
  4. GET /open-api/push/history — verify delivery. Status flow: PENDING → PULLED → COMPLETED (or FAILED / CANCELLED).
  5. Optionally DELETE /open-api/push to cancel the pending image before the device wakes.
  6. Optionally PUT /open-api/device/interval to change wake frequency. Takes effect after the next scheduled pull, not the upcoming one.

Examples

Query device status:

curl https://einkshot-349134901638.us-central1.run.app/open-api/device/status \
  -H "Authorization: Bearer $BLOOMIN8_TOKEN_\x3CNAME>"

Response: { "device": { "name", "width", "height", "orientation", "remote_image_interval", "has_pending", "estimated_push_time", ... } }

Push image via URL:

curl -X POST https://einkshot-349134901638.us-central1.run.app/open-api/push \
  -H "Authorization: Bearer $BLOOMIN8_TOKEN_\x3CNAME>" \
  -H "Content-Type: application/json" \
  -d '{"image_url": "https://example.com/photo.jpg"}'

Response: { "remote_image_id": "ri_xyz789", "estimated_push_time": "2026-04-02T11:00:00Z" }

Push markdown content:

curl -X POST https://einkshot-349134901638.us-central1.run.app/open-api/push \
  -H "Authorization: Bearer $BLOOMIN8_TOKEN_\x3CNAME>" \
  -H "Content-Type: application/json" \
  -d '{"content_type": "markdown", "content": "# Hello World\
Today is a great day.", "theme": "minimal"}'

Themes: minimal (default), dark, paper. Server auto-renders markdown to an image matching the device screen size. Note: Markdown-to-image rendering is a cloud-side feature. Local BLE+LAN mode uploads raw images only — if you need to display markdown content via local mode, render it to an image yourself first (e.g. Puppeteer HTML → screenshot).

Key Concepts

  1. Push ≠ instant display. The e-ink device sleeps to save power and wakes on a schedule (10m / 1h / 3h / 6h). The pushed image displays on the next wake. The estimated_push_time field tells you when.
  2. Last-wins — the device only displays the most recently pushed image. If you push multiple times before the device wakes, earlier images are skipped.
  3. Interval changes are delayed — only affect the wake after the next one, since the on-device alarm is already set.
  4. Markdown rendering — the server auto-renders markdown to an image matching the device screen size. See layout rules below to estimate content fit.

Markdown Rendering Rules

Content that exceeds the screen is clipped — no scrolling or pagination. Use the formula below to estimate capacity for any screen size.

Scaling formula:

scale = min(width / 375, height / 812)
All base values below are multiplied by this scale factor.

Base values (before scaling):

Element Base Font Line Height Base Vertical Cost
Body text 18 ×1.7 30.6 + 16 margin
h1 40 (bold) ×1.3 52 + 24 top + 16 bottom
h2 36 (semibold) ×1.3 46.8 + 24 top + 10 bottom
h3 28 (semibold) ×1.4 39.2 + 16 top + 10 bottom
Code block 15 ×1.5 22.5 per line + 40 padding
List item 18 ×1.6 28.8 + 6 gap

Container padding (base): top/bottom = 50, left/right = 60

Quick reference for common screens:

Screen Scale Content Area Body Lines CJK/Line Latin/Line
480×800 0.985 362×702 ~23 ~18 ~45
1200×1600 1.97 964×1403 ~23 ~27 ~65

Body line count is similar across sizes because font and screen scale proportionally. The main difference is characters per line.

Capacity estimates (body text, any screen):

  • Content area: (width - 120×scale) × (height - 100×scale)
  • Lines: content_height / (30.6 × scale)~23 lines for both common screens
  • CJK chars/line: content_width / (20 × scale)
  • Latin chars/line: content_width / (8 × scale)
  • With an h1 title: subtract ~5 lines

Practical guidelines:

  • Each heading costs 2–3 body lines of vertical space — use sparingly
  • Code blocks cost extra due to padding — keep them short
  • For long articles, split into multiple pushes or truncate to fit
  • Supported: h1–h3, p, ul/ol, blockquote, code, table, hr, strong, em, strikethrough (GFM)
  • Themes: minimal (white, default), dark (black), paper (cream/sepia)

Error Handling

All errors return { "success": false, "error": "ERROR_CODE", "message": "..." }.

  • 401 — Missing or invalid Bearer token
  • 403 — Remote push not enabled on device
  • 400 invalid-argument — Bad input: missing image, file >10MB, content >50KB, invalid interval, etc.

Mode 2: Local BLE + LAN (Instant)

Control devices directly over Bluetooth and local WiFi. Images display immediately after upload — no waiting for the next wake cycle.

Device image requirements: The e-ink hardware only accepts JPEG baseline images whose dimensions exactly match the screen size (e.g. 480×800 or 1200×1600). The Bloomin8 CLI handles format conversion and resize automatically — but screen size must be known (via BLE info, cache, or explicit --resize WxH).

Prerequisites

Requires Python 3 with BLE and HTTP libraries. Verify and install:

python3 -c "import bleak, aiohttp, PIL" 2>/dev/null || pip install bleak aiohttp pillow
Package Purpose
bleak BLE scanning and device communication
aiohttp HTTP image upload to device
pillow Image resize/crop to fit screen

Platform notes:

  • macOS — Allow Terminal / your IDE in System Settings → Privacy & Security → Bluetooth
  • Windows — Requires Windows 10+ (native BLE support via WinRT)
  • Linux — Requires BlueZ 5.43+ and DBus (sudo apt install bluez); run with a user in the bluetooth group or use sudo

The CLI script is bundled at scripts/bloomin8_cli.py (the Bloomin8 CLI) relative to this skill file.

Scan for Devices

Find nearby Bloomin8 devices via BLE advertisement:

python scripts/bloomin8_cli.py scan
python scripts/bloomin8_cli.py scan --timeout 15
python scripts/bloomin8_cli.py scan --json

Output is deduplicated by device ID — each device appears once with the strongest signal. Raw advertisement count is shown for reference (BLE devices broadcast repeatedly, so raw count >> actual device count).

Battery display: Only firmware ≥ 1.8.30 broadcasts battery level in BLE advertisements. Older devices will show "N/A". Battery is always available via the info command (which queries the device directly).

Get Device Info

Query device details (IP, firmware, screen size, battery) via BLE wake + notification:

# By device name (partial match)
python scripts/bloomin8_cli.py info --name "Living Room"

# By device ID (from BLE manufacturer data)
python scripts/bloomin8_cli.py info --id "CABBF337"

# JSON output for programmatic use
python scripts/bloomin8_cli.py info --name "Living Room" --json

Timing: The info command takes ~20-30 seconds. It first sends a BLE wake command, waits 8 seconds for the device to boot its WiFi stack, then sends up to 5 getInfo requests (5s timeout each). This is normal — set user expectations accordingly.

Caching: Successful info results are cached to ~/.bloomin8/device_cache.json. If BLE discovery or getInfo fails on a subsequent call, the CLI falls back to cached IP and screen size automatically.

Returns both BLE and HTTP device info including:

{
  "sta_ip": "192.168.x.x",
  "ssid": "WiFi-Name",
  "batt": 48,
  "ver": "1.8.35",
  "w": 1200,
  "h": 1600
}

Upload Image (Instant Display)

Upload an image and display it on the device immediately:

# Auto-discover device via BLE, auto-resize to screen size
python scripts/bloomin8_cli.py upload --name "Living Room" --file image.jpg

# Direct IP (skip BLE discovery entirely — fastest path)
python scripts/bloomin8_cli.py upload --ip 192.168.8.223 --file image.jpg --resize 480x800

# Name + IP combo: skip BLE, use cache for screen size auto-resize
python scripts/bloomin8_cli.py upload --name "Living Room" --ip 192.168.8.199 --file image.jpg

# Explicit screen size (required when no BLE or cache available)
python scripts/bloomin8_cli.py upload --name "Living Room" --file image.jpg --resize 480x800

# Upload without displaying
python scripts/bloomin8_cli.py upload --name "Living Room" --file image.jpg --no-show

# Resize modes: cover (default, center crop), contain (fit with white bg), stretch
python scripts/bloomin8_cli.py upload --name "Living Room" --file image.jpg --mode contain

# JSON output
python scripts/bloomin8_cli.py upload --ip 192.168.8.223 --file image.jpg --resize 480x800 --json

Auto-resize behavior:

  • Via BLE (--name only): reads screen dimensions from device, auto-resizes. This is the safest path.
  • Via name + IP (--name + --ip): skips BLE entirely, looks up cached screen size by device name. Best for repeated uploads after an initial info. Recommended over --ip alone — name is a stable device identifier, whereas IPs can change or be reused by different devices.
  • Via IP (--ip only, no --resize): checks cache for a device matching that IP. If cached screen size is found, auto-resizes using it. If no cache hit, aborts — pass --resize WxH or run info first to populate the cache. Note: IP matching may be unreliable if devices change IPs (DHCP). Prefer --name + --ip for safe cache lookup.

Workflow: BLE scan → connect → wake → get IP + screen size → convert & resize to JPEG baseline → HTTP POST to device /upload endpoint. With --ip, the BLE steps are skipped entirely. Input can be any Pillow-supported format (JPEG, PNG, WebP, BMP, etc.) — the CLI always converts to JPEG baseline output.

Manage Upstream Settings (Advanced)

Configure the device's cloud pull mechanism. This controls how the device fetches images from the Bloomin8 cloud server on a schedule — it's the on-device side of Mode 1 (Cloud API). When upstream is enabled and a token is set, the device periodically pulls pending images pushed via the Cloud API.

When to use: Enabling/disabling cloud push for a device, changing the pull schedule, or pointing the device at a custom server. Most users don't need this — the Bloomin8 app manages these settings. Use this when debugging cloud delivery issues or for advanced configuration.

# View current settings
python scripts/bloomin8_cli.py upstream --ip 192.168.8.223

# Enable upstream with token
python scripts/bloomin8_cli.py upstream --ip 192.168.8.223 --on --token "your-token"

# Disable upstream
python scripts/bloomin8_cli.py upstream --ip 192.168.8.223 --off

# Set custom upstream URL and cron
python scripts/bloomin8_cli.py upstream --ip 192.168.8.223 --url "https://custom.server/api" --cron "0 */6 * * *"

Local Mode Limitations

  • Requires the machine running OpenClaw to have Bluetooth hardware
  • Device must be within BLE range (~10m) for discovery and wake
  • Device must be on the same WiFi network for HTTP upload — same subnet is not enough: AP isolation, VLAN separation, or different access points on the same network can block connectivity. After getting an IP via info, verify reachability with curl http://\x3Cip>/whistle before attempting upload.
  • No cloud token needed — communication is direct

Device Cache

Successful info calls cache device data (name, device_id, IP, screen size) to ~/.bloomin8/device_cache.json. This path is intentionally outside the skill directory — device data persists across skill upgrades/reinstalls and is shared by all Bloomin8 tools. This enables:

  • BLE failure fallback — if BLE scan/getInfo times out, the CLI checks cache for a known IP
  • Fast --ip uploads — use --name "Living Room" --ip 192.168.x.x to skip BLE and still get auto-resize from cached screen size
  • Cache entries include a timestamp; IPs may change if the device reconnects to a different network

JSON Output (--json)

All commands support --json for structured output. When enabled, human-readable emoji/text output is suppressed and a single JSON object is printed to stdout. This is the recommended mode for programmatic/agent use.


Troubleshooting Decision Tree

When an operation fails, follow this diagnostic flow:

Upload / Display Failed

Upload failed?
├─ Check device reachable: curl http://\x3Cip>/whistle
│  ├─ ✅ Reachable → image format issue. Verify JPEG baseline, exact screen dimensions.
│  └─ ❌ Unreachable →
│     ├─ Try BLE wake: python scripts/bloomin8_cli.py info --name "\x3Cname>"
│     │  ├─ ✅ Got new IP → retry upload with new IP
│     │  └─ ❌ BLE also failed →
│     │     ├─ Check Bluetooth permissions (macOS: System Settings → Privacy → Bluetooth)
│     │     ├─ Check device proximity (BLE range ~10m)
│     │     └─ Fall back to Cloud API: POST /open-api/push (device displays on next wake)
│     └─ No BLE hardware → Cloud API is the only option

BLE Scan Finds No Devices

No devices found?
├─ Bluetooth enabled on host machine?
├─ Terminal/IDE has Bluetooth permission? (macOS)
├─ Device powered on and within ~10m?
├─ Try longer scan: --scan-timeout 20
└─ If all fail → use Cloud API with known token

Screen Size Unknown

No screen size for resize?
├─ Check cache: cat ~/.bloomin8/device_cache.json
├─ Run info to populate cache: python scripts/bloomin8_cli.py info --name "\x3Cname>"
├─ Pass explicit size: --resize 480x800 (standard) or --resize 1200x1600 (large)
└─ Common sizes: 480×800 (7.3"), 1200×1600 (10.3")

Still Not Working?

If the above troubleshooting steps don't resolve the issue:

  1. Visit the Bloomin8 Help Center for detailed guides and FAQs
  2. Check the Bloomin8 website for the latest product updates and firmware info
  3. Contact Bloomin8 support through the Help Center for further assistance

Guardrails

  • Always obtain user consent before performing BLE scans, probing local network IPs, or using stored API tokens. Never perform these operations silently.
  • Never fabricate device IDs, token values, or image URLs.
  • If a push or upload fails, report the error — do not retry without user confirmation.
  • Do not change the wake interval without explicit user instruction.
  • For local mode, if BLE scan finds no devices, suggest the user check Bluetooth permissions and device proximity.
安全使用建议
This skill appears coherent with its stated purpose, but keep these practical points in mind before installing: - The skill will perform BLE scans and probe local IPs for devices; the SKILL.md instructs you to confirm scans — pay attention to prompts and don't consent if you don't want local discovery. - You must set device-scoped tokens in environment variables named BLOOMIN8_TOKEN_<DEVICE_NAME>. Only provide tokens you created for the specific device and revoke/regenerate them if you suspect misuse. - The included CLI caches device metadata and IPs at ~/.bloomin8/device_cache.json. If you have privacy concerns, review or delete that file periodically. - Install Python deps (bleak, aiohttp, pillow) in a virtualenv rather than system-wide to limit exposure. - The cloud API URL is a Google Cloud Run endpoint shown in SKILL.md; if you want extra assurance, verify the project/repo (homepage) and the token semantics before using remote pushes. If any of these behaviors are unacceptable (automatic BLE scanning, local IP probing, or storing device info), do not enable the skill or only use cloud-only flows and keep tokens minimal.
功能分析
Type: OpenClaw Skill Name: bloomin8 Version: 2.2.5 The bloomin8 skill provides legitimate functionality for controlling e-ink photo frames via a Cloud API and local BLE/LAN communication. The bundled Python script (scripts/bloomin8_cli.py) implements device discovery, image resizing using Pillow, and HTTP-based uploads to local devices. The SKILL.md instructions include explicit guardrails requiring the AI agent to obtain user consent before performing Bluetooth scans or network probing. No evidence of malicious intent, data exfiltration, or unauthorized persistence was found; the behaviors are consistent with the stated purpose of managing hardware devices.
能力标签
requires-oauth-token
能力评估
Purpose & Capability
Name/description (BLE + cloud push) align with requirements: python3/pip and Python packages (bleak, aiohttp, pillow) are reasonable for BLE, HTTP, and image handling; required env vars are device-scoped BLOOMIN8_TOKEN_* tokens which match the cloud API usage described.
Instruction Scope
SKILL.md focuses on device discovery, status queries, local BLE wake/upload, and cloud REST calls. It explicitly instructs the agent to request user confirmation before BLE scans or probing an IP. The instructions do probe local hosts/IPs and access env vars for tokens — both are necessary for the described functionality.
Install Mechanism
This is instruction-only with one CLI script included; there is no remote download or opaque installer. It requires pip packages but does not perform arbitrary network installs or pull code from unknown shorteners or personal servers.
Credentials
Only BLOOMIN8_TOKEN_* device tokens are required (device-bound tokens per the docs). No unrelated credentials or broad secrets are requested. The skill caches device info locally under ~/.bloomin8/device_cache.json, which is proportionate to its purpose but worth noting.
Persistence & Privilege
The skill is not always-loaded and does not request elevated platform privileges. It writes a per-user cache (~/.bloomin8) which is appropriate for remembering device IPs/sizes; it does not modify other skills or system-wide settings.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install bloomin8
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /bloomin8 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v2.2.5
Fix small screen size description: 7.5 inch → 7.3 inch
v2.2.4
Add homepage link, require explicit user consent before BLE scans and token usage, rename CLI to bloomin8_cli.py
v2.2.3
Switch API base URL from dev to production server
v2.2.2
clarify cache matching logic: name+IP uses name lookup (recommended), IP-only uses IP lookup with DHCP warning
v2.2.1
local-first mode selection, troubleshooting decision tree, --ip cache lookup by IP, upstream marked as advanced, one-liner dependency check
v2.2.0
Enforce JPEG baseline + exact screen-size output; abort upload when screen size unknown; add image sourcing guidance and device format constraints to SKILL.md; remove unused image_utils.py
v2.0.1
Fix: cmd_info missing subscribe_notifications and getInfo command, causing info retrieval to always timeout
v2.0.0
Add local BLE + LAN mode: scan nearby devices, get device info, upload images with instant display. Bundled Python CLI scripts (eink_cli.py, image_utils.py). Device identity bridging across cloud and local modes via device name.
v1.1.0
Token management no longer requires remote push enabled; push/cancel/interval endpoints now document remote_image_on requirement
v1.0.0
Initial release: push images/markdown to e-ink frames, check status, track delivery, change wake schedule
元数据
Slug bloomin8
版本 2.2.5
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 10
常见问题

Bloomin8 是什么?

Push images or markdown to a Bloomin8 e-ink photo frame via cloud API (async) or local BLE+LAN (instant). Scan nearby devices, check status, track delivery,... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 221 次。

如何安装 Bloomin8?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install bloomin8」即可一键安装,无需额外配置。

Bloomin8 是免费的吗?

是的,Bloomin8 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Bloomin8 支持哪些平台?

Bloomin8 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Bloomin8?

由 xander887(@xander887)开发并维护,当前版本 v2.2.5。

💬 留言讨论