通过mqtt 点灯

news2025/6/3 10:55:13

1 解析mqtt 传过来的json

        用cjson 解析。

2   类似mvc的结构,调用具体的动作函数

  1. 定义设备处理结构体:使用结构体数组映射设备名称与处理函数,实现可扩展的指令分发
  2. 分离设备逻辑:为每个设备(如 LED、Motor)编写独立的处理函数,保持模块解耦
  3. 统一 JSON 解析流程:在解析函数中通过遍历结构体数组匹配指令,调用对应处理函数
  4. 状态校验机制:对输入的状态值进行合法性校验,避免无效操作

完整修改后代码

#include "system.h"
#include "SysTick.h"
#include "led.h"         // 添加LED函数声明头文件
#include "usart.h"
#include "wifi_config.h"
#include "wifi_function.h"
#include <string.h>
#include "cJSON.h"

// 声明外部变量
extern struct STRUCT_USARTx_Fram strEsp8266_Fram_Record;

// 函数声明
void ProcessWiFiData(uint8_t *data, uint16_t length);
void HandleMQTTMessage(const char *topic, const char *message, const char *message_le);

// 全局变量
char topic_id[20] = "topic911";
char sub_topic_id[20] = "topic108";
uint8_t wifi_rx_buffer[RX_BUF_MAX_LEN]; // 用于暂存接收数据的缓冲区

// ========== 设备处理结构体定义 ==========
typedef enum {
    DEVICE_LED,
    DEVICE_MOTOR,
    DEVICE_UNKNOWN
} DeviceType;

typedef struct {
    const char *device_name;        // 设备名称(JSON键名)
    DeviceType device_type;         // 设备类型枚举
    void (*handler)(const char *state); // 处理函数指针
} DeviceHandler;

// ========== 设备处理函数实现 ==========
// LED处理函数(假设LED_Init()已在led.h中声明)
void LedHandler(const char *state) {
    if (strcmp(state, "on") == 0) {
        LED_ON(); // 假设LED_ON()在led.c中实现
        printf("Led turned on\r\n");
    } else if (strcmp(state, "off") == 0) {
        LED_OFF(); // 假设LED_OFF()在led.c中实现
        printf("Led turned off\r\n");
    } else {
        printf("Invalid state for LED: %s\r\n", state);
    }
}

// Motor处理函数(需根据实际硬件实现)
void MotorHandler(const char *state) {
    if (strcmp(state, "on") == 0) {
        // 这里添加电机启动代码
        printf("Motor started\r\n");
    } else if (strcmp(state, "off") == 0) {
        // 这里添加电机关闭代码
        printf("Motor stopped\r\n");
    } else {
        printf("Invalid state for Motor: %s\r\n", state);
    }
}

// 设备处理注册表(可扩展)
DeviceHandler device_handlers[] = {
    {"Led", DEVICE_LED, LedHandler},
    {"Motor", DEVICE_MOTOR, MotorHandler},
    {NULL, DEVICE_UNKNOWN, NULL} // 结束标志
};

// ========== JSON解析函数扩展 ==========
void parse_json_message(const char *message) {
    cJSON *root;
    cJSON *item; // 修正变量名,避免未使用警告

    if (message == NULL) {
        printf("错误:传入的JSON字符串为空\n");
        return;
    }

    root = cJSON_Parse(message);
    if (!root) {
        printf("JSON格式错误:%s\n", cJSON_GetErrorPtr());
        return;
    }

    // 遍历JSON对象中的键值对(修正变量声明位置)
    item = root->child; // 变量声明已在代码块开头,此处直接使用
    while (item) {
        const char *device_name = item->string;
        const char *state = item->valuestring;
        
        // 查找设备处理器
        DeviceHandler *handler = device_handlers;
        while (handler->device_name) {
            if (strcmp(device_name, handler->device_name) == 0) {
                handler->handler(state);
                break;
            }
            handler++;
        }

        if (!handler->device_name) { // 未找到处理器
            printf("Unknown device: %s\r\n", device_name);
        }
        item = item->next;
    }

    cJSON_Delete(root); // 释放内存
}

int main() {
    // 初始化部分保持不变...
    SysTick_Init(72);
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    USART1_Init(9600);
    LED_Init(); // 假设LED初始化函数在led.c中
    // Motor_Init(); // 如有电机初始化需添加

    WiFi_Config();

    printf("Hello, world!\r\n");
    printf("\r\n====================================\r\n");
    printf("STM32 + ESP8266 JSON Command Handler\r\n");
    printf("Supported devices: Led, Motor\r\n");
    printf("====================================\r\n");

    // 初始化WiFi和MQTT
    ESP8266_STA_TCP_Client_MQTT();
    if (ESP8266_Set_MQTT_Sub(sub_topic_id, "0")) {
        printf("\r\nSubscribed to MQTT topic successfully!\r\n");
    } else {
        printf("\r\nFailed to subscribe to MQTT topic!\r\n");
    }

    if (ESP8266_MQTT_Public_key_Value(topic_id, "aa", "01")) {
        printf("\r\nPublished MQTT message successfully!\r\n");
    } else {
        printf("\r\nFailed to publish MQTT message!\r\n");
    }

    while (1) {
        // 处理WiFi数据
        if (strEsp8266_Fram_Record.InfBit.FramFinishFlag) {
            uint16_t data_len; // 声明在代码块开头
            __disable_irq();   // 进入临界区
            data_len = strEsp8266_Fram_Record.InfBit.FramLength;

            // 复制数据到本地缓冲区
            memcpy(wifi_rx_buffer, strEsp8266_Fram_Record.Data_RX_BUF, data_len);
            wifi_rx_buffer[data_len] = '\0'; // 添加字符串结束符

            // 清除标志和计数器
            strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0;
            strEsp8266_Fram_Record.InfBit.FramLength = 0;
            __enable_irq(); // 退出临界区

            // 处理接收到的数据
            ProcessWiFiData(wifi_rx_buffer, data_len);
        }
        // 其他业务逻辑...
        delay_ms(100);
    }
    // 添加换行符避免警告
    printf("\n");
}

// 处理WiFi数据的函数
void ProcessWiFiData(uint8_t *data, uint16_t length) {
    // 示例:直接打印原始数据
    printf("[RAW DATA] %s\r\n", data);

    // 检查是否是MQTT消息
    if (strstr((char *)data, "+MQTTSUBRECV:") != NULL) {
        // 解析MQTT消息
        char *topic_start = strchr((char *)data, ',') + 1;
        char *msg_length_start = strchr(topic_start, ',') + 1;
        char *msg_start = strchr(msg_length_start, ',') + 1;

        // 提取主题和消息
        char topic[32] = {0};
        char msg_length[32] = {0};
        char message[128] = {0};

        sscanf(topic_start, "%[^,]", topic);
        sscanf(msg_length_start, "%[^,]", msg_length);
        sscanf(msg_start, "%[^,]", message);
        HandleMQTTMessage(topic, message, msg_length);
    }
    // 可以添加其他协议处理...
}

// 处理MQTT消息
void HandleMQTTMessage(const char *topic, const char *message, const char *message_length) {
    printf("Received MQTT message:\r\n");
    printf("Topic: %s\r\n", topic);         // topic_id
    printf("Message: %s\r\n\r\n", message); // json 字符串
    // todo: 根据实际需求处理消息
    parse_json_message(message); // 解析JSON消息
}
// 添加换行符避免警告

用cjson 解析:

参考 STM32单片机与cJSON:构建并解析JSON数据_stm32 cjson-CSDN博客

// ========== JSON解析函数扩展 ==========
void parse_json_message(const char *message) {
    cJSON *root;
    cJSON *item; // 修正变量名,避免未使用警告

    if (message == NULL) {
        printf("错误:传入的JSON字符串为空\n");
        return;
    }

    root = cJSON_Parse(message);
    if (!root) {
        printf("JSON格式错误:%s\n", cJSON_GetErrorPtr());
        return;
    }

    // 遍历JSON对象中的键值对(修正变量声明位置)
    item = root->child; // 变量声明已在代码块开头,此处直接使用
    while (item) {
        const char *device_name = item->string;
        const char *state = item->valuestring;
        
        // 查找设备处理器
        DeviceHandler *handler = device_handlers;
        while (handler->device_name) {
            if (strcmp(device_name, handler->device_name) == 0) {
                handler->handler(state);
                break;
            }
            handler++;
        }

        if (!handler->device_name) { // 未找到处理器
            printf("Unknown device: %s\r\n", device_name);
        }
        item = item->next;
    }

    cJSON_Delete(root); // 释放内存
}

传递 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2394750.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据-273 Spark MLib - 基础介绍 机器学习算法 决策树 分类原则 分类原理 基尼系数 熵

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大模型篇章已经开始&#xff01; 目前已经更新到了第 22 篇&#xff1a;大语言模型 22 - MCP 自动操作 FigmaCursor 自动设计原型 Java篇开…

基于 Spring Boot + Vue 的墙绘产品展示交易平台设计与实现【含源码+文档】

项目简介 本系统是一个基于 Spring Boot Vue 技术栈开发的墙绘产品展示交易平台&#xff0c;旨在提供一个高效、便捷的在线商城平台&#xff0c;方便用户浏览、选购墙绘产品&#xff0c;并提供管理员进行商品管理、订单管理等功能。系统采用了前后端分离的架构&#xff0c;前…

【机器学习】支持向量机

文章目录 一、支持向量机简述1.概念2.基本概念3.算法介绍4.线性可分5.算法流程 二、实验1.代码介绍2.模型流程3.实验结果4.实验小结 一、支持向量机简述 1.概念 支持向量机&#xff08;SVM&#xff09;是一类按监督学习方式对数据进行二元分类的广义线性分类器&#xff0c;其…

ONLYOFFICE深度解锁系列.4-OnlyOffice客户端原理-真的不支持多端同步

最近很多客户多要求直接部署onlyoffice服务端,还问能否和onlyoffice的客户端进行文件同步,当时真是一脸懵,还有的是老客户,已经安装了onlyoffice协作空间的,也在问如何配置客户端和协作空间的对接。由于问的人太多了,这里统一回复,先说结论,再说原理: 1.onlyoffice document s…

LLMTIME: 不用微调!如何用大模型玩转时间序列预测?

今天是端午节&#xff0c;端午安康&#xff01;值此传统佳节之际&#xff0c;我想和大家分享一篇关于基于大语言模型的时序预测算法——LLMTIME。随着人工智能技术的飞速发展&#xff0c;利用大型预训练语言模型&#xff08;LLM&#xff09;进行时间序列预测成为一个新兴且极具…

2.从0开始搭建vue项目(node.js,vue3,Ts,ES6)

从“0到跑起来一个 Vue 项目”&#xff0c;重点是各个工具之间的关联关系、职责边界和技术演化脉络。 从你写代码 → 到代码能跑起来 → 再到代码可以部署上线&#xff0c;每一步都有不同的工具参与。 &#x1f63a;&#x1f63a;1. 安装 Node.js —— 万事的根基 Node.js 是…

【pycharm】如何连接远程仓库进行版本管理(应用版本)

软件&#xff1a;Pycharm OS&#xff1a;Windows 一、Git基础设置 这里略过Git安装&#xff0c;需要可以参考&#xff1a;windows安装git&#xff08;全网最详细&#xff0c;保姆教程&#xff09;-CSDN博客 1. 配置Git 打开GitBash。分次输入下列命令。 git config --…

linux 1.0.7

用户和权限的含义与作用 linux中的用户和文件 用户的权限是非常重要的 而且有些程序需要使用管理员身份去执行 这些都是非常重要的 不可能让所有的人拥有所有的权限 这样的工具可以避免非法的手段来修改计算机中的数据 linux之所以安全还是权限管理做的很棒 每个登录的用户都有…

IEEE P370:用于高达 50 GHz 互连的夹具设计和数据质量公制标准

大多数高频仪器&#xff0c;如矢量网络分析仪 &#xff08;VNA&#xff09; 和时域反射仪 &#xff08;TDR&#xff09;&#xff0c;都可以在同轴接口的末端进行非常好的测量。然而&#xff0c;复杂系统中使用的互连很少具有同轴接口。用于表征这些设备的夹具的设计和实施会对测…

Denoising Autoencoders 视频截图 DAEs简单实现 kaggle 去噪编码器

https://www.bilibili.com/video/BV1syzrYaEtw Denoising Autoencoders (DAEs) 是一种无监督学习模型&#xff0c;属于自动编码器&#xff08;Autoencoder&#xff09;的一种扩展形式。它们的目标是通过训练神经网络来学习数据的鲁棒表示&#xff08;robust representation&a…

GoogLeNet网络模型

GoogLeNet网络模型 诞生背景 在2014年的ImageNet图像识别挑战赛中&#xff0c;一个GoogLeNet的网络架构大放异彩&#xff0c;与VGG不同的是&#xff0c;VGG用的是3*3的卷积&#xff0c;而GoogLeNet从1*1到7*7的卷积核都用&#xff0c;也就是使用不同大小的卷积核组合。 网络…

仿真科普|弥合市场需求断层,高性能仿真,“性能”与“安全”如何兼得?

2025年3月&#xff0c;塔塔科技&#xff08;Tata Technologies&#xff09;确认曾在去年遭受勒索软件组织“猎手国际”&#xff08;Hunters International&#xff09;的攻击&#xff0c;1.4TB工程数据被窃取&#xff0c;涉及航空发动机热障涂层工艺参数等超过 73 万份文件。 X…

Maven---配置本地仓库

目录 5. 5.1在Maven路径下新建文件夹用于本地仓库存储 5.2 复制本地仓库路径 5.3 找到配置文件路径&#xff0c;使用VSCode方式打开 5.4 新增一行代码 5.5 复制本地仓库路径&#xff0c;设置存储路径 5.1在Maven路径下新建文件夹用于本地仓库存储 5.2 复制本地仓库路径 5…

【C++ 】智能指针:内存管理的 “自动导航仪”

目录 一、引入 二、智能指针的两大特性&#xff1a; 1、RAII 特点&#xff1a; 好处&#xff1a; 2、行为像指针 三、智能指针起初的缺陷&#xff1a;拷贝问题 四、几种智能指针的介绍。 1、C98出现的智能指针——auto_ptr auto_ptr解决上述拷贝构造的问题&#xff1a…

设备制造行业项目管理难点解析,如何有效解决?

在设备制造行业&#xff0c;项目管理是企业运营的核心环节&#xff0c;直接影响项目交付效率、成本控制和盈利能力。然而&#xff0c;由于行业特性复杂、项目周期长、涉及部门多&#xff0c;企业在实际操作中常常面临诸多管理痛点。金众诚工程项目管理系统&#xff0c;依托金蝶…

浅谈 PAM-2 到 PAM-4 的信令技术演变

通信信令技术演进&#xff1a;从 PAM-2 到 PAM-4 在当今数字化高速发展的时代&#xff0c;数据传输需求呈爆炸式增长&#xff0c;行业对通信带宽的要求愈发严苛。为顺应这一趋势&#xff0c;通信信令技术不断革新&#xff0c;曾经占据主导地位的不归零&#xff08;NRZ&#xff…

Protos-SIP:经典 SIP 协议模糊测试工具!全参数详细教程!Kali Linux教程!

简介 该测试套件的目的是评估会话发起协议 (SIP) 实现的实现级别安全性和稳健性。 Protos-SIP 是一款专为 SIP 协议模糊测试&#xff08;Fuzzing&#xff09;设计的工具&#xff0c;最初由 OUSPG&#xff08;Oulu University Secure Programming Group&#xff09;开发&#…

复数三角不等式简介及 MATLAB 演示

复数三角不等式简介及 MATLAB 演示 1. 复数三角不等式简介 复数三角不等式&#xff08;Complex Triangle Inequality&#xff09;是复数的一种重要性质&#xff0c;它类似于普通的三角不等式&#xff0c;但适用于复数空间。具体来说&#xff0c;复数三角不等式可以描述复数之…

【Doris基础】Apache Doris 基本架构深度解析:从存储到查询的完整技术演进

目录 1 引言 2 Doris 架构全景图 2 核心组件技术解析 2.1 Frontend 层&#xff08;FE&#xff09; 2.2 Backend 层&#xff08;BE&#xff09; 3 数据存储与复制机制 3.1 存储架构演进 3.2 副本复制策略 4 查询处理全流程解析 4.1 查询生命周期 5 高可用设计 5.1 F…

程序人生-hellohelloo

计算机系统 大作业 题 目 程序人生-Hello’s P2P 专 业 计算机与电子通信 学   号 2023111976 班   级 23L0504 学 生 孙恩旗     指 导 教 师 刘宏伟    计算机科…