0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【HarmonyOS HiSpark Wi-Fi IoT 套件试用连载】九:远程TCP通信

开发板试用精选 来源:开发板试用 作者:电子发烧友论坛 2022-11-02 14:18 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

本文来源电子发烧友社区,作者:李元江, 帖子地址:https://bbs.elecfans.com/jishu_2028163_1_1.html

今天的帖子是关于如何让手机可以与wifiiot进行远程通信。通过远程的TCP中转服务端,让手机与板子进行可以进行远程数据传输。
一、数据传输过程
该过程与局域网内的TCP服务端与客户端数据传输过程很类似。局域网内是这样的,两个设备在同一个局域网内,一个作为TCP服务端,一个作为TCP客户端,这样这两个设备就是进行局域网内的数据通信。但是两个设备不在同一个网络内,数据传输在上面的方法是行不通的。这时可以借助一个在公网的TCP中转服务端,实现两个设备的远程数据传输。数据传输过程为两个设备都作为TCP客户端,一个设备把数据传输到服务端,然后服务端把数据传输到另一个设备。但是这也要求,这两个设备的网络是可以连接到公网的,否则是无法连接到公网的TCP服务端。
二、软件设计
首先我们需要一个在公网的TCP客户端。如果各位自己有云服务器的,可以自行搭建一个TCP中转服务端。我使用的客户端是别人用于测试的客户端。软件方面需要考虑几个问题:
  • 连接服务器的切换在我的上几个帖子上,需要连接其他服务器获取时间数据或者获取天气数据。这时,我们需要在进行连接服务器切换,确保获取的数据正常。
  • 连接状态检测我们还需要进行连接状态检查,如果与TCP服务端断开,是无法正常进行数据交互的。
  • 连接重连如果检查到连接断开,或者没有连接成功,需要重新尝试进行与服务端的连接。
1、TCP相关函数
新建tcp_connect.c tcp_connect.h文件,里面主要是与TCP连接、TCP连接断开、TCP数据发送、数据接收相关的函数。注意:TCPIPADDR、TCPPORT是公网TCP客户端IP地址和端口号。其实这几个函数是在之前的tcp例程中拆分出来的,把一个函数划分为四个函数而已。
  • 设置接收超时之前的例程中,没有加入接收超时机制,如果没有接收到数据,会一直呈现阻塞状态,其他任务可能会出现无法正常运行的状态,所以我们需要加入超时机制,超过一定时间没接收到数据,也会推出退出接收过程。timeval 在头文件中。//设置接收超时struct timeval timeout={2,0};//1sif (setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval)) == -1){ printf("setsockopt failed!rn"); //goto do_cleanup;}
  • tcp_connect.c
  1. #include "tcp_connect.h"
  2. //#define TCPIPADDR "192.168.3.9"
  3. //#define TCPPORT 5678
  4. #define TCPIPADDR "115.29.109.104"
  5. #define TCPPORT 6545
  6. static int sockfd;
  7. static int netId;
  8. static struct sockaddr_in serverAddr = {0};
  9. TCP_STATIC connect_status = DISCONNECTED;
  10. //extern char sendData[30];
  11. bool TcpConnect(void)
  12. {
  13. bool connectflag = false;
  14. WifiDeviceConfig config = {0};
  15. // 准备AP的配置参数
  16. strcpy(config.ssid, PARAM_HOTSPOT_SSID);
  17. strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
  18. config.securityType = PARAM_HOTSPOT_TYPE;
  19. osDelay(10);
  20. netId= ConnectToHotspot(&config);
  21. sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
  22. serverAddr.sin_family = AF_INET;// AF_INET表示IPv4协议
  23. serverAddr.sin_port = htons(TCPPORT);// 端口号,从主机字节序转为网络字节序
  24. if (inet_pton(AF_INET, TCPIPADDR , &serverAddr.sin_addr) <= 0) {  // 将主机IP地址从“点分十进制”字符串 转化为 标准格式(32位整数)
  25. printf("inet_pton failed!rn");
  26. goto do_cleanup;
  27. }
  28. //设置接收超时
  29. struct timeval timeout={2,0};//1s
  30. if (setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval)) == -1)
  31. {
  32. printf("setsockopt failed!rn");
  33. //goto do_cleanup;
  34. }
  35. // 尝试和目标主机建立连接,连接成功会返回0 ,失败返回 -1
  36. if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
  37. printf("connect failed!rn");
  38. goto do_cleanup;
  39. }
  40. printf("connect to server %s success!rn",TCPIPADDR);
  41. connectflag = true;
  42. connect_status = CONNECTED;
  43. do_cleanup:
  44. return connectflag;
  45. }
  46. bool TcpDisconnect(void){
  47. close(sockfd);
  48. DisconnectWithHotspot(netId);
  49. connect_status = DISCONNECTED;
  50. return true;
  51. }
  52. bool TcpSend(char *data,int len){
  53. // printf("send start!n");
  54. int retval = send(sockfd, data , len, 0);
  55. if (retval < 0) {
  56. //printf("send request failed!rn");
  57. return false;
  58. }
  59. else{
  60. // printf("send OK!n");
  61. return true;
  62. }
  63. }
  64. extern char revData[30];
  65. bool TcpRev(void){
  66. int retval =0;
  67. retval = recv(sockfd, &revData, sizeof(revData), 0);
  68. if (retval <= 0) {
  69. // printf("rev from server failed or done, %ld!rn", retval);
  70. return false;
  71. }
  72. revData[retval] = '';
  73. return true;
  74. }
复制代码
  • tcp_connect.h
  1. #ifndef __TCP_CONNECT_H
  2. #define __TCP_CONNECT_H
  3. #include
  4. #include
  5. #include
  6. #include "net_demo.h"
  7. #include "net_common.h"
  8. #include "net_params.h"
  9. #include "wifi_connecter.h"
  10. #include "ohos_init.h"
  11. #include "cmsis_os2.h"
  12. typedef enum{
  13. DISCONNECTED = 0,
  14. CONNECTED,
  15. }TCP_STATIC;
  16. extern TCP_STATIC connect_status;
  17. bool TcpConnect(void);
  18. bool TcpDisconnect(void);
  19. bool TcpSend(char *data,int len);
  20. bool TcpRev(void);
  21. #endif/*__TCP_CONNECT_H*/
复制代码
2、TCP数据接收和发送任务
新建tcptask.c 这里面这要是新建两个任务,一个是数据发送任务,一个是数据发送任务。
  • 数据发送任务在数据发送任务中,如果与服务端连接状态正常,会每隔两秒发送一次数据到服务端。这里有连接状态检查和连接重连机制,如果数据发送不成功,则把连接状态看为是未连接状态。在未连接状态,每隔两秒会尝试重新连接服务端,直到再一次成功连接上服务端。
  • 数据接收任务为了保证能够随时接收到服务端发送过来的数据,该任务会每10ms调度一次。在连接状态为已连接情况下,会执行TCP数据接收函数。

  1. #include
  2. #include
  3. #include
  4. #include "tcp_connect.h"
  5. #include "ohos_init.h"
  6. #include "cmsis_os2.h"
  7. char sendData[]="hellow tcp!";
  8. char revData[30]="";
  9. typedef enum{
  10. GET_NORMAL =0 ,
  11. GET_PROPRESS,
  12. GET_SUC,
  13. GET_FAIL,
  14. }GET_STATUS;
  15. extern GET_STATUS Get_Status;
  16. static void TcpSendTask(void *arg)
  17. {
  18. sleep(3);
  19. uint8_t i = 0;
  20. while(1){
  21. if(TcpConnect())
  22. {
  23. printf("Tcp Connect Sucn");
  24. break;
  25. }
  26. else{
  27. i++;
  28. }
  29. if(i>10)
  30. break;
  31. }
  32. if(i>10)
  33. printf("Tcp Connect failn");
  34. (void)arg;
  35. while(1)
  36. {
  37. if(connect_status == CONNECTED)
  38. {
  39. if(!TcpSend(sendData,sizeof(sendData)-1)){
  40. connect_status = DISCONNECTED;
  41. TcpDisconnect();
  42. }
  43. }
  44. else{
  45. if(Get_Status == GET_NORMAL){
  46. if(TcpConnect()){
  47. printf("Tcp Connect Sucn");
  48. }
  49. }
  50. }
  51. sleep(2);
  52. }
  53. }
  54. static void TcpSendTaskHandle(void)
  55. {
  56. osThreadAttr_t attr;
  57. attr.name = "TcpSendTask";
  58. attr.attr_bits = 0U;
  59. attr.cb_mem = NULL;
  60. attr.cb_size = 0U;
  61. attr.stack_mem = NULL;
  62. attr.stack_size = 4096;
  63. attr.priority = osPriorityNormal;
  64. if (osThreadNew(TcpSendTask, NULL, &attr) == NULL) {
  65. printf("[TcpSendTaskHandle] Falied to create TcpSendTask!n");
  66. }
  67. }
  68. APP_FEATURE_INIT(TcpSendTaskHandle);
  69. static void TcpRevTask(void *arg){
  70. (void)arg;
  71. while(1)
  72. {
  73. if(connect_status == CONNECTED)
  74. {
  75. if(TcpRev()){
  76. printf("%s",revData);
  77. }
  78. }
  79. usleep(10000);
  80. }
  81. }
  82. static void TcpRevTaskHandle(void)
  83. {
  84. osThreadAttr_t attr;
  85. attr.name = "TcpRevTask";
  86. attr.attr_bits = 0U;
  87. attr.cb_mem = NULL;
  88. attr.cb_size = 0U;
  89. attr.stack_mem = NULL;
  90. attr.stack_size = 4096;
  91. attr.priority = osPriorityNormal;
  92. if (osThreadNew(TcpRevTask, NULL, &attr) == NULL) {
  93. printf("[TcpRevTaskHandle] Falied to create TcpRevTask!n");
  94. }
  95. }
  96. APP_FEATURE_INIT(TcpRevTaskHandle);
复制代码
3、连接服务器切换
前面也说了,在获取时间或者天气数据时,需要进行连接服务端的切换,确保能接收到正确的数据。在keytask.c文件进行修改。在获取时间和天气函数前加上TCP服务断开函数,获取完之后,加上TCP连接函数。

  1. if((voltage>0.45 && voltage<0.65)&&(!keyflag))
  2. {
  3. keyflag = true;
  4. if(connect_status == CONNECTED)
  5. TcpDisconnect();
  6. //OledShowString(16,7,"Sync time...",1);
  7. //getNtpTime();
  8. //OledFillScreen(0);
  9. switch (Now_Screen){
  10. case TIMESCREEN:
  11. //OledShowString(16,7,"Sync time...",1);
  12. Get_Status = GET_PROPRESS;
  13. if(getNtpTime()){
  14. Get_Status = GET_SUC;
  15. }
  16. //OledFillScreen(0);
  17. else
  18. {
  19. //OledShowString(0,7,"Get fail...",1);
  20. Get_Status = GET_FAIL;
  21. }
  22. break;
  23. case NOWSCREEN:
  24. //OledShowString(0,7,"Get Weather...",1);
  25. Get_Status = GET_PROPRESS;
  26. if(getWeather())
  27. //OledFillScreen(0);
  28. Get_Status = GET_SUC;
  29. else
  30. {
  31. //OledShowString(0,7,"Get fail...",1);
  32. Get_Status = GET_FAIL;
  33. }
  34. break;
  35. case TOSCREEN:
  36. Get_Status = GET_PROPRESS;
  37. if(getWeather())
  38. Get_Status = GET_SUC;
  39. else
  40. {
  41. Get_Status = GET_FAIL;
  42. }
  43. break;
  44. case ATOSCREEN:
  45. Get_Status = GET_PROPRESS;
  46. if(getWeather())
  47. Get_Status = GET_SUC;
  48. else
  49. {
  50. Get_Status = GET_FAIL;
  51. }
  52. break;
  53. default:
  54. break;
  55. }
  56. TcpConnect();
  57. }
复制代码
三、演示情况
在手机端需要安装网络调试助手,附件里有我在大学时自己做的一个APP,里面包含网络调试功能。感兴趣的可以自己下载安装,就是界面很丑,有时间再进行好好进行优化。
连接到服务端,该服务端与wifiiot连接的服务端IP和端口一致。
211727v97o5r3o58pd1o0p.jpg
手机数据接收情况,每隔两秒会接收到wifiiot发送过来的“hello tcp!”信息。
211735a2sxxx3z07fxsosx.jpg
手机端发送123456,wifiiot成功接收到数据,并通过串口打印出来。
211751uy3ml242j8338z1b.png
四、总结
通过公网的TCP中转服务端,实现两个不同网络的设备之间进行远程数据传输,这只是两个设备之间进行远程通信的一种方式。现在不能设置连接wifi和服务端的IP、端口,后面有时间再慢慢进行改进吧。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • wi-fi
    +关注

    关注

    15

    文章

    2485

    浏览量

    130209
  • HarmonyOS
    +关注

    关注

    80

    文章

    2157

    浏览量

    36416
  • HiSpark
    +关注

    关注

    1

    文章

    156

    浏览量

    7815
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Lantronix xPico Wi-Fi嵌入式设备服务器评估套件使用指南

    Lantronix xPico Wi-Fi嵌入式设备服务器评估套件使用指南 在电子设备开发领域,嵌入式设备服务器的应用越来越广泛。Lantronix的xPico Wi-Fi嵌入式设备服务器评估
    的头像 发表于 05-21 14:05 83次阅读

    如何在此设置中为 CASE 启用 TCP 以进行 Wi-Fi 调试吗?

    TCP.但是,我不确定 FRDM-RW612型 设备和芯片工具端需要哪些配置或步骤才能强制 CASE over TCP. 谁能指导我如何在此设置中为 CASE 启用 TCP 以进行 Wi-F
    发表于 05-15 06:25

    技术资讯 I Wi-Fi 模块设计

    Wi-Fi模块可实现无缝连接和数据交换,对设备进行远程控制和监测。Wi-Fi模块设计旨在打造一套紧凑且高效的软硬件解决方案,使设备能够通过Wi-Fi网络
    的头像 发表于 02-27 17:12 995次阅读
    技术资讯 I <b class='flag-5'>Wi-Fi</b> 模块设计

    ESP32 Wi-Fi 控制 LED 灯的原理

    在智能家居、物联网设备中,用手机通过Wi-Fi控制灯光、风扇或插座,已经非常普遍。而在嵌入式开发中,ESP32是最常用的Wi-Fi模块之一。本文将带你系统理解:ESP32是如何通过Wi-Fi实现
    的头像 发表于 01-09 19:04 709次阅读
    ESP32 <b class='flag-5'>Wi-Fi</b> 控制 LED 灯的原理

    Wi-Fi:无线连接的全球通用语

    一、什么是Wi-FiWi-FiWi-Fi联盟制造商的商标认证,是基于IEEE 802.11标准的无线局域网技术。它允许电子设备在特定范围内无线接入网络,实现高速数据交换与互联网访问,已成为
    发表于 01-07 09:49

    Nordic发布nRF7002 EBII 开发板, 支持Wi-Fi 6, 解锁nRF54L新玩法

    Wi-Fi 6 功能,帮助开发人员创建高性能、高能效的Wi-Fi 6 物联网解决方案。 基于 Nordic 的 nRF7002 Wi-Fi 协同 IC,nRF7002 EBII帮助 采用
    发表于 12-10 11:58

    无线模块全解析:Wi-Fi模块、蓝牙模块、双频Wi-Fi、MQTT协议与低功耗方案

    什么是Wi-Fi/What is Wi-Fi,首先Wi-Fi又称“无线热点”或“无线网络”,是Wi-Fi联盟的商标,一个基于IEEE 802.11标准的无线局域网技术。“
    的头像 发表于 12-10 09:52 110次阅读
    无线模块全解析:<b class='flag-5'>Wi-Fi</b>模块、蓝牙模块、双频<b class='flag-5'>Wi-Fi</b>、MQTT协议与低功耗方案

    Wi-Fi模块选型指南 | 低功耗蓝牙/Wi-Fi 6模块推荐 | 物联网设备集成攻略

    物联网的快速发展,Wi-Fi技术的成熟的情况下,越来越多的场景需要用到Wi-Fi来无线传输数据,尤其是移动设备中,怎么再设备中选择合适的Wi-Fi模块呢?下面我们来介绍下Wi-Fi模块
    的头像 发表于 12-09 11:27 1478次阅读
    <b class='flag-5'>Wi-Fi</b>模块选型指南 | 低功耗蓝牙/<b class='flag-5'>Wi-Fi</b> 6模块推荐 | 物联网设备集成攻略

    浅谈Wi-Fi 6E与Wi-Fi 7的关键器件——BAW滤波器新技术

    ,美国联邦通信委员会(FCC)投票通过将6GHz频谱划为免许可频段供Wi-Fi使用,这标志着Wi-Fi正式进入“三频”时代——除Wi-Fi 6及前代技术使用的2.4GHz和5GHz频段
    发表于 09-19 18:29 2579次阅读
    浅谈<b class='flag-5'>Wi-Fi</b> 6E与<b class='flag-5'>Wi-Fi</b> 7的关键器件——BAW滤波器新技术

    如何更新 NuMaker IoT 板上的 Wi-Fi 模块固件?

    更新 NuMaker IoT 板上的 Wi-Fi 模块固件
    发表于 09-04 08:28

    LitePoint Wi-Fi测试软件减轻客户设计负担

    Wi-Fi 7于一年多前获得Wi-Fi联盟认证以来,作为最新一代通信技术,Wi-Fi正逐步成为用户实现无所不在无线连接的新选择。随着每一代Wi-F
    的头像 发表于 08-06 15:34 1480次阅读
    LitePoint <b class='flag-5'>Wi-Fi</b>测试软件减轻客户设计负担

    Texas Instruments CC335x SimpleLink™双频Wi-Fi® 6配套IC数据手册

    ) 和Wi-Fi 5 (802.11ac)。这些CC335x是Texas Instruments的第10代连接组合芯片。因此,CC335x基于成熟的技术设计而成。这些器件非常适合配备运行TCP/IP的Linux或
    的头像 发表于 07-23 11:37 1903次阅读
    Texas Instruments CC335x SimpleLink™双频<b class='flag-5'>Wi-Fi</b>® 6配套IC数据手册

    Wi-Fi FEM价格战,真的不可避免吗?

    ,康希通信是头部公司;手机Wi-Fi FEM,唯捷创芯是头部公司;IoT FEM,三伍微是头部公司。三伍微为什么选择I
    的头像 发表于 06-19 16:44 849次阅读

    Wi-Fi 8:开启极高可靠性 (UHR) 连接的新纪元——1

    。2021年,Wi-Fi 6E 横空出世,凭借6GHz 频带的独特优势,使Wi-Fi 正式迈入真三频 (Real Tri-Band) 共存的通信技术时代。2024年,科学家们再次凭借着4096QAM
    发表于 06-13 11:09

    ‌迅通PTR7002 Wi-Fi 6模块技术解析

    驱动库‌及AT指令集,支持通过SPI或UART与主控芯片通信。开发者可通过配套的‌SDK 2.1.4版本‌直接调用Wi-Fi 6的OFDMA和TWT(目标唤醒时间)功能,实现多设备低延时调度。 根据
    发表于 06-10 10:38