Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

PetOS BLE Gateway

БесплатноНе проверен

MCP server for controlling an ESP32-C3 PetOS watch over BLE. Enables scanning, connecting, sending pet actions, and showing frames through MCP tools.

GitHubEmbed

Описание

MCP server for controlling an ESP32-C3 PetOS watch over BLE. Enables scanning, connecting, sending pet actions, and showing frames through MCP tools.

README

PetOS BLE Gateway is a local Node.js bridge for controlling PetOS ESP32 round watch devices over BLE.

It exposes three control surfaces over the same device session:

  • A browser dashboard for scanning, connecting, and sending pet commands.
  • An HTTP API for scripts and local tools.
  • A stdio MCP server for Codex, Claude, and other MCP clients.
Web UI / HTTP API / MCP tool
        |
        v
Node.js gateway
        | BLE JSON + notify state
        v
PetOS watch
        |
        +-- optional WiFi RLE upload endpoint

The gateway keeps Node and watch state synchronized from BLE notifications: connection profile, WiFi IP/ports, active upload progress, active pet slot, current tab, and audio state.

Hardware/Firmware Assumptions

The current firmware family accepts JSON writes on:

  • Service UUID: 7f2a0001-4f6d-45f6-b805-2b0a7a0f9c01
  • Write characteristic UUID: 7f2a0002-4f6d-45f6-b805-2b0a7a0f9c01
  • Notify characteristic UUID: 7f2a0003-4f6d-45f6-b805-2b0a7a0f9c01

The gateway detects the connected device profile from BLE advertising:

  • PetOS-C3: 240x240 C3 round watch, 200px / 24-color pet package target, no audio/IMU controls.
  • PetOS-S3: 360x360 SmartRing Plus, 360px / 48-color pet package target, audio, volume, brightness, IMU/auto-rotate, and pet scale controls.

Device capabilities are returned by /api/status and /api/capabilities. The Web UI, HTTP API, and MCP tools use those capabilities to disable or reject unsupported actions.

Requirements

  • macOS with Bluetooth enabled
  • Node.js 20+
  • A PetOS watch firmware advertising as PetOS-C3 or PetOS-S3

This project uses @abandonware/noble for BLE access. On macOS, the terminal or app running Node may need Bluetooth permission in System Settings.

Install

npm install

Run The Web Gateway

npm start

Open:

http://127.0.0.1:8787

The page lets you scan, connect, see the detected device profile, send named actions, show a fixed frame, switch pet slots, switch watch tabs, show or clear a pet speech bubble, update the watch text page, or write raw JSON. It can also pack Codex pets into .idxrle packages, list saved packages with a preview frame, and upload a saved package to the watch over BLE or WiFi. If a package does not fit the connected device profile, its upload button is disabled with the reason shown in the card.

CLI Smoke Tests

Scan:

npm run scan -- 7000

Send an action:

npm run send -- '{"cmd":"pet.action","value":"review"}'

Show a fixed frame:

npm run send -- '{"cmd":"pet.frame","value":12}'

Upload a pet RLE package:

npm run upload -- /absolute/path/to/pet.idxrle

Pack a Codex pet into a watch-ready RLE package:

npm run pack -- cloud-strife

Pack and upload in one command:

npm run pack-upload -- cloud-strife

The packer uses the standard Codex pet 8x9 sprite sheet layout, removes empty cells, and excludes run_right / run_left for the watch package. When connected, pack defaults follow the device profile: C3 defaults to 200x200 / 24 colors, S3 defaults to 360x360 / 48 colors. Packed packages are saved under packed/<pet>/. Running the same pet/settings again reuses the matching .idxrle; add --force to rebuild:

npm run pack -- cloud-strife --force

BLE JSON Protocol

Play an action:

{"cmd":"pet.action","value":"idle"}
{"cmd":"pet.action","value":"review"}

Show one fixed frame:

{"cmd":"pet.frame","value":12}

Show or clear a pet speech bubble:

{"cmd":"pet.say","text":"Codex 收到了,开始思考"}
{"cmd":"pet.bubble.clear"}

Switch pet slot or UI tab:

{"cmd":"pet.slot","value":1}
{"cmd":"ui.tab","value":"settings","animate":1}

Show multiline text on the second watch page:

{"cmd":"watch.text","title":"Market","text":"#22c55e CPO +2.3%#\n#f97316 NVDA +1.1%#"}

The watch firmware supports LVGL label recolor syntax for simple rich text:

#22c55e green text# #f97316 orange text#

This is not HTML or Markdown. It supports multiline text and color spans, but not mixed font sizes, bold text, or embedded images.

Supported actions in the current firmware:

  • idle
  • waving
  • jumping
  • failed
  • waiting
  • running
  • review

Upload a new pet package:

{"cmd":"rle.begin","size":561600}

Then send binary BLE chunks:

"RLEC" + uint32_le(offset) + raw bytes

Finish:

{"cmd":"rle.end"}

The firmware writes to the selected pet slot (/pets/pet0.idxrle, /pets/pet1.idxrle, or /pets/pet2.idxrle). During upload the watch hides pet frames and shows a progress bar plus an abort button. After rle.end, the gateway waits for the watch notification:

{"event":"rle.complete","a":41,"b":778786}

The web/CLI upload should only be treated as successful after this watch-side acknowledgement. If the upload is interrupted, upload the .idxrle again.

For larger S3 packages, the gateway can configure WiFi over BLE, receive the watch IP/ports from BLE notifications, and upload the .idxrle over the watch TCP pull protocol. BLE upload remains available as a fallback.

HTTP API

Status:

curl http://127.0.0.1:8787/api/status

Capabilities only:

curl http://127.0.0.1:8787/api/capabilities

Scan:

curl -X POST http://127.0.0.1:8787/api/scan \
  -H 'content-type: application/json' \
  -d '{"timeoutMs":7000}'

Connect:

curl -X POST http://127.0.0.1:8787/api/connect \
  -H 'content-type: application/json' \
  -d '{}'

Play an action:

curl -X POST http://127.0.0.1:8787/api/action/review \
  -H 'content-type: application/json' \
  -d '{}'

Send raw JSON:

curl -X POST http://127.0.0.1:8787/api/send \
  -H 'content-type: application/json' \
  -d '{"cmd":"pet.frame","value":12}'

Update the second watch page text:

curl -X POST http://127.0.0.1:8787/api/watch/text \
  -H 'content-type: application/json' \
  -d '{"title":"Market","text":"#22c55e CPO +2.3%#\n#f97316 NVDA +1.1%#"}'

Show or clear the pet speech bubble:

curl -X POST http://127.0.0.1:8787/api/pet/say \
  -H 'content-type: application/json' \
  -d '{"text":"Codex 收到了,开始思考"}'

curl -X POST http://127.0.0.1:8787/api/pet/bubble/clear \
  -H 'content-type: application/json' \
  -d '{}'

Switch pet slot or watch tab:

curl -X POST http://127.0.0.1:8787/api/pet/slot \
  -H 'content-type: application/json' \
  -d '{"value":1}'

curl -X POST http://127.0.0.1:8787/api/tab \
  -H 'content-type: application/json' \
  -d '{"value":"settings"}'

Configure or disconnect watch WiFi:

curl -X POST http://127.0.0.1:8787/api/wifi/config \
  -H 'content-type: application/json' \
  -d '{"ssid":"YOUR_SSID","password":"YOUR_PASSWORD"}'

curl -X POST http://127.0.0.1:8787/api/wifi/disconnect \
  -H 'content-type: application/json' \
  -d '{}'

Upload an .idxrle file:

curl -X POST 'http://127.0.0.1:8787/api/rle/upload?chunkSize=160&delayMs=10' \
  -H 'content-type: application/octet-stream' \
  --data-binary @/absolute/path/to/pet.idxrle

List saved packages:

curl http://127.0.0.1:8787/api/rle/packages

Upload a saved package from packed/:

curl -X POST http://127.0.0.1:8787/api/rle/upload-file \
  -H 'content-type: application/json' \
  -d '{"file":"cloud-strife/cloud-strife_watch-no-lr_200_24.idxrle","chunkSize":160,"delayMs":10}'

Use WiFi for the same saved package:

curl -X POST http://127.0.0.1:8787/api/rle/upload-file \
  -H 'content-type: application/json' \
  -d '{"file":"cloud-strife/cloud-strife_watch-no-lr_360_48.idxrle","transport":"wifi","slot":0}'

Pack a Codex pet:

curl -X POST http://127.0.0.1:8787/api/rle/pack \
  -H 'content-type: application/json' \
  -d '{"name":"cloud-strife","colors":24,"size":200}'

Pack and upload:

curl -X POST http://127.0.0.1:8787/api/rle/pack-upload \
  -H 'content-type: application/json' \
  -d '{"name":"cloud-strife","colors":24,"size":200,"chunkSize":160,"delayMs":10}'

S3-only audio and display controls:

curl -X POST http://127.0.0.1:8787/api/audio/play/meizuo \
  -H 'content-type: application/json' \
  -d '{}'

curl -X POST http://127.0.0.1:8787/api/audio/volume \
  -H 'content-type: application/json' \
  -d '{"value":80}'

curl -X POST http://127.0.0.1:8787/api/display/brightness \
  -H 'content-type: application/json' \
  -d '{"value":80}'

curl -X POST http://127.0.0.1:8787/api/display/autorotate \
  -H 'content-type: application/json' \
  -d '{"enabled":true}'

curl -X POST http://127.0.0.1:8787/api/pet/scale \
  -H 'content-type: application/json' \
  -d '{"value":120}'

MCP Server

Start the gateway first:

npm start

Then run the MCP server:

npm run mcp

For an MCP client, use this command:

node /absolute/path/to/petos-ble-gateway/src/mcp-server.js

Available MCP tools:

  • petos_status
  • petos_scan
  • petos_connect
  • petos_send_json
  • petos_play_action
  • petos_select_pet
  • petos_say
  • petos_clear_bubble
  • petos_open_tab
  • petos_show_frame
  • petos_show_text
  • petos_upload_rle
  • petos_pack_rle
  • petos_pack_upload_pet
  • petos_play_sound
  • petos_set_volume
  • petos_set_brightness
  • petos_set_auto_rotate
  • petos_set_pet_scale

The MCP server calls the local gateway at http://127.0.0.1:8787 by default. Override with:

PETOS_GATEWAY_URL=http://127.0.0.1:8787 npm run mcp

Troubleshooting

If the device does not appear in macOS Bluetooth settings, use this gateway or a BLE scanner such as nRF Connect/LightBlue. Ordinary BLE GATT devices often do not appear like keyboards or headphones.

If scanning hangs or returns no devices:

  • Make sure the watch firmware is advertising PetOS-C3.
  • Make sure the Node process has Bluetooth permission.
  • Try npm run scan -- 10000.
  • Restart the gateway after toggling Bluetooth permissions.

If action buttons appear to do nothing, check the log panel. A successful send looks like:

sent {"cmd":"pet.action","value":"review"}

from github.com/ilimei/petos-ble-gateway

Установка PetOS BLE Gateway

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/ilimei/petos-ble-gateway

FAQ

PetOS BLE Gateway MCP бесплатный?

Да, PetOS BLE Gateway MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для PetOS BLE Gateway?

Нет, PetOS BLE Gateway работает без API-ключей и переменных окружения.

PetOS BLE Gateway — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить PetOS BLE Gateway в Claude Desktop, Claude Code или Cursor?

Открой PetOS BLE Gateway на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare PetOS BLE Gateway with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development