目录
巴法云平台域名
巴法云平台搭建
TCP简介
订阅、发布简介
代码示例
wifi_sta_connect.c
wifi_sta_example.c
移植步骤
巴法云TCP客户端接入详解
命令字段说明
订阅主题
发布
订阅主题,并获取一条历史消息
获取一次时间
获取一次已发消息
发送心跳
set 指令
up 指令
app 指令
编译并烧录
实验现象
巴法云云平台官网
巴法开放平台_巴法云_巴法物联网云平台
巴法云云平台搭建
比如我们这里将主题命名为ledtest,点击新建主题
创建成功后可以看到下面出现了一个主题
TCP简介
TCP 是一种面向连接的、可靠的、基于字节流的传输层通信协议,传输层协议常用的有TCP和UDP,像常见的http协议或mqtt协议,都是在TCP上传输的,TCP用途广泛,一般可以联网的设备,都支持TCP协议传输。
订阅、发布简介
通俗的来讲,订阅、发布是两种不同的信号 订阅:订阅某一个主题,订阅之后,就可以收到发往该主题的消息。 发布:向某个主题发送消息。 例如:当某个设备订阅了主题“X”,这时向主题“X”发送的任何消息,设备都可以收到,因为设备已经订阅上了该主题。
直接上干货!
代码示例
wifi_sta_connect.c
/*
* Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "securec.h"
#include "cmsis_os2.h"
#include "ohos_init.h"
#include "wifi_device.h"
#include "lwip/ip4_addr.h"
#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "wifi_error_code.h"
#define DEF_TIMEOUT 15
#define ONE_SECOND 1
#define SELECT_WLAN_PORT "wlan0"
#define SELECT_WIFI_SECURITYTYPE WIFI_SEC_TYPE_OPEN
#define STD_TIMEZONE_OFFSET (+8)
#define OD_DELAY_100 100
#define OD_DELAY_200 200
static int g_staScanSuccess = 0;
static int g_ConnectSuccess = 0;
static int ssid_count = 0;
static WifiErrorCode wifi_error;
static WifiEvent g_wifiEventHandler = {0};
static int wifi_sta_init_state = 0;
int sock_fd;
int addr_length;
const int timeZone = 8;
static void WiFiInit(void);
static void WaitScanResult(void);
static int WaitConnectResult(void);
static void OnWifiScanStateChangedHandler(int state, int size);
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info);
static void OnHotspotStaJoinHandler(StationInfo *info);
static void OnHotspotStateChangedHandler(int state);
static void OnHotspotStaLeaveHandler(StationInfo *info);
void DisableWIFI(void)
{
DisableWifi();
}
static void OnHotspotStaJoinHandler(StationInfo *info)
{
(void)info;
printf("STA join AP\\n");
return;
}
static void OnHotspotStaLeaveHandler(StationInfo *info)
{
(void)info;
printf("HotspotStaLeave:info is null.\\n");
return;
}
static void OnHotspotStateChangedHandler(int state)
{
printf("HotspotStateChanged:state is %d.\\n", state);
return;
}
static void WiFiInit(void)
{
printf("<–Wifi Init–>\\r\\n");
g_wifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChangedHandler;
g_wifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChangedHandler;
g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;
wifi_error = RegisterWifiEvent(&g_wifiEventHandler);
if (wifi_error != WIFI_SUCCESS)
{
printf("register wifi event fail!\\r\\n");
}
else
{
printf("register wifi event succeed!\\r\\n");
}
}
static void OnWifiScanStateChangedHandler(int state, int size)
{
(void)state;
if (size > 0)
{
ssid_count = size;
g_staScanSuccess = 1;
}
return;
}
static int result;
int WifiConnect(const char *ssid, const char *psk)
{
WifiScanInfo *info = NULL;
unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;
static struct netif *g_lwip_netif = NULL;
WifiDeviceConfig select_ap_config = {0};
osDelay(OD_DELAY_200);
printf("<–System Init–>\\r\\n");
WiFiInit();
if (EnableWifi() != WIFI_SUCCESS)
{
printf("EnableWifi failed, wifi_error = %d\\n", wifi_error);
return -1;
}
if (IsWifiActive() == 0)
{
printf("Wifi station is not actived.\\n");
return -1;
}
info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
if (info == NULL)
{
printf("faild to create wifiscanInfo.\\n");
return -1;
}
do
{
ssid_count = 0;
g_staScanSuccess = 0;
Scan();
WaitScanResult();
wifi_error = GetScanInfoList(info, &size);
} while (g_staScanSuccess != 1);
strcpy_s(select_ap_config.ssid, sizeof(select_ap_config.ssid), ssid);
printf("[%s][%s] \\r\\n", select_ap_config.ssid, select_ap_config.preSharedKey);
select_ap_config.securityType = SELECT_WIFI_SECURITYTYPE;
if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS)
{
if (ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1)
{
printf("WiFi connect succeed!\\r\\n");
wifi_sta_init_state = 1;
}
}
osDelay(OD_DELAY_100);
return 0;
}
static int WaitConnectResult(void)
{
int ConnectTimeout = DEF_TIMEOUT;
while (ConnectTimeout > 0)
{
sleep(1);
ConnectTimeout–;
if (g_ConnectSuccess == 1)
{
printf("WaitConnectResult:wait success[%d]s\\n", (DEF_TIMEOUT – ConnectTimeout));
break;
}
}
if (ConnectTimeout <= 0)
{
printf("WaitConnectResult:timeout!\\n");
return 0;
}
return 1;
}
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info)
{
(void)info;
if (state > 0)
{
g_ConnectSuccess = 1;
printf("callback function for wifi connect\\r\\n");
}
else
{
g_ConnectSuccess = 0;
printf("connect wifi_error, please check password, state:%d, try connect again\\r\\n", state);
esp_wifi_connect();
}
return;
}
static void WaitScanResult(void)
{
int scanTimeout = DEF_TIMEOUT;
while (scanTimeout > 0)
{
sleep(ONE_SECOND);
scanTimeout–;
if (g_staScanSuccess == 1)
{
printf("WaitScanResult:wait success[%d]s\\n", (DEF_TIMEOUT – scanTimeout));
break;
}
}
if (scanTimeout <= 0)
{
printf("WaitScanResult:timeout!\\n");
}
}
wifi_sta_example.c
/*
* Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "securec.h"
#include "cmsis_os2.h"
#include "ohos_run.h"
#include "lwip/sockets.h"
#include "lwip/ip_addr.h"
#include "wifi_device.h"
#include <string.h>
#define OPEN_WIFI_NAME "test"
// #define SERVER_IP"192.168.31.67"
#define SERVER_IP "119.91.109.180"
#define SERVER_PORT 8344
#define OD_DELAY_1000 1000
#define OD_DELAY_100 100
#define RECV_LEN 511
#define STACK_SIZE 4096
#define PRIORITY 25
osThreadId_t wifi_test_id = NULL;
void wifi_test(void)
{
int sock = -1;
struct sockaddr_in client_addr;
char recv_data[512] = {0};
int recv_data_len;
WifiConnect(OPEN_WIFI_NAME);
printf("start wifi_test test\\r\\n");
while (1)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
printf("Socket error\\n");
osDelay(OD_DELAY_100);
continue;
}
memset_s(&(client_addr), sizeof(client_addr), 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(SERVER_PORT);
client_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
printf("try connect to server " SERVER_IP " :%d \\n", SERVER_PORT);
if (connect(sock, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1)
{
closesocket(sock);
osDelay(OD_DELAY_1000);
continue;
}
printf("Connect to tcp server successful!\\n");
write(sock, "cmd=1&uid=4e2a189d769e4511bd5885742aa3edcb&topic=ledtest\\r\\n", strlen("cmd=1&uid=4e2a189d769e4511bd5885742aa3edcb&topic=ledtest\\r\\n"));
while (1)
{
recv_data_len = recv(sock, recv_data, RECV_LEN, 0);
if (recv_data_len <= 0)
{
break;
}
else
{
recv_data[recv_data_len] = '\\0';
printf("recv: %s\\n", recv_data);
}
}
}
}
static void wifi_test_example(void)
{
osThreadAttr_t attr;
attr.name = "wifi_test";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = STACK_SIZE;
attr.priority = PRIORITY;
wifi_test_id = osThreadNew((osThreadFunc_t)wifi_test, NULL, &attr);
if (wifi_test_id == NULL)
{
printf("Failed to create wifi_test thread!\\n");
}
}
OHOS_APP_RUN(wifi_test_example);
BUILD.gn
# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"wifi_sta_example.c",
"wifi_sta_connect.c"
]
include_dirs = [
"//foundation/communication/wifi_lite/interfaces/wifiservice",
"//device/board/esp/esp32/liteos_m/hals/driver/wifi_lite"
]
}
移植步骤
移植本代码中有几个部分需要注意:
修改连接热点名方法:将wifi_sta_example.c中OPEN_WIFI_NAME的宏定义修改为热点名即可
但经笔者测试,直接填入"bemfa.com"无法连接上该服务器,推测是无法进行DNS解析,所以我们直接连接IP地址,可以通过cmd打开windows终端 – ping bemfa.com查看域名对应的IP地址
巴法云TCP客户端接入详解
命令字段说明
cmd:消息类型
cmd=1 时为订阅消息,当设备发送一次此消息类型,之后就可以收到发往该主题的消息
cmd=2 时为发布消息,向订阅该主题的设备发送消息
cmd=3 是订阅消息,和cmd=1相同,并且会拉取一次已发送过的消息
cmd=7 是获取时间,获取当前北京时间
cmd=9 为遗嘱消息,拉取一次已经发送的消息
uid:用户私钥
可在控制台获取
topic:用户主题
可以在控制台创建主题,格式为英文或数字,相当于设备标识
msg: 为消息体
用户想要发送到某个主题的数据
符号说明
\\r\\n: 为回车换符,每条指令后都需要有回车换行。
&: 为连接符,各字段间用'&'隔离。
心跳说明
发送任意数据 为心跳消息,包括上述指令也算是心跳,但要以回车换行结尾。
心跳消息是告诉服务器设备还在线,建议60秒发送一次,超过65秒未发送心跳会掉线。
订阅主题
订阅主题,单次最多订阅八个主题
cmd=1&uid=xxxxxxxxxxxxxxxxxxxxxxx&topic=xxx1,xxx2,xxx3,xxx4\\r\\n
正常返回:
cmd=1&res=1
发布
cmd=2&uid=xxxxxxxxxxxxxxxxxxxxxxx&topic=light002&msg=off\\r\\n
正常返回:
cmd=2&res=1
订阅主题,并获取一条历史消息
cmd=3&uid=xxxxxxxxxxxxxxxxxxxxxxx&topic=light002\\r\\n
正常返回:
cmd=3&uid=xxxxxxxxxxxxxxxxxxxxxxx&topic=light002&msg=on
获取一次时间
cmd=7&uid=xxxxxxxxxxxxxxxxxxxxxxx&type=1\\r\\n
正常返回:
2021-06-11 16:39:27
type=1 获取当前日期和时间,例如:2021-06-11 17:20:54
type=2 获取当前时间,例如:17:20:54
type=3 获取当前时间戳,例如:1623403325
获取一次已发消息
cmd=9&uid=7d54f85af42976ee3c2693e6xxxxxxxx&topic=light002\\r\\n
正常返回:
cmd=9&uid=xxxxxxxxxxxxxxxxxxxxxxx&topic=light002&msg=on
发送心跳
ping\\r\\n
正常返回:
cmd=0&res=1
发送任意数据,并以\\r\\n结尾,都为心跳消息,包括上述发布、订阅指令也都算是心跳。 心跳消息是告诉服务器设备还在线,建议60秒发送一次,超过65秒未发送心跳会掉线。
set 指令
推送消息时:主题名后加/set推送消息,表示向所有订阅这个主题的设备们推送消息,假如推送者自己也订阅了这个主题,消息不会被推送给它自己,以防止自己推送的消息被自己接收。 例如向主题 light002推送数据,可为 light002/set 。
示例:
cmd=2&uid=4d9ec352e0376f2110a0c601a2857225&topic=light002/set&msg=on
up 指令
推送消息时:主题名后加/up推送消息,表示只更新云端数据,不进行任何推送。 例如向主题 light002推送数据,可为light002/up。
示例:
cmd=2&uid=4d9ec352e0376f2110a0c601a2857225&topic=light002/up&msg=on
app 指令
订阅时:主题名后加/app订阅主题,不会占用设备在线状态,即不会显示设备在线,可用于app、小程序等订阅时使用。
示例:
cmd=1&uid=4d9ec352e0376f2110a0c601a2857225&topic=light002/app
编译并烧录
在源码根目录下使用hb工具对写好的代码进行编译
选择mini级系统
同理 产品选择esp公司下的esp32
选择完毕后在源码根目录下执行hb build -f 进行编译
编译完成后会有如下界面,并且编译后的代码固件位于:out\\esp32\\esp32
使用烧录软件进行烧录:
点击start,等待烧录完成
实验现象
按下ESP32开发板上的EN键,即可观察到实验现象:
可以看到我们已经成功连接上TCP服务器,我们打开云平台查看是否有客户端对主题ledtest进行了订阅
我们尝试在云平台进行手动发布信息:hello openharmony!
在串口助手上成功打印出了该信息
后续大家自行将手动发布信息改成使用命令的方式进行发布即可!订阅相同主题的设备都可以收到发布的信息! 本项目代码已上传至gitee:ESP32_Oh: ESP32移植Openharmony
评论前必须登录!
注册