526 lines
17 KiB
C#
526 lines
17 KiB
C#
using ModelContextProtocol;
|
||
using ModelContextProtocol.Server;
|
||
using System.ComponentModel;
|
||
using System.Globalization;
|
||
using System.Text.Json;
|
||
|
||
namespace AspNetCoreMcpServer.Tools;
|
||
|
||
[McpServerToolType]
|
||
public sealed class IotDeviceTools
|
||
{
|
||
// 模拟设备状态存储
|
||
private static readonly Dictionary<string, DeviceState> _deviceStates = new();
|
||
|
||
public IotDeviceTools()
|
||
{
|
||
// 初始化一些默认设备
|
||
InitializeDefaultDevices();
|
||
}
|
||
|
||
private void InitializeDefaultDevices()
|
||
{
|
||
_deviceStates["living_room_light"] = new DeviceState
|
||
{
|
||
Id = "living_room_light",
|
||
Name = "客厅灯",
|
||
Type = "light",
|
||
IsOn = false,
|
||
Brightness = 100,
|
||
Temperature = 4000
|
||
};
|
||
|
||
_deviceStates["bedroom_curtain"] = new DeviceState
|
||
{
|
||
Id = "bedroom_curtain",
|
||
Name = "卧室窗帘",
|
||
Type = "curtain",
|
||
IsOn = false,
|
||
Position = 0
|
||
};
|
||
|
||
_deviceStates["living_room_ac"] = new DeviceState
|
||
{
|
||
Id = "living_room_ac",
|
||
Name = "客厅空调",
|
||
Type = "air_conditioner",
|
||
IsOn = false,
|
||
Temperature = 26,
|
||
Mode = "cool",
|
||
FanSpeed = "medium"
|
||
};
|
||
}
|
||
|
||
// ==================== 灯光控制 ====================
|
||
|
||
[McpServerTool, Description("控制灯光的开关状态")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "light")]
|
||
public async Task<string> ControlLight(
|
||
[Description("设备ID,例如: living_room_light, bedroom_light")] string deviceId,
|
||
[Description("开关状态: on 或 off")] string action)
|
||
{
|
||
await Task.Delay(100); // 模拟网络延迟
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "light")
|
||
{
|
||
return $"错误: {deviceId} 不是灯光设备";
|
||
}
|
||
|
||
bool turnOn = action.ToLower() == "on";
|
||
device.IsOn = turnOn;
|
||
|
||
return $"""
|
||
设备控制成功
|
||
设备: {device.Name} ({deviceId})
|
||
状态: {(turnOn ? "已开启" : "已关闭")}
|
||
亮度: {device.Brightness}%
|
||
色温: {device.Temperature}K
|
||
""";
|
||
}
|
||
|
||
[McpServerTool, Description("调节灯光亮度")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "light")]
|
||
public async Task<string> SetLightBrightness(
|
||
[Description("设备ID")] string deviceId,
|
||
[Description("亮度值 (0-100)")] int brightness)
|
||
{
|
||
await Task.Delay(100);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "light")
|
||
{
|
||
return $"错误: {deviceId} 不是灯光设备";
|
||
}
|
||
|
||
if (brightness < 0 || brightness > 100)
|
||
{
|
||
return "错误: 亮度值必须在 0-100 之间";
|
||
}
|
||
|
||
device.Brightness = brightness;
|
||
if (brightness > 0 && !device.IsOn)
|
||
{
|
||
device.IsOn = true;
|
||
}
|
||
|
||
return $"""
|
||
亮度调节成功
|
||
设备: {device.Name}
|
||
当前亮度: {brightness}%
|
||
状态: {(device.IsOn ? "开启" : "关闭")}
|
||
""";
|
||
}
|
||
|
||
[McpServerTool, Description("调节灯光色温")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "light")]
|
||
public async Task<string> SetLightTemperature(
|
||
[Description("设备ID")] string deviceId,
|
||
[Description("色温值 (2700-6500K)")] int temperature)
|
||
{
|
||
await Task.Delay(100);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "light")
|
||
{
|
||
return $"错误: {deviceId} 不是灯光设备";
|
||
}
|
||
|
||
if (temperature < 2700 || temperature > 6500)
|
||
{
|
||
return "错误: 色温值必须在 2700-6500K 之间";
|
||
}
|
||
|
||
device.Temperature = temperature;
|
||
|
||
string tempDesc = temperature < 3500 ? "暖光" : temperature < 5000 ? "自然光" : "冷光";
|
||
|
||
return $"""
|
||
色温调节成功
|
||
设备: {device.Name}
|
||
当前色温: {temperature}K ({tempDesc})
|
||
亮度: {device.Brightness}%
|
||
""";
|
||
}
|
||
|
||
// ==================== 窗帘控制 ====================
|
||
|
||
[McpServerTool, Description("控制窗帘的开关")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "curtain")]
|
||
public async Task<string> ControlCurtain(
|
||
[Description("设备ID,例如: bedroom_curtain")] string deviceId,
|
||
[Description("操作: open(打开), close(关闭), stop(停止)")] string action)
|
||
{
|
||
await Task.Delay(200); // 模拟窗帘运行时间
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "curtain")
|
||
{
|
||
return $"错误: {deviceId} 不是窗帘设备";
|
||
}
|
||
|
||
string result = action.ToLower() switch
|
||
{
|
||
"open" => HandleCurtainOpen(device),
|
||
"close" => HandleCurtainClose(device),
|
||
"stop" => HandleCurtainStop(device),
|
||
_ => "错误: 无效的操作,请使用 open, close 或 stop"
|
||
};
|
||
|
||
return result;
|
||
}
|
||
|
||
[McpServerTool, Description("设置窗帘打开的位置")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "curtain")]
|
||
public async Task<string> SetCurtainPosition(
|
||
[Description("设备ID")] string deviceId,
|
||
[Description("位置百分比 (0-100),0表示完全关闭,100表示完全打开")] int position)
|
||
{
|
||
await Task.Delay(150);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "curtain")
|
||
{
|
||
return $"错误: {deviceId} 不是窗帘设备";
|
||
}
|
||
|
||
if (position < 0 || position > 100)
|
||
{
|
||
return "错误: 位置值必须在 0-100 之间";
|
||
}
|
||
|
||
device.Position = position;
|
||
device.IsOn = position > 0;
|
||
|
||
return $"""
|
||
窗帘位置调节成功
|
||
设备: {device.Name}
|
||
当前位置: {position}%
|
||
状态: {(position == 0 ? "完全关闭" : position == 100 ? "完全打开" : "部分打开")}
|
||
""";
|
||
}
|
||
|
||
// ==================== 空调控制 ====================
|
||
|
||
[McpServerTool, Description("控制空调的开关")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "air_conditioner")]
|
||
public async Task<string> ControlAirConditioner(
|
||
[Description("设备ID,例如: living_room_ac")] string deviceId,
|
||
[Description("开关状态: on 或 off")] string action)
|
||
{
|
||
await Task.Delay(100);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "air_conditioner")
|
||
{
|
||
return $"错误: {deviceId} 不是空调设备";
|
||
}
|
||
|
||
bool turnOn = action.ToLower() == "on";
|
||
device.IsOn = turnOn;
|
||
|
||
return $"""
|
||
空调控制成功
|
||
设备: {device.Name}
|
||
状态: {(turnOn ? "已开启" : "已关闭")}
|
||
{(turnOn ? $"温度: {device.Temperature}°C\n模式: {GetModeDescription(device.Mode)}\n风速: {GetFanSpeedDescription(device.FanSpeed)}" : "")}
|
||
""";
|
||
}
|
||
|
||
[McpServerTool, Description("设置空调温度")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "air_conditioner")]
|
||
public async Task<string> SetAirConditionerTemperature(
|
||
[Description("设备ID")] string deviceId,
|
||
[Description("目标温度 (16-30°C)")] int temperature)
|
||
{
|
||
await Task.Delay(100);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "air_conditioner")
|
||
{
|
||
return $"错误: {deviceId} 不是空调设备";
|
||
}
|
||
|
||
if (temperature < 16 || temperature > 30)
|
||
{
|
||
return "错误: 温度必须在 16-30°C 之间";
|
||
}
|
||
|
||
device.Temperature = temperature;
|
||
if (!device.IsOn)
|
||
{
|
||
device.IsOn = true;
|
||
}
|
||
|
||
return $"""
|
||
空调温度设置成功
|
||
设备: {device.Name}
|
||
目标温度: {temperature}°C
|
||
当前模式: {GetModeDescription(device.Mode)}
|
||
风速: {GetFanSpeedDescription(device.FanSpeed)}
|
||
""";
|
||
}
|
||
|
||
[McpServerTool, Description("设置空调模式")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "air_conditioner")]
|
||
public async Task<string> SetAirConditionerMode(
|
||
[Description("设备ID")] string deviceId,
|
||
[Description("模式: cool(制冷), heat(制热), fan(送风), dry(除湿), auto(自动)")] string mode)
|
||
{
|
||
await Task.Delay(100);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "air_conditioner")
|
||
{
|
||
return $"错误: {deviceId} 不是空调设备";
|
||
}
|
||
|
||
var validModes = new[] { "cool", "heat", "fan", "dry", "auto" };
|
||
if (!validModes.Contains(mode.ToLower()))
|
||
{
|
||
return $"错误: 无效的模式。有效模式: {string.Join(", ", validModes)}";
|
||
}
|
||
|
||
device.Mode = mode.ToLower();
|
||
|
||
return $"""
|
||
空调模式设置成功
|
||
设备: {device.Name}
|
||
当前模式: {GetModeDescription(device.Mode)}
|
||
温度: {device.Temperature}°C
|
||
风速: {GetFanSpeedDescription(device.FanSpeed)}
|
||
""";
|
||
}
|
||
|
||
[McpServerTool, Description("设置空调风速")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "air_conditioner")]
|
||
public async Task<string> SetAirConditionerFanSpeed(
|
||
[Description("设备ID")] string deviceId,
|
||
[Description("风速: low(低), medium(中), high(高), auto(自动)")] string fanSpeed)
|
||
{
|
||
await Task.Delay(100);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
if (device.Type != "air_conditioner")
|
||
{
|
||
return $"错误: {deviceId} 不是空调设备";
|
||
}
|
||
|
||
var validSpeeds = new[] { "low", "medium", "high", "auto" };
|
||
if (!validSpeeds.Contains(fanSpeed.ToLower()))
|
||
{
|
||
return $"错误: 无效的风速。有效风速: {string.Join(", ", validSpeeds)}";
|
||
}
|
||
|
||
device.FanSpeed = fanSpeed.ToLower();
|
||
|
||
return $"""
|
||
空调风速设置成功
|
||
设备: {device.Name}
|
||
当前风速: {GetFanSpeedDescription(device.FanSpeed)}
|
||
模式: {GetModeDescription(device.Mode)}
|
||
温度: {device.Temperature}°C
|
||
""";
|
||
}
|
||
|
||
// ==================== 通用查询 ====================
|
||
|
||
[McpServerTool, Description("获取所有IoT设备的状态")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "all")]
|
||
public async Task<string> GetAllDevicesStatus()
|
||
{
|
||
await Task.Delay(50);
|
||
|
||
var statusList = _deviceStates.Values.Select(device =>
|
||
{
|
||
string status = device.Type switch
|
||
{
|
||
"light" => $"开关: {(device.IsOn ? "开" : "关")}, 亮度: {device.Brightness}%, 色温: {device.Temperature}K",
|
||
"curtain" => $"位置: {device.Position}%, 状态: {(device.Position == 0 ? "关闭" : device.Position == 100 ? "打开" : "部分打开")}",
|
||
"air_conditioner" => $"开关: {(device.IsOn ? "开" : "关")}, 温度: {device.Temperature}°C, 模式: {GetModeDescription(device.Mode)}, 风速: {GetFanSpeedDescription(device.FanSpeed)}",
|
||
_ => "未知设备类型"
|
||
};
|
||
|
||
return $"""
|
||
[{device.Type.ToUpper()}] {device.Name} ({device.Id})
|
||
{status}
|
||
""";
|
||
});
|
||
|
||
return $"当前设备总数: {_deviceStates.Count}\n\n" + string.Join("\n---\n", statusList);
|
||
}
|
||
|
||
[McpServerTool, Description("获取指定设备的详细状态")]
|
||
[McpMeta("category", "iot")]
|
||
[McpMeta("device", "all")]
|
||
public async Task<string> GetDeviceStatus(
|
||
[Description("设备ID")] string deviceId)
|
||
{
|
||
await Task.Delay(50);
|
||
|
||
if (!_deviceStates.ContainsKey(deviceId))
|
||
{
|
||
return $"错误: 找不到设备 {deviceId}\n\n可用设备: {string.Join(", ", _deviceStates.Keys)}";
|
||
}
|
||
|
||
var device = _deviceStates[deviceId];
|
||
|
||
string details = device.Type switch
|
||
{
|
||
"light" => $"""
|
||
开关状态: {(device.IsOn ? "开启" : "关闭")}
|
||
亮度: {device.Brightness}%
|
||
色温: {device.Temperature}K ({(device.Temperature < 3500 ? "暖光" : device.Temperature < 5000 ? "自然光" : "冷光")})
|
||
""",
|
||
"curtain" => $"""
|
||
位置: {device.Position}%
|
||
状态: {(device.Position == 0 ? "完全关闭" : device.Position == 100 ? "完全打开" : "部分打开")}
|
||
""",
|
||
"air_conditioner" => $"""
|
||
开关状态: {(device.IsOn ? "开启" : "关闭")}
|
||
温度设置: {device.Temperature}°C
|
||
运行模式: {GetModeDescription(device.Mode)}
|
||
风速: {GetFanSpeedDescription(device.FanSpeed)}
|
||
""",
|
||
_ => "未知设备类型"
|
||
};
|
||
|
||
return $"""
|
||
设备信息
|
||
名称: {device.Name}
|
||
ID: {device.Id}
|
||
类型: {device.Type}
|
||
|
||
{details}
|
||
""";
|
||
}
|
||
|
||
// ==================== 辅助方法 ====================
|
||
|
||
private string HandleCurtainOpen(DeviceState device)
|
||
{
|
||
device.Position = 100;
|
||
device.IsOn = true;
|
||
return $"""
|
||
窗帘正在打开...
|
||
设备: {device.Name}
|
||
目标位置: 100% (完全打开)
|
||
预计时间: 5秒
|
||
""";
|
||
}
|
||
|
||
private string HandleCurtainClose(DeviceState device)
|
||
{
|
||
device.Position = 0;
|
||
device.IsOn = false;
|
||
return $"""
|
||
窗帘正在关闭...
|
||
设备: {device.Name}
|
||
目标位置: 0% (完全关闭)
|
||
预计时间: 5秒
|
||
""";
|
||
}
|
||
|
||
private string HandleCurtainStop(DeviceState device)
|
||
{
|
||
return $"""
|
||
窗帘已停止
|
||
设备: {device.Name}
|
||
当前位置: {device.Position}%
|
||
""";
|
||
}
|
||
|
||
private static string GetModeDescription(string? mode) => mode switch
|
||
{
|
||
"cool" => "制冷",
|
||
"heat" => "制热",
|
||
"fan" => "送风",
|
||
"dry" => "除湿",
|
||
"auto" => "自动",
|
||
_ => "未知"
|
||
};
|
||
|
||
private static string GetFanSpeedDescription(string? speed) => speed switch
|
||
{
|
||
"low" => "低速",
|
||
"medium" => "中速",
|
||
"high" => "高速",
|
||
"auto" => "自动",
|
||
_ => "未知"
|
||
};
|
||
}
|
||
|
||
// 设备状态数据模型
|
||
internal class DeviceState
|
||
{
|
||
public string Id { get; set; } = "";
|
||
public string Name { get; set; } = "";
|
||
public string Type { get; set; } = "";
|
||
public bool IsOn { get; set; }
|
||
|
||
// 灯光属性
|
||
public int Brightness { get; set; }
|
||
public int Temperature { get; set; }
|
||
|
||
// 窗帘属性
|
||
public int Position { get; set; }
|
||
|
||
// 空调属性
|
||
public string? Mode { get; set; }
|
||
public string? FanSpeed { get; set; }
|
||
} |