张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )...

  所谓 UWP 样式的汉堡菜单,我曾在“张高兴的 UWP 开发笔记:汉堡菜单进阶”里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色的矩形用来表示 ListView 的选中。如下图

  但怎样通过 Xamarin.Forms ,将这一样式的汉堡菜单带入到 Android 与 iOS 中呢?

 

  一、大纲-细节模式简介

  讲代码前首先来说说这种导航模式,官方称“大纲-细节模式”(MasterDetail)。左侧的汉堡菜单称为“大纲”(Master),右侧的页面称为“细节”(Detail)。Xamarin.Froms 为项目提供了若干种导航模式,“大纲-细节”为其中一种。

 

  二、项目简介

  效果图:

  不多说废话,看代码实在些。

  本示例是使用 Visual Studio 2017 创建的 Cross-Platform 项目,项目名为”HamburgerMenuDemo“,模板为空白项目。(GitHub:https://github.com/ZhangGaoxing/xamarin-forms-demo/tree/master/HamburgerMenuDemo

  待项目创建完成后,解决方案共包含四个项目:共享代码项目、 Android 项目、 iOS 项目、 UWP 项目。共享代码项目为存放共享页面的地方,个人觉得和类库还是有点区别的。

  

  三、共享代码项目 HamburgerMenuDemo 

  首先添加几个页面,根目录下添加一个 MasterPage.xaml 页面,用于”大纲视图“。添加一个 Views 文件夹,用于存放子页面,向其中添加3个界面:Page1、Page2、Page3。添加一个 MasterPageItem.cs 类。

  1. MasterPageItem.cs

  和 UWP 的汉堡菜单一样,首先要创建一个类,作为导航的项目,用来绑定 ListView 。名字叫 MasterPageItem.cs 。

  里面的属性有页面的标题 Title,左侧的图标 Icon,图标的字体 FontFamily,目的页面 DestPage,还有左侧的矩形显示 Selected 与 颜色 Color。由于要实现双向绑定,还要实现接口 INotifyPropertyChanged。要注意的是,Color 类型为 Xamarin.Forms 中的。

代码如下

public class MasterPageItem : INotifyPropertyChanged
{
    // 字体路径,用于引入 Segoe MDL2 Assets 字体
    public string FontFamily { get; set; }

    // 字体图标转义
    public string Icon { get; set; }

    // 标题
    public string Title { get; set; }

    // 目的页
    public Type DestPage { get; set; }

    // 用于显示左侧填充矩形,双向绑定
    private bool selected = false;
    public bool Selected
    {
        get { return selected; }
        set
        {
            selected = value;
            this.OnPropertyChanged("Selected");
        }
    }

    // 选中颜色,双向绑定 ( using Xamarin.Forms )
    private Color color = new Color();
    public Color Color
    {
        get { return color; }
        set
        {
            color = value;
            this.OnPropertyChanged("Color");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

  2. MasterPage.xaml

  MasterPage 为”大纲“视图,即左侧显示 ListView 的页面。本项目的 MasterPage 分为两栏,分一级菜单与二级菜单,即置顶一个 ListView 与置底一个 ListView 。 ListView 的 ItemTemplate 与 UWP 稍有不同,左侧的填充矩形换成了 BoxView,二级菜单的上边线由 Border 换成了高度为1的 BoxView。代码如下

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HamburgerMenuDemo.MasterPage"
             Icon="hamburger.png"
             Title=" ">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="1" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        
        <!--一级菜单-->
        <ListView x:Name="PrimaryListView" VerticalOptions="StartAndExpand" SeparatorVisibility="None">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid HeightRequest="48">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="48"/>
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            
                            <BoxView BackgroundColor="{Binding Color}" WidthRequest="5" HeightRequest="26" HorizontalOptions="Start" VerticalOptions="Center" IsVisible="{Binding Selected}" />
                            <Label Text="{Binding Icon}" FontFamily="{Binding FontFamily}" TextColor="{Binding Color}" FontSize="16" HorizontalOptions="Center" VerticalOptions="Center" />
                            <Label Grid.Column="1" Text="{Binding Title}" TextColor="{Binding Color}" FontSize="14" VerticalOptions="Center" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <!--BoxView 充当 Border-->
        <BoxView BackgroundColor="Gray" Grid.Row="1" HorizontalOptions="FillAndExpand" />

        <!--二级菜单-->
        <ListView x:Name="SecondaryListView" Grid.Row="2" VerticalOptions="End" SeparatorVisibility="None" Margin="0,-6,0,0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid HeightRequest="48">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="48"/>
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>

                            <BoxView BackgroundColor="{Binding Color}" WidthRequest="5" HeightRequest="26" HorizontalOptions="Start" VerticalOptions="Center" IsVisible="{Binding Selected}" />
                            <Label x:Name="IconLabel" Text="{Binding Icon}" FontFamily="{Binding FontFamily}" TextColor="{Binding Color}" FontSize="16" HorizontalOptions="Center" VerticalOptions="Center" />
                            <Label Grid.Column="1" Text="{Binding Title}" TextColor="{Binding Color}" FontSize="14" VerticalOptions="Center" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</ContentPage>

  MasterPage.xaml.cs 代码也需要讲下,不知是怎么回事,以上 Xaml 代码直接运行时两个菜单会显示不正常,只显示一个菜单,<RowDefinition Height="Auto" /> 在这个 ContentPage 里好像无效。因此我在后台代码设置了二级菜单的高度,也就是48 * secondaryItems.Count。两个 ListView 需要通过属性的方式,向 MainPage 传递控件。字体路径各个项目不同,需要单独设置,我后面会说。MasterPage.xaml.cs 代码如下

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MasterPage : ContentPage
{
    // 向 MainPage 传递控件
    public ListView primaryListView { get { return PrimaryListView; } }
    public ListView secondaryListView { get { return SecondaryListView; } }

    public MasterPage()
    {
        InitializeComponent();

        // 设置不同平台的字体路径
        string fontFamily;
        switch (Device.RuntimePlatform)
        {
            case "Android":
                fontFamily = "segmdl2.ttf#Segoe MDL2 Assets";
                break;

            case "iOS":
                fontFamily = "Segoe MDL2 Assets";
                break;

            case "Windows":
                fontFamily = "/Assets/segmdl2.ttf#Segoe MDL2 Assets";
                break;

            case "WinPhone":
                fontFamily = "/Assets/segmdl2.ttf#Segoe MDL2 Assets";
                break;

            default:
                fontFamily = "segmdl2.ttf#Segoe MDL2 Assets";
                break;
        }

        // 列表项
        var primaryItems = new List<MasterPageItem>() {
                new MasterPageItem
                {
                    Title = "Page1",
                    FontFamily = fontFamily,
                    Icon = "\xE10F",
                    Color = Color.DeepSkyBlue,
                    Selected = true,
                    DestPage = typeof(Page1)
                },
                new MasterPageItem
                {
                    Title = "Page2",
                    FontFamily = fontFamily,
                    Icon = "\xE11F",
                    Color = Color.Black,
                    Selected = false,
                    DestPage = typeof(Page2)
                },
                new MasterPageItem
                {
                    Title = "Page3",
                    FontFamily = fontFamily,
                    Icon = "\xE12F",
                    Color = Color.Black,
                    Selected = false,
                    DestPage = typeof(Page2)
                }
            };

        var secondaryItems = new List<MasterPageItem>() {
                new MasterPageItem
                {
                    Title = "设置",
                    FontFamily = fontFamily,
                    Icon = "\xE713",
                    Color = Color.Black,
                    Selected = false,
                    DestPage = typeof(SettingPage)
                },
                new MasterPageItem
                {
                    Title = "关于",
                    FontFamily = fontFamily,
                    Icon = "\xE783",
                    Color = Color.Black,
                    Selected = false,
                    DestPage = typeof(AboutPage)
                }
            };

        // ListView 数据绑定
        PrimaryListView.ItemsSource = primaryItems;
        SecondaryListView.ItemsSource = secondaryItems;

        // 设置二级菜单高度
        SecondaryListView.HeightRequest = 48 * secondaryItems.Count;
    }
}

  3. MainPage.xaml

  下面来修改一下 MainPage.xaml 。MainPage.xaml 为应用的入口页面,可在 App.xaml.cs 中更改。将 MainPage 中的根元素替换为 MasterDetailPage 。注释很详细,不多说了

<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:HamburgerMenuDemo"
             x:Class="HamburgerMenuDemo.MainPage"
             xmlns:views="clr-namespace:HamburgerMenuDemo.Views">

    <!--大纲视图-->
    <MasterDetailPage.Master>
        <!--引入 MasterPage 并给个名称,用于后台设置 MasterPage 传递过来的 ListView-->
        <local:MasterPage x:Name="masterPage" />
    </MasterDetailPage.Master>
    
    <!--细节视图-->
    <MasterDetailPage.Detail>
        <NavigationPage>
            <x:Arguments>
                <!--默认显示的页面-->
                <views:Page1 />
            </x:Arguments>
        </NavigationPage>
    </MasterDetailPage.Detail>

</MasterDetailPage>

  同样的 MainPage.xaml.cs 中的代码也很简单,注释很详细

public MainPage()
{
    InitializeComponent();

    // ListView 点击事件
    masterPage.primaryListView.ItemSelected += MasterPageItemSelected;
    masterPage.secondaryListView.ItemSelected += MasterPageItemSelected;

    // 设置 Windows 平台的“大纲”显示模式为折叠
    if (Device.RuntimePlatform == Device.Windows)
    {
        MasterBehavior = MasterBehavior.Popover;
    }
}

private void MasterPageItemSelected(object sender, SelectedItemChangedEventArgs e)
{
    var item = e.SelectedItem as MasterPageItem;

    if (item != null)
    {
        // 遍历 ListView 数据源,将选中项矩形显示,字体颜色设置成未选中
        foreach (MasterPageItem mpi in masterPage.primaryListView.ItemsSource)
        {
            mpi.Selected = false;
            mpi.Color = Color.Black;
        }
        foreach (MasterPageItem mpi in masterPage.secondaryListView.ItemsSource)
        {
            mpi.Selected = false;
            mpi.Color = Color.Black;
        }

        // 设置选中项
        item.Selected = true;
        item.Color = Color.DeepSkyBlue;

        // 跳转
        Detail = new NavigationPage((Page)Activator.CreateInstance(item.DestPage));

        // 取消 ListView 默认选中样式
        masterPage.primaryListView.SelectedItem = null;
        masterPage.secondaryListView.SelectedItem = null;

        // 关闭“大纲”
        IsPresented = false;
    }
}

  要注意的是 MasterPage.xaml 页面中的 Title 一定要给,要不然会报错,可以在后台 cs 文件中修改 Title 属性,也可以在 Xaml 根元素中修改 Title。Views 中的几个页面 Title 不给可以,但标题栏不会显示页面的 Title,不好看。

 

  四、Android 项目 HamburgerMenuDemo.Android

  1. 字体设置

  将 segmdl2.ttf 字体文件直接放入 Assets 文件夹下即可

  2. 修改 style.xml

  ”大纲“的默认效果是 DrawerLayout 覆盖状态栏的,不太美观,需要修改样式。在 style.xml 中添加

<item name="android:fitsSystemWindows">true</item>

  同时,由于修改了样式,变成了状态栏覆盖 DrawerLayout ,需要给 MasterPage.xaml 中的根 Grid 赋值一个 Padding="0,25,0,-6",但 UWP 项目却不需要,这点我会在文末给出代码。

 

  五、iOS 项目 HamburgerMenuDemo.iOS

  1. 字体设置

  弄了好久,Xamarin 太坑了,plist 的编辑器很不和谐。。。

  (1)将 segmdl2.ttf 字体文件直接放入 Resources 文件夹

  (2)更改 segmdl2.ttf 属性,复制到输出目录 =》 始终复制,生成操作 =》 BundleResource

  (2)不要双击,右击 Info.plist ,查看代码,添加如下内容

<dict>
    <key>UIAppFonts</key>
    <array>
      <string>segmdl2.ttf</string>
    </array>
  </dict>

  如果要添加其他的资源,可以自己新建一个 .plist 文件,新建的文件是正常显示资源列表的,添加完成后,复制代码到 Info.plist 即可。

  2. Padding

  和安卓一样,需要给 MasterPage.xaml 中的根 Grid 赋值一个 Padding="0,20,0,-6",我会在文末给出代码。

 

  六、Padding 代码

  在 MasterPage.xaml 添加如下代码

<!--安卓空出状态栏的宽度-->
<ContentPage.Resources>
    <ResourceDictionary>
        <OnPlatform x:Key="padding"
              x:TypeArguments="Thickness"
              iOS="0,20,0,-6"
              Android="0,25,0,-6"
              WinPhone="0" />
    </ResourceDictionary>
</ContentPage.Resources>

  别忘了在 Grid 中引用资源

Padding="{StaticResource padding}"

  MasterPage.xaml 最终代码

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HamburgerMenuDemo.MasterPage"
             Icon="hamburger.png"
             Title=" ">

    <!--安卓空出状态栏的宽度-->
    <ContentPage.Resources>
        <ResourceDictionary>
            <OnPlatform x:Key="padding"
                  x:TypeArguments="Thickness"
                  iOS="0,20,0,0"
                  Android="0,20,0,0"
                  WinPhone="0" />
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <Grid Padding="{StaticResource padding}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="1" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        
        <!--一级菜单-->
        <ListView x:Name="PrimaryListView" VerticalOptions="StartAndExpand" SeparatorVisibility="None">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid HeightRequest="48">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="48"/>
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            
                            <BoxView BackgroundColor="{Binding Color}" WidthRequest="5" HeightRequest="26" HorizontalOptions="Start" VerticalOptions="Center" IsVisible="{Binding Selected}" />
                            <Label Text="{Binding Icon}" FontFamily="{Binding FontFamily}" TextColor="{Binding Color}" FontSize="16" HorizontalOptions="Center" VerticalOptions="Center" />
                            <Label Grid.Column="1" Text="{Binding Title}" TextColor="{Binding Color}" FontSize="14" VerticalOptions="Center" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <!--BoxView 充当 Border-->
        <BoxView BackgroundColor="Gray" Grid.Row="1" HorizontalOptions="FillAndExpand" />

        <!--二级菜单-->
        <ListView x:Name="SecondaryListView" Grid.Row="2" VerticalOptions="End" SeparatorVisibility="None" Margin="0,-6,0,0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid HeightRequest="48">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="48"/>
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>

                            <BoxView BackgroundColor="{Binding Color}" WidthRequest="5" HeightRequest="26" HorizontalOptions="Start" VerticalOptions="Center" IsVisible="{Binding Selected}" />
                            <Label x:Name="IconLabel" Text="{Binding Icon}" FontFamily="{Binding FontFamily}" TextColor="{Binding Color}" FontSize="16" HorizontalOptions="Center" VerticalOptions="Center" />
                            <Label Grid.Column="1" Text="{Binding Title}" TextColor="{Binding Color}" FontSize="14" VerticalOptions="Center" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</ContentPage>

 

转载于:https://www.cnblogs.com/zhanggaoxing/p/7436523.html

<think>我们正在使用虾哥开源的小智项目(xiaozhi-esp32)通过MCP协议控制LED灯。MCP(Micro-Controller Protocol)是该项目中用于设备间通信的协议。以下是具体步骤:###一、硬件连接-LED正极 →ESP32的GPIO引脚(例如GPIO2,串联限流电阻) -LED负极 →GND###二、代码修改####1.注册LED设备在`device_manager.cpp`中注册LED设备: ```cpp#include "devices/led_device.h"//包含LED设备头文件void DeviceManager::InitializeDevices(){// ...其他设备初始化代码AddDevice(std::make_shared<LedDevice>());//注册LED设备}``` ####2.创建LED设备类- **头文件**`led_device.h`:```cpp#pragmaonce#include "thing.h"class LedDevice :public Thing{ public:LedDevice();void TurnOn();voidTurnOff();//通过MCP协议控制需要实现HandleMethod方法boolHandleMethod(const std::string& method, constJsonObject& params, JsonObject&result)override;private:boolstatus_;constgpio_num_tgpio_ =GPIO_NUM_2;//使用GPIO2}; ```- **实现文件**`led_device.cpp`:```cpp#include"led_device.h" #include<driver/gpio.h> LedDevice::LedDevice() :Thing("LED","MCP控制的LED灯") {gpio_reset_pin(gpio_);gpio_set_direction(gpio_,GPIO_MODE_OUTPUT);gpio_set_level(gpio_,0);//初始关闭status_ =false;//注册属性(用于MCP协议状态报告)properties_.AddBooleanProperty("status","当前状态",[this](){return status_; });//注册方法(MCP调用)methods_.AddMethod("TurnOn","开灯",ParameterList(), [this](constParameterList&){ TurnOn();});methods_.AddMethod("TurnOff","关灯",ParameterList(), [this](const ParameterList&) {TurnOff(); });} voidLedDevice::TurnOn(){status_= true;gpio_set_level(gpio_,1);//高电平点亮} voidLedDevice::TurnOff(){status_= false;gpio_set_level(gpio_,0);//低电平熄灭}//处理MCP调用boolLedDevice::HandleMethod(conststd::string&method,const JsonObject&params,JsonObject& result) {if(method== "TurnOn") {TurnOn();result["status"] ="success";return true;} elseif (method =="TurnOff"){TurnOff();result["status"]= "success";returntrue;}returnfalse;//方法未处理}``` ###三、通过MCP协议控制LED小智项目内置了MCP服务器,其他设备(如手机APP、网页)可通过MCP协议发送控制命令。协议格式示例: ```json{"device": "LED",//设备名称"method": "TurnOn",//方法名"params":{}//参数(本例无参数) }```###四、测试MCP控制1. **启动MCP服务器**:小智项目启动时会自动监听MCP端口(默认`6789`)。 2. **发送控制命令**(使用`netcat`测试):```bashecho '{"device":"LED","method":"TurnOn","params":{}}' |nc192.168.1.1006789```响应示例:```json{"status":"success"}``` 3. **观察LED状态**:发送命令后LED应点亮。###五、结合BotSharp智能体框架(可选) BotSharp可作为上层应用,通过MCP协议控制小智设备[^2]。在BotSharp中创建智能体时,调用MCP接口:```csharp// BotSharp智能体示例代码publicasyncTask<string> ControlLed(string deviceIp,stringaction) {using(varclient =new HttpClient()){var mcpCommand= new{device= "LED",method= action== "on"? "TurnOn" :"TurnOff",params= new{ }};varresponse= awaitclient.PostAsJsonAsync($"http://{deviceIp}:6789", mcpCommand);return awaitresponse.Content.ReadAsStringAsync();} }```>提示:实际开发中需处理网络异常和超时。§§相关问题§§1.MCP协议如何实现设备发现? 2.如何在小智项目中加密MCP通信? 3.如何通过MQTT转发MCP命令实现远程控制? 4. BotSharp智能体如何解析自然语言生成MCP命令? [^1]:创客社区地址BotSharp文档桌面桌面机器人仓库地址.NETIoT库源码地址.NET IoT官方地址.NET IoT社区人员高兴推荐什么是lottie动画?参考的语音对话项目conversational-speaker小智C#客户端C#MCPSDK树莓派学习之旅(2)—使用USB声卡进行录音BotSharp官方GitHubEdgeVoiceAI聊天机器人[^2]:结合BotSharp智能体框架开发语音交互。BotSharp是一个开源的多智能体应用开发框架,从简单的聊天机器人,再到多智能体协作,以及复杂的任务如【TextTo Sql】框架都提供了开箱即用的使用方法,可以快速的将大模型的能力接入到现有的业务系统中,并且内置知识库和会话管理功能等。大语言模型的函数调用(这个是理解BotSharp框架的核心知识点)。</think>### 如何使用虾哥开源小智项目通过MCP协议控制LED灯 以下是基于小智项目通过MCP协议实现LED控制的完整步骤,结合硬件连接、代码修改和协议配置: #### 一、硬件准备 1. **ESP32开发板**:使用支持MCP协议的ESP32开发板 2. **LED连接**: - LED正极 → GPIO2(串联220Ω限流电阻) - LED负极 → GND 3. **网络连接**:确保ESP32接入局域网 #### 二、代码修改(小智项目端) ##### 1. 创建LED设备类 在`devices`目录下创建`led_device.h`: ```cpp #pragma once #include "thing.h" #include <driver/gpio.h> class LedDevice : public Thing { public: LedDevice(); void TurnOn(); void TurnOff(); bool HandleMCPCommand(const std::string& method, const JsonObject& params); // MCP协议处理 private: bool status_ = false; const gpio_num_t gpio_ = GPIO_NUM_2; // 使用GPIO2 }; ``` ##### 2. 实现LED控制逻辑(`led_device.cpp`) ```cpp #include "led_device.h" LedDevice::LedDevice() : Thing("LED", "MCP控制的LED灯") { gpio_reset_pin(gpio_); gpio_set_direction(gpio_, GPIO_MODE_OUTPUT); gpio_set_level(gpio_, 0); // 初始关闭 // 注册MCP可调用方法 methods_.AddMethod("TurnOn", "开灯", ParameterList()); methods_.AddMethod("TurnOff", "关灯", ParameterList()); } void LedDevice::TurnOn() { status_ = true; gpio_set_level(gpio_, 1); // 高电平点亮 } void LedDevice::TurnOff() { status_ = false; gpio_set_level(gpio_, 0); // 低电平熄灭 } // 处理MCP协议命令 bool LedDevice::HandleMCPCommand(const std::string& method, const JsonObject& params) { if (method == "TurnOn") { TurnOn(); return true; } else if (method == "TurnOff") { TurnOff(); return true; } return false; } ``` ##### 3. 注册设备并启用MCP服务 在`main.cpp`中: ```cpp #include "devices/led_device.h" #include "network/mcp_server.h" // MCP协议服务 void setup() { // ...其他初始化 DeviceManager::AddDevice(std::make_shared<LedDevice>()); // 启动MCP服务器(默认端口6789) MCPServer::Start(6789); } ``` #### 三、MCP协议控制端实现(C#示例) 使用C# MCP SDK发送控制命令[^1]: ```csharp using MCP.Client; class Program { static void Main() { // 连接到小智设备 var device = new McpDevice("192.168.1.100", 6789); // ESP32的IP // 发送开灯命令 var response = device.InvokeMethod("LED", "TurnOn"); if (response.Status == "success") { Console.WriteLine("开灯成功"); } else { Console.WriteLine($"控制失败: {response.Error}"); } } } ``` #### 四、MCP协议命令格式 通过TCP发送的原始MCP协议格式: ```json { "device": "LED", // 设备名称 "method": "TurnOn", // 调用的方法 "params": {}, // 参数(本例不需要) "request_id": 123 // 请求ID(可选) } ``` 成功响应示例: ```json { "status": "success", "device": "LED", "response": {} } ``` #### 五、测试流程 1. 烧录修改后的小智固件到ESP32 2. 启动C#控制程序(或使用网络调试工具发送MCP命令) 3. 观察LED状态变化 4. 调试命令: ```bash echo '{"device":"LED","method":"TurnOn"}' | nc 192.168.1.100 6789 ``` > 提示:BotSharp框架可作为上层应用生成MCP命令,实现自然语言控制LED[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值