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 客户端示例
依赖
go mod init ailight-client
go get tinygo.org/x/bluetooth
完整代码
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 <mode>")
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")
}
使用方式
# 编译
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
封装为函数
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
}
调用示例
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 |
✅ 完整支持 |
推荐用于部署 |
注意事项
- 连接稳定性:每次发送指令需要重新扫描和连接,建议封装连接池
- 超时处理:扫描和连接都设置了 10 秒超时
- 并发控制:BLE 连接不支持并发,需要加锁
- 重连机制:建议实现自动重连逻辑