【XR806开发板试用】XR806在U8G2上增加MQTT+JSON控制

一、前言

  1. U8G2移植参见之前写的文章 https://aijishu.com/a/1060000000292472
  2. 本次增加MQTT+JSON是站在大佬的肩膀上,参见 https://aijishu.com/a/1060000000284320
  3. CJSON的使用,参见 https://blog.csdn.net/fengxinlinux/article/details/53121287

二、成果

  1. 目录结构:在这里插入图片描述

  2. test_mqtt.c 基本上照搬大佬的代码,内容如下:

#include <stdio.h>
#include <string.h>
#include "ohos_init.h"
#include "kernel/os/os.h"#include "wifi_device.h"
#include "common/framework/net_ctrl.h"
#include "net/mqtt/MQTTClient-C/MQTTClient.h"
#include "cjson/cJSON.h"static OS_Thread_t g_main_thread;
static OS_Thread_t g_mqtt_thread;#define PWM_OUTPUT_CHL        PWM_GROUP1_CH2
#define PWM_OUTPUT_MODE       PWM_CYCLE_MODE#define WIFI_DEVICE_CONNECT_AP_SSID "TP-LINK_EEF3" /* 这里填你家路由器的SSID */
#define WIFI_DEVICE_CONNECT_AP_PSK "13677668125"  /* 这里填你家路由器的PWD */#define MQTT_DEMO_CLIENT_ID "12345"
#define MQTT_DEMO_HOST_NAME "broker-cn.emqx.io" /* 这个是免费调试用的MQTT服务器地址 */
#define MQTT_DEMO_PORT      "1883"
#define MQTT_DEMO_USERNAME  "12345678"
#define MQTT_DEMO_PASSWORD  "12345678"
#define MQTT_RESP_TOPIC "/to/weixin/display" /* 设备发出来的TOPIC */
#define MQTT_RECV_TOPIC  "/to/xr806/display" /* 手机发出来的TOPIC */
#define MQTT_DEMO_BUF_SIZE (2*1024)static MQTTPacket_connectData mqtt_demo_connectData = MQTTPacket_connectData_initializer;
static Client mqtt_demo_client;
static Network mqtt_demo_network;
static int max_duty_ratio = 0;static int mqtt_demo_publish(char *topic, char *msg) ;void test_set_str(uint8_t *pstr, uint8_t plen);static int mqtt_demo_init(void)
{char *send_buf;char *recv_buf;mqtt_demo_connectData.clientID.cstring = MQTT_DEMO_CLIENT_ID;mqtt_demo_connectData.keepAliveInterval = 30; /* 30s */mqtt_demo_connectData.cleansession = 0;mqtt_demo_connectData.MQTTVersion = 4; /* Version of MQTT 3.1.1 */send_buf = malloc(MQTT_DEMO_BUF_SIZE);if (send_buf == NULL){printf("no memory\n");return -1;}recv_buf = malloc(MQTT_DEMO_BUF_SIZE);if (recv_buf == NULL){free(send_buf);printf("no memory\n");return -1;}/* init network */NewNetwork(&mqtt_demo_network);/* init mqtt client object */MQTTClient(&mqtt_demo_client, &mqtt_demo_network, 6000,(unsigned char *)send_buf, MQTT_DEMO_BUF_SIZE,(unsigned char *)recv_buf, MQTT_DEMO_BUF_SIZE);/* set username and password */mqtt_demo_connectData.username.cstring = MQTT_DEMO_USERNAME;mqtt_demo_connectData.password.cstring = MQTT_DEMO_PASSWORD;return 0;
}static int mqtt_demo_connect(char *host_name, char *host_port)
{int ret = -1;ret = ConnectNetwork(&mqtt_demo_network, host_name, atoi(host_port));if (ret != 0) {printf("mqtt connect faild, ret:%d, host:%s, port:%s\n", ret, host_name, host_port);goto exit;}ret = MQTTConnect(&mqtt_demo_client, &mqtt_demo_connectData);if (ret != 0) {printf("mqtt connect faild, ret:%d\n", ret);mqtt_demo_network.disconnect(&mqtt_demo_network);goto exit;}printf("mqtt connected\n");
exit:return ret;
}static void mqtt_demo_msg_cb(MessageData *data)
{printf("get a message, topic: %.*s, msg: %.*s\n", data->topicName->lenstring.len,data->topicName->lenstring.data, data->message->payloadlen,(char *)data->message->payload);if(!strncmp(data->topicName->lenstring.data, MQTT_RECV_TOPIC, 15) && data->message->payloadlen){char *payload = data->message->payload;cJSON *root;cJSON *json_display;root = cJSON_Parse(payload);if (root){json_display = cJSON_GetObjectItem(root, "display");if (json_display){printf("mqtt display!\r\n");test_set_str(json_display->valuestring, strlen(json_display->valuestring));cJSON * usr;usr  = cJSON_CreateObject();   /* 创建根数据对象 */cJSON_AddStringToObject(usr, "msg", "success");  /* 加入键值,加字符串 */char *out = cJSON_Print(usr);   //将json形式打印成正常字符串形 */printf("%s\n", out);mqtt_demo_publish(MQTT_RESP_TOPIC, out);/* 释放内存 */cJSON_Delete(usr);}cJSON_Delete(root);  /* 释放内存 */}}
}static int mqtt_demo_subscribe(char *topic)
{int ret = -1;if (mqtt_demo_client.isconnected) {ret = MQTTSubscribe(&mqtt_demo_client, topic, 0, mqtt_demo_msg_cb);if (ret != 0)printf("mqtt subscribe faild ret:%d\n", ret);}return ret;
}static int mqtt_demo_unsubscribe(char *topic)
{int ret = -1;if (mqtt_demo_client.isconnected){ret = MQTTUnsubscribe(&mqtt_demo_client, topic);if (ret != 0)printf("mqtt unsubscribe faild, ret:%d\n", ret);}return ret;
}static int mqtt_demo_publish(char *topic, char *msg)
{int ret = -1;MQTTMessage message;memset(&message, 0, sizeof(message));message.qos = 0;message.retained = 0; /* disable retain the message in server */message.payload = msg;message.payloadlen = strlen(msg);ret = MQTTPublish(&mqtt_demo_client, topic, &message);if (ret != 0)printf("mqtt publish faild, ret:%d\n", ret);return ret;
}static int mqtt_demo_disconnect(void)
{int ret = -1;if (mqtt_demo_client.isconnected) {ret = MQTTDisconnect(&mqtt_demo_client);if (ret != 0)printf("mqtt disconnect fail, ret:%d\n", ret);mqtt_demo_network.disconnect(&mqtt_demo_network);}return ret;
}static void mqtt_demo_deinit(void)
{if (mqtt_demo_client.buf) {free(mqtt_demo_client.buf);mqtt_demo_client.buf = NULL;}if (mqtt_demo_client.readbuf) {free(mqtt_demo_client.readbuf);mqtt_demo_client.readbuf = NULL;}
}static void mqtt_task(void *arg)
{int ret;int reconnect_times = 0;mqtt_demo_init();ret = mqtt_demo_connect(MQTT_DEMO_HOST_NAME, MQTT_DEMO_PORT);if (ret != 0)goto exit;ret = mqtt_demo_subscribe(MQTT_RECV_TOPIC);if (ret != 0)goto exit;mqtt_demo_publish(MQTT_RESP_TOPIC, "mqtt ready");while (1){ret = MQTTYield(&mqtt_demo_client, 300);if (ret != 0){printf("mqtt yield err, ret:%d\n", ret);
reconnect:printf("mqtt reconnect\n");mqtt_demo_disconnect();ret = mqtt_demo_connect(MQTT_DEMO_HOST_NAME, MQTT_DEMO_PORT);if (ret != 0){reconnect_times++;if (reconnect_times > 5)goto exit;OS_MSleep(5000); //5sgoto reconnect;}}}exit:mqtt_demo_unsubscribe(MQTT_RECV_TOPIC);mqtt_demo_disconnect();mqtt_demo_deinit();OS_ThreadDelete(&g_mqtt_thread);
}static void net_cb(uint32_t event, uint32_t data, void *arg)
{uint16_t type = EVENT_SUBTYPE(event);switch (type){case NET_CTRL_MSG_NETWORK_UP:printf("NET_CTRL_MSG_NETWORK_UP\n");if (!OS_ThreadIsValid(&g_mqtt_thread)){OS_ThreadCreate(&g_mqtt_thread, "connect_to_server_task",mqtt_task, (void *)NULL,  OS_THREAD_PRIO_APP, (8 * 1024));}break;case NET_CTRL_MSG_NETWORK_DOWN:break;default:break;}
}static void MainThread(void *arg)
{printf("Mqtt start\r\n");if (WIFI_SUCCESS != EnableWifi()){printf("Error: EnableWifi fail\n");return;}OS_Sleep(1);if (WIFI_SUCCESS != Scan()){printf("Error: Scan fail.\n");return;}OS_Sleep(3); /* 这里为了方便用延时,实际用回调更好,否则3秒可能不够 */const char ssid_want_connect[] = WIFI_DEVICE_CONNECT_AP_SSID;const char psk[] = WIFI_DEVICE_CONNECT_AP_PSK;WifiScanInfo scan_results[30];unsigned int scan_num = 30;if (WIFI_SUCCESS != GetScanInfoList(scan_results, &scan_num)){printf("Error: GetScanInfoList fail.\n");return;}WifiDeviceConfig config = { 0 };int netId = 0;int i;for (i = 0; i < scan_num; i++){printf("ssid: %s    ", scan_results[i].ssid);printf("securityType: %d\n", scan_results[i].securityType);if (0 == strcmp(scan_results[i].ssid, ssid_want_connect)){memcpy(config.ssid, scan_results[i].ssid,WIFI_MAX_SSID_LEN);memcpy(config.bssid, scan_results[i].bssid,WIFI_MAC_LEN);strcpy(config.preSharedKey, psk);config.securityType = scan_results[i].securityType;config.wapiPskType = WIFI_PSK_TYPE_ASCII;config.freq = scan_results[i].frequency;break;}}if (i >= scan_num){printf("Error: No found ssid in scan_results\n");return;}if (WIFI_SUCCESS != AddDeviceConfig(&config, &netId)){printf("Error: AddDeviceConfig Fail\n");return;}printf("Config Success\n");if (WIFI_SUCCESS != ConnectTo(netId)){printf("Error: ConnectTo Fail\n");return;}observer_base *net_ob;net_ob = sys_callback_observer_create(CTRL_MSG_TYPE_NETWORK, NET_CTRL_MSG_ALL, net_cb, NULL);if (net_ob == NULL)return;if (sys_ctrl_attach(net_ob) != 0)return;while (1){OS_MSleep(500);}
}void LEDMain(void)
{if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL, OS_THREAD_PRIO_APP, 4 * 1024) != OS_OK) {printf("[ERR] Create MainThread Failed\n");}
}
  1. main.c内容如下:
#include <stdio.h>
#include "ohos_init.h"
#include "kernel/os/os.h"
#include "test_i2c.h"
#include  "test_mqtt.h"
#include "iot_i2c.h"
#include "oled.h"
#include "u8g2.h"static OS_Thread_t g_main_thread;
static uint8_t status=  0;
static uint8_t str[8] = {0};uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr);
void delay_ms(uint32_t ms);void test_set_str(uint8_t *pstr, uint8_t plen)
{uint8_t vi;status = 1;for (vi = 0; vi < plen; vi++){str[vi] = pstr[vi];}str[vi] = 0;
}static void MainThread(void *arg)
{u8g2_t u8g2;IotI2CTest();u8g2_Setup_sh1106_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8g2_gpio_and_delay_stm32);//u8g2_InitDisplay(&u8g2);u8g2_SetPowerSave(&u8g2, 0);u8g2_ClearDisplay(&u8g2);u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_chinese1);u8g2_DrawCircle(&u8g2, 55, 30,  5,  U8G2_DRAW_ALL);u8g2_DrawCircle(&u8g2, 65, 30,  5,  U8G2_DRAW_ALL);u8g2_DrawCircle(&u8g2, 75, 30,  5,  U8G2_DRAW_ALL);u8g2_DrawUTF8(&u8g2, 20, 50, "你好, XR806!");u8g2_SendBuffer(&u8g2);while (1){if (status == 1){status = 0;printf("u8g2 display:%s\r\n", str);memset(u8g2.tile_buf_ptr, 0, 128*24/8);u8g2_DrawUTF8(&u8g2, 20, 20, str);u8g2_SendBuffer(&u8g2);}printf("hello world!\n");LOS_Msleep(1000);}
}uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{switch(msg){case U8X8_MSG_GPIO_AND_DELAY_INIT:break;case U8X8_MSG_DELAY_MILLI:delay_ms(arg_int);break;default:return 0;}return 1;
}uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{static uint8_t buffer[131];		/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */static uint8_t buf_idx;uint8_t *data;switch(msg){case U8X8_MSG_BYTE_SEND:data = (uint8_t *)arg_ptr;while( arg_int > 0 ){buffer[buf_idx++] = *data;data++;arg_int--;}break;case U8X8_MSG_BYTE_INIT:/* add your custom code to init i2c subsystem */break;case U8X8_MSG_BYTE_START_TRANSFER:buf_idx = 0;break;case U8X8_MSG_BYTE_END_TRANSFER:if (buf_idx != 132){for (uint8_t i = 0; i < buf_idx; i++){OLED_WR_Byte(buffer[i], OLED_CMD);}}else{for (uint8_t i = 1; i < 4; i++){OLED_WR_Byte(buffer[i], OLED_CMD);}for (uint8_t i = 4; i < buf_idx; i++){OLED_WR_Byte(buffer[i], OLED_DATA);}}break;default:return 0;}return 1;
}void delay_ms(uint32_t ms)
{uint16_t i,  j;for (i = 0; i < ms; i++){for (j = 0; j < 10; j++){__asm("nop");}}
}void HelloTestMain(void)
{if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL,OS_THREAD_PRIO_APP, 4 * 1024) != OS_OK) {printf("[ERR] Create MainThread Failed\n");}LEDMain();
}SYS_RUN(HelloTestMain);
  1. 这里说明一个很奇怪的现象,u8g2_t u8g2;这个变量我改为全局静态变量后,LCD显示内容不对,会出现硬件错误并重启MCU,所以我把u8g2部分代码移动到main.c,通过全局的标志来刷新显示,这一点有待完善,应该使用系统队列来完成此操作。
  2. **效果展示,不知道怎么把图片旋转,知道的留言告诉我,谢谢。在这里插入图片描述

在这里插入图片描述

三、结束语

文章只是初次尝试,实际项目还需要很多的优化,不过使用这个芯片开发感觉还是很迅速,并且有大佬在前方引路还是很奈斯的。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++类和对象】类和对象的引入

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

《二》Qt Creator工具介绍与使用

一、关于界面 点击文件--->新建文件或项目会出现如下图&#xff1a; 我们选择第一个 点击下一步下一步&#xff1a; 继续下一步直到结束&#xff1a; 二&#xff0c;具体文件介绍 我们点击pro查看以下 QT core gui第1行 表示使用qt的core和gui库&#xff0c;如果以后…

VScode配置C++环境进行运行和调试

文章目录 1、配置开发环境&#xff1a;即可以安装MinGW-w64&#xff08;Windows平台的一个gcc/g编译器&#xff09;2、在VScode中安装C/C插件3、VScode的编译和运行的配置4、VScode的调试的配置 1、配置开发环境&#xff1a;即可以安装MinGW-w64&#xff08;Windows平台的一个g…

计算机网络—TCP协议详解:协议构成、深度解析(1)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;マリンブルーの庭園—ずっと真夜中でいいのに。 0:34━━━━━━️&#x1f49f;──────── 3:34 &#x1f504; ◀️…

r3live 使用前提 雷达-相机外参标定 livox_camera_lidar_calibration

标定的是相机到雷达的,R3live下面配置的雷达到相机的,所以要把得到外参旋转矩阵求逆,再填入,平移矩阵则取负 港科大livox_camera_calib虽然操作方便&#xff0c;但是使用mid360雷达会有视角问题&#xff08;投影三维点到相机&#xff09;&#xff0c;尝试了很多场景&#xff0c…

群晖NAS安装Synology Office与Drive结合内网穿透实现本地文件公网分享与远程协作

文章目录 本教程解决的问题是&#xff1a;1. 本地环境配置2. 制作本地分享链接3. 制作公网访问链接4. 公网ip地址访问您的分享相册5. 制作固定公网访问链接 本教程解决的问题是&#xff1a; 1.Word&#xff0c;PPT&#xff0c;Excel等重要文件存在本地环境&#xff0c;如何在编…

如何用JAVA如何实现Word、Excel、PPT在线前端预览编辑的功能?

背景 随着信息化的发展&#xff0c;在线办公也日益成为了企业办公和个人学习不可或缺的一部分&#xff0c;作为微软Office的三大组成部分&#xff1a;Word、Excel和PPT也广泛应用于各种在线办公场景&#xff0c;但是由于浏览器限制及微软Office的不开源等特性&#xff0c;导致…

Ubuntu系统器怎么关闭防火墙?Ubuntu系统关闭防火墙命令

与许多Linux发行版&#xff0c;甚至Windows和 macOS 一样&#xff0c;Ubuntu系统也配备了防火墙。这是一项安全功能&#xff0c;可以阻止来自系统上不需要的源的连接。但有时&#xff0c;如果您想让所有网络流量通过&#xff0c;您可能需要禁用它。您甚至可能还想在防火墙上打开…

springboot+Vue项目部署到云服务器上

一、下载配置ngnix 1.压缩包下载并上传 链接: https://pan.baidu.com/s/1m2LKV8ci4WXkAWdJXIeUFQ 提取码: 0415 2.解压 tar -xzvf 压缩包名 3.编译nginx 在解压好的文件夹下,依次执行&#xff1a; ./configure 来到nginx默认安装路径/usr/local/nginx 依次执行命令 mak…

关系(四)利用python绘制气泡图

关系&#xff08;四&#xff09;利用python绘制气泡图 气泡图&#xff08;Bubble plot&#xff09;简介 气泡图是散点图的变种&#xff0c;可以利用圆的大小来可视化第三个变量。 快速绘制 基于seaborn import matplotlib.pyplot as plt import seaborn as sns from gapminde…

一次网卡驱动BUG故障的排错历程

前言 在日常运维中&#xff0c;总会遇到一些棘手的故障或问题&#xff0c;尤其面临多系统融合的兼容性或一些融合节点可能存在未知bug等方面&#xff0c;排错难度都会增加。 本文将从一次小事件为入口进行延伸&#xff0c;将宿主机esxi基础系统的多融合节点故障的排错历程展开…

谷歌浏览器的开发者插件vue-devtools

在这里我留下一个git地址用来下载插件包&#xff0c;首先在自己喜欢的位置创建一个新的文件夹&#xff0c;起一个自己喜欢的文件夹名字&#xff0c;下载到包后&#xff0c;然后点进文件夹里下载依赖&#xff0c;npm install,下载后如下面这个样子 git clone https://gitee.com…