package iotcontrol import ( "context" "fmt" "git.yeij.top/AskaEth/Cyrene-Plugins/sdk" ) // IoTController extends IoTClient with control operations. type IoTController interface { GetDevice(ctx context.Context, deviceID string) (*sdk.IoTDeviceState, error) SetDeviceProperty(ctx context.Context, deviceID, property string, value interface{}) error ToggleDevice(ctx context.Context, deviceID string) (*sdk.IoTDeviceState, error) } type IoTControlPlugin struct { sdk.BasePlugin iotClient IoTController } func NewIoTControlPlugin(client IoTController) *IoTControlPlugin { return &IoTControlPlugin{iotClient: client} } func (p *IoTControlPlugin) Metadata() sdk.PluginMetadata { return sdk.PluginMetadata{ Name: "iot_control", DisplayName: "IoT Device Control", Version: "1.0.0", Description: "Control smart home devices: toggle, set temperature/brightness/mode/color", Category: "iot", Author: sdk.PluginAuthor{Name: "Cyrene Team"}, } } func (p *IoTControlPlugin) Tools() []sdk.Tool { return []sdk.Tool{&IoTControlTool{iotClient: p.iotClient}} } type IoTControlTool struct { sdk.BaseTool iotClient IoTController } func (t *IoTControlTool) Definition() sdk.ToolDefinition { return sdk.ToolDefinition{ ID: "iot_control", Name: "iot_control", DisplayName: "IoT Device Control", Description: "Control smart home devices. Supports toggle, turn_on, turn_off, set_temperature, set_brightness, set_position, set_mode, set_color.", Category: "iot", Complexity: sdk.ComplexitySimple, DangerLevel: "medium", Parameters: map[string]interface{}{ "type": "object", "properties": map[string]interface{}{ "device_id": map[string]interface{}{"type": "string"}, "action": map[string]interface{}{"type": "string", "enum": []string{"toggle", "turn_on", "turn_off", "set_temperature", "set_brightness", "set_position", "set_mode", "set_color"}}, "value": map[string]interface{}{}, }, "required": []string{"device_id", "action"}, }, } } func (t *IoTControlTool) Validate(args map[string]interface{}) error { for _, k := range []string{"device_id", "action"} { if _, ok := args[k]; !ok { return fmt.Errorf("missing required parameter: %s", k) } } return nil } func (t *IoTControlTool) Execute(ctx context.Context, args map[string]interface{}) (*sdk.ToolResult, error) { if t.iotClient == nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: "IoT client not configured"}, nil } deviceID, _ := args["device_id"].(string) if deviceID == "" { deviceID, _ = args["entity_id"].(string) } action := normalizeAction(args) switch action { case "turn_on", "turn_off": status := "on" if action == "turn_off" { status = "off" } if err := t.iotClient.SetDeviceProperty(ctx, deviceID, "status", status); err != nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: err.Error()}, nil } return &sdk.ToolResult{ToolName: "iot_control", Success: true, Output: fmt.Sprintf("Device %s turned %s", deviceID, status)}, nil case "set_temperature": value := toFloat64(args["value"]) old := "" if dev, err := t.iotClient.GetDevice(ctx, deviceID); err == nil { old = fmt.Sprintf(" (was %.1fC)", dev.Temperature) } if err := t.iotClient.SetDeviceProperty(ctx, deviceID, "temperature", value); err != nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: err.Error()}, nil } return &sdk.ToolResult{ToolName: "iot_control", Success: true, Output: fmt.Sprintf("Temperature set to %.1fC%s", value, old)}, nil case "set_brightness": value := toFloat64(args["value"]) if err := t.iotClient.SetDeviceProperty(ctx, deviceID, "brightness", value); err != nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: err.Error()}, nil } return &sdk.ToolResult{ToolName: "iot_control", Success: true, Output: fmt.Sprintf("Brightness set to %.0f%%", value)}, nil case "set_position": value := toFloat64(args["value"]) if err := t.iotClient.SetDeviceProperty(ctx, deviceID, "position", value); err != nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: err.Error()}, nil } return &sdk.ToolResult{ToolName: "iot_control", Success: true, Output: fmt.Sprintf("Position set to %.0f%%", value)}, nil case "set_mode": value, _ := args["value"].(string) if err := t.iotClient.SetDeviceProperty(ctx, deviceID, "mode", value); err != nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: err.Error()}, nil } return &sdk.ToolResult{ToolName: "iot_control", Success: true, Output: fmt.Sprintf("Mode set to %s", value)}, nil case "set_color": value, _ := args["value"].(string) if err := t.iotClient.SetDeviceProperty(ctx, deviceID, "color", value); err != nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: err.Error()}, nil } return &sdk.ToolResult{ToolName: "iot_control", Success: true, Output: fmt.Sprintf("Color set to %s", value)}, nil case "toggle": dev, err := t.iotClient.ToggleDevice(ctx, deviceID) if err != nil { return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: err.Error()}, nil } return &sdk.ToolResult{ToolName: "iot_control", Success: true, Output: fmt.Sprintf("Device %s toggled to %s", deviceID, dev.Status)}, nil default: return &sdk.ToolResult{ToolName: "iot_control", Success: false, Error: fmt.Sprintf("unknown action: %s", action)}, nil } } func normalizeAction(args map[string]interface{}) string { action, _ := args["action"].(string) // Chinese aliases switch action { case "打开": return "turn_on" case "关闭", "关掉", "关上": return "turn_off" case "设置温度", "调温度": return "set_temperature" case "设置亮度", "调亮度": return "set_brightness" case "设置位置": return "set_position" case "设置模式": return "set_mode" case "设置颜色": return "set_color" case "开关", "切换": return "toggle" } return action } func toFloat64(v interface{}) float64 { switch n := v.(type) { case float64: return n case int: return float64(n) case int64: return float64(n) case string: var f float64 fmt.Sscanf(n, "%f", &f) return f } return 0 }