@@ -0,0 +1,425 @@
package tools
import (
"context"
"encoding/json"
"fmt"
)
// IoTControlTool IoT 设备控制工具
type IoTControlTool struct {
iotClient * IoTClient
}
// NewIoTControlTool 创建 IoT 控制工具
func NewIoTControlTool ( iotClient * IoTClient ) * IoTControlTool {
return & IoTControlTool { iotClient : iotClient }
}
// Definition 返回工具定义
func ( t * IoTControlTool ) Definition ( ) ToolDefinition {
return ToolDefinition {
Name : "iot_control" ,
Description : "控制家中智能设备。可以开关灯光、空调、窗帘、门锁等设备,也可以调节温度、亮度、位置、模式、颜色等属性。" +
"\n支持的操作:toggle(切换开关状态)、turn_on(打开设备)、turn_off(关闭设备)、" +
"set_temperature(设置空调温度,需要 value 参数,单位°C)、" +
"set_brightness(设置灯光亮度,需要 value 参数,0-100)、" +
"set_position(设置窗帘位置,需要 value 参数,0-100, 0=关闭 100=全开)、" +
"set_mode(设置空调模式,需要 value 参数,可选值: cool/heat/auto)、" +
"set_color(设置灯光颜色,需要 value 参数,可选值: warm_white/cool_white/colorful) " ,
Parameters : map [ string ] interface { } {
"type" : "object" ,
"properties" : map [ string ] interface { } {
"device_id" : map [ string ] interface { } {
"type" : "string" ,
"description" : "要控制的设备ID。可选值: light-livingroom, light-bedroom, ac-livingroom, ac-bedroom, curtain-livingroom, lock-door" ,
} ,
"action" : map [ string ] interface { } {
"type" : "string" ,
"enum" : [ ] string { "toggle" , "turn_on" , "turn_off" , "set_temperature" , "set_brightness" , "set_position" , "set_mode" , "set_color" } ,
"description" : "要执行的操作。toggle:切换开关状态;turn_on:打开设备;turn_off:关闭设备;set_temperature:设置空调温度(需配合value参数);set_brightness:设置灯光亮度(需配合value参数);set_position:设置窗帘位置(需配合value参数);set_mode:设置空调模式(需配合value参数);set_color:设置灯光颜色(需配合value参数)" ,
} ,
"value" : map [ string ] interface { } {
"type" : "number" ,
"description" : "操作的值。set_temperature 时表示目标温度(°C),set_brightness 时表示亮度百分比(0-100),set_position 时表示窗帘开合程度(0-100)。action 为 set_temperature/set_brightness/set_position 时必须提供。set_mode 时为字符串(cool/heat/auto),set_color 时为字符串(warm_white/cool_white/colorful) " ,
} ,
} ,
"required" : [ ] string { "device_id" , "action" } ,
} ,
}
}
// Execute 执行设备控制
func ( t * IoTControlTool ) Execute ( ctx context . Context , arguments map [ string ] interface { } ) ( * ToolResult , error ) {
if t . iotClient == nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : "IoT 客户端未初始化" ,
} , nil
}
// 参数别名:entity_id → device_id
deviceID , _ := arguments [ "device_id" ] . ( string )
if deviceID == "" {
deviceID , _ = arguments [ "entity_id" ] . ( string )
}
action , _ := arguments [ "action" ] . ( string )
if deviceID == "" {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : "缺少设备ID(请使用 device_id 参数)" ,
} , nil
}
if action == "" {
action = "toggle"
}
// 处理属性设置类操作
switch action {
case "set_temperature" :
return t . handleSetTemperature ( deviceID , arguments )
case "set_brightness" :
return t . handleSetBrightness ( deviceID , arguments )
case "set_position" :
return t . handleSetPosition ( deviceID , arguments )
case "set_mode" :
return t . handleSetMode ( deviceID , arguments )
case "set_color" :
return t . handleSetColor ( deviceID , arguments )
}
// 处理开关类操作:需要获取当前设备状态
currentDevice , err := t . iotClient . GetDevice ( deviceID )
if err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "获取设备状态失败: %v" , err ) ,
} , nil
}
switch action {
case "turn_on" :
// 如果设备已经开启,不需要操作
if currentDevice . Status == "on" || currentDevice . Status == "open" || currentDevice . Status == "unlocked" {
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "设备 %s (%s) 已经处于开启状态,无需操作。" , currentDevice . Name , deviceID ) ,
} , nil
}
if err := t . iotClient . ToggleDevice ( deviceID ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "打开设备失败: %v" , err ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已打开设备: %s" , currentDevice . Name ) ,
} , nil
case "turn_off" :
// 如果设备已经关闭,不需要操作
if currentDevice . Status == "off" || currentDevice . Status == "closed" || currentDevice . Status == "locked" {
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "设备 %s (%s) 已经处于关闭状态,无需操作。" , currentDevice . Name , deviceID ) ,
} , nil
}
if err := t . iotClient . ToggleDevice ( deviceID ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "关闭设备失败: %v" , err ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已关闭设备: %s" , currentDevice . Name ) ,
} , nil
default : // "toggle"
if err := t . iotClient . ToggleDevice ( deviceID ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "操作设备失败: %v" , err ) ,
} , nil
}
// 获取切换后的状态
updatedDevice , err := t . iotClient . GetDevice ( deviceID )
if err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已成功切换设备 %s 的状态。" , currentDevice . Name ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已成功操作设备: %s\n当前状态: %s" , updatedDevice . Name , formatDeviceLine ( * updatedDevice ) ) ,
} , nil
}
}
// extractValue 从 arguments 中提取 value 参数(支持 value/Value 及数字/字符串类型)
func extractValue ( arguments map [ string ] interface { } ) interface { } {
if v , ok := arguments [ "value" ] ; ok {
return v
}
return nil
}
// handleSetTemperature 处理设置温度
func ( t * IoTControlTool ) handleSetTemperature ( deviceID string , arguments map [ string ] interface { } ) ( * ToolResult , error ) {
val := extractValue ( arguments )
if val == nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : "缺少 value 参数,请指定目标温度(如 24)" ,
} , nil
}
// 先获取当前设备信息
currentDevice , err := t . iotClient . GetDevice ( deviceID )
if err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "获取设备状态失败: %v" , err ) ,
} , nil
}
temperature , ok := toFloat64 ( val )
if ! ok {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "温度值无效: %v" , val ) ,
} , nil
}
if err := t . iotClient . SetDeviceProperty ( deviceID , "temperature" , temperature ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "设置温度失败: %v" , err ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已将 %s 温度从 %.1f°C 调整为 %.1f°C" , currentDevice . Name , currentDevice . Temperature , temperature ) ,
} , nil
}
// handleSetBrightness 处理设置亮度
func ( t * IoTControlTool ) handleSetBrightness ( deviceID string , arguments map [ string ] interface { } ) ( * ToolResult , error ) {
val := extractValue ( arguments )
if val == nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : "缺少 value 参数,请指定亮度值(0-100) " ,
} , nil
}
// 先获取当前设备信息
currentDevice , err := t . iotClient . GetDevice ( deviceID )
if err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "获取设备状态失败: %v" , err ) ,
} , nil
}
brightness , ok := toFloat64 ( val )
if ! ok {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "亮度值无效: %v" , val ) ,
} , nil
}
if err := t . iotClient . SetDeviceProperty ( deviceID , "brightness" , brightness ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "设置亮度失败: %v" , err ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已将 %s 亮度调整为 %d%%" , currentDevice . Name , int ( brightness ) ) ,
} , nil
}
// handleSetPosition 处理设置窗帘位置
func ( t * IoTControlTool ) handleSetPosition ( deviceID string , arguments map [ string ] interface { } ) ( * ToolResult , error ) {
val := extractValue ( arguments )
if val == nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : "缺少 value 参数,请指定位置值(0=关闭, 100=全开)" ,
} , nil
}
currentDevice , err := t . iotClient . GetDevice ( deviceID )
if err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "获取设备状态失败: %v" , err ) ,
} , nil
}
position , ok := toFloat64 ( val )
if ! ok {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "位置值无效: %v" , val ) ,
} , nil
}
if err := t . iotClient . SetDeviceProperty ( deviceID , "position" , position ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "设置窗帘位置失败: %v" , err ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已将 %s 窗帘调整为 %d%%" , currentDevice . Name , int ( position ) ) ,
} , nil
}
// handleSetMode 处理设置空调模式
func ( t * IoTControlTool ) handleSetMode ( deviceID string , arguments map [ string ] interface { } ) ( * ToolResult , error ) {
val := extractValue ( arguments )
if val == nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : "缺少 value 参数,请指定模式(cool/heat/auto) " ,
} , nil
}
mode , ok := val . ( string )
if ! ok {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "模式值无效: %v" , val ) ,
} , nil
}
currentDevice , err := t . iotClient . GetDevice ( deviceID )
if err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "获取设备状态失败: %v" , err ) ,
} , nil
}
if err := t . iotClient . SetDeviceProperty ( deviceID , "mode" , mode ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "设置模式失败: %v" , err ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已将 %s 模式切换为 %s" , currentDevice . Name , mode ) ,
} , nil
}
// handleSetColor 处理设置灯光颜色
func ( t * IoTControlTool ) handleSetColor ( deviceID string , arguments map [ string ] interface { } ) ( * ToolResult , error ) {
val := extractValue ( arguments )
if val == nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : "缺少 value 参数,请指定颜色(warm_white/cool_white/colorful) " ,
} , nil
}
color , ok := val . ( string )
if ! ok {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "颜色值无效: %v" , val ) ,
} , nil
}
currentDevice , err := t . iotClient . GetDevice ( deviceID )
if err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "获取设备状态失败: %v" , err ) ,
} , nil
}
if err := t . iotClient . SetDeviceProperty ( deviceID , "color" , color ) ; err != nil {
return & ToolResult {
ToolName : "iot_control" ,
Success : false ,
Error : fmt . Sprintf ( "设置颜色失败: %v" , err ) ,
} , nil
}
return & ToolResult {
ToolName : "iot_control" ,
Success : true ,
Data : fmt . Sprintf ( "已将 %s 灯光颜色切换为 %s" , currentDevice . Name , color ) ,
} , nil
}
// toFloat64 将 interface{} 转换为 float64
func toFloat64 ( v interface { } ) ( float64 , bool ) {
switch val := v . ( type ) {
case float64 :
return val , true
case float32 :
return float64 ( val ) , true
case int :
return float64 ( val ) , true
case int64 :
return float64 ( val ) , true
case json . Number :
f , err := val . Float64 ( )
return f , err == nil
default :
return 0 , false
}
}