[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M70H7NFQF896ZNB2CVZFC1P9":3,"skill-same:01M70H7NFQF896ZNB2CVZFC1P9":122},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":49,"ownerHtmlUrl":50,"ownerBlogUrl":51,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M70H7NFQF896ZNB2CVZFC1P9","hardware-protocols",null,"Expert hardware communication protocols including MQTT, I2C, SPI, UART, BLE, and WiFi. Use when implementing device-to-device communication, designing MQTT messaging systems, configuring bus protocols, integrating wireless connectivity, troubleshooting protocol issues, or setting up multi-device embedded systems. Particularly relevant for IoT projects, embedded systems with multiple peripherals, and distributed sensor networks.","shengdabai\u002FTony-Claude-Code-Skills","shengdabai","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F116417419?v=4","01M70F6D2WY5PQV5A92BKYJQEW","Tony Sheng","01M70F6D3GAAAYZ5H4CC1G8VXM",3,"MIT","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"protocols","hardware","hardware protocols","use","ble","networks","for","mqtt","communication","embedded systems","when","sensor","implementing","issues","up","expert","wifi","relevant","messaging","projects","2026-11-10 10:12:30",false,"---\nname: hardware-protocols\ndescription: Expert hardware communication protocols including MQTT, I2C, SPI, UART, BLE, and WiFi. Use when implementing device-to-device communication, designing MQTT messaging systems, configuring bus protocols, integrating wireless connectivity, troubleshooting protocol issues, or setting up multi-device embedded systems. Particularly relevant for IoT projects, embedded systems with multiple peripherals, and distributed sensor networks.\n---\n\n# Hardware Communication Protocols\n\n## Overview\n\nImplement reliable hardware communication protocols for embedded systems. This skill covers MQTT (message broker architecture), I2C\u002FSPI (synchronous bus protocols), UART (serial communication), BLE (Bluetooth Low Energy), and WiFi networking. Use this skill when designing communication between microcontrollers, sensors, displays, and networked devices.\n\n## When to Use This Skill\n\nInvoke this skill when:\n- Setting up MQTT broker and client communication\n- Designing topic hierarchies and message flows\n- Implementing I2C sensor reading or device control\n- Configuring SPI displays or high-speed peripherals\n- Establishing UART communication with AT command devices\n- Creating BLE GATT services and characteristics\n- Integrating WiFi connectivity with reconnection strategies\n- Troubleshooting protocol timing or connection issues\n- Building multi-device embedded systems (like Orbit)\n\n## Protocol Selection Guide\n\nChoose the appropriate protocol based on requirements:\n\n**MQTT** - Publish\u002Fsubscribe messaging for distributed systems\n- Use when: Multiple devices need synchronized state updates\n- Topology: Many-to-many through central broker\n- Range: Network-dependent (WiFi\u002FEthernet)\n- Data rate: Lightweight messaging (KB\u002Fs)\n- Orbit usage: All devices ↔ Jetson broker for timer sync, commands\n\n**I2C** - Two-wire synchronous bus for short-distance peripherals\n- Use when: Multiple low-speed sensors\u002Fdevices on shared bus\n- Topology: Master\u002Fslave (one master, multiple slaves)\n- Range: \u003C1 meter on PCB\n- Data rate: 100 KHz - 3.4 MHz\n- Orbit usage: Onboard sensors (temperature, accelerometer)\n\n**SPI** - Four-wire synchronous bus for high-speed peripherals\n- Use when: Fast displays, memory, or sensor communication needed\n- Topology: Master\u002Fslave with individual chip selects\n- Range: \u003C1 meter on PCB\n- Data rate: Up to 50+ MHz\n- Orbit usage: TFT displays on Presto and T-Embed\n\n**UART** - Asynchronous serial for point-to-point communication\n- Use when: Simple bidirectional communication or AT commands\n- Topology: Point-to-point (one-to-one)\n- Range: \u003C15 meters without RS-232\u002FRS-485 drivers\n- Data rate: 9600 - 115200+ baud typical\n- Orbit usage: Debug console, GPS modules\n\n**BLE** - Wireless personal area network with low power\n- Use when: Battery-powered wireless communication needed\n- Topology: Star (central and peripherals)\n- Range: ~10 meters indoors\n- Data rate: ~1 Mbps (effective ~100 KB\u002Fs)\n- Orbit usage: Presto ↔ Android app for notifications\n\n**WiFi** - High-speed wireless networking\n- Use when: Internet connectivity or high-bandwidth local network needed\n- Topology: Star (access point and stations)\n- Range: ~50 meters indoors\n- Data rate: 54 Mbps - 1+ Gbps\n- Orbit usage: All devices connect to home WiFi for MQTT access\n\n## MQTT Implementation\n\n### Broker Setup\n\nFor Orbit's Jetson Nano or any Linux-based MQTT broker, configure Mosquitto with both TCP (embedded devices) and WebSocket (web clients) support.\n\nReference the configuration template in `assets\u002Fmosquitto.conf` and apply it:\n\n```bash\nsudo cp assets\u002Fmosquitto.conf \u002Fetc\u002Fmosquitto\u002Fmosquitto.conf\nsudo systemctl restart mosquitto\nsudo systemctl enable mosquitto\n```\n\nTest the configuration:\n\n```bash\n# Test TCP listener (port 1883)\nmosquitto_pub -h localhost -t test\u002Ftopic -m \"hello\"\n\n# Test WebSocket listener (port 9001)\n# Requires mqtt.js or similar WebSocket MQTT client\nnode -e \"const mqtt=require('mqtt'); const c=mqtt.connect('ws:\u002F\u002Flocalhost:9001'); c.on('connect',()=>{c.publish('test\u002Ftopic','hello');c.end();})\"\n```\n\n### Topic Design Patterns\n\nDesign topic hierarchies for clarity and scalability:\n\n```\n\u003Cproject>\u002F\u003Ccategory>\u002F\u003Caction>\u002F\u003Ctarget>\n\nExamples:\norbit\u002Ftimer\u002Fstate\u002Fcurrent          - Current timer state (retained)\norbit\u002Ftimer\u002Fcontrol\u002Fstart          - Command to start timer\norbit\u002Ftimer\u002Fcontrol\u002Fpause          - Command to pause timer\norbit\u002Fdevice\u002Fpresto\u002Fstatus         - Presto device status (retained)\norbit\u002Fdevice\u002Ftembed\u002Fbattery        - T-Embed battery level\norbit\u002Falert\u002Fvisual\u002Fall             - Visual alert to all devices\norbit\u002Falert\u002Fvisual\u002Fpresto          - Visual alert to specific device\norbit\u002Fmetrics\u002Ffocus\u002F1234567890     - Focus metrics with timestamp\n```\n\n**Topic naming conventions:**\n- Use lowercase with underscores or hyphens\n- Structure hierarchically: general → specific\n- Use `state` for current values (typically retained)\n- Use `control` or `command` for actions\n- Include device ID when targeting specific devices\n- Add timestamp suffix for time-series data\n\n### QoS Level Selection\n\nChoose Quality of Service level based on message importance:\n\n**QoS 0 (At most once)** - Fire and forget\n- Use for: Frequent sensor updates, non-critical status\n- Example: `orbit\u002Fdevice\u002Fpresto\u002Frssi` (WiFi signal strength)\n- Trade-off: Lowest overhead, possible message loss\n\n**QoS 1 (At least once)** - Acknowledged delivery\n- Use for: Commands, important state changes, timer sync\n- Example: `orbit\u002Ftimer\u002Fcontrol\u002Fstart`, `orbit\u002Ftimer\u002Fstate\u002Fcurrent`\n- Trade-off: Guaranteed delivery, possible duplicates\n\n**QoS 2 (Exactly once)** - Guaranteed single delivery\n- Use for: Critical commands where duplicates cause problems\n- Example: Payment transactions, irreversible actions\n- Trade-off: Highest overhead, slowest delivery\n- Note: Rarely needed in Orbit; QoS 1 is typically sufficient\n\n### Retained Messages and Last Will\n\nUse retained messages for state that new clients need immediately:\n\n```python\n# Publish retained message (state persists on broker)\nclient.publish(\"orbit\u002Ftimer\u002Fstate\u002Fcurrent\",\n               json.dumps({\"running\": True, \"remaining\": 900}),\n               qos=1,\n               retain=True)\n\n# New clients automatically receive last retained message\n```\n\nConfigure Last Will and Testament for disconnect detection:\n\n```python\n# Set LWT when connecting\nclient.will_set(\"orbit\u002Fdevice\u002Fpresto\u002Fstatus\",\n                json.dumps({\"online\": False}),\n                qos=1,\n                retain=True)\n\n# On normal connection, publish online status\nclient.publish(\"orbit\u002Fdevice\u002Fpresto\u002Fstatus\",\n               json.dumps({\"online\": True}),\n               qos=1,\n               retain=True)\n\n# If connection lost, broker automatically publishes LWT\n```\n\n### Connection and Reconnection Strategy\n\nImplement robust reconnection with exponential backoff. See `scripts\u002Fmqtt_connection.py` for a complete reference implementation.\n\nKey principles:\n1. **Clean Session vs Persistent Session**\n   - Clean session (clean_start=True): Discard subscriptions on disconnect\n   - Persistent session (clean_start=False): Maintain subscriptions and queue QoS 1\u002F2 messages\n   - Orbit: Use persistent sessions for devices, clean for short-lived clients\n\n2. **Keep-Alive Interval**\n   - Set to 60 seconds for stable networks\n   - Set to 30 seconds for unreliable WiFi\n   - Must send PING before interval expires to maintain connection\n\n3. **Automatic Reconnection**\n   - Implement exponential backoff: 1s, 2s, 4s, 8s... up to 60s\n   - Reset backoff timer on successful connection\n   - Queue messages locally during disconnection (with size limit)\n\n4. **Connection State Handling**\n   - Implement connection callbacks: on_connect, on_disconnect\n   - Re-subscribe to topics in on_connect callback\n   - Update UI\u002FLEDs to show connection status\n   - Log connection events for debugging\n\n## I2C Protocol\n\n### Master Configuration\n\nConfigure I2C master on ESP32 or RP2350:\n\n```cpp\n\u002F\u002F ESP-IDF example\n#include \"driver\u002Fi2c.h\"\n\n#define I2C_MASTER_SCL_IO    22      \u002F\u002F GPIO for SCL\n#define I2C_MASTER_SDA_IO    21      \u002F\u002F GPIO for SDA\n#define I2C_MASTER_FREQ_HZ   100000  \u002F\u002F 100 KHz standard mode\n\ni2c_config_t conf = {\n    .mode = I2C_MODE_MASTER,\n    .sda_io_num = I2C_MASTER_SDA_IO,\n    .scl_io_num = I2C_MASTER_SCL_IO,\n    .sda_pullup_en = GPIO_PULLUP_ENABLE,\n    .scl_pullup_en = GPIO_PULLUP_ENABLE,\n    .master.clk_speed = I2C_MASTER_FREQ_HZ,\n};\n\ni2c_param_config(I2C_NUM_0, &conf);\ni2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);\n```\n\n**Pull-up resistors**: Required for I2C operation\n- Typical values: 2.2 KΩ - 10 KΩ\n- Lower values (2.2 KΩ) for longer traces or higher capacitance\n- Higher values (10 KΩ) for slower speeds or power savings\n- Many development boards include onboard pull-ups\n\n### Device Addressing\n\nI2C uses 7-bit addressing (128 possible addresses):\n\n```\nCommon I2C addresses:\n0x68 - MPU-6050 (accelerometer\u002Fgyroscope)\n0x76 or 0x77 - BMP280 (pressure\u002Ftemperature)\n0x3C or 0x3D - SSD1306 (OLED display)\n0x48-0x4F - ADS1115 (ADC)\n\nSpecial addresses:\n0x00 - General call address\n0x01-0x07 - Reserved\n0x78-0x7F - Reserved\n```\n\nScan for devices on the bus:\n\n```cpp\nfor (uint8_t addr = 1; addr \u003C 127; addr++) {\n    i2c_cmd_handle_t cmd = i2c_cmd_link_create();\n    i2c_master_start(cmd);\n    i2c_master_write_byte(cmd, (addr \u003C\u003C 1) | I2C_MASTER_WRITE, true);\n    i2c_master_stop(cmd);\n\n    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 50 \u002F portTICK_PERIOD_MS);\n    i2c_cmd_link_delete(cmd);\n\n    if (ret == ESP_OK) {\n        printf(\"Found device at 0x%02X\\n\", addr);\n    }\n}\n```\n\n### Reading Sensors\n\nReference implementation in `scripts\u002Fi2c_sensor.py` demonstrates reading from I2C sensors with proper error handling.\n\nBasic I2C read transaction:\n\n```cpp\nesp_err_t i2c_read_sensor(uint8_t device_addr, uint8_t reg_addr,\n                          uint8_t* data, size_t len) {\n    i2c_cmd_handle_t cmd = i2c_cmd_link_create();\n\n    \u002F\u002F Write register address\n    i2c_master_start(cmd);\n    i2c_master_write_byte(cmd, (device_addr \u003C\u003C 1) | I2C_MASTER_WRITE, true);\n    i2c_master_write_byte(cmd, reg_addr, true);\n\n    \u002F\u002F Read data\n    i2c_master_start(cmd);  \u002F\u002F Repeated start\n    i2c_master_write_byte(cmd, (device_addr \u003C\u003C 1) | I2C_MASTER_READ, true);\n    i2c_master_read(cmd, data, len, I2C_MASTER_LAST_NACK);\n    i2c_master_stop(cmd);\n\n    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 \u002F portTICK_PERIOD_MS);\n    i2c_cmd_link_delete(cmd);\n\n    return ret;\n}\n```\n\n**Error handling:**\n- Check return value for timeout or NACK\n- Retry with exponential backoff on transient failures\n- Reset bus on persistent failures\n- Log errors with context (address, register, data)\n\n## SPI Protocol\n\n### Master Configuration\n\nConfigure SPI master for displays or high-speed peripherals:\n\n```cpp\n\u002F\u002F ESP-IDF example for SPI display\n#include \"driver\u002Fspi_master.h\"\n\n#define PIN_MOSI  23\n#define PIN_CLK   18\n#define PIN_CS    5\n#define PIN_DC    17  \u002F\u002F Data\u002FCommand select\n#define PIN_RST   16  \u002F\u002F Reset\n\nspi_bus_config_t bus_cfg = {\n    .mosi_io_num = PIN_MOSI,\n    .miso_io_num = -1,  \u002F\u002F Not used for display\n    .sclk_io_num = PIN_CLK,\n    .quadwp_io_num = -1,\n    .quadhd_io_num = -1,\n    .max_transfer_sz = 320 * 240 * 2 + 8,  \u002F\u002F Display buffer size\n};\n\nspi_device_interface_config_t dev_cfg = {\n    .clock_speed_hz = 40 * 1000 * 1000,  \u002F\u002F 40 MHz\n    .mode = 0,  \u002F\u002F SPI mode 0 (CPOL=0, CPHA=0)\n    .spics_io_num = PIN_CS,\n    .queue_size = 7,\n    .pre_cb = nullptr,  \u002F\u002F Pre-transfer callback\n};\n\nspi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO);\nspi_bus_add_device(SPI2_HOST, &dev_cfg, &spi_handle);\n```\n\n### SPI Modes (CPOL and CPHA)\n\nSPI has four modes based on clock polarity and phase:\n\n```\nMode | CPOL | CPHA | Description\n-----|------|------|--------------------------------------------------\n0    | 0    | 0    | Data sampled on rising edge, shifted on falling\n1    | 0    | 1    | Data sampled on falling edge, shifted on rising\n2    | 1    | 0    | Data sampled on falling edge, shifted on rising\n3    | 1    | 1    | Data sampled on rising edge, shifted on falling\n\nCommon devices:\n- Most displays: Mode 0 or Mode 3\n- SD cards: Mode 0\n- MAX31855 thermocouple: Mode 0\n```\n\nVerify the correct mode in the datasheet - using the wrong mode causes garbled data.\n\n### DMA Transfers\n\nUse DMA for large data transfers to reduce CPU load:\n\n```cpp\n\u002F\u002F Prepare transaction\nspi_transaction_t trans = {\n    .length = buffer_size * 8,  \u002F\u002F Length in bits\n    .tx_buffer = buffer,\n    .rx_buffer = nullptr,\n};\n\n\u002F\u002F Non-blocking DMA transfer\nspi_device_queue_trans(spi_handle, &trans, portMAX_DELAY);\n\n\u002F\u002F Do other work while transfer happens...\n\n\u002F\u002F Wait for completion\nspi_transaction_t* ret_trans;\nspi_device_get_trans_result(spi_handle, &ret_trans, portMAX_DELAY);\n```\n\n**Performance considerations:**\n- Use DMA for transfers >64 bytes\n- Align buffers to 4-byte boundaries for DMA\n- Queue multiple transactions to keep bus busy\n- Consider double-buffering for continuous updates\n\nSee `scripts\u002Fspi_display.py` for a complete SPI display driver example.\n\n## UART Protocol\n\n### Configuration\n\nConfigure UART with proper frame format:\n\n```cpp\n\u002F\u002F ESP-IDF example\n#include \"driver\u002Fuart.h\"\n\n#define UART_NUM      UART_NUM_1\n#define TXD_PIN       17\n#define RXD_PIN       16\n#define BAUD_RATE     115200\n\nuart_config_t uart_config = {\n    .baud_rate = BAUD_RATE,\n    .data_bits = UART_DATA_8_BITS,\n    .parity = UART_PARITY_DISABLE,\n    .stop_bits = UART_STOP_BITS_1,\n    .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,\n};\n\nuart_param_config(UART_NUM, &uart_config);\nuart_set_pin(UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);\nuart_driver_install(UART_NUM, 1024, 1024, 0, NULL, 0);\n```\n\n**Flow control:**\n- None: Simple point-to-point, ensure receiver can keep up\n- Software (XON\u002FXOFF): Use when hardware flow control unavailable\n- Hardware (RTS\u002FCTS): Preferred for reliable high-speed communication\n\n### AT Command Interface\n\nMany modules (WiFi, BLE, GPS) use AT command interface. Reference `scripts\u002Fuart_parser.py` for a complete command parser with state machine.\n\nBasic AT command handling:\n\n```cpp\nvoid send_at_command(const char* cmd, char* response, size_t max_len) {\n    \u002F\u002F Send command with CR+LF\n    uart_write_bytes(UART_NUM, cmd, strlen(cmd));\n    uart_write_bytes(UART_NUM, \"\\r\\n\", 2);\n\n    \u002F\u002F Read response with timeout\n    int len = uart_read_bytes(UART_NUM, (uint8_t*)response,\n                              max_len - 1, 1000 \u002F portTICK_PERIOD_MS);\n    response[len] = '\\0';\n\n    \u002F\u002F Check for OK\u002FERROR\n    if (strstr(response, \"OK\")) {\n        \u002F\u002F Success\n    } else if (strstr(response, \"ERROR\")) {\n        \u002F\u002F Failed\n    }\n}\n```\n\n**AT command best practices:**\n- Wait for \"OK\" before sending next command\n- Implement timeout for each command\n- Handle unsolicited responses (events)\n- Buffer partial lines until CR+LF received\n- Use state machine for complex command sequences\n\n## BLE Protocol\n\n### GATT Server Structure\n\nDesign GATT services with characteristics for each data type:\n\n```\nService: Timer Control (UUID: custom)\n├── Characteristic: State (UUID: 0x2A00)\n│   ├── Properties: Read, Notify\n│   ├── Value: {\"running\": bool, \"remaining\": uint32}\n│   └── Descriptor: CCCD (0x2902) for notifications\n├── Characteristic: Command (UUID: 0x2A01)\n│   ├── Properties: Write\n│   └── Value: {\"action\": \"start\"|\"pause\"|\"reset\", \"duration\": uint32}\n└── Characteristic: Battery (UUID: 0x2A19)\n    ├── Properties: Read, Notify\n    └── Value: uint8 (percentage)\n```\n\n### Connection Parameters\n\nOptimize connection intervals for use case:\n\n```cpp\n\u002F\u002F Fast updates (timer display): 20ms - 40ms interval\n\u002F\u002F Power saving (idle): 200ms - 400ms interval\n\nble_gap_conn_params_t conn_params = {\n    .min_conn_interval = 16,  \u002F\u002F 16 * 1.25ms = 20ms\n    .max_conn_interval = 32,  \u002F\u002F 32 * 1.25ms = 40ms\n    .slave_latency = 0,       \u002F\u002F No latency for real-time updates\n    .conn_sup_timeout = 400,  \u002F\u002F 400 * 10ms = 4s timeout\n};\n```\n\n**Trade-offs:**\n- Faster intervals: Lower latency, higher power consumption\n- Slower intervals: Longer latency, better battery life\n- Slave latency: Skip N intervals to save power (adds latency)\n\n### Notifications vs Indications\n\nChoose the appropriate characteristic property:\n\n**Notifications** (unacknowledged)\n- Use for: Frequent sensor updates, timer ticks\n- Advantage: Lower overhead, higher throughput\n- Disadvantage: No delivery guarantee\n\n**Indications** (acknowledged)\n- Use for: Important commands, critical state changes\n- Advantage: Guaranteed delivery with acknowledgment\n- Disadvantage: Higher overhead, lower throughput\n\nReference `scripts\u002Fble_gatt_server.py` for a complete BLE GATT server implementation.\n\n## WiFi Integration\n\n### Connection Management\n\nImplement robust WiFi connection with automatic reconnection:\n\n```cpp\n\u002F\u002F ESP-IDF example\nvoid wifi_init() {\n    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();\n    esp_wifi_init(&cfg);\n\n    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);\n    esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL);\n\n    wifi_config_t wifi_config = {\n        .sta = {\n            .ssid = WIFI_SSID,\n            .password = WIFI_PASS,\n            .threshold.authmode = WIFI_AUTH_WPA2_PSK,\n        },\n    };\n\n    esp_wifi_set_mode(WIFI_MODE_STA);\n    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);\n    esp_wifi_start();\n}\n\nvoid event_handler(void* arg, esp_event_base_t event_base,\n                   int32_t event_id, void* event_data) {\n    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {\n        esp_wifi_connect();  \u002F\u002F Auto-reconnect\n    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {\n        \u002F\u002F Connected - start MQTT client\n    }\n}\n```\n\n### mDNS Service Discovery\n\nUse mDNS to discover MQTT broker without hardcoded IP:\n\n```cpp\n\u002F\u002F Advertise MQTT broker (Jetson)\nmdns_init();\nmdns_hostname_set(\"orbit-broker\");\nmdns_service_add(\"Orbit MQTT\", \"_mqtt\", \"_tcp\", 1883, NULL, 0);\n\n\u002F\u002F Discover MQTT broker (devices)\nmdns_result_t* results = NULL;\nesp_err_t err = mdns_query_ptr(\"_mqtt\", \"_tcp\", 3000, 20, &results);\n\nif (err == ESP_OK && results) {\n    mdns_result_t* r = results;\n    while (r) {\n        printf(\"Found MQTT broker: %s at %s:%d\\n\",\n               r->hostname, ip4addr_ntoa(&r->addr->addr.u_addr.ip4), r->port);\n        r = r->next;\n    }\n    mdns_query_results_free(results);\n}\n```\n\n## Orbit System Integration\n\n### Device Communication Architecture\n\n```\n                    ┌─────────────────┐\n                    │  Jetson Nano    │\n                    │  MQTT Broker    │\n                    │  (Mosquitto)    │\n                    └────────┬────────┘\n                             │\n        ┌────────────────────┼────────────────────┐\n        │                    │                    │\n  WiFi (MQTT)          WiFi (MQTT)          WiFi (MQTT)\n        │                    │                    │\n┌───────▼────────┐  ┌────────▼────────┐  ┌───────▼────────┐\n│ Presto (RP2350)│  │ T-Embed (ESP32) │  │  Stream Deck   │\n│  SPI Display   │  │  SPI Display    │  │   (WebSocket)  │\n│  BLE Server    │  │  I2C Sensors    │  │                │\n└───────┬────────┘  └─────────────────┘  └────────────────┘\n        │\n   BLE (GATT)\n        │\n┌───────▼────────┐\n│  Android App   │\n│  BLE Client    │\n└────────────────┘\n```\n\n### Message Flow Examples\n\n**Timer Start from Stream Deck:**\n1. User presses Stream Deck button\n2. Plugin publishes: `orbit\u002Ftimer\u002Fcontrol\u002Fstart` with `{\"duration\": 1500}`\n3. Jetson receives and broadcasts: `orbit\u002Ftimer\u002Fstate\u002Fcurrent` (retained)\n4. All devices receive state update and display timer\n5. Presto sends BLE notification to Android app\n\n**Visual Alert:**\n1. Jetson detects timer completion\n2. Publishes: `orbit\u002Falert\u002Fvisual\u002Fall` with `{\"priority\": \"standard\", \"pattern\": \"pulse\"}`\n3. Presto and T-Embed display visual alerts\n4. Devices acknowledge: `orbit\u002Fdevice\u002F{id}\u002Fack`\n\n**Battery Level Monitoring:**\n1. T-Embed periodically checks battery via I2C fuel gauge\n2. Publishes: `orbit\u002Fdevice\u002Ftembed\u002Fbattery` with percentage\n3. Jetson logs metric and checks threshold\n4. If low: `orbit\u002Falert\u002Fvisual\u002Ftembed` with low battery warning\n\n## Troubleshooting\n\n### MQTT Issues\n\n**Connection refused:**\n- Check firewall: `sudo ufw allow 1883` and `sudo ufw allow 9001`\n- Verify broker running: `sudo systemctl status mosquitto`\n- Check logs: `sudo journalctl -u mosquitto -f`\n\n**Messages not received:**\n- Verify topic spelling (case-sensitive)\n- Check QoS level and subscription\n- Monitor with: `mosquitto_sub -h localhost -t '#' -v` (all topics)\n\n**WebSocket connection fails:**\n- Verify WebSocket listener in mosquitto.conf\n- Test with: `wscat -c ws:\u002F\u002Fbroker-ip:9001\u002Fmqtt`\n- Check CORS if from browser\n\n### I2C Issues\n\n**Device not detected:**\n- Check wiring: SDA\u002FSCL not swapped\n- Verify pull-up resistors present (2.2K - 10K)\n- Scan bus: Use I2C scanner code above\n- Check device address in datasheet (some have configurable bits)\n\n**Timeout or NACK:**\n- Reduce clock speed (try 100 KHz)\n- Check power supply to device\n- Verify device is ready (some need initialization delay)\n- Check for bus contention (multiple masters)\n\n### SPI Issues\n\n**Garbled data:**\n- Verify SPI mode (CPOL\u002FCPHA)\n- Check clock speed (try slower)\n- Confirm MISO\u002FMOSI not swapped\n- Verify CS timing (some devices need delay)\n\n**No response:**\n- Check chip select (active low typically)\n- Verify device powered\n- Check MOSI\u002FCLK signals with logic analyzer\n- Some devices need initialization sequence\n\n### BLE Issues\n\n**Connection drops:**\n- Increase connection timeout\n- Reduce connection interval\n- Check for RF interference\n- Verify power supply stable\n\n**Cannot discover device:**\n- Check advertising interval and window\n- Verify device name\u002FUUID\n- Check iOS\u002FAndroid BLE permissions\n- Scan longer or restart Bluetooth\n\n### WiFi Issues\n\n**Cannot connect:**\n- Verify SSID and password\n- Check WiFi band (2.4 GHz vs 5 GHz)\n- Try static IP if DHCP fails\n- Check router firewall\u002FMAC filtering\n\n**Frequent disconnections:**\n- Reduce WiFi power saving\n- Improve signal strength (closer to AP)\n- Check for channel congestion\n- Use WiFi analyzer to find better channel\n\n## Bundled Resources\n\n### scripts\u002F\n\nExecutable reference implementations:\n- `mqtt_connection.py` - MQTT client with robust reconnection logic\n- `ble_gatt_server.py` - BLE GATT server with services and characteristics\n- `i2c_sensor.py` - I2C sensor reading with error handling\n- `spi_display.py` - SPI display driver with DMA\n- `uart_parser.py` - UART command parser with state machine\n\nThese can be executed directly or adapted for specific hardware platforms.\n\n### references\u002F\n\nDetailed protocol documentation:\n- `mqtt_reference.md` - Complete MQTT protocol specification and patterns\n- `embedded_bus_protocols.md` - I2C, SPI, UART detailed specs\n- `wireless_protocols.md` - BLE and WiFi comprehensive guides\n- `orbit_integration.md` - Orbit-specific integration patterns and topic schemas\n\nLoad these references when deep protocol knowledge is needed.\n\n### assets\u002F\n\nConfiguration templates:\n- `mosquitto.conf` - Production-ready Mosquitto configuration (TCP + WebSocket)\n- `platformio_examples\u002F` - PlatformIO project configurations for ESP32 and RP2350\n\nCopy these templates to projects and customize as needed.\n","# Hardware Communication Protocols\n\n## Overview\n\nImplement reliable hardware communication protocols for embedded systems. This skill covers MQTT (message broker architecture), I2C\u002FSPI (synchronous bus protocols), UART (serial communication), BLE (Bluetooth Low Energy), and WiFi networking. Use this skill when designing communication between microcontrollers, sensors, displays, and networked devices.\n\n## When to Use This Skill\n\nInvoke this skill when:\n- Setting up MQTT broker and client communication\n- Designing topic hierarchies and message flows\n- Implementing I2C sensor reading or device control\n- Configuring SPI displays or high-speed peripherals\n- Establishing UART communication with AT command devices\n- Creating BLE GATT services and characteristics\n- Integrating WiFi connectivity with reconnection strategies\n- Troubleshooting protocol timing or connection issues\n- Building multi-device embedded systems (like Orbit)\n\n## Protocol Selection Guide\n\nChoose the appropriate protocol based on requirements:\n\n**MQTT** - Publish\u002Fsubscribe messaging for distributed systems\n- Use when: Multiple devices need synchronized state updates\n- Topology: Many-to-many through central broker\n- Range: Network-dependent (WiFi\u002FEthernet)\n- Data rate: Lightweight messaging (KB\u002Fs)\n- Orbit usage: All devices ↔ Jetson broker for timer sync, commands\n\n**I2C** - Two-wire synchronous bus for short-distance peripherals\n- Use when: Multiple low-speed sensors\u002Fdevices on shared bus\n- Topology: Master\u002Fslave (one master, multiple slaves)\n- Range: \u003C1 meter on PCB\n- Data rate: 100 KHz - 3.4 MHz\n- Orbit usage: Onboard sensors (temperature, accelerometer)\n\n**SPI** - Four-wire synchronous bus for high-speed peripherals\n- Use when: Fast displays, memory, or sensor communication needed\n- Topology: Master\u002Fslave with individual chip selects\n- Range: \u003C1 meter on PCB\n- Data rate: Up to 50+ MHz\n- Orbit usage: TFT displays on Presto and T-Embed\n\n**UART** - Asynchronous serial for point-to-point communication\n- Use when: Simple bidirectional communication or AT commands\n- Topology: Point-to-point (one-to-one)\n- Range: \u003C15 meters without RS-232\u002FRS-485 drivers\n- Data rate: 9600 - 115200+ baud typical\n- Orbit usage: Debug console, GPS modules\n\n**BLE** - Wireless personal area network with low power\n- Use when: Battery-powered wireless communication needed\n- Topology: Star (central and peripherals)\n- Range: ~10 meters indoors\n- Data rate: ~1 Mbps (effective ~100 KB\u002Fs)\n- Orbit usage: Presto ↔ Android app for notifications\n\n**WiFi** - High-speed wireless networking\n- Use when: Internet connectivity or high-bandwidth local network needed\n- Topology: Star (access point and stations)\n- Range: ~50 meters indoors\n- Data rate: 54 Mbps - 1+ Gbps\n- Orbit usage: All devices connect to home WiFi for MQTT access\n\n## MQTT Implementation\n\n### Broker Setup\n\nFor Orbit's Jetson Nano or any Linux-based MQTT broker, configure Mosquitto with both TCP (embedded devices) and WebSocket (web clients) support.\n\nReference the configuration template in `assets\u002Fmosquitto.conf` and apply it:\n\n```bash\nsudo cp assets\u002Fmosquitto.conf \u002Fetc\u002Fmosquitto\u002Fmosquitto.conf\nsudo systemctl restart mosquitto\nsudo systemctl enable mosquitto\n```\n\nTest the configuration:\n\n```bash\n# Test TCP listener (port 1883)\nmosquitto_pub -h localhost -t test\u002Ftopic -m \"hello\"\n\n# Test WebSocket listener (port 9001)\n# Requires mqtt.js or similar WebSocket MQTT client\nnode -e \"const mqtt=require('mqtt'); const c=mqtt.connect('ws:\u002F\u002Flocalhost:9001'); c.on('connect',()=>{c.publish('test\u002Ftopic','hello');c.end();})\"\n```\n\n### Topic Design Patterns\n\nDesign topic hierarchies for clarity and scalability:\n\n```\n\u003Cproject>\u002F\u003Ccategory>\u002F\u003Caction>\u002F\u003Ctarget>\n\nExamples:\norbit\u002Ftimer\u002Fstate\u002Fcurrent          - Current timer state (retained)\norbit\u002Ftimer\u002Fcontrol\u002Fstart          - Command to start timer\norbit\u002Ftimer\u002Fcontrol\u002Fpause          - Command to pause timer\norbit\u002Fdevice\u002Fpresto\u002Fstatus         - Presto device status (retained)\norbit\u002Fdevice\u002Ftembed\u002Fbattery        - T-Embed battery level\norbit\u002Falert\u002Fvisual\u002Fall             - Visual alert to all devices\norbit\u002Falert\u002Fvisual\u002Fpresto          - Visual alert to specific device\norbit\u002Fmetrics\u002Ffocus\u002F1234567890     - Focus metrics with timestamp\n```\n\n**Topic naming conventions:**\n- Use lowercase with underscores or hyphens\n- Structure hierarchically: general → specific\n- Use `state` for current values (typically retained)\n- Use `control` or `command` for actions\n- Include device ID when targeting specific devices\n- Add timestamp suffix for time-series data\n\n### QoS Level Selection\n\nChoose Quality of Service level based on message importance:\n\n**QoS 0 (At most once)** - Fire and forget\n- Use for: Frequent sensor updates, non-critical status\n- Example: `orbit\u002Fdevice\u002Fpresto\u002Frssi` (WiFi signal strength)\n- Trade-off: Lowest overhead, possible message loss\n\n**QoS 1 (At least once)** - Acknowledged delivery\n- Use for: Commands, important state changes, timer sync\n- Example: `orbit\u002Ftimer\u002Fcontrol\u002Fstart`, `orbit\u002Ftimer\u002Fstate\u002Fcurrent`\n- Trade-off: Guaranteed delivery, possible duplicates\n\n**QoS 2 (Exactly once)** - Guaranteed single delivery\n- Use for: Critical commands where duplicates cause problems\n- Example: Payment transactions, irreversible actions\n- Trade-off: Highest overhead, slowest delivery\n- Note: Rarely needed in Orbit; QoS 1 is typically sufficient\n\n### Retained Messages and Last Will\n\nUse retained messages for state that new clients need immediately:\n\n```python\n# Publish retained message (state persists on broker)\nclient.publish(\"orbit\u002Ftimer\u002Fstate\u002Fcurrent\",\n               json.dumps({\"running\": True, \"remaining\": 900}),\n               qos=1,\n               retain=True)\n\n# New clients automatically receive last retained message\n```\n\nConfigure Last Will and Testament for disconnect detection:\n\n```python\n# Set LWT when connecting\nclient.will_set(\"orbit\u002Fdevice\u002Fpresto\u002Fstatus\",\n                json.dumps({\"online\": False}),\n                qos=1,\n                retain=True)\n\n# On normal connection, publish online status\nclient.publish(\"orbit\u002Fdevice\u002Fpresto\u002Fstatus\",\n               json.dumps({\"online\": True}),\n               qos=1,\n               retain=True)\n\n# If connection lost, broker automatically publishes LWT\n```\n\n### Connection and Reconnection Strategy\n\nImplement robust reconnection with exponential backoff. See `scripts\u002Fmqtt_connection.py` for a complete reference implementation.\n\nKey principles:\n1. **Clean Session vs Persistent Session**\n   - Clean session (clean_start=True): Discard subscriptions on disconnect\n   - Persistent session (clean_start=False): Maintain subscriptions and queue QoS 1\u002F2 messages\n   - Orbit: Use persistent sessions for devices, clean for short-lived clients\n\n2. **Keep-Alive Interval**\n   - Set to 60 seconds for stable networks\n   - Set to 30 seconds for unreliable WiFi\n   - Must send PING before interval expires to maintain connection\n\n3. **Automatic Reconnection**\n   - Implement exponential backoff: 1s, 2s, 4s, 8s... up to 60s\n   - Reset backoff timer on successful connection\n   - Queue messages locally during disconnection (with size limit)\n\n4. **Connection State Handling**\n   - Implement connection callbacks: on_connect, on_disconnect\n   - Re-subscribe to topics in on_connect callback\n   - Update UI\u002FLEDs to show connection status\n   - Log connection events for debugging\n\n## I2C Protocol\n\n### Master Configuration\n\nConfigure I2C master on ESP32 or RP2350:\n\n```cpp\n\u002F\u002F ESP-IDF example\n#include \"driver\u002Fi2c.h\"\n\n#define I2C_MASTER_SCL_IO    22      \u002F\u002F GPIO for SCL\n#define I2C_MASTER_SDA_IO    21      \u002F\u002F GPIO for SDA\n#define I2C_MASTER_FREQ_HZ   100000  \u002F\u002F 100 KHz standard mode\n\ni2c_config_t conf = {\n    .mode = I2C_MODE_MASTER,\n    .sda_io_num = I2C_MASTER_SDA_IO,\n    .scl_io_num = I2C_MASTER_SCL_IO,\n    .sda_pullup_en = GPIO_PULLUP_ENABLE,\n    .scl_pullup_en = GPIO_PULLUP_ENABLE,\n    .master.clk_speed = I2C_MASTER_FREQ_HZ,\n};\n\ni2c_param_config(I2C_NUM_0, &conf);\ni2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);\n```\n\n**Pull-up resistors**: Required for I2C operation\n- Typical values: 2.2 KΩ - 10 KΩ\n- Lower values (2.2 KΩ) for longer traces or higher capacitance\n- Higher values (10 KΩ) for slower speeds or power savings\n- Many development boards include onboard pull-ups\n\n### Device Addressing\n\nI2C uses 7-bit addressing (128 possible addresses):\n\n```\nCommon I2C addresses:\n0x68 - MPU-6050 (accelerometer\u002Fgyroscope)\n0x76 or 0x77 - BMP280 (pressure\u002Ftemperature)\n0x3C or 0x3D - SSD1306 (OLED display)\n0x48-0x4F - ADS1115 (ADC)\n\nSpecial addresses:\n0x00 - General call address\n0x01-0x07 - Reserved\n0x78-0x7F - Reserved\n```\n\nScan for devices on the bus:\n\n```cpp\nfor (uint8_t addr = 1; addr \u003C 127; addr++) {\n    i2c_cmd_handle_t cmd = i2c_cmd_link_create();\n    i2c_master_start(cmd);\n    i2c_master_write_byte(cmd, (addr \u003C\u003C 1) | I2C_MASTER_WRITE, true);\n    i2c_master_stop(cmd);\n\n    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 50 \u002F portTICK_PERIOD_MS);\n    i2c_cmd_link_delete(cmd);\n\n    if (ret == ESP_OK) {\n        printf(\"Found device at 0x%02X\\n\", addr);\n    }\n}\n```\n\n### Reading Sensors\n\nReference implementation in `scripts\u002Fi2c_sensor.py` demonstrates reading from I2C sensors with proper error handling.\n\nBasic I2C read transaction:\n\n```cpp\nesp_err_t i2c_read_sensor(uint8_t device_addr, uint8_t reg_addr,\n                          uint8_t* data, size_t len) {\n    i2c_cmd_handle_t cmd = i2c_cmd_link_create();\n\n    \u002F\u002F Write register address\n    i2c_master_start(cmd);\n    i2c_master_write_byte(cmd, (device_addr \u003C\u003C 1) | I2C_MASTER_WRITE, true);\n    i2c_master_write_byte(cmd, reg_addr, true);\n\n    \u002F\u002F Read data\n    i2c_master_start(cmd);  \u002F\u002F Repeated start\n    i2c_master_write_byte(cmd, (device_addr \u003C\u003C 1) | I2C_MASTER_READ, true);\n    i2c_master_read(cmd, data, len, I2C_MASTER_LAST_NACK);\n    i2c_master_stop(cmd);\n\n    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 \u002F portTICK_PERIOD_MS);\n    i2c_cmd_link_delete(cmd);\n\n    return ret;\n}\n```\n\n**Error handling:**\n- Check return value for timeout or NACK\n- Retry with exponential backoff on transient failures\n- Reset bus on persistent failures\n- Log errors with context (address, register, data)\n\n## SPI Protocol\n\n### Master Configuration\n\nConfigure SPI master for displays or high-speed peripherals:\n\n```cpp\n\u002F\u002F ESP-IDF example for SPI display\n#include \"driver\u002Fspi_master.h\"\n\n#define PIN_MOSI  23\n#define PIN_CLK   18\n#define PIN_CS    5\n#define PIN_DC    17  \u002F\u002F Data\u002FCommand select\n#define PIN_RST   16  \u002F\u002F Reset\n\nspi_bus_config_t bus_cfg = {\n    .mosi_io_num = PIN_MOSI,\n    .miso_io_num = -1,  \u002F\u002F Not used for display\n    .sclk_io_num = PIN_CLK,\n    .quadwp_io_num = -1,\n    .quadhd_io_num = -1,\n    .max_transfer_sz = 320 * 240 * 2 + 8,  \u002F\u002F Display buffer size\n};\n\nspi_device_interface_config_t dev_cfg = {\n    .clock_speed_hz = 40 * 1000 * 1000,  \u002F\u002F 40 MHz\n    .mode = 0,  \u002F\u002F SPI mode 0 (CPOL=0, CPHA=0)\n    .spics_io_num = PIN_CS,\n    .queue_size = 7,\n    .pre_cb = nullptr,  \u002F\u002F Pre-transfer callback\n};\n\nspi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO);\nspi_bus_add_device(SPI2_HOST, &dev_cfg, &spi_handle);\n```\n\n### SPI Modes (CPOL and CPHA)\n\nSPI has four modes based on clock polarity and phase:\n\n```\nMode | CPOL | CPHA | Description\n-----|------|------|--------------------------------------------------\n0    | 0    | 0    | Data sampled on rising edge, shifted on falling\n1    | 0    | 1    | Data sampled on falling edge, shifted on rising\n2    | 1    | 0    | Data sampled on falling edge, shifted on rising\n3    | 1    | 1    | Data sampled on rising edge, shifted on falling\n\nCommon devices:\n- Most displays: Mode 0 or Mode 3\n- SD cards: Mode 0\n- MAX31855 thermocouple: Mode 0\n```\n\nVerify the correct mode in the datasheet - using the wrong mode causes garbled data.\n\n### DMA Transfers\n\nUse DMA for large data transfers to reduce CPU load:\n\n```cpp\n\u002F\u002F Prepare transaction\nspi_transaction_t trans = {\n    .length = buffer_size * 8,  \u002F\u002F Length in bits\n    .tx_buffer = buffer,\n    .rx_buffer = nullptr,\n};\n\n\u002F\u002F Non-blocking DMA transfer\nspi_device_queue_trans(spi_handle, &trans, portMAX_DELAY);\n\n\u002F\u002F Do other work while transfer happens...\n\n\u002F\u002F Wait for completion\nspi_transaction_t* ret_trans;\nspi_device_get_trans_result(spi_handle, &ret_trans, portMAX_DELAY);\n```\n\n**Performance considerations:**\n- Use DMA for transfers >64 bytes\n- Align buffers to 4-byte boundaries for DMA\n- Queue multiple transactions to keep bus busy\n- Consider double-buffering for continuous updates\n\nSee `scripts\u002Fspi_display.py` for a complete SPI display driver example.\n\n## UART Protocol\n\n### Configuration\n\nConfigure UART with proper frame format:\n\n```cpp\n\u002F\u002F ESP-IDF example\n#include \"driver\u002Fuart.h\"\n\n#define UART_NUM      UART_NUM_1\n#define TXD_PIN       17\n#define RXD_PIN       16\n#define BAUD_RATE     115200\n\nuart_config_t uart_config = {\n    .baud_rate = BAUD_RATE,\n    .data_bits = UART_DATA_8_BITS,\n    .parity = UART_PARITY_DISABLE,\n    .stop_bits = UART_STOP_BITS_1,\n    .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,\n};\n\nuart_param_config(UART_NUM, &uart_config);\nuart_set_pin(UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);\nuart_driver_install(UART_NUM, 1024, 1024, 0, NULL, 0);\n```\n\n**Flow control:**\n- None: Simple point-to-point, ensure receiver can keep up\n- Software (XON\u002FXOFF): Use when hardware flow control unavailable\n- Hardware (RTS\u002FCTS): Preferred for reliable high-speed communication\n\n### AT Command Interface\n\nMany modules (WiFi, BLE, GPS) use AT command interface. Reference `scripts\u002Fuart_parser.py` for a complete command parser with state machine.\n\nBasic AT command handling:\n\n```cpp\nvoid send_at_command(const char* cmd, char* response, size_t max_len) {\n    \u002F\u002F Send command with CR+LF\n    uart_write_bytes(UART_NUM, cmd, strlen(cmd));\n    uart_write_bytes(UART_NUM, \"\\r\\n\", 2);\n\n    \u002F\u002F Read response with timeout\n    int len = uart_read_bytes(UART_NUM, (uint8_t*)response,\n                              max_len - 1, 1000 \u002F portTICK_PERIOD_MS);\n    response[len] = '\\0';\n\n    \u002F\u002F Check for OK\u002FERROR\n    if (strstr(response, \"OK\")) {\n        \u002F\u002F Success\n    } else if (strstr(response, \"ERROR\")) {\n        \u002F\u002F Failed\n    }\n}\n```\n\n**AT command best practices:**\n- Wait for \"OK\" before sending next command\n- Implement timeout for each command\n- Handle unsolicited responses (events)\n- Buffer partial lines until CR+LF received\n- Use state machine for complex command sequences\n\n## BLE Protocol\n\n### GATT Server Structure\n\nDesign GATT services with characteristics for each data type:\n\n```\nService: Timer Control (UUID: custom)\n├── Characteristic: State (UUID: 0x2A00)\n│   ├── Properties: Read, Notify\n│   ├── Value: {\"running\": bool, \"remaining\": uint32}\n│   └── Descriptor: CCCD (0x2902) for notifications\n├── Characteristic: Command (UUID: 0x2A01)\n│   ├── Properties: Write\n│   └── Value: {\"action\": \"start\"|\"pause\"|\"reset\", \"duration\": uint32}\n└── Characteristic: Battery (UUID: 0x2A19)\n    ├── Properties: Read, Notify\n    └── Value: uint8 (percentage)\n```\n\n### Connection Parameters\n\nOptimize connection intervals for use case:\n\n```cpp\n\u002F\u002F Fast updates (timer display): 20ms - 40ms interval\n\u002F\u002F Power saving (idle): 200ms - 400ms interval\n\nble_gap_conn_params_t conn_params = {\n    .min_conn_interval = 16,  \u002F\u002F 16 * 1.25ms = 20ms\n    .max_conn_interval = 32,  \u002F\u002F 32 * 1.25ms = 40ms\n    .slave_latency = 0,       \u002F\u002F No latency for real-time updates\n    .conn_sup_timeout = 400,  \u002F\u002F 400 * 10ms = 4s timeout\n};\n```\n\n**Trade-offs:**\n- Faster intervals: Lower latency, higher power consumption\n- Slower intervals: Longer latency, better battery life\n- Slave latency: Skip N intervals to save power (adds latency)\n\n### Notifications vs Indications\n\nChoose the appropriate characteristic property:\n\n**Notifications** (unacknowledged)\n- Use for: Frequent sensor updates, timer ticks\n- Advantage: Lower overhead, higher throughput\n- Disadvantage: No delivery guarantee\n\n**Indications** (acknowledged)\n- Use for: Important commands, critical state changes\n- Advantage: Guaranteed delivery with acknowledgment\n- Disadvantage: Higher overhead, lower throughput\n\nReference `scripts\u002Fble_gatt_server.py` for a complete BLE GATT server implementation.\n\n## WiFi Integration\n\n### Connection Management\n\nImplement robust WiFi connection with automatic reconnection:\n\n```cpp\n\u002F\u002F ESP-IDF example\nvoid wifi_init() {\n    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();\n    esp_wifi_init(&cfg);\n\n    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);\n    esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL);\n\n    wifi_config_t wifi_config = {\n        .sta = {\n            .ssid = WIFI_SSID,\n            .password = WIFI_PASS,\n            .threshold.authmode = WIFI_AUTH_WPA2_PSK,\n        },\n    };\n\n    esp_wifi_set_mode(WIFI_MODE_STA);\n    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);\n    esp_wifi_start();\n}\n\nvoid event_handler(void* arg, esp_event_base_t event_base,\n                   int32_t event_id, void* event_data) {\n    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {\n        esp_wifi_connect();  \u002F\u002F Auto-reconnect\n    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {\n        \u002F\u002F Connected - start MQTT client\n    }\n}\n```\n\n### mDNS Service Discovery\n\nUse mDNS to discover MQTT broker without hardcoded IP:\n\n```cpp\n\u002F\u002F Advertise MQTT broker (Jetson)\nmdns_init();\nmdns_hostname_set(\"orbit-broker\");\nmdns_service_add(\"Orbit MQTT\", \"_mqtt\", \"_tcp\", 1883, NULL, 0);\n\n\u002F\u002F Discover MQTT broker (devices)\nmdns_result_t* results = NULL;\nesp_err_t err = mdns_query_ptr(\"_mqtt\", \"_tcp\", 3000, 20, &results);\n\nif (err == ESP_OK && results) {\n    mdns_result_t* r = results;\n    while (r) {\n        printf(\"Found MQTT broker: %s at %s:%d\\n\",\n               r->hostname, ip4addr_ntoa(&r->addr->addr.u_addr.ip4), r->port);\n        r = r->next;\n    }\n    mdns_query_results_free(results);\n}\n```\n\n## Orbit System Integration\n\n### Device Communication Architecture\n\n```\n                    ┌─────────────────┐\n                    │  Jetson Nano    │\n                    │  MQTT Broker    │\n                    │  (Mosquitto)    │\n                    └────────┬────────┘\n                             │\n        ┌────────────────────┼────────────────────┐\n        │                    │                    │\n  WiFi (MQTT)          WiFi (MQTT)          WiFi (MQTT)\n        │                    │                    │\n┌───────▼────────┐  ┌────────▼────────┐  ┌───────▼────────┐\n│ Presto (RP2350)│  │ T-Embed (ESP32) │  │  Stream Deck   │\n│  SPI Display   │  │  SPI Display    │  │   (WebSocket)  │\n│  BLE Server    │  │  I2C Sensors    │  │                │\n└───────┬────────┘  └─────────────────┘  └────────────────┘\n        │\n   BLE (GATT)\n        │\n┌───────▼────────┐\n│  Android App   │\n│  BLE Client    │\n└────────────────┘\n```\n\n### Message Flow Examples\n\n**Timer Start from Stream Deck:**\n1. User presses Stream Deck button\n2. Plugin publishes: `orbit\u002Ftimer\u002Fcontrol\u002Fstart` with `{\"duration\": 1500}`\n3. Jetson receives and broadcasts: `orbit\u002Ftimer\u002Fstate\u002Fcurrent` (retained)\n4. All devices receive state update and display timer\n5. Presto sends BLE notification to Android app\n\n**Visual Alert:**\n1. Jetson detects timer completion\n2. Publishes: `orbit\u002Falert\u002Fvisual\u002Fall` with `{\"priority\": \"standard\", \"pattern\": \"pulse\"}`\n3. Presto and T-Embed display visual alerts\n4. Devices acknowledge: `orbit\u002Fdevice\u002F{id}\u002Fack`\n\n**Battery Level Monitoring:**\n1. T-Embed periodically checks battery via I2C fuel gauge\n2. Publishes: `orbit\u002Fdevice\u002Ftembed\u002Fbattery` with percentage\n3. Jetson logs metric and checks threshold\n4. If low: `orbit\u002Falert\u002Fvisual\u002Ftembed` with low battery warning\n\n## Troubleshooting\n\n### MQTT Issues\n\n**Connection refused:**\n- Check firewall: `sudo ufw allow 1883` and `sudo ufw allow 9001`\n- Verify broker running: `sudo systemctl status mosquitto`\n- Check logs: `sudo journalctl -u mosquitto -f`\n\n**Messages not received:**\n- Verify topic spelling (case-sensitive)\n- Check QoS level and subscription\n- Monitor with: `mosquitto_sub -h localhost -t '#' -v` (all topics)\n\n**WebSocket connection fails:**\n- Verify WebSocket listener in mosquitto.conf\n- Test with: `wscat -c ws:\u002F\u002Fbroker-ip:9001\u002Fmqtt`\n- Check CORS if from browser\n\n### I2C Issues\n\n**Device not detected:**\n- Check wiring: SDA\u002FSCL not swapped\n- Verify pull-up resistors present (2.2K - 10K)\n- Scan bus: Use I2C scanner code above\n- Check device address in datasheet (some have configurable bits)\n\n**Timeout or NACK:**\n- Reduce clock speed (try 100 KHz)\n- Check power supply to device\n- Verify device is ready (some need initialization delay)\n- Check for bus contention (multiple masters)\n\n### SPI Issues\n\n**Garbled data:**\n- Verify SPI mode (CPOL\u002FCPHA)\n- Check clock speed (try slower)\n- Confirm MISO\u002FMOSI not swapped\n- Verify CS timing (some devices need delay)\n\n**No response:**\n- Check chip select (active low typically)\n- Verify device powered\n- Check MOSI\u002FCLK signals with logic analyzer\n- Some devices need initialization sequence\n\n### BLE Issues\n\n**Connection drops:**\n- Increase connection timeout\n- Reduce connection interval\n- Check for RF interference\n- Verify power supply stable\n\n**Cannot discover device:**\n- Check advertising interval and window\n- Verify device name\u002FUUID\n- Check iOS\u002FAndroid BLE permissions\n- Scan longer or restart Bluetooth\n\n### WiFi Issues\n\n**Cannot connect:**\n- Verify SSID and password\n- Check WiFi band (2.4 GHz vs 5 GHz)\n- Try static IP if DHCP fails\n- Check router firewall\u002FMAC filtering\n\n**Frequent disconnections:**\n- Reduce WiFi power saving\n- Improve signal strength (closer to AP)\n- Check for channel congestion\n- Use WiFi analyzer to find better channel\n\n## Bundled Resources\n\n### scripts\u002F\n\nExecutable reference implementations:\n- `mqtt_connection.py` - MQTT client with robust reconnection logic\n- `ble_gatt_server.py` - BLE GATT server with services and characteristics\n- `i2c_sensor.py` - I2C sensor reading with error handling\n- `spi_display.py` - SPI display driver with DMA\n- `uart_parser.py` - UART command parser with state machine\n\nThese can be executed directly or adapted for specific hardware platforms.\n\n### references\u002F\n\nDetailed protocol documentation:\n- `mqtt_reference.md` - Complete MQTT protocol specification and patterns\n- `embedded_bus_protocols.md` - I2C, SPI, UART detailed specs\n- `wireless_protocols.md` - BLE and WiFi comprehensive guides\n- `orbit_integration.md` - Orbit-specific integration patterns and topic schemas\n\nLoad these references when deep protocol knowledge is needed.\n\n### assets\u002F\n\nConfiguration templates:\n- `mosquitto.conf` - Production-ready Mosquitto configuration (TCP + WebSocket)\n- `platformio_examples\u002F` - PlatformIO project configurations for ESP32 and RP2350\n\nCopy these templates to projects and customize as needed.\n",{"name":5,"description":7},"main","7850740bd837adb32f0a109ab2af82482196c6f2","skills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols",1,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills","https:\u002F\u002Fzturnsgo.com","https:\u002F\u002Fgithub.com\u002Fshengdabai","https:\u002F\u002Fzturnsgo.com\u002F","AI × education creator — producer, not consumer. Taught 6,000+ learners; shipping learning tools & daily essays with Claude Code, practicing @xiaolai's way 🥋","2026-11-01 21:28:23",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add shengdabai\u002FTony-Claude-Code-Skills --skill hardware-protocols",{"tool":60,"command":61},"bunx","bunx skills add shengdabai\u002FTony-Claude-Code-Skills --skill hardware-protocols",{"tool":63,"command":64},"pnpm","pnpm dlx skills add shengdabai\u002FTony-Claude-Code-Skills --skill hardware-protocols","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002FSKILL.md",true,[68,74,78,82,88,92,96,100,106,110,114,118],{"path":69,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":72,"sourceHtmlUrl":73},"assets\u002Fmosquitto.conf","ASSET","资产文件",6284,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fassets\u002Fmosquitto.conf",{"path":75,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":76,"sourceHtmlUrl":77},"assets\u002Fplatformio_examples\u002Fesp32_mqtt.ini",4221,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fassets\u002Fplatformio_examples\u002Fesp32_mqtt.ini",{"path":79,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":80,"sourceHtmlUrl":81},"assets\u002Fplatformio_examples\u002Frp2350_presto.ini",3453,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fassets\u002Fplatformio_examples\u002Frp2350_presto.ini",{"path":83,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":86,"sourceHtmlUrl":87},"references\u002Fembedded_bus_protocols.md","REFERENCE","参考文档",8892,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Freferences\u002Fembedded_bus_protocols.md",{"path":89,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":90,"sourceHtmlUrl":91},"references\u002Fmqtt_reference.md",9238,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Freferences\u002Fmqtt_reference.md",{"path":93,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":94,"sourceHtmlUrl":95},"references\u002Forbit_integration.md",14278,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Freferences\u002Forbit_integration.md",{"path":97,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":98,"sourceHtmlUrl":99},"references\u002Fwireless_protocols.md",10806,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Freferences\u002Fwireless_protocols.md",{"path":101,"resourceType":102,"resourceTypeDesc":103,"sizeBytes":104,"sourceHtmlUrl":105},"scripts\u002Fble_gatt_server.py","SCRIPT","脚本",11891,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fscripts\u002Fble_gatt_server.py",{"path":107,"resourceType":102,"resourceTypeDesc":103,"sizeBytes":108,"sourceHtmlUrl":109},"scripts\u002Fi2c_sensor.py",10250,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fscripts\u002Fi2c_sensor.py",{"path":111,"resourceType":102,"resourceTypeDesc":103,"sizeBytes":112,"sourceHtmlUrl":113},"scripts\u002Fmqtt_connection.py",10685,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fscripts\u002Fmqtt_connection.py",{"path":115,"resourceType":102,"resourceTypeDesc":103,"sizeBytes":116,"sourceHtmlUrl":117},"scripts\u002Fspi_display.py",9309,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fscripts\u002Fspi_display.py",{"path":119,"resourceType":102,"resourceTypeDesc":103,"sizeBytes":120,"sourceHtmlUrl":121},"scripts\u002Fuart_parser.py",11379,"https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002F_collections\u002Frghamilton3-dotfiles\u002Fdot_claude\u002Fskills\u002Fhardware-protocols\u002Fscripts\u002Fuart_parser.py",[123,142,176,201,223,243],{"skillNo":124,"name":125,"nameZh":6,"description":126,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":134,"publishedAt":39},"01M70P17DAD4C1C47NPH6A96EM","xiaolai-methodology","以李笑来(Li Xiaolai)的思考方式、方法论与表达风格,为用户做全方位 1-on-1 教练指导,覆盖创业、赚钱、投资、学习、自学、读书写作、用 AI、以及人生心态与自我管理。当用户提到 \"李笑来\"、\"笑来\"、\"笑来老师\"、\"扮演李笑来\"、\"找笑来聊聊\"、\"笑来怎么看\"、\"xiaolai\"、\"把时间当作朋友\"、\"通往财富自由之路\"、\"定投改变命运\"、\"韭菜的自我修养\"、\"自学是门手艺\"、\"让时间陪你慢慢变富\"、\"七年就是一辈子\"、\"元认知\"、\"活在未来\"、\"复利\u002F长期主义\"、\"践行\"、\"痴迷改进\"、\"个人商业模式\u002F出售时间\"、\"睡后收入\"、\"定投\"、\"财富自由\"、\"操作系统升级\"、\"最少必要知识\"、\"北极星提示词\"、\"用 AI 该怎么学\u002F思考\" 等任一触发词,或当用户带着关于创业\u002F赚钱\u002F投资\u002F学习\u002F职业\u002F重大人生决策的困惑、希望被人用笑来式的「逻辑 + 大白话 + 类比 + 重新定义 + 践行导向」来点醒和指导时,自动进入李笑来教练模式。","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fxiaolai-methodology\u002FSKILL.md",[129],{"categoryNo":130,"categoryName":131,"taxonomyType":132,"taxonomyTypeDesc":133},"01JBSEEDCAT000000000000018","写作与文案","SCENARIO","使用场景",[135,136,137,138,139,140,141],"methodology","xiaolai","xiaolai methodology","朋友","投资","writing","收入",{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":156,"publishedAt":39},"01M70P13NB9YP7ACJR1S861CDS","zread","Produce and consume a wiki-style knowledge base for a code repository via the `zread` CLI and its on-disk output under `.\u002F.zread\u002Fwiki\u002F`. Use this skill whenever the user wants to understand, onboard onto, explore, summarize, map, or get an overview of an unfamiliar codebase; asks for architecture docs, a project wiki, a repo walkthrough, module\u002Fpackage explanations, or \"what does this repo do\"; wants to generate, regenerate, resume, browse, or serve code documentation locally; or mentions zread \u002F zread.ai directly. Also use it proactively before diving into a large unknown repo — if `.\u002F.zread\u002Fwiki\u002Fcurrent` exists, read the generated pages instead of crawling source file-by-file; if it doesn't, consider offering to run `zread generate`. The trigger is the intent (understand a codebase through generated docs), not the literal word \"zread\".","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fzread\u002FSKILL.md",[148,151],{"categoryNo":149,"categoryName":150,"taxonomyType":132,"taxonomyTypeDesc":133},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":152,"categoryName":153,"taxonomyType":154,"taxonomyTypeDesc":155},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[144,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175],"knowledge","wiki","explore","walkthrough","project","get","knowledge base","run","generate","intent","cli","map","documentation","project wiki","disk","architecture","code","unknown","generated",{"skillNo":177,"name":178,"nameZh":6,"description":179,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":180,"categories":181,"keywords":186,"publishedAt":39},"01M70P10S4SWMZQ8BJAFBFDRW3","youtube","Launch the YouTube Creator Agent to auto-generate videos.\nUse when: user types \u002Fyoutube, wants to create YouTube videos,\ngenerate video content, or upload to YouTube.\nKeywords: youtube, video, 视频, 创作视频, 发布视频","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fyoutube\u002FSKILL.md",[182,183],{"categoryNo":149,"categoryName":150,"taxonomyType":132,"taxonomyTypeDesc":133},{"categoryNo":184,"categoryName":185,"taxonomyType":154,"taxonomyTypeDesc":155},"01JBSEEDCAT000000000000036","内容创作者",[178,187,188,189,190,191,192,193,165,194,195,196,29,22,197,198,199,200],"user","content","视频","creator","generate video","videos","launch","video content","create","upload","auto","types","Video","创作",{"skillNo":202,"name":203,"nameZh":6,"description":204,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":205,"categories":206,"keywords":208,"publishedAt":39},"01M70P0YE95D8BACZCGV8BK90K","youtube-script-sync","Sync, update, or optimize Tony's GetNote knowledge base `Youtube视频逐字稿` by turning each parent recording or first-person idea note into an idempotent child note containing a directly recordable YouTube long-video or Shorts script. Use when the user says “更新\u002F同步\u002F优化 Youtube视频逐字稿知识库”, or says “更新\u002F同步\u002F优化该知识库” while this knowledge base is the active context.","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fyoutube-script-sync\u002FSKILL.md",[207],{"categoryNo":149,"categoryName":150,"taxonomyType":132,"taxonomyTypeDesc":133},[209,210,178,211,212,199,213,214,215,216,217,218,219,220,163,221,29,22,157,222],"sync","script","youtube script sync","recording","shorts","first","base","person","update","active","child","optimize","idempotent","long",{"skillNo":224,"name":225,"nameZh":6,"description":226,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":227,"categories":228,"keywords":233,"publishedAt":39},"01M70P0WMV5XT0EEC0N445PW07","writing-skills","How to write SKILL.md files that trigger reliably and teach effectively. Use when creating, improving, or reviewing Claude Code skills.","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fxiaolai\u002Fnlpm\u002Fskills\u002Fnlpm\u002Fwriting-skills\u002FSKILL.md",[229,230,231,232],{"categoryNo":130,"categoryName":131,"taxonomyType":132,"taxonomyTypeDesc":133},{"categoryNo":149,"categoryName":150,"taxonomyType":132,"taxonomyTypeDesc":133},{"categoryNo":152,"categoryName":153,"taxonomyType":154,"taxonomyTypeDesc":155},{"categoryNo":184,"categoryName":185,"taxonomyType":154,"taxonomyTypeDesc":155},[234,140,235,236,237,238,173,29,22,239,240,241,242],"writing skills","how","teach","write skill","write","claude code skills","files","how to","trigger",{"skillNo":244,"name":245,"nameZh":6,"description":246,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":247,"categories":248,"keywords":251,"publishedAt":39},"01M70P0SJFR4YVJQBGMHKGSKXT","writing-rules","How to write .claude\u002Frules\u002F files that Claude actually follows. Use when creating, improving, or reviewing project rules.","https:\u002F\u002Fgithub.com\u002Fshengdabai\u002FTony-Claude-Code-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fxiaolai\u002Fnlpm\u002Fskills\u002Fnlpm\u002Fwriting-rules\u002FSKILL.md",[249,250],{"categoryNo":130,"categoryName":131,"taxonomyType":132,"taxonomyTypeDesc":133},{"categoryNo":184,"categoryName":185,"taxonomyType":154,"taxonomyTypeDesc":155},[252,140,253,161,254,240,29,235,238,22,241],"Rules","writing rules","project rules"]