【X806开发板试用】串口数据透传阿里云IOT

news2025/1/24 7:27:37

上成果

在这里插入图片描述

阿里云对接需要用的是PRODUCTKEY,DEVICENAME和DEVICESECRET,开始直接用MQTT的例子硬怼,没成功,后面看了文档,发现阿里云对接的client_id,username和password是通过三要素生成的。
在这里插入图片描述

找了一下代码,发现再device/xradio/xr806/xr_skylark/src/net/cloud/aliyun下面有阿里云的东西,遂打开看了一下,刚好有加密过程。就直接拿过来用了,不过这里出现了一点小插曲,一直引用不到里面的接口。折腾了半天不行,一怒之下,给复制出来了。

代码

创建app站内有很多文章就不再赘述,创建好以后代码结构如下:
在这里插入图片描述

其中,inc是把device/xradio/xr806/xr_skylark/include/net/cloud/aliyun下面的inc复制出来的;
src下面的aliyun,是直接把
device/xradio/xr806/xr_skylark/src/net/cloud/aliyun
复制出来的;

wifi,mqtt,uart的都有例子,就拿过来,改一改。大体流程是
先初始化wifi,连接wifi成功获取到网络权限以后,初始化mqtt的task,待mqtt的task连接到阿里云iot以后,初始化uart task,初始化OK以后开始轮询接收uart1数据,并透传给阿里云。

不BB了,直接上代码:
ohosdemo下的BUILD.gn

group("ohosdemo") {
    deps = [
        #"hello_demo:app_hello",
        "mqtt2uart_demo:app_uart2mqtt",
    ]
}

mqtt2uart_demo下的BUILD.gn


import("//device/xradio/xr806/liteos_m/config.gni")

static_library("app_uart2mqtt") {
   configs = []

   sources = [
      "src/main.c",
      "src/aliyun/alink_auth.c",
      "src/aliyun/alink_ca.c",
      "src/aliyun/alink_cjson_get.c",
      "src/aliyun/alink_mqtt_client.c",
      "src/aliyun/alink_utils.c",
   ]

   cflags = board_cflags

   include_dirs = board_include_dirs
   include_dirs += [
      "inc",
      "//kernel/liteos_m/kernel/arch/include",
      "//base/iot_hardware/peripheral/interfaces/kits",
      
      ".",
      "//utils/native/lite/include",
      "//foundation/communication/wifi_lite/interfaces/wifiservice",
      "//device/xradio/xr806/xr_skylark/project"
   ]
}

main.c

#include <string.h>
#include "ohos_init.h"
#include "kernel/os/os.h"

#include "iot_gpio.h"
#include "wifi_device.h"
#include "common/framework/net_ctrl.h"
#include "mqtt_client.h"
#include "driver/chip/hal_uart.h"

#include "iot_uart.h"
static OS_Thread_t g_main_thread;
static OS_Thread_t g_mqtt_thread;
static OS_Thread_t g_uart_thread;


#define WIFI_DEVICE_CONNECT_AP_SSID "XXXXX"//这里填你家路由器的SSID
#define WIFI_DEVICE_CONNECT_AP_PSK "XXXXX"//这里填你家路由器的PWD

#define MQTT_CLIENT_ID "2022666"
#define MQTT_HOST_NAME "iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define MQTT_PORT      "1883"
#define MQTT_PRODUCTKEY  "a1oz5VdCSZk"
#define MQTT_DEVICENAME  "DHTER000S"
#define MQTT_DEVICESECRET  "8368b89e723216bccb471434969391e5"
#define MQTT_SECUREMODE "2"

#define MQTT_RECV_TOPIC MQTT_PRODUCTKEY"/"MQTT_DEVICENAME"/user/get" //下发TOPIC
#define MQTT_UPDATE_TOPIC MQTT_PRODUCTKEY"/"MQTT_DEVICENAME"/user/update"//上报TOPIC

#define MQTT_BUF_SIZE (2*1024)

static MQTTPacket_connectData mqtt_demo_connectData = MQTTPacket_connectData_initializer;
static Client mqtt_demo_client;
static Network mqtt_demo_network;

#define UART_BUFFER_MAXSIZE 100

static int mqtt_demo_publish(char *topic, char *msg) ;

static int mqtt_demo_init(void) {
    char *send_buf;
    char *recv_buf;

    mqtt_para_init();
    aliot_device_info(MQTT_PRODUCTKEY,
					    MQTT_DEVICENAME,
					    MQTT_DEVICESECRET,
					    MQTT_CLIENT_ID,
					    MQTT_SECUREMODE);
	
    printf("str_clientID = %s\n", xr_devc_info.client_id);
	printf("str_user_name = %s\n", xr_devc_info.user_name);
	printf("sha1_pwd = %s\n", xr_devc_info.password);
	
	mqtt_demo_connectData.clientID.cstring = xr_devc_info.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_BUF_SIZE);
    if (send_buf == NULL) {
        printf("no memory\n");
        return -1;
    }
    recv_buf = malloc(MQTT_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_BUF_SIZE,
               (unsigned char *)recv_buf, MQTT_BUF_SIZE);

    /* set username and password */
    mqtt_demo_connectData.username.cstring = xr_devc_info.user_name;
    mqtt_demo_connectData.password.cstring = xr_devc_info.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);
}

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 uart_task(void *arg)
{
	int ret;
	unsigned int uart_id = 1;
	unsigned int uart_len;
	unsigned char uart_rx_buffer[UART_BUFFER_MAXSIZE];
	unsigned char uart_tx_buffer[UART_BUFFER_MAXSIZE];

	static IotUartAttribute uart_param = { 115200,
						   IOT_UART_DATA_BIT_8,
						   IOT_UART_STOP_BIT_1,
						   IOT_UART_PARITY_NONE,
						   0,
						   0,
						   0 };

	printf("uart%d test start\r\n", uart_id);
	IoTUartInit(uart_id, &uart_param);
	
	IoTUartWrite(uart_id, "uart1 init OK\r\n", 15);

	while (1) {
		memset((char *)uart_rx_buffer, 0, UART_BUFFER_MAXSIZE);
		ret = IoTUartRead(uart_id, uart_rx_buffer, UART_BUFFER_MAXSIZE);
		if (ret > 0) {
			printf("recv len=%d, data:%s\r\n", ret, uart_rx_buffer);
			if(0 == mqtt_demo_publish(MQTT_UPDATE_TOPIC, uart_rx_buffer))
			{
			    memset(uart_tx_buffer, 0, UART_BUFFER_MAXSIZE);
			    uart_len = snprintf((char *)uart_tx_buffer,
								    UART_BUFFER_MAXSIZE,
								    "uart%d send data:[%s] OK\r\n", 
								    uart_id, 
								    uart_rx_buffer);
			    IoTUartWrite(uart_id, uart_tx_buffer, uart_len);
			}
			else
			{
				printf("Publish data failed!!\n");
			}
		}
		OS_MSleep(100); //100ms
	}

exit:
	IoTUartDeinit(uart_id);
	OS_ThreadDelete(&g_uart_thread);
	printf("uart%d test end\r\n", uart_id);
}

static void mqtt_task(void *arg)   {
    int ret;
    int reconnect_times = 0;

    mqtt_demo_init();

    ret = mqtt_demo_connect(MQTT_HOST_NAME, MQTT_PORT);
    if (ret != 0)
        goto exit;

    ret = mqtt_demo_subscribe(MQTT_RECV_TOPIC);
    if (ret != 0)
        goto exit;

	mqtt_demo_publish(MQTT_UPDATE_TOPIC, "mqtt init OK");
	if (!OS_ThreadIsValid(&g_uart_thread)) {
		OS_ThreadCreate(&g_uart_thread, "uart_task",
							uart_task, (void *)NULL,  OS_THREAD_PRIO_APP, (8 * 1024));
	}

    while (1) {
        ret = MQTTYield(&mqtt_demo_client, 500);
        if (ret != 0) {
            printf("mqtt yield err, ret:%d\n", ret);
reconnect:
            printf("mqtt reconnect\n");
            mqtt_demo_disconnect();
            ret = mqtt_demo_connect(MQTT_HOST_NAME, MQTT_PORT);
            if (ret != 0) {
                reconnect_times++;
                if (reconnect_times > 5)
                    goto exit;
                OS_MSleep(5000); //5s
                goto reconnect;
            }
        }
    }

exit:
    printf("mqtt disconnect\n");
    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("MainThread 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 UART2MQTTMain(void) {
    if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL, OS_THREAD_PRIO_APP, 4 * 1024) != OS_OK) {
        printf("[ERR] Create MainThread Failed\n");
    }
}
SYS_RUN(UART2MQTTMain);

遇到的问题

1.aliyun的lib引用不到
偷懒,直接复制出来的;
2.mqtt yield err, ret:-1
抓包发现,有时候发的keepalive包没有得到响应,怀疑是本地网络不好,后来连上家里的wifi就没问题了。
做了一个简单的修改,发包一次不响应过会再发一次。三次收不到才认为是短线,才发起reconnect。
文件:MQTTClient.c
函数:int keepalive(Client* c)

修改如下:

if (expired(&c->last_sent) || expired(&c->last_received))
    {
        if (c->ping_outstanding)
        {
        	MQTT_WARN("PINGRESP not received in keepalive interval %d.\n",c->ping_outstanding);
		if(c->ping_outstanding <= 3){
		    Timer timer;
	            InitTimer(&timer);
	            countdown_ms(&timer, 1000);
	            int len = MQTTSerialize_pingreq(c->buf, c->buf_size);
	            if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESS) // send the ping packet
					c->ping_outstanding++;
		    }
		    else
		    {
            	rc = FAILURE; /* PINGRESP not received in keepalive interval */
		    }
           }
		else
		{
                Timer timer;
                InitTimer(&timer);
                countdown_ms(&timer, 1000);
                int len = MQTTSerialize_pingreq(c->buf, c->buf_size);
                if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESS) // send the ping packet
                    c->ping_outstanding = 1;
           }
    }

待优化

  1. 串口透传部分目前是接过来数据就上传,没有加缓冲,数据量大时候,可能会丢数据可以加一下队列;
  2. aliyun部分代码引用最好不要复制,引用原位置代码最好;

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

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

相关文章

禁止safari浏览器网页双击缩放功能

普通浏览器 普通浏览器&#xff0c;只需要增加meta标签禁止缩放功能就行了 <meta content"widthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalable0;" name"viewport" /> user-scalableno或0 //禁止双指缩放页面initial-scale1.0…

nginx平滑升级,信号使用,分割日志

信号 kill -l 看信号大全 nginx -h 中可以看到的信号较少 s signal : send signal to a master process: stop, quit, reopen, reload 可以使用man手册来查看详细的信号 如果没安装&#xff0c;去源码包里找到man文件 man 路径/nginx.8 不加路径打不开man帮助 st…

【这个词(Sequence-to-Sequence)在深度学习中怎么解释,有什么作用?】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;深度学习笔记 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Sequence-to-Sequence&#xff08;Seq2Seq&#xff09; Sequence-to-Sequence&#xff08;Seq2Seq…

继电器测试中需要注意的安全事项有哪些?

继电器广泛应用于电气控制系统中的开关元件&#xff0c;其主要功能是在输入信号的控制下实现输出电路的断开或闭合。在继电器测试过程中&#xff0c;为了确保测试的准确性和安全性&#xff0c;需要遵循一定的安全事项。以下是在进行继电器测试时需要注意的安全事项&#xff1a;…

leetcode:46.全排列

1.什么是排列&#xff1f; 有顺序&#xff01;&#xff01; 2.树形结构&#xff1a; 使用used数组进行标记取过的元素&#xff0c;一个元素一个元素地进行取值&#xff0c;取完之后将used数组进行标记。 3.代码实现&#xff1a;&#xff08;循环从i0开始&#xff0c;而不是…

【Java EE初阶二十五】简单的表白墙(一)

1. 前端部分 1.1 前端代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wid…

python Matplotlib Tkinter--pack 框架案例

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 pillow 10.1.0 版本一 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的遥感目标检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本文介绍了一种基于深度学习的遥感目标检测系统系统的代码&#xff0c;采用最先进的YOLOv8算法并对比YOLOv7、YOLOv6、YOLOv5等算法的结果&#xff0c;能够准确识别图像、视频、实时视频流以及批量文件中的遥感目标。文章详细解释了YOLOv8算法的原理&#xff0…

路坦利集群虚拟机断网处理方法

路坦利集群虚拟机断网处理方法 问题描述&#xff1a; 在路坦利集群中&#xff0c;虚拟机时不时断网&#xff0c;导致业务中断&#xff0c;临时解决办法为新增网卡配置相同IP&#xff0c;然后禁用旧网卡网络临时恢复。 注&#xff1a; 该配置必须让虚拟化平台上层交换机和宿…

GPT 的基础 - T(Transformer)

我们知道GPT的含义是&#xff1a; Generative - 生成下一个词 Pre-trained - 文本预训练 Transformer - 基于Transformer架构 我们看到Transformer模型是GPT的基础&#xff0c;这篇博客梳理了一下Transformer的知识点。 BERT:通过自监督的方式,在大规模语料上预训练得到的Tran…

[C++核心编程](二):引用

目录 基本语法 引用做函数参数 引用做函数返回值 常量引用 基本语法 给变量取别名&#xff1a;数据类型 &别名 原名&#xff1b; 本质&#xff1a;指针常量&#xff08;指针的指向不可改&#xff0c;指向的值可改&#xff09; int value 10;int &index value; …

【Linux】head命令使用

head命令 head是一个在 Unix 和 Unix-like 操作系统中常用的命令行工具&#xff0c;用于输出文件的前 n 行。默认为 10&#xff0c;即显示 10 行的内容。 语法 head [options] [file(s)] head命令 -Linux手册页 选项及作用 执行令 &#xff1a; head --help 执行命令结果…

如何使用GAP-Burp-Extension扫描潜在的参数和节点

关于GAP-Burp-Extension GAP-Burp-Extension是一款功能强大的Burp扩展&#xff0c;该工具在getAllParams扩展的基础上进行了升级&#xff0c;该工具不仅可以帮助广大研究人员在安全审计过程中扫描潜在的参数&#xff0c;而且还可以搜索潜在的链接并使用这些参数进行测试&#…

git commit 后,本地远端都没有记录,消失不见

今天git commit 之后发现远端没有记录&#xff0c;本地没有最新代码记录 git commit 后&#xff0c;提交记录会消失不见的原因可能是&#xff1a; git只git commit了&#xff0c;没有push到远程分支&#xff0c;切换到其他分支时丢失。而且看不到提交记录&#xff0c;和找不到…

14:00面试,14:06就出来了,问的实在是太变态了

我从一家小公司转投到另一家公司&#xff0c;期待着新的工作环境和机会。然而&#xff0c;新公司的加班文化让我有些始料未及。虽然薪资相对较高&#xff0c;但长时间的工作和缺乏休息使我身心俱疲。 就在我逐渐适应这种高强度的工作节奏时&#xff0c;公司突然宣布了一则令人…

架构设计实践:熟悉架构设计方法论,并动手绘制架构设计图

文章目录 一、架构设计要素1、架构设计目标2、架构设计模式&#xff08;1&#xff09;分而治之&#xff08;2&#xff09;迭代式设计 3、架构设计的输入&#xff08;1&#xff09;概览&#xff08;2&#xff09;功能需求 - WH分析法&#xff08;3&#xff09;质量 - “怎么”分…

【SRE系列之Jenkins的使用】--实现ssh和http克隆

1、Jenkins的概念 1.1Jenkins的介绍 Jenkins是一个独立的开源软件项目&#xff0c;是基于Java开发的一种CI&#xff08;Continuous integration&#xff0c;持续集成&#xff09; &CD (Continuous Delivery&#xff0c;持续交付)工具&#xff0c;用于监控持续重复的工作&a…

Three.js-01快速入门

1.导入three.js库 说明&#xff1a;资源在主页里面能够找到&#xff0c;如果不想使用本地的three.module.js文件&#xff0c;也可以使用在线的文件。 import * as THREE from "../three.module.js"// import * as THREE from https://unpkg.com/three/build/three.m…

jmap -heap pid 报错了

1.jmap工具所在的jdk版本和要查看的代码的版本不一致 2.jdk1.8支持jmap -heap 而jdk 11以上不支持这个命令 可以jmap -h查看

【架构笔记1】剃刀思维-如无必要,勿增实体

欢迎来到文思源想的架构空间&#xff0c;前段时间博主做了一个工作经历复盘&#xff0c;10年开发路&#xff0c;走了不少弯路&#xff0c;也算积累了不少软件开发、架构设计的经验和心得&#xff0c;确实有必要好好盘一盘&#xff0c;作为个人的总结&#xff0c;同时也留给有缘…