#2020征文-开发板#基于TCP控制鸿蒙3861三色灯板亮灭(附demo指导) 精华

Mr_qzk
发布于 2021-1-5 12:57
浏览
5收藏

跟着许思维老师的脚步,在许大神的影响之下才诞生了这个demo

首先把整个demo跑起来的演示视频放上来,让大家看看最终实现的一个效果,视频链接(点击可看):基于TCP来控制鸿蒙Hi3861三色灯板的灯的亮灭

这玩意,说简单也不简单,说复杂吧也不复杂。

这里先说一下demo源码如何使用:

这里我已经把整个demo源码作为附件上传了,大家把文件解压后放在源码目录中:applications/sample/wifi-iot/app文件夹下,然后修改该文件夹下的BUILD.gn,将其内容修改为:

import("//build/lite/config/component/lite_component.gni")

lite_component("app") {
    features = [
        "iothardware:wifi_demo",
    ]
}

这里我还是先按照老规矩说一下总体的大概思路:

1.PC和Hi3861开发板之间使用无线连接到同一个局域网中。

2.Hi3861作为客户端,PC作为服务端建立TCP连接。

3.Hi3861作为客户端接受到PC端发送的相应指令来进行相应的控制三色灯板的操作。

说完了大概思路,就可以说操作需要注意的一个点了:在把Hi3861烧好之后进行测试的时候,需要先开启服务端(这里我是直接拿linux下的netcat,小伙伴完全可以换成自己熟悉的,都可以),然后在reset一下Hi3861开发板

下面开始按照大概思路来分成三块讲解代码

1.PC和Hi3861开发板之间使用无线连接到同一个局域网中

1.1 首先定义了wifi需要的两个监听事件OnWifiConnectionChanged和OnWifiScanStateChanged

static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
    if (!info) return;

    printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state);
    PrintLinkedInfo(info);

    if (state == WIFI_STATE_AVALIABLE) {
        g_connected = 1;
    } else {
        g_connected = 0;
    }
}
static void OnWifiScanStateChanged(int state, int size)
{
    printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size);
}

1.2 定义了一个打印wifi信息的辅助函数

static void PrintLinkedInfo(WifiLinkedInfo* info)
{
    if (!info) return;
    static char macAddress[32] = {0};
    unsigned char* mac = info->bssid;
    snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n",
        macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid);
}

1.3 开始真正的wifi连接流程

(void)arg;
WifiErrorCode errCode;
WifiEvent eventListener = {
    .OnWifiConnectionChanged = OnWifiConnectionChanged,
    .OnWifiScanStateChanged = OnWifiScanStateChanged
};
WifiDeviceConfig apConfig = {0};
int netId = -1;
osDelay(10);
errCode = RegisterWifiEvent(&eventListener);
printf("RegisterWifiEvent: %d\r\n", errCode);
strcpy(apConfig.ssid, "helloworld");
strcpy(apConfig.preSharedKey, "12345678");
apConfig.securityType = WIFI_SEC_TYPE_PSK;
errCode = EnableWifi();
printf("EnableWifi: %d\r\n", errCode);
osDelay(10);
errCode = AddDeviceConfig(&apConfig, &netId);
printf("AddDeviceConfig: %d\r\n", errCode);
g_connected = 0;
errCode = ConnectTo(netId);
printf("ConnectTo(%d): %d\r\n", netId, errCode);
while (!g_connected) {
    osDelay(10);
}
printf("g_connected: %d\r\n", g_connected);
osDelay(50);
struct netif* iface = netifapi_netif_find("wlan0");
if (iface) {
    err_t ret = netifapi_dhcp_start(iface);
    printf("netifapi_dhcp_start: %d\r\n", ret);
    osDelay(200); // wait DHCP server give me IP
    ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL);
    printf("netifapi_netif_common: %d\r\n", ret);
}

2.Hi3861作为客户端,PC作为服务端建立TCP连接。

2.1 先配置TCP协议

ssize_t retval = 0;
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
unsigned short port=5678;
struct sockaddr_in serverAddr = {0};
serverAddr.sin_family = AF_INET;  // AF_INET表示IPv4协议
serverAddr.sin_port = htons(port);  // 端口号,从主机字节序转为网络字节序
if (inet_pton(AF_INET, PARAM_SERVER_ADDR, &serverAddr.sin_addr) <= 0) {  // 将主机IP地址从“点分十进制”字符串 转化为 标准格式(32位整数)
printf("inet_pton failed!\r\n");
goto do_cleanup;

2.2 调用connect函数进行连接,这里确保连接之后,才可以

    if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
        printf("connect failed!\r\n");
        goto do_cleanup;
    }
    printf("connect to server %s success!\r\n", PARAM_SERVER_ADDR);

2.3 调用recv接口接收从PC服务端发来的消息

retval = recv(sockfd, &response, sizeof(response), 0);
if (retval <= 0) {
    printf("send response from server failed or done, %ld!\r\n", retval);
    goto do_cleanup;
}
response[retval] = '\0';
printf("recv response{%s} %ld from server done!\r\n", response, retval);

3.Hi3861作为客户端接受到PC端发送的相应指令来进行相应的控制三色灯板的操作。

3.1 先进行Hi3861控制三色开发板的基础设置

    GpioInit();
    IoSetFunc(RED_LED_PIN_NAME,RED_LED_PIN_FUNCTION);
    IoSetFunc(GREEN_LED_PIN_NAME,GREEN_LED_PIN_FUNCTION);
    IoSetFunc(RELLOW_LED_PIN_NAME,RELLOW_LED_PIN_FUNCTION);
    GpioSetDir(RED_LED_PIN_NAME,WIFI_IOT_GPIO_DIR_OUT);
    GpioSetDir(GREEN_LED_PIN_NAME,WIFI_IOT_GPIO_DIR_OUT);
    GpioSetDir(RELLOW_LED_PIN_NAME,WIFI_IOT_GPIO_DIR_OUT);

3.2 根据TCP协议接收到的信息,判断后选择GpioSetOutputVal进行三色灯开关控制

    if(strncmp(RED_ON,response,5) == 0){
        printf("red on----------------");
        GpioSetOutputVal(RED_LED_PIN_NAME,LED_BRIGHT);
    }
    else if(strncmp(RED_OFF,response,6) == 0){
        printf("red off--------------");
        GpioSetOutputVal(RED_LED_PIN_NAME,LED_DARK);
    }else if(strncmp(GREEN_ON,response,7) == 0){
        printf("red on----------------");
        GpioSetOutputVal(GREEN_LED_PIN_NAME,LED_BRIGHT);
    }
    else if(strncmp(GREEN_OFF,response,8) == 0){
        printf("red off--------------");
        GpioSetOutputVal(GREEN_LED_PIN_NAME,LED_DARK);
    }else
        if(strncmp(RELLOW_ON,response,8) == 0){
        printf("red on----------------");
        GpioSetOutputVal(RELLOW_LED_PIN_NAME,LED_BRIGHT);
    }
    else if(strncmp(RELLOW_OFF,response,9) == 0){
        printf("red off--------------");
        GpioSetOutputVal(RELLOW_LED_PIN_NAME,LED_DARK);
    }else
    {
        printf("error index");
    }

上述所有源码见附件,有什么问题欢迎留言交流

ps:分享一个调试中困扰了我好长时间的一个问题,就是在调试过程中Hi3861的无线很不稳定,连接上一会儿就会掉,然后又连接,我一度以为是代码的问题,苦苦探求,之后才发现问题的根源是我公司的同时使用的wifi太多了,把无线信道都占了,导致我使用的只支持2.4G的小破路由器根本不稳定,给大家分享这个坑,遇到的话直接跳过去,别重蹈我的覆辙了......

基于TCP控制鸿蒙3861三色灯板亮灭demo.zip 16.02K 243次下载
5
收藏 5
回复
举报
9条回复
按时间正序
/
按时间倒序
鲜橙加冰
鲜橙加冰

我相信许大神已经看到这篇文章了。

回复
2021-1-5 13:47:39
hushuo
hushuo

此处应当@许思维 老师 O(∩_∩)O哈哈~

已于2021-1-5 13:49:55修改
回复
2021-1-5 13:49:44
kekenai
kekenai

向作者和许老师学习

回复
2021-1-5 13:51:59
鸿蒙开发者社区官方账号
鸿蒙开发者社区官方账号

楼主可以给自己上传一个头像,提高自身辨识度的同时,也方便大家及时关注到你的更新哟~

回复
2021-1-5 13:56:17
鲜橙加冰
鲜橙加冰 回复了 鸿蒙开发者社区官方账号
楼主可以给自己上传一个头像,提高自身辨识度的同时,也方便大家及时关注到你的更新哟~

嗯,发满五篇还有权限开启自己的专栏。拥有自己的一块印第安保留地。

2
回复
2021-1-5 13:57:32
Mr_qzk
Mr_qzk 回复了 鸿蒙开发者社区官方账号
楼主可以给自己上传一个头像,提高自身辨识度的同时,也方便大家及时关注到你的更新哟~

今天我去换头像了,显示已保存,可是还是没有刷新哦。。。

回复
2021-1-5 14:17:32
Mr_qzk
Mr_qzk 回复了 鲜橙加冰
嗯,发满五篇还有权限开启自己的专栏。拥有自己的一块印第安保留地。

专栏会开的,哈哈哈

回复
2021-1-5 14:18:05
wx5d7329c406e95
wx5d7329c406e95

netcat 已经开启服务端,目前vscode中已经检测到wifi信息,后面发送代码的方式不太清楚。麻烦大佬再介绍下哈

 

bssid: FE:5C:68:E0:7F:87, rssi: 0, connState: 0, reason: 0, ssid: helloworld
g_connected: 1
netifapi_dhcp_start: 0
server :
        server_id : 192.168.137.1
        mask : 255.255.255.0, 1
        gw : 192.168.137.1
        T0 : 604800
        T1 : 302400
        T2 : 453600
clients <1> :
        mac_idx mac             addr            state   lease   tries   rto
        0       54f15f2fd6a8    192.168.137.236 10      0       1       2       
netifapi_netif_common: 0
connect failed!
do_cleanup...
已于2021-7-21 17:21:37修改
回复
2021-7-21 16:50:15
wx5d7329c406e95
wx5d7329c406e95 回复了 wx5d7329c406e95
netcat 已经开启服务端,目前vscode中已经检测到wifi信息,后面发送代码的方式不太清楚。麻烦大佬再介绍下哈 bssid: FE:5C:68:E0:7F:87, rssi: 0, connState: 0, reason: 0, ssid: helloworld g_connected: 1 netifapi_dhcp_start: 0 server : server_id : 192.168.137.1 mask : 255.255.255.0, 1 gw : 192.168.137.1 T0 ...

已经搞定,感谢。

#define PARAM_SERVER_ADDR "192.168.137.1"

后面的ip需要哦设置成开发板打印的ip地址

netcat 需要设置成代码中对应的端口

unsigned short port=5678;

 

netcat win端命令

nc -L -p 5678

 

回复
2021-7-22 09:51:33
回复
    相关推荐