【XR806开发板试用】基于WEBSOCKET实现人机交互(控制开关灯)以及开发问题记录

一、开发板编译、功能介绍

根据官方文档编译烧录成功后,我们修改下官方例子,进行开发来实现websocket。
整体流程:开发板先自动寻找指定的wifi并且连接,连接成功后,通过websocket来与服务端连接,连接成功后,服务端就可以控制开发板开关灯。

二、代码编写以及功能实现

进入目录 device/xradio/xr806/ohosdemo/
修改BUILD.gn文件新增demo:app_demo
group(“ohosdemo”) {
deps = [
#“hello_demo:app_hello”,
#“iot_peripheral:app_peripheral”,
#“wlan_demo:app_WlanTest”,
#“LED:app_led”,
“demo:app_demo”,
]
}
创建demo目录 tree -L 1
├── BUILD.gn
└── main.c
BUILD.gn内容:

import("//device/xradio/xr806/liteos_m/config.gni")static_library("app_demo") {configs = []sources = ["main.c",]cflags = board_cflagsinclude_dirs = board_include_dirsinclude_dirs += ["//kernel/liteos_m/kernel/arch/include","//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 <stdio.h>
#include <string.h>#include "ohos_init.h"
#include "kernel/os/os.h"
#include "iot_gpio.h"#include "wifi_device.h"
#include "wifi_hotspot.h"#include "net/libwebsockets/libwebsockets.h"#define WIFI_DEVICE_CONNECT_AP_SSID "um"  //wifi名称
#define WIFI_DEVICE_CONNECT_AP_PSK "12345678" //wifi密码#define WEBSOCKET_HOST      "192.168.10.21"    //服务器IP
#define WEBSOCKET_PORT      9999                //服务器端口
#define WEBSOCKET_PATH      "/ws"               //websocket路径#define LIGHT_OPEN          "/light/open"       //开灯指令
#define LIGHT_CLOSE         "/light/close"               //关灯指令static OS_Thread_t g_main_thread;#define GPIO_ID_PA21 21#define MAX_PAYLOAD_SIZE  10 * 1024/*** 会话上下文对象,结构根据需要自定义*/
struct session_data {int msg_count;unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];int len;
};/*** 某个协议下的连接发生事件时,执行的回调函数** wsi:指向WebSocket实例的指针* reason:导致回调的事件* user 库为每个WebSocket会话分配的内存空间* in 某些事件使用此参数,作为传入数据的指针* len 某些事件使用此参数,说明传入数据的长度*/
int callback( struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len ) {struct session_data *data = (struct session_data *) user;switch ( reason ) {case LWS_CALLBACK_CLIENT_ESTABLISHED:   // 连接到服务器后的回调lwsl_notice( "Connected to server ok!\n" );break;case LWS_CALLBACK_CLIENT_RECEIVE:       // 接收到服务器数据后的回调,数据为in,其长度为lenlwsl_notice( "Rx: %s\n", (char *) in );if (strncmp(in, LIGHT_CLOSE, len)){//开灯操作IoTGpioSetOutputVal(GPIO_ID_PA21, 1);}else if (strncmp(in, LIGHT_OPEN, len)){//关灯操作IoTGpioSetOutputVal(GPIO_ID_PA21, 0);}break;case LWS_CALLBACK_CLIENT_WRITEABLE:     // 当此客户端可以发送数据时的回调if ( data->msg_count < 3 ) {// 前面LWS_PRE个字节必须留给LWSmemset( data->buf, 0, sizeof( data->buf ));char *msg = (char *) &data->buf[ LWS_PRE ];data->len = sprintf( msg, "你好 %d", ++data->msg_count );lwsl_notice( "Tx: %s\n", msg );// 通过WebSocket发送文本消息lws_write( wsi, &data->buf[ LWS_PRE ], data->len, LWS_WRITE_TEXT );}break;}return 0;
}/*** 支持的WebSocket子协议数组* 子协议即JavaScript客户端WebSocket(url, protocols)第2参数数组的元素* 你需要为每种协议提供回调函数*/
struct lws_protocols protocols[] = {{//协议名称,协议回调,接收缓冲区大小"ws", callback, sizeof( struct session_data ), MAX_PAYLOAD_SIZE,},{NULL, NULL,   0 // 最后一个元素固定为此格式}
};//连接wifi,并且打印ip
static int wifiConnect()
{const char ssid_want_connect[] = WIFI_DEVICE_CONNECT_AP_SSID;const char psk[] = WIFI_DEVICE_CONNECT_AP_PSK;if (WIFI_SUCCESS != EnableWifi()) {printf("Error: EnableWifi fail.\n");return -1;}OS_Sleep(1);if (WIFI_STA_ACTIVE == IsWifiActive())printf("Wifi is active.\n");OS_Sleep(1);if (WIFI_SUCCESS != Scan()) {printf("Error: Scan fail.\n");return -1;}OS_Sleep(3);WifiScanInfo scan_results[30];unsigned int scan_num = 30;if (WIFI_SUCCESS != GetScanInfoList(scan_results, &scan_num)) {printf("Error: GetScanInfoList fail.\n");return -1;}WifiDeviceConfig config = { 0 };int netId = 0;int i;for (i = 0; i < scan_num; i++) {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 -1;}if (WIFI_SUCCESS != AddDeviceConfig(&config, &netId)) {printf("Error: AddDeviceConfig Fail\n");return -1;}if (WIFI_SUCCESS != ConnectTo(netId)) {printf("Error: ConnectTo Fail\n");return -1;}printf("ConnectTo Success\n");OS_Sleep(15);return 0;
}void wifiDisconnect()
{printf("\n=========== DisConnect Test Start ===========\n");if (WIFI_SUCCESS != Disconnect()) {printf("Error: Disconnect Fail\n");return;}printf("Disconnect Success\n");if (WIFI_SUCCESS != DisableWifi()) {printf("Error: DisableWifi fail.\n");return;}printf("DisableWifi Success\n");printf("\n=========== DisConnect Test End ===========\n");
}static void MainThread(void *arg)                                               
{int s32Ret = 0;s32Ret = wifiConnect();if (0 != s32Ret){printf("wifiConnect failed\n");return;}IoTGpioInit(GPIO_ID_PA21);IoTGpioSetDir(GPIO_ID_PA21, IOT_GPIO_DIR_OUT);// 用于创建vhost或者context的参数struct lws_context_creation_info ctx_info = { 0 };ctx_info.port = CONTEXT_PORT_NO_LISTEN;
//    ctx_info.iface = NULL;ctx_info.protocols = protocols;ctx_info.gid = -1;ctx_info.uid = -1;// 创建一个WebSocket处理器struct lws_context *context = lws_create_context( &ctx_info );char address[] = WEBSOCKET_HOST;int port = WEBSOCKET_PORT;char addr_port[256] = { 0 };sprintf(addr_port, "%s:%u", address, port & 65535 );// 客户端连接参数struct lws_client_connect_info conn_info = { 0 };conn_info.context = context;conn_info.address = address;conn_info.port = port;conn_info.path = WEBSOCKET_PATH;conn_info.host = addr_port;conn_info.origin = addr_port;conn_info.protocol = protocols[ 0 ].name;// 下面的调用触发LWS_CALLBACK_PROTOCOL_INIT事件// 创建一个客户端连接struct lws *wsi = lws_client_connect_via_info( &conn_info );while (1) {// 执行一次事件循环(Poll),最长等待1000毫秒lws_service( context, 1000 );/*** 下面的调用的意义是:当连接可以接受新数据时,触发一次WRITEABLE事件回调* 当连接正在后台发送数据时,它不能接受新的数据写入请求,所有WRITEABLE事件回调不会执行*/lws_callback_on_writable( wsi );}// 销毁上下文对象lws_context_destroy( context );wifiDisconnect();
}
//连接websocket 进行开灯,关灯操作//wifi 连接
void demoMain(void)                                                              //(2)
{printf("websocket Test Start\n");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(demoMain); 

三、效果演示

服务器用了网上下载的个WebssocketMan工具来模拟,网盘链接
链接:https://pan.baidu.com/s/1t82q_1evB5Zla-Hc1m4SYA
提取码:4pxu
在这里插入图片描述

登陆成功后打印显示:
在这里插入图片描述

登录后平台收到“/light/open”消息为点灯,“/light/close”为关灯
演示截图:
在这里插入图片描述
在这里插入图片描述

四、问题记录

在打开wifi例子,编译过程中遇到了分区叠加的错误,具体如图(感谢群里的朋友、社区以及论坛的帮助)
在这里插入图片描述

因为内存分配不够,官方文档描述
device\xradio\xr806\xr_skylark\project\image_cfg\readme.md
在这里插入图片描述

按照网上说的修改:
device\xradio\xr806\xr_skylark\project\demo\wlan_ble_demo\image\xr806\image_wlan_ble.cfg 分配不能够生效
最终解决:xr806\device\xradio\xr806\xr_skylark\project\demo\audio_demo\image\xr806\目录中将 image_auto_cal.cfg替换image.cfg

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

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

相关文章

【SVG】前端-不依靠第三方包怎么画连线???

如何用SVG实现连线功能 在Web开发中&#xff0c;我们经常会遇到需要在页面上绘制图形或者实现一些图形交互的场景。SVG&#xff08;Scalable Vector Graphics&#xff09;作为一种用于描述二维图形的XML标记语言&#xff0c;在这方面提供了极大的便利。本文将以一个具体的例子…

蜡烛图K线图采用PictureBox控件绘制是实现量化交易的第一步非python量化

用vb6.0开发的量化交易软件 VB6量化交易软件的演示视频演示如上 股票软件中的蜡烛图是非常重要的一个东西&#xff0c;这里用VB6.0自带的Picture1控件的Line方法就可以实现绘制。 关于PictureBox 中的line 用法 msdn 上的说明为如下所示 object.Line [Step] …

LabVIEW电液伺服作动器

LabVIEW电液伺服作动器 随着工业自动化技术的快速发展&#xff0c;电液伺服作动器在各类精密控制领域得到了广泛应用。基于CRIO架构&#xff0c;利用LabVIEW软件开发了一套电液伺服作动器测控系统&#xff0c;实现了高精度的位移同步控制与测量&#xff0c;有效提高了系统的控…

3.Gen<I>Cam文件配置

Gen<I>Cam踩坑指南 我使用的是大恒usb相机&#xff0c;第一步到其官网下载大恒软件安装包,安装完成后图标如图所示&#xff0c;之后连接相机&#xff0c;打开软件&#xff0c;相机显示一切正常。之后查看软件的安装目录如图&#xff0c;发现有GenICam和GenTL两个文件&am…

uniapp无感登录封装

全局请求封装 https://blog.csdn.net/qq_42618566/article/details/109308690 无感登录封装 import {http} from "./index.js" let requestsQueue []; // 请求队列// 记录请求队列 export function recordRequests(path, params, loading, method) {requestsQueu…

JVM高频面试点(一):Java类加载过程

1.概述 在 Java 中&#xff0c;类加载过程是指将 Java 类的字节码加载到内存中&#xff0c;并转换为 Java 虚拟机能够识别和执行的数据结构的过程。类加载是 Java 虚拟机执行 Java 程序的必要步骤之一&#xff0c;它负责加载程序中用到的类和接口。下图所示是 ClassLoader 加载…

鸿蒙车载原生开发,拓展新版图

一天内连发“五弹”、HiCar 4.0首次上车 华为鸿蒙狂扩“汽车朋友圈”-上游新闻 汇聚向上的力量 3月15日&#xff0c;在“华为云&华为终端云服务创新峰会2024”上&#xff0c;华为首批汽车行业伙伴广汽传祺、岚图汽车、零跑汽车、凯翼汽车加入鸿蒙生态合作&#xff0c;华为…

FPGA高端项目:FPGA基于GS2971+GS2972架构的SDI视频收发+OSD动态字符叠加,提供1套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案的SDI接收发送本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI接收HLS多路视频融合叠加应用本方案的S…

工业物联网平台在水务环保、暖通制冷、电力能源等行业的应用

随着科技的不断发展&#xff0c;工业物联网平台作为连接物理世界与数字世界的桥梁&#xff0c;正逐渐成为推动各行业智能化转型的关键力量。在水务环保、暖通制冷、电力能源等行业&#xff0c;工业物联网平台的应用尤为广泛&#xff0c;对于提升运营效率、降低能耗、优化管理等…

mac安装rust开发环境,使用brew安装和全局配置

mac下使用brew可以一键安装环境&#xff1a; brew install rustup 安装完成执行&#xff1a; rustup-init 按照提示配置即可&#xff1a; 出现&#xff1a; 想要全局生效&#xff1a; echo export PATH"$HOME/.cargo/bin:$PATH" >> ~/.bash_profile source…

【Unity+Vuforia】AR 发布安卓的设置

Player Settings > Resolution and Presentation > Default Orientation portrait Player Settings > Other Settings > Auto Graphics API 取消勾选 Player Settings > Other Settings > Graphics APIs 选择OpenGLES3删除其他的 Player Settings…

【elasticsearch实战】从零开始设计全站搜索引擎

业务需求 最近需要一个全站搜索的功能&#xff0c;我们的站点的特点是数据多源&#xff0c;即有我们本地数据库&#xff0c;也包含了第三方数据源&#xff0c;我们的数据类型除了网页&#xff0c;还包括了各种类型的文档&#xff0c;例如&#xff1a;doc、pdf、excel、ppt等格…

MapReduce的原理分析

1.概述 MapReduce的思想核心是“分而治之,先分再合”&#xff0c;适用于大量复杂任务处理场景(大规模数据处理场景)。 MapReduce分两个阶段: map阶段(分)&#xff1a;如果任何可以拆分并且没有依赖&#xff0c;那么就把复杂的任务拆分成小任务&#xff0c;拆分成小任务之后&a…

Ubuntu 安装 KVM 虚拟化

1. Ubuntu 安装 KVM 虚拟化 KVM 是 Linux 内核中一个基于 hypervisor 的虚拟化模块&#xff0c;它允许用户在 Linux 操作系统上创建和管理虚拟机。 如果机器的CPU不支持硬件虚拟化扩展&#xff0c;是无法使用KVM(基于内核的虚拟机)直接创建和运行虚拟机的。此时最多只能使用…

SpringBoot3整合Elasticsearch8.x之全面保姆级教程

整合ES 环境准备 安装配置ES&#xff1a;https://blog.csdn.net/qq_50864152/article/details/136724528安装配置Kibana&#xff1a;https://blog.csdn.net/qq_50864152/article/details/136727707新建项目&#xff1a;新建名为web的SpringBoot3项目 elasticsearch-java 公…

uploads-labs靶场(1-10关)

一、搭建环境: 下载upload-labs源代码 下载链接&#xff1a;https://codeload.github.com/c0ny1/upload-labs/zip/refs/heads/master 将压缩包解压后的文件名改为upload-labs&#xff0c;然后放入phpstudy\www目录下 二、关卡通关: 1、pass-01&#xff08;前端绕过&#xf…

B. Array Fix

思路&#xff1a;我们倒着看&#xff0c;首先判断以下当前元素有没有被操作过&#xff0c;被操作过的话&#xff0c;那么需要改为操作后的数&#xff0c;然后跟当前数的前一个数进行比较&#xff0c;如果a[i] < a[i - 1]的话&#xff0c;那么需要将a[i - 1]拆分&#xff0c;…

【SpringBoot】头条新闻项目实现CRUD登录注册

文章目录 一、头条案例介绍二、技术栈介绍三、前端搭建四、基于SpringBoot搭建项目基础架构4.1 数据库脚本执行4.2 搭建SprintBoot工程4.2.1 导入依赖:4.2.2 编写配置4.2.3 工具类准备 4.3 MybatisX逆向工程 五、后台功能开发5.1 用户模块开发5.1.1 jwt 和 token 介绍5.1.2 jwt…

huawei services HK华为云服务

huaweiserviceshk是一种云计算服务&#xff0c;为华为云服务用户提供了多种服务&#xff0c;包括云服务器、数据库、存储、网络等&#xff0c;用户可以根据自己的需求选择不同的服务并支付相应的费用 如何付费呢&#xff0c;这里可以使用441112&#xff0c;点击获取 卡片信息在…

springboot+poi-tl根据模板导出word(含动态表格和图片),并将导出的文档压缩zip导出

springbootpoi-tl根据模板导出word&#xff08;含动态表格和图片&#xff09; 官网&#xff1a;http://deepoove.com/poi-tl/ 参考网站&#xff1a;https://blog.csdn.net/M625387195/article/details/124855854 pom导入的maven依赖 <dependency><groupId>com.dee…