# AI-Light BLE 接口文档 ## 设备信息 | 项目 | 值 | |------|-----| | 设备名称 | `AI-Light` | | Service UUID | `b8b7e001-7a6b-4f4f-9a8b-11c0ffee0001` | | Characteristic UUID | `b8b7e002-7a6b-4f4f-9a8b-11c0ffee0001` | | Characteristic 属性 | READ / WRITE / NOTIFY | ## 支持的模式 | 模式 | 说明 | 灯效 | |------|------|------| | `init` | 初始化状态 | 三色一起呼吸 | | `thinking` | 思考中 | 绿→黄→红 连贯跑马灯 | | `ai` | AI 处理中 | 三色柔和波浪 | | `busy` | 忙碌状态 | 黄灯淡入淡出 | | `success` | 成功状态 | 绿灯常亮 | | `error` | 错误状态 | 红灯快速闪烁 | | `alarm` | 警告状态 | 红黄交替警灯 | | `traffic` | 交通灯模式 | 绿→黄→红 循环 | | `off` | 关闭 | 全灭 | | `red` | 红灯 | 红灯常亮 | | `yellow` | 黄灯 | 黄灯常亮 | | `green` | 绿灯 | 绿灯常亮 | | `idle` | 空闲(自动转为 traffic) | 同 traffic | ## 超时规则 - 普通模式运行 **5分钟** → 自动进入 `traffic` - `traffic` 运行 **10分钟** → 自动进入 `off` ## Go 客户端示例 ### 依赖 ```bash go mod init ailight-client go get tinygo.org/x/bluetooth ``` ### 完整代码 ```go package main import ( "fmt" "os" "time" "tinygo.org/x/bluetooth" ) var ( serviceUUID = bluetooth.NewUUID([16]byte{0xb8, 0xb7, 0xe0, 0x01, 0x7a, 0x6b, 0x4f, 0x4f, 0x9a, 0x8b, 0x11, 0xc0, 0xff, 0xee, 0x00, 0x01}) modeCharUUID = bluetooth.NewUUID([16]byte{0xb8, 0xb7, 0xe0, 0x02, 0x7a, 0x6b, 0x4f, 0x4f, 0x9a, 0x8b, 0x11, 0xc0, 0xff, 0xee, 0x00, 0x01}) ) func main() { if len(os.Args) < 2 { fmt.Println("Usage: ailight-client ") fmt.Println("Modes: init, thinking, ai, busy, success, error, alarm, traffic, off, red, yellow, green") os.Exit(1) } mode := os.Args[1] adapter := bluetooth.DefaultAdapter if err := adapter.Enable(); err != nil { fmt.Printf("Failed to enable BLE adapter: %v\n", err) os.Exit(1) } // 扫描并连接设备 fmt.Println("Scanning for AI-Light...") found := false var device bluetooth.Device done := make(chan struct{}) go func() { adapter.Scan(func(adapter *bluetooth.Adapter, scanResult bluetooth.ScanResult) { if scanResult.LocalName() == "AI-Light" { adapter.StopScan() found = true var err error device, err = adapter.Connect(scanResult.Address, bluetooth.ConnectionParams{}) if err != nil { fmt.Printf("Failed to connect: %v\n", err) os.Exit(1) } close(done) } }) }() select { case <-done: // 连接成功 case <-time.After(10 * time.Second): fmt.Println("Connection timeout") os.Exit(1) } if !found { fmt.Println("Device not found") os.Exit(1) } fmt.Println("Connected to AI-Light") // 发现服务和特征 services, err := device.DiscoverServices([]bluetooth.UUID{serviceUUID}) if err != nil { fmt.Printf("Failed to discover services: %v\n", err) os.Exit(1) } if len(services) == 0 { fmt.Println("Service not found") os.Exit(1) } characteristics, err := services[0].DiscoverCharacteristics([]bluetooth.UUID{modeCharUUID}) if err != nil { fmt.Printf("Failed to discover characteristics: %v\n", err) os.Exit(1) } if len(characteristics) == 0 { fmt.Println("Characteristic not found") os.Exit(1) } // 写入模式 _, err = characteristics[0].WriteString(mode) if err != nil { fmt.Printf("Write failed: %v\n", err) os.Exit(1) } fmt.Printf("Sent mode: %s\n", mode) // 断开连接 device.Disconnect() fmt.Println("Disconnected") } ``` ### 使用方式 ```bash # 编译 go build -o ailight-client main.go # 切换模式 ./ailight-client thinking ./ailight-client busy ./ailight-client success ./ailight-client error ./ailight-client traffic ./ailight-client off ``` ### 封装为函数 ```go package ailight import ( "fmt" "time" "tinygo.org/x/bluetooth" ) var ( serviceUUID = bluetooth.NewUUID([16]byte{0xb8, 0xb7, 0xe0, 0x01, 0x7a, 0x6b, 0x4f, 0x4f, 0x9a, 0x8b, 0x11, 0xc0, 0xff, 0xee, 0x00, 0x01}) modeCharUUID = bluetooth.NewUUID([16]byte{0xb8, 0xb7, 0xe0, 0x02, 0x7a, 0x6b, 0x4f, 0x4f, 0x9a, 0x8b, 0x11, 0xc0, 0xff, 0xee, 0x00, 0x01}) ) // SetMode 设置灯效模式 func SetMode(mode string) error { adapter := bluetooth.DefaultAdapter if err := adapter.Enable(); err != nil { return fmt.Errorf("enable adapter: %w", err) } // 扫描设备 var device bluetooth.Device found := make(chan bool, 1) go func() { adapter.Scan(func(adapter *bluetooth.Adapter, scanResult bluetooth.ScanResult) { if scanResult.LocalName() == "AI-Light" { adapter.StopScan() var err error device, err = adapter.Connect(scanResult.Address, bluetooth.ConnectionParams{}) found <- err == nil } }) }() select { case ok := <-found: if !ok { return fmt.Errorf("connect failed") } case <-time.After(10 * time.Second): return fmt.Errorf("scan timeout") } defer device.Disconnect() // 发现服务 services, err := device.DiscoverServices([]bluetooth.UUID{serviceUUID}) if err != nil || len(services) == 0 { return fmt.Errorf("service not found") } // 发现特征 characteristics, err := services[0].DiscoverCharacteristics([]bluetooth.UUID{modeCharUUID}) if err != nil || len(characteristics) == 0 { return fmt.Errorf("characteristic not found") } // 写入模式 _, err = characteristics[0].WriteString(mode) if err != nil { return fmt.Errorf("write failed: %w", err) } return nil } ``` ### 调用示例 ```go package main import ( "fmt" "ailight" ) func main() { // AI 开始思考 ailight.SetMode("thinking") // 执行任务... // 任务完成 ailight.SetMode("success") // 出错 ailight.SetMode("error") // 关闭 ailight.SetMode("off") } ``` ## 平台支持 | 平台 | 支持情况 | 备注 | |------|----------|------| | Linux | ✅ 完整支持 | 需要 BlueZ | | Windows | ⚠️ 部分支持 | 需要额外配置 | | Raspberry Pi | ✅ 完整支持 | 推荐用于部署 | ## 注意事项 1. **连接稳定性**:每次发送指令需要重新扫描和连接,建议封装连接池 2. **超时处理**:扫描和连接都设置了 10 秒超时 3. **并发控制**:BLE 连接不支持并发,需要加锁 4. **重连机制**:建议实现自动重连逻辑