【调试模式】微信小程序和华为开发板通信

12 篇文章 4 订阅
2 篇文章 0 订阅

本篇文章主要是对微信小程序连接小熊派的通信过程进行记录与整合。下面将以点亮开发板的灯为案例来讲,如果浏览量可以的话,我会尝试出正式开发环境下微信小程序与华为开发板通信的案例,请点赞或评论。

开发环境

【开发板】:BearPi-HM_Nano
【芯片手册】:Hi3861V100
【微信小程序版本】:稳定版 Stable Build (1.05.2201240 | 1.06.2201240)

开发板UDP接口

socket.h中包含声明UDP协议相关接口函数。

接口名功能描述
socket创建套接字
bind将ip和端口绑定到嵌套字
sendto将数据由指定的socket发送给对方主机
recvfrom从指定主机接收UDP数据
close关闭套接字

在这里插入图片描述
开启和连接UDP服务器的条件:

  1. 需要连接WiFi
  2. 客户端与服务器需要在同一局域网

UDP服务器创建流程

下面将会按照顺序讲解UDP服务器整体创建过程

  1. 连接WiFi
    通过连接WiFi可以知道UDP服务器的IP地址,后续微信小程序通过这个IP地址发送消息。
    WifiConnect(WIFI_ACCOUNT, WIFI_PASSWD);
    
  2. 创建Socket
    网络通信需要创建socket,这样两个端才能通过套接字发送和接收数据。
    // 0 AF_UNSPEC: 适用于指定主机名和服务名且适合任何协议族的地址
    // 2 AF_INET: Ipv4
    // 10 AF_INET6: Ipv6
    // 1 SOCK_STREAM: TCP协议 网络层
    // 2 SOCK_DGRAM: UDP协议 网络层
    // 3 SOCK_RAW: 套接字 网络层 
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
    
  3. 设置UDP服务器和UDP客户端
    通过设置INADDR_ANY参数接收任何主机发送过来的数据,并且指定服务器使用哪个端口。
    // htonl函数将32位数主机字节顺序转换成网络字节顺序
    // INADDR_ANY 0.0.0.0	((in_addr_t) 0x00000000)
    struct sockaddr_in server_sock;						// 服务器		
    server_sock.sin_family = AF_INET;					// 地址族
    server_sock.sin_addr.s_addr = htonl(INADDR_ANY);	// IP地址
    server_sock.sin_port = htons(8888);					// 端口号
    struct sockaddr_in client_sock;						// 客户端
    
  4. Socket与UDP服务器进行绑定
    bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)
    

上面的步骤完成后,可以通过sendto()recvfrom()发送和接收数据。

开启UDP服务器完整代码(不含LED部分)

#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

#include "lwip/sockets.h"
#include "wifi_connect.h"

#define WIFI_ACCOUNT "请填写WiFi的SSID"
#define WIFI_PASSWD "请填写WiFi的密码"
#define _PROT_ "请填写服务器的端口号"

int sock_fd, new_sock_fd;
char recvBuff[512];
char *buff = "I'm UDP Server.\r\n";
static void UDPServerTask(void)
{
	printf("Into UDPServerTask!\r\n");
    // 服务器地址信息
    struct sockaddr_in server_sock;
    server_sock.sin_family = AF_INET;
    server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
    server_sock.sin_port = htons(_PROT_);
    // 客户端地址信息
    struct sockaddr_in client_sock;
    socklen_t sin_size;
    // 连接WiFi
	printf("Into WiFi!\r\n");
    WifiConnect(WIFI_ACCOUNT, WIFI_PASSWD);
    // 创建socket
	printf("Create Socket\r\n");
    if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("Socket Is Error.\r\n");
        exit(1);
    }
    
    // 清理数据
	printf("Clean Data.\r\n");
    bzero(&server_sock, sizeof(server_sock));
    
    // 调用 Bind 绑定Socket和UAP服务器
	printf("Bind Socket and Adrr.\r\n");
    if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
    {
        perror("Bind Is Error.\r\n");
        exit(1);
    }
    
    ssize_t ret;
    while (1)
    {
        sin_size = sizeof(struct sockaddr_in);
        while (1)
        {
            // 清理缓存数据
			printf("Clean Data.\r\n");
            bzero(recvBuff, sizeof(recvBuff));
            // 接收数据
            if ((ret = recvfrom(sock_fd, recvBuff, sizeof(recvBuff), 0, (struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1)
            {
                printf("Recv Error.\r\n");
            }
            // 发送数据
            if ((ret = sendto(new_sock_fd, buff, strlen(buff) + 1, 0, (struct sockaddr *)&client_sock, sizeof(client_sock))) == -1)
            {
                printf("Send : \r\n");
            }
        }
        // 关闭UAP服务器
		printf("Close Server.\r\n");
        close(new_sock_fd);
    }
}

/* UDP 服务的入口函数 */
static void UDPServerEntry(void)
{
    osThreadAttr_t threadAttr;
    threadAttr.attr_bits = 0U;
    threadAttr.cb_mem = NULL;
    threadAttr.cb_size = 0U;
    threadAttr.stack_mem = NULL;
    threadAttr.stack_size = 10240;
    threadAttr.priority = 24;
    threadAttr.name = "UDPServerTask";
    if (osThreadNew((osThreadFunc_t)UDPServerTask, NULL, &threadAttr) == NULL){
        printf("Falied To Create UDPServerTask.\r\n");
    }
}

APP_FEATURE_INIT(UDPServerEntry);
相关函数说明
/* 用来将上一个函数发生错误的原因输出到标准设备(stderr) */
void perror(const char *);
/* 置字节字符串前size个字节为零且包括‘\0’ */
int bzero((void *)(target), (size_t)(size));
/* 在许多操作系统命令行壳层和脚本语言中含有的命令,此命令导致shell或程序终止 */
int exit(1);
/* UDP服务器断开 */
int close(int);

微信UDP客户端创建流程

创建UDP客户端基本流程:

  1. 创建UDP客户端
    this.udp = wx.createUDPSocket();
    
  2. 绑定端口号
    可以不指定port,将会随机绑定一个本机可用端口号
    this.udp.bind(number port);
    
  3. 设置接收函数
    callback为处理接收到消息的函数
    this.udp.onMessage(function callback);
    
  4. 向UDP服务器发送消息
    this.udp.send(Object object);
    

UDP客户端完整代码(不含LED部分)

<!--index.wxml-->
<view class="container">
  <button bindtap="send">向UDP服务发送消息</button>
</view>

<view class="res_container"> 
  {{udpResData}}
</view>
// index.js
const app = getApp()
let Utf8ArrayToStr = require('./Utf8ArrayToStr.js');
Page({
  data: {
    udpResData: ''
  },
  // 点击处理事件
  send: function(e) {
    // 向指定的 IP 和 port 发送消息
    this.udp.send({
      address: '172.17.3.8',
      port: '3641',
      message: 'hello, how are you'
    })
  },

  // UDP 接收到数据的事件处理函数,参数res={message,remoteInfo}
  onUdpMessage: function(res) {
    console.log(res);

    if(res.remoteInfo.size > 0) {
      console.log('onUdpMessage() 接收数据 ' + res.remoteInfo.size + ' 字节:' + JSON.stringify(res, null, '\t'));
      
      // 接收onMessage 收到的message是ArrayBuffer缓冲,不能直接输出,要另转String处理
      // 此工具类可以解决 uint8Array转String 中文乱码的问题
      let messageStr = Utf8ArrayToStr.Utf8ArrayToStr(new Uint8Array(res.message))

      // 更新接收内容
      this.setData({
        udpResData: 'udp接收到的内容: ' + messageStr
      })
    }
  },

  // 页面加载完成事件由系统调用
  onLoad: function () {
    // 新建udp实例
    this.udp = wx.createUDPSocket()

    // udp绑定本机
    this.udp.bind()

    // 指定接收事件处理函数,监听收到消息的事件
    this.udp.onMessage(this.onUdpMessage) 

    console.log('页面 index 加载完成事件onLoad()')
  },
})
// Utf8ArrayToStr.js
function Utf8ArrayToStr(array) {
  var out, i, len, c;
  var char2, char3;

  out = "";
  len = array.length;
  i = 0;
  while (i < len) {
    c = array[i++];
    switch (c >> 4) {
      case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
        out += String.fromCharCode(c);
        break;
      case 12: case 13:
        char2 = array[i++];
        out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
        break;
      case 14:
        char2 = array[i++];
        char3 = array[i++];
        out += String.fromCharCode(((c & 0x0F) << 12) |
          ((char2 & 0x3F) << 6) |
          ((char3 & 0x3F) << 0));
        break;
    }
  }
  return out;
}

module.exports = {
  Utf8ArrayToStr: Utf8ArrayToStr
}

效果图

在这里插入图片描述
在这里插入图片描述
首先你需要知道udp服务是个不稳定的,他不能保证能连接到服务器。所以需要多次发送数据,板子才能接收到。

相应UI界面代码下载链接:https://download.csdn.net/download/hjh_cos/83066593

如果你是无意刷到这篇文章并看到这里,希望你给我的文章来一个赞赞👍👍。如果你不同意其中的内容或有什么问题都可以在下方评论区留下你的想法或疑惑,谢谢你的支持!!😀😀

参考资料

  1. HarmonyOS WiFi编程开发–UDP服务端
  2. 微信小程序局域网通信之UDP通信demo
  3. UDPSocket | 微信开发文档
  4. 【鸿蒙2.0设备开发教程】小熊派HarmonyOS 鸿蒙·季 开发教程_哔哩哔哩_bilibili
  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hjhcos

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值