hi3861 OpenHarmony 网络应用

        hi3861芯片集成WiFi功能,鸿蒙是为了实现万物互联而设计的系统,所以系统内集成了完善的联网功能,只需根据需求调用系统功能就可以。

        我自己归纳为2大部分:

        第一步WiFi接入

                1. 设备初始化,系统默认已经加载网络设备,就是知道有这个过程就好。

static int Wifi_Event_Init(void)
{
    if(hi_wifi_config_callback(1, NULL, NULL) != HISI_OK)
    {
        return 0;
    }
    if(hi_wifi_register_event_callback(Wifi_Event_CD) != HISI_OK)
    {
        return 0;
    }
    return 1;
}

                先检查,是否加载,没加载就加载一下,如果有问题返回0,添加回调,实时反馈网络状态信息。

                2. 输入Wifi用户名密码,然后搜索,找到匹配的Wifi热点就连接。


static int WiFi_STA_Start(char *wifi_name, char *wifi_pass)
{
    int sta_namlen = sizeof(sta_ifname);
    if(hi_wifi_sta_start(sta_ifname, &sta_namlen) != HISI_OK)
    {
        return 0;
    }
    if(hi_wifi_sta_scan() != HISI_OK)
    {
        return 0;
    }
    while(wifi_state != 1)
    {
        osDelay(10);
    }
    unsigned int ap_num = 8;
    unsigned int ap_info_len = sizeof(hi_wifi_ap_info) * ap_num;
    hi_wifi_ap_info *ap_list = malloc(ap_info_len);
    memset_s(ap_list, ap_info_len, 0, ap_info_len);
    if(hi_wifi_sta_scan_results(ap_list, &ap_num) != HISI_OK)
    {
        return 0;
    }
    int idx;
    for(idx = 0; idx < ap_num; idx ++)
    {
        if(strlen(wifi_name) == strlen(ap_list[idx].ssid))
        {
            if(memcmp(wifi_name, ap_list[idx].ssid, strlen(wifi_name)) == HISI_OK)
            {
                conn_ap = 1;
                break;
            }
        }
    }
    if(conn_ap == 0)
    {
        free(ap_list);
        return 0;
    }
    hi_wifi_assoc_request conn_req = {0};
    memcpy_s(conn_req.ssid, (HI_WIFI_MAX_SSID_LEN + 1), wifi_name, strlen(wifi_name));
    conn_req.auth = ap_list[idx].auth;
    memcpy_s(conn_req.key, (HI_WIFI_MAX_KEY_LEN + 1), wifi_pass, strlen(wifi_pass));
    memcpy_s(conn_req.bssid, HI_WIFI_MAC_LEN, ap_list[idx].bssid, strlen(ap_list[idx].bssid));
    conn_req.pairwise = 0;
    if(hi_wifi_sta_connect(&conn_req) != HISI_OK)
    {
        return 0;
    }
    while(wifi_state != 2)
    {
        osDelay(10);
    }
    free(ap_list);
    return 1;
}

         代码写的有点啰嗦,但是过程基本一步步都写到,等待系统反馈,接入成功就返回。

                3.通过DHCP配置协议分配地址

static int WiFi_DHCP_Start(void)
{
    wlan_netif = netifapi_netif_find(sta_ifname);
    if (wlan_netif == NULL )
    {
        return 0;
    }
    if(netifapi_dhcp_start(wlan_netif) != ERR_OK)
    {
        return 0;
    }
    osDelay(200);
    return 1;
}

        这样就有了一个IP地址,就可以配置网络协议进行通信了。

第二步通过网络协议通信

        常用的网络协议就是TCP / UDP,我采用的是TCP协议,让hi3861作为服务端,外部应用做为客户端连接hi3861, 这个方式主要是为了方便,hi3861运行中再设置参数很麻烦,不如就被动接入,用TCP协议发现发送没有被接收,可以认为客户端以断开,就可以关闭网络,或者重启网络。

        TCP/IP协议都是标准的流程。

        创建服务端套接字

int TCP_Server_Socket(char *server_ip, unsigned short server_port)
{
    int ret = 0;
    int server_sock = -1;
    server_sock = lwip_socket(AF_INET, SOCK_STREAM, 0);
    if(server_sock < 0)
    {
        return -1;
    }
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(server_port);
    server_addr.sin_addr.s_addr = inet_addr(server_ip);
    ret = lwip_bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if(ret < 0)
    {
        return -1;
    }
    ret = lwip_listen(server_sock, 1);
    if(ret < 0)
    {
        return -1;
    }
    return server_sock;
}

        接入客户端,这个步骤是阻塞的,一直等待有客户端接入,才进行后面的操作。

int TCP_Server_Accept(int server_sock, char *client_ip, unsigned short *client_port)
{
    int client_sock = -1;
    struct sockaddr_in client_addr;
    memset(&client_addr, 0, sizeof(client_addr));
    socklen_t addr_len = sizeof(client_addr);
    client_sock = lwip_accept(server_sock, (struct sockaddr *)&client_addr, &addr_len);
    if(client_sock < 0)
    {
        return -1;
    }
    *client_port = ntohs(client_addr.sin_port);
    memset(client_ip, 0, sizeof(client_ip));
    strcpy(client_ip, inet_ntoa(client_addr.sin_addr));
    return client_sock;
}

        接通后就是收发通信

int TCP_Recv_Nonblocking(int client_sock, unsigned char *recv_buff, size_t buff_size)
{
    int len;
    len = lwip_recv(client_sock, recv_buff, buff_size, MSG_DONTWAIT);
    if(len < 0)
    {
        return -1;
    }
    return len;
}

int TCP_Send(int client_sock, unsigned char *send_buff, size_t buff_size)
{
    int ret;
    ret = lwip_send(client_sock, send_buff, buff_size, 0);
    if(ret < 0)
    {
        return -1;
    }
    return ret;
}

        接收是非阻塞模式,每次检查是否有信息输入,如果没有就跳过。

        这样一个完整的网络应用就完成了。实际使用还要考虑使用的易用性。

        比如接入WIFI,调试中可以把WiFi的用户名密码写在代码里,但是改变环境,如果在使用中输入用户名密码呢?我知道有2种方式,一种是先将Hi3861自己设置为热点,通过手机或者其他设备访问hi3861,进行通信输入用户名密码,然后再将hi3861切换到站点模式连接WiFi。还有一种很方便的是碰一碰外设来输入用户名密码,或者是串口方式。

        我做了一个通过红外遥控器输入的方法。

        通过输入ASCII码来输入内容。

        

        主菜单:

        

        因为屏幕太小了,为了尽量显示大一点字体,一行只能显示16个字符,所以都是简写,简的只有我自己能看懂吧。

        [1] 输入用户名密码 [2] 连接网络 [3] 网络通信 [4] 网络关闭

        

        这是输入页,按数字输入ASCII码,显示相应的字符,插入到数组里。

        觉得这个功能也许有些场合能用上,实现过程挺碎的,如果代码看不懂,就加我QQ:1164192255,也许能交换出更好的方法。

        主要函数:


hi_void Device_Init(hi_void);

int WiFi_Conn_Start(char *wifi_name, char *wifi_pass, char *ip_str);
void Wifi_Conn_Stop(void);

int TCP_Server_Socket(char *server_ip, unsigned short server_port);
int TCP_Server_Accept(int server_sock, char *client_ip, unsigned short *client_port);
int TCP_Recv(int client_sock, unsigned char *recv_buff, size_t buff_size);
int TCP_Recv_Nonblocking(int client_sock, unsigned char *recv_buff, size_t buff_size);
int TCP_Send(int client_sock, unsigned char *send_buff, size_t buff_size);

int UDP_Socket(int udp_port, char *udp_ip);
int UDP_Recvfrom(int udp_sock, unsigned char *recv_buff, size_t buff_size, int *client_port, char *client_ip);
int UDP_Sendto(int udp_sock, unsigned char *send_buff, size_t buff_size, int client_port, char *client_ip);

void Socket_Close(int *sock);



// 网络连接
hi_u8 Network_Connection(hi_void);

// 网络关闭
hi_u8 Network_Close(hi_void);

// 发送数据
hi_u8 Send_Data(hi_void);

// 接收数据
hi_u8 Recv_Data(hi_void);

// 返回 用户名 和 密码
hi_void Get_Name_Pass(char *n, char *p);

// 红外 控制
hi_u8 RC_Control(hi_u8 val);

// 显示
hi_void Display_Menu(hi_u8 n);

按键设置:

                

先写到这。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值