尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
C# WinForm MQTT客户端实例:协议选型、订阅发布与避坑指南
简介面向 C# WinForm 开发者的 MQTT 客户端实例StdioMQTT-master适合需要接入 MQTT 服务器、学习消息遥测传输协议或搭建桌面端物联网验证工具的开发人员。压缩包共 121 个文件、7.82MB含 13 个 cs 源码文件、35 个 dll 依赖库、16 个 pdb 调试符号及 config、sln、ico 等工程文件解压后可在 Visual Studio 中直接打开运行。实例实现 MQTT 客户端基本结构覆盖网络连接、消息发布与订阅、消息接收、服务器地址与端口配置等功能并通过 WinForms 界面支持输入主题、用户名、密码和消息体代码还涉及 QoS、遗嘱消息、Keep Alive 与异步网络编程便于理解协议细节并二次开发。目前已有 209 人学习适合 C# 入门至中级开发者快速上手并投入实际项目。1. 一个 c# winform MQTT客户端实例能省掉两周的协议摸索做上位机开发的工程师拿到“c# winform MQTT客户端实例”这类项目包诉求通常很具体设备端把数据按 MQTT 协议发到 Broker我需要在 Windows 窗体里实时显示温度、状态、报警还要能下发指令。这套东西看着不大真从零做要踩不少坑——协议概念、C# 侧的库选型、UI 线程和消息回调的纠缠每一项都能耗掉一两天。这个实例包的价值就是把连接、订阅、发布、刷新界面这条链路给你摆好你只需要改 Broker 地址和设备主题。它适合工控、物联网、智能家居这种设备与上位机打交道的场景无论是刚接触 MQTT 的新手还是想找一个可靠骨架的熟手都可以拿它当起点。接下来按一条可复现的路径拆开讲协议和选型为什么这样定代码怎么落参数怎么调踩坑记录在哪。2. MQTT 协议核心与 C# 库选型订阅模型、QoS 和 MQTTnet 为什么值得用2.1 MQTT 协议的一根主线Broker、主题、通配符0 基础学习 mqtt 协议最先要纠正的是把它当成 HTTP 那种“客户端请求、服务器应答”的模型。MQTT 是发布/订阅模型所有消息都发给一个叫 Broker 的中间件设备是发布者WinForm 客户端是订阅者同时也可以是发布者下发指令。订阅者向 Broker 声明自己关心哪些主题Broker 负责把主题匹配的消息推给对应订阅者发布者和订阅者彼此不直接连也不需要知道对方地址。主题用 / 分层比如 device/device001/data。订阅端支持两个通配符 匹配单层# 匹配剩余所有层。要订阅全部设备的上报数据写 device//data调试时想观察所有消息写 #。这个 # 在开发阶段很管用但生产环境慎用它会把系统主题、遗嘱主题全拉进来解析压力和网络流量都会翻几倍。QoS 三个等级直接决定可靠性。QoS 0 最多一次丢了就丢了QoS 1 至少一次保证 Broker 和客户端都确认收到但可能重复投递QoS 2 恰好一次协议开销最大、吞吐最差绝大多数上位机场景用不上。很多人搜“mqtt 怎么保证不丢失消息至少一次”答案就在这条链路上发布端和订阅端的 QoS 都设为 1业务层再对重复消息做幂等处理。消息体里带一个自增序列号或时间戳接收端发现序列号跳变就知道漏了一条。还有两个概念一开始就要吃透CleanSession 和遗嘱消息。CleanSession 为 true 时每次连接都是全新会话Broker 不保留任何历史订阅和离线消息为 false 时Broker 保留会话客户端掉线期间到达的 QoS 1/2 消息会在重连后补发代价是服务端内存占用上升且 ClientId 必须固定。遗嘱消息是连接时预先登记的一小段报文客户端因网络异常而非主动断开时Broker 会替它把遗嘱发到指定主题这是设备掉线检测最基础的手段。2.2 MQTTnet 还是 M2Mqtt新项目我无脑选 MQTTnetC# 侧的 MQTT 库存量最大的是两个。M2Mqtt 是 paho.mqtt.m2mqtt 的移植API 老派、按事件回调、重连基本靠手写.NET Framework 4.0 时代留下的一批工控项目都在用它。MQTTnet 是后来居上的开源库API 更现代异步模型天然贴合 async/await内置 TLS 和 WebSocket 支持同一套代码还能复用到 WPF、.NET MAUI 项目里。如果你在纠结 winform、wpf、.net maui 三选一通信层用 MQTTnet 就不用推翻重写。我的选型结论很直接新项目选 MQTTnet特别是打算长期维护的上位机。连接管理、断线重连、订阅结果检查在 MQTTnet 里都是显式 API出错能拿到完整异常栈M2Mqtt 要实现同样的可靠性得自己补大量胶水代码时间一长就成了只有作者能看懂的私货。M2Mqtt 唯一的优势是老工程兼容如果源码包里已经引用它且跑得通也不急着换但要确认维护状态Broker 端上 MQTT 5 特性后容易踩空。选型时还有协议版本这件事。MQTT 3.1.1 和 MQTT 5 的会话、遗嘱、用户属性实现都不完全一样。MQTTnet 同时支持两者默认走 3.1.1跟绝大多数 Broker 兼容性最好。WinForm 项目我建议先用 3.1.1 跑通链路确认设备端和 Broker 都支持 5 了再切换否则一些依赖用户属性的诊断功能会莫名失效。2.3 实例包解开后代码应该怎么分层这类“c# winform MQTT客户端实例”不管源码出自谁手合理的结构通常绕不开三块窗体层、通信服务层、配置层。窗体层放连接按钮、数据显示表格、日志区通信服务层单独封装一个类负责连接、订阅、发布、重连和消息分发不直接碰任何控件配置层用 app.config 或设置文件保存 Broker 地址、端口、用户名、密码、主题前缀。我见过不少初学者的写法是把 MQTTnet 代码直接堆进 Form1.cs消息回调里直接操作 DataGridView。短期演示没问题一旦要加断线重连、消息日志、多设备路由整个窗体就成了几百行的大杂烩改一个地方炸两个地方。所以拿到任何实例包先看它是不是把通信逻辑和 UI 分离了没分离的先分离再继续这是后面所有操作能复现的前提也是判断一个实例包值不值得投入的及格线。3. 用 MQTTnet 跑通订阅发布连接参数、订阅代码与 UI 刷新3.1 建工程和装包NuGet 引用与本地 Broker 准备第一步先建一个 WinForm 工程.NET Framework 4.6.1 或 .NET 6 都行。老工程在 Package Manager Console 里执行 Install-Package新工程用 dotnet CLI。装包命令一行dotnet add package MQTTnet装完看一眼版本确认是 4.x 系列。3.x 的老 API 已停更网上搜到的 3.x 示例代码复制到 4.x 工程里基本编译不过别在这种地方浪费时间。测试 Broker 如果还没有常见做法是拿 EMQX 或 Mosquitto 的 zip 包解压然后在管理员 PowerShell 里把它注册成 Windows 服务sc create mosquitto binPath C:\tools\mosquitto\mosquitto.exe -c C:\tools\mosquitto\mosquitto.conf start auto sc start mosquittobinPath的等号右边必须有一个空格这是 Windows 服务命令的老规矩。注册成功后客户端连 127.0.0.1:1883 就能调试。这一步属于环境准备别省后面排错时你会需要一个完全可控的 Broker而不是拿生产环境当试验场。3.2 连接参数详解Broker 地址、ClientId、KeepAlive、遗嘱连接是把所有参数先摆到桌面上。下面是封装好的 MqttClientService每个 With 方法都对应一个可调参数public async Task ConnectAsync(string host, int port, string clientId, string username, string password, string willTopic) { var mqttFactory new MqttFactory(); _client mqttFactory.CreateMqttClient(); var options new MqttClientOptionsBuilder() .WithTcpServer(host, port) // Broker 地址和端口 .WithClientId(clientId) // 客户端唯一标识 .WithCredentials(username, password) // 无认证时传空串 .WithKeepAlivePeriod(TimeSpan.FromSeconds(30)) // 心跳周期 .WithCleanSession(true) // 每次连接全新会话 .WithWillTopic(willTopic) // 遗嘱主题 .WithWillPayload(offline) // 遗嘱消息内容 .WithWillQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) .WithWillRetainFlag(true) .Build(); _client.ApplicationMessageReceivedAsync OnApplicationMessageReceived; var result await _client.ConnectAsync(options, CancellationToken.None); if (result.ResultCode ! MqttClientConnectResultCode.Success) throw new Exception($连接失败返回码: {result.ResultCode}); }参数说明几条关键的。ClientId 在同一 Broker 内必须唯一两个客户端用同一个 ClientId 连接后者会把前者踢下线这是后面“连接成功但马上离线”的头号原因调试阶段可以在 ClientId 后拼接 Guid 后缀规避。KeepAlive 30 秒表示客户端每 30 秒发一次心跳Broker 在 1.5 倍周期内没收到任何报文就判定掉线。CleanSession 为 true 适合测试生产环境要消息不丢后面会专门说。遗嘱参数只在网络异常断开时生效正常调用 DisconnectAsync 不会触发遗嘱这个区别排错时会反复用到。3.3 订阅和发布最小可用写法与订阅结果检查订阅的关键是主题过滤器里的通配符和 QoS。多主题订阅直接累积 WithTopicFilterpublic async Task SubscribeTopicsAsync() { var subOptions new MqttClientSubscribeOptionsBuilder() .WithTopicFilter(device//report, MqttQualityOfServiceLevel.AtLeastOnce) .WithTopicFilter(device//alarm, MqttQualityOfServiceLevel.AtLeastOnce) .WithTopicFilter(gateway/status, MqttQualityOfServiceLevel.AtLeastOnce) .Build(); var result await _client.SubscribeAsync(subOptions, CancellationToken.None); foreach (var item in result.Items) { if (item.ResultCode ! MqttClientSubscribeResultCode.GrantedQos0 item.ResultCode ! MqttClientSubscribeResultCode.GrantedQos1 item.ResultCode ! MqttClientSubscribeResultCode.GrantedQos2) { Log($订阅被拒绝: {item.TopicFilter.Topic}, {item.ResultCode}); } } }订阅结果一定要检查别假设一定成功。被拒绝的常见原因是权限不足或主题格式非法比如把保留字塞进主题里。不同 MQTTnet 版本的枚举名可能有差异编译不过时去 NuGet 缓存里查一下当前版本的枚举定义。发布方法关注三件事Topic、Payload、QoS。业务里下发指令通常是把对象序列化成 JSONPayload 传 byte[]public async Task PublishAsync(string topic, string jsonPayload, bool retain false) { var message new MqttApplicationMessageBuilder() .WithTopic(topic) .WithPayload(Encoding.UTF8.GetBytes(jsonPayload)) .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) .WithRetainFlag(retain) .Build(); await _client.PublishAsync(message, CancellationToken.None); }retain 参数要特别提醒retaintrue 时 Broker 会保存这条消息未来任何新订阅者一订阅就立刻收到。适合存设备的“最新状态”比如把在线状态 retain 成一条 online/offline 消息新客户端一上来就能知道全局状态。但下发命令绝对不要 retain命令是瞬时的重复投递给设备就是事故。消息回调里只做轻量转换把 topic 和 payload 抛给上层事件不要在这里写日志、操作数据库、刷新界面private Task OnApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e) { var topic e.ApplicationMessage.Topic; var json Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment.ToArray()); OnMessageReceived?.Invoke(topic, json); return Task.CompletedTask; }3.4 从收到消息到刷新界面Invoke 的正确姿势MQTTnet 的消息回调线程不是 UI 线程直接在这个回调里操作 DataGridView 会抛跨线程异常或运气好不抛但界面卡死。标准做法是在窗体侧把消息抛回 UI 线程private void OnMqttMessage(string topic, string payload) { if (InvokeRequired) { BeginInvoke(new Actionstring, string(OnMqttMessage), topic, payload); return; } dataGridView1.Rows.Add( DateTime.Now.ToString(HH:mm:ss.fff), topic, payload); }InvokeRequired 为 true 说明当前线程不是 UI 线程BeginInvoke 会把委托异步丢回 UI 线程执行。这里用 BeginInvoke 而不是 Invoke是因为在消息回调里同步 Invoke 容易和 UI 线程相互等待出现类似死锁的假象。窗口关闭时在 FormClosing 里调用 DisconnectAsync否则下次调试会看到旧连接残留。4. 上位机化改造多主题路由、DataGridView 高频刷新与断线重连4.1 多主题订阅与路由分发一台上位机管几十上百台设备订阅就不能是单条主题了。按设备前缀和消息类型拆开订阅回调里的 topic 字符串就是路由键private void OnMqttMessage(string topic, string payload) { if (topic.StartsWith(device/) topic.EndsWith(/report)) HandleDeviceReport(topic, payload); else if (topic.EndsWith(/alarm)) HandleAlarm(topic, payload); else if (topic.StartsWith(gateway/)) HandleGatewayStatus(topic, payload); }路由按主题后缀区分比解析 JSON 里的 type 字段快也不依赖消息体格式。这里容易犯的错是把设备编号直接写死进订阅主题比如订阅 device/device001/data换一台设备就要重新订阅。正确做法是用 通配符把设备编号参数化设备列表变更时只改路由表不用动订阅逻辑。网关状态主题我建议单独订阅和业务数据分开处理避免网关心跳冲淡设备数据的展示。4.2 DataGridView 高频刷新队列加定时器批量灌高频数据是 WinForm 上位机的第一道坎。消息一秒来几百条每条都用 BeginInvoke 直接加一行界面必卡。我一般做法是中间加一个 ConcurrentQueueUI 定时器每 300 毫秒批量取一次private ConcurrentQueueDisplayItem _queue new(); private System.Windows.Forms.Timer _uiTimer; private void InitUiTimer() { _uiTimer new System.Windows.Forms.Timer(); _uiTimer.Interval 300; _uiTimer.Tick (s, e) FlushGrid(); _uiTimer.Start(); } private void OnMqttMessage(string topic, string payload) { _queue.Enqueue(new DisplayItem { Time DateTime.Now, Topic topic, Data payload }); } private void FlushGrid() { var batch new ListDisplayItem(200); while (batch.Count 200 _queue.TryDequeue(out var item)) batch.Add(item); if (batch.Count 0) return; dataGridView1.SuspendLayout(); foreach (var item in batch) { int idx dataGridView1.Rows.Add( item.Time.ToString(HH:mm:ss.fff), item.Topic, item.Data); // 上报数据里有 0/1 状态字段时直接映射到 CheckBox 列 // if (TryGetStatus(item.Data, out var status)) // dataGridView1[colStatus.Index, idx].Value (status 1); } dataGridView1.ResumeLayout(); // 超过 5000 行删最旧的防止绘制越来越慢 while (dataGridView1.Rows.Count 5000) dataGridView1.Rows.RemoveAt(0); }消息回调只做 Enqueue不碰任何控件UI 定时器攒批灌给 DataGridView单次绘制控制在 200 行以内。行数上限 5000 是经验值超过之后 RemoveAt(0) 的代价会增大这时考虑只显示最近 1000 行全量数据落 SQLite 或日志文件。这一条是血泪经验忘掉它必然卡死。4.3 断线重连指数退避与手动断开标记Broker 重启、网络闪断、防火墙超时都会让连接静默断开。上位机的断线重连是基本盘做不好设备数据就会在运维眼皮底下丢失。我的重连逻辑放在 DisconnectedAsync 事件里private bool _manualDisconnect false; private int _retryCount 0; public async Task DisconnectAsync() { _manualDisconnect true; await _client.DisconnectAsync(); } private async Task OnDisconnected(MqttClientDisconnectedEventArgs e) { if (_manualDisconnect) return; while (_client.IsConnected false _retryCount 10) { try { await Task.Delay(TimeSpan.FromSeconds( Math.Min(Math.Pow(2, _retryCount), 30))); // 2s,4s,8s…封顶30s await _client.ConnectAsync(_options, CancellationToken.None); await SubscribeTopicsAsync(); // 重连后重新订阅 _retryCount 0; } catch (Exception ex) { _retryCount; Log($重连失败第 {_retryCount} 次: {ex.Message}); } } }重连间隔用指数退避2 秒、4 秒、8 秒封顶 30 秒避免 Broker 还在启动时客户端高频重连打爆日志。重连成功后必须重新订阅全部主题因为 CleanSessiontrue 的会话在断线时已经清掉了订阅关系。手动断开标记 _manualDisconnect 必须提前置位否则你点“断开”按钮也会触发重连逻辑这是很多人翻车的细节。如果当前 MQTTnet 版本在复连时报“client 已存在”类异常把重连改成重新 new 一个 IMqttClient 实例同样适用这段逻辑。5. 避坑连接黑匣子、UI 卡死与 QoS 误区的 5 个现场5.1 现象一连上了却一条消息都收不到这大概是 MQTT 调试里出现频率最高的问题。连接返回成功界面也提示在线但数据表格空白。一半以上是主题写错——设备实际发到 device/device001/data你订了 device//report当然匹配不上。建议调试时先用 MQTT Explorer 连同一个 Broker订阅 # 看设备真实发布主题再回头改自己的订阅。第二种常见原因是 ClientId 冲突。同一 Broker 上另一个客户端占了相同 ClientId自己刚连上就被踢下线表象就是“连接成功、马上离线”。解决方式是 ClientId 加随机后缀或设备唯一标识同时检查是否开了多个调试实例。第三种原因是 CleanSessiontrue 且订阅 QoS0离线期间消息全丢上线后又偏偏没有新消息看起来就像收不到。把 QoS 提到 1并根据业务决定是否改 CleanSessionfalse。5.2 现象二消息一来窗体就卡死消息频率稍微起来界面就“未响应”。原因链路很清晰每条消息回调都调 Invoke/BeginInvokeUI 线程永远在排队画 DataGridView系统消息排不上队窗口就卡住了。解决办法是 4.2 节那套队列加定时器批量刷新别在消息回调里做任何 UI 操作。另一个连环翻车点是在回调里同步写日志每条消息都 File.AppendAllText 或 Insert 数据库磁盘 IO 直接拖垮消息线程。日志和数据库写入必须扔到后台 Task或者攒一批再写。把这两点改掉99% 的 WinForm 卡死都能缓解。5.3 现象三收到的中文变成乱码MQTT 的 Payload 本质是 byte[]协议不约束字符编码编码全靠两端约定。最常见的现场是设备端用 GB2312 编码C# 端按 UTF-8 解中文全变成 “温度” 这类乱码反过来设备端 UTF-8、客户端用默认编码也会乱。解决方式是先确认设备端编码统一用 UTF-8。如果必须解析 GB2312.NET Core 下要先用 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) 注册代码页编码提供程序否则 Encoding.GetEncoding(GB2312) 直接抛异常。这是 .NET Core 和 .NET Framework 行为的明显差异老工程师也容易在迁移时踩进去。5.4 现象四设备拔线了界面上它还“在线”设备断电、拔网线Broker 和客户端之间没有 TCP 连接断开的通知只能靠心跳超时。KeepAlive 设 60 秒的话Broker 最迟 90 秒才判定设备掉线再发遗嘱上位机检测到可能已经过去两分钟。更隐蔽的是很多设备端压根没实现遗嘱发布。我一般做三层兜底第一层设备连接时登记遗嘱掉线后 Broker 往 device/status 发 offline第二层上位机自己维护一个心跳超时定时器超过 N 秒没收到某设备任何主题消息就标记离线第三层设备周期性主动上报心跳作为前两层的补充。三层里至少做两层不然“在线”状态就是个纸糊的绿灯。注意实测遗嘱时用拔网线模拟非正常断开点 Disconnect 按钮是不会触发遗嘱的。5.5 现象五QoS 1 还是丢消息QoS 1 号称“至少一次”但很多人的实测结果是照样丢。原因通常是三个之一订阅端设 QoS 1、发布端设 QoS 0协议实际生效等级取两者最小值结果还是 0CleanSessiontrue 导致离线期间消息不补发Broker 端的消息队列容量被占满旧消息被丢弃。搜“mqtt怎么保证不丢失消息至少一次”的人多半就是卡在这几个组合里。正确组合是发布端 QoS 1、订阅端 QoS 1、CleanSessionfalse、ClientId 固定Broker 端把会话过期时间调大。同时建议在消息体里塞一个自增序列号接收端监控序列号跳变跳了就说明中间还有漏发这时候再做补偿查询比无脑提高 QoS 更实际。QoS 2 的“恰好一次”能解决重复但吞吐会明显掉不是所有场景都付得起这个代价。6. 收尾前必做的一轮验证消息计数、MQTT Explorer 对照与日志落点给实例包收尾前我建议做一轮端到端验证而不是界面看着“好像能跑”就完事。第一件事是消息计数验证 QoS准备一个测试发布程序循环发布 10000 条消息每条带自增序号客户端收到后计数并检查序号连续性。代码很简单private int _receivedCount 0; private int _lastSeq 0; private void OnMqttMessage(string topic, string payload) { int seq ExtractSeq(payload); if (seq ! _lastSeq 1) Log($序号跳变: {_lastSeq} - {seq}); _lastSeq seq; Interlocked.Increment(ref _receivedCount); }这轮测试能暴露主题匹配、QoS 组合、消息积压三个层面的问题比盯着界面看有没有数据可靠得多。第二件事是用 MQTT Explorer 做对照订阅 # 观察原始主题和 payload确认不是客户端解析代码偷偷吞掉了消息。日志落点只保留三类连接与重连结果、订阅被拒绝的记录、序号跳变和 QoS 降级告警。日志别打到 UI 文本框里落到文件并用时间戳命名出问题时能按时间窗对得上现场。这套验证做完这个客户端实例才算真正从“能连上”变成“能交付”。我自己早期就是跳过了计数验证把 100 个模拟设备一开界面和数据对不上账花了一个下午才发现是 QoS 订阅和发布端的等级不匹配。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

基于蒙特卡洛法的电动汽车充电负荷计算MATLAB仿真程序

基于蒙特卡洛法的电动汽车充电负荷计算MATLAB仿真程序

简介:针对电动汽车充电负荷预测这一电力系统规划的关键问题,这份MATLAB程序提供了基于蒙特卡洛法的完整计算方案,面向电力系统研究人员、电动汽车方向学生及工程师,适用于充电基础设施规划与电网调度分析。程序通过大量随机抽样模…

📅 2026/11/2 10:29:02
微服务架构在数据开发中的实践与优化

微服务架构在数据开发中的实践与优化

1. 微服务设计模式与数据开发的天然契合 数据开发领域正经历着从传统ETL管道向实时化、智能化方向的演进。在这个过程中,微服务架构展现出了与数据开发需求高度匹配的特性。我们团队在过去三年中,逐步将单体数据平台拆分为微服务架构,最直观的…

📅 2026/11/2 10:29:02
A2A 1.0协议:智能体间通信的标准化解决方案

A2A 1.0协议:智能体间通信的标准化解决方案

1. A2A 1.0协议概述 A2A(Agent-to-Agent)1.0协议是Google Cloud主导开发的智能体间通信开放标准。这个协议解决了一个关键痛点:在AI代理生态系统中,不同厂商开发的智能体往往采用各自封闭的通信方式,导致系统间形成信息…

📅 2026/11/2 10:24:02
MORE NEWS

更多资讯

📰

YOLO26最新创新改进系列:样条KAN令牌主干,1×1 卷积给每个通道一个固定权重:让 YOLO26 的主干用样条函数去表达非线性!

YOLO26最新创新改进系列:样条KAN令牌主干,11 卷积给每个通道一个固定权重:让 YOLO26 的主干用样条函数去表达非线性! 截止目前,YOLO26最新创新改进系列已更新100种,排列组合后可达到上万种创新模型&#x…

📰

人生有哪些突破:辞掉稳妥的工作去做一件自己真正在意的事、搬到一个谁也不认识的城市、把攒了三年的钱投进一个还没验证的产品、四十岁去学一门和本职毫无关系的技能、把“不好意思开口“的那句话认真说一遍

人生有哪些突破:一份从临终遗憾倒推出来的清单 有位护士叫布朗妮韦尔(Bronnie Ware),在姑息护理病房工作了很多年。她记录下临终者最常说的遗憾,后来写成《临终前最后悔的五件事》。这几条被转述过无数次,因为它们几乎一模一样: 我希望能有勇气过忠于自己的生活,而不是…

📰

写给果酒创业者|十一月,我们打算这么干[特殊字符]

写给果酒创业者|十一月,我们打算这么干🔥 常有人说:做工厂、做品牌,只盯月度计划,格局不大。 但我们坚信: 所有好结果,都不是突然爆发, 而是月月落地、慢慢沉淀出来的。 …

📰

RK3588上手笔记:1、MobaXterm连接与串口接收解析

MobaXterm 选择: 波特率:`1500000` 数据位:`8` 停止位:`1` 校验:`None` 流控:`None` 也就是:`1500000-8-N-1`。野火 LubanCat-4 的 Debug 串口默认参数就是这个。 电脑必须接 3.3V USB-TTL 串口模块,才会出现 COMx。 板子上的 USB-C OTG 烧录口不能直接作为调试串口。 …

📰

多 Agent 客服的短期记忆改造:用 Redis + Checkpointer 管理会话状态

前言 mall-customer 的短期记忆原本是一个手写的 Redis 封装:把对话消息按会话 ID 存进 Redis list,读的时候取最近 N 条。封装本身是通的,但它和 Agent 图之间是断开的——消息存下来了,模型看不到。用户第一轮说"我要退款…

📰

FreeRTos 正点原子 笔记(2):解读 FreeRTOSConfig . h;函数名前缀 v x u 等;port 代表移植层,平台适配层;configTOTAL_HEAP_SIZE 的内存管理

(6)FreeRTOSConfig.h 配置文件作用 :(7) 还是老师例题里的版本, F429,加上老师的讲解 : #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H/* 头文件 */ #include "./SYSTEM/sys/sys.h" #include "…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬