Dayu200与Hi3861 TCP通信(JS)

系统 OpenHarmony
OpenHarmony 3.1 Release 版本首次支持复杂标准带屏设备以及复杂 UI 类应用开发,在内核层、系统服务层、框架层以及开发资源 & 工具链方面,实现基础能力再升级,标志着 OpenHarmony 迈向新的转折阶段。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

说明

  • OH系统版本:OpenHarmony3.1Release
  • IDE: 3.0.0.900
  • 实现语言:JS

1、TCP JS接口

(1)接口分析

参考地址:​​Socket连接​

TCP通信流程:

Initial TCP ————> Bind IP ————> Connect Target IP ————> Send/Receive

  • 初始化IP相关配置:
- 引用模块: import socket from '@ohos.net.socket'
- 添加权限:ohos.permission.INTERNET、ohos.permission.GET_WIFI_INFO
- 创建对象:let tcp = socket.constructTCPSocketInstance();
  • 绑定IP与端口号
bind(address: NetAddress, callback: AsyncCallback<void>): void
绑定IP地址和端口,端口可以指定或由系统随机分配。使用callback方法作为异步方法。
需要权限:ohos.permission.INTERNET
系统能力:SystemCapability.Communication.NetStack
示例:
let tcp = socket.constructTCPSocketInstance();
tcp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => {
if (err) {
console.log('bind fail');
return;
}
console.log('bind success');
})
  • 连接目标IP
connect(options: TCPConnectOptions, callback: AsyncCallback<void>): void
连接到指定的IP地址和端口。使用callback方法作为异步方法。
需要权限:ohos.permission.INTERNET
系统能力:SystemCapability.Communication.NetStack
示例:
let tcp = socket.constructTCPSocketInstance();
tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}, err => {
if (err) {
console.log('connect fail');
return;
}
console.log('connect success');
})
  • 发送/接收数据
//发送数据  
send(options: TCPSendOptions, callback: AsyncCallback<void>): void
通过TCPSocket连接发送数据。使用callback方式作为异步方法。
说明: connect方法调用成功后,才可调用此方法。
需要权限:ohos.permission.INTERNET
系统能力:SystemCapability.Communication.NetStack
示例:
tcpSend()
{
tcp.send({
data: this.app_msg,
}, err => {
if (err) {
console.log('send fail');
return;
}
});
},
//接收数据 并解析数据为String
on(type: ‘message’, callback: Callback<{message: ArrayBuffer, remoteInfo: SocketRemoteInfo}>): void
订阅TCPSocket连接的接收消息事件。使用callback方式作为异步方法。
系统能力:SystemCapability.Communication.NetStack
tcp.on('message', value => {
console.log("on message")
let buffer = value.message
let dataView = new DataView(buffer)
let str = ""
for (let i = 0;i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i))
}
console.log("on connect received:" + str)
this.receive_data=str;
prompt.showToast({
message:str,
duration:1000
});
});

(2)TPC send实现

按照上一节的流程,编写对应的JS程序即可。UI如下:

#DAYU200体验官# Dayu200与Hi3861 TCP通信(JS)-开源基础软件社区

第一个按钮用于绑定IP,并设置订阅TCPSocket相关的订阅事件。

 tcpClient()
{
// 订阅TCPSocket相关的订阅事件
tcp.on('message', value => {
console.log("on message")
let buffer = value.message
let dataView = new DataView(buffer)
let str = ""
for (let i = 0;i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i))
}
console.log("on connect received:" + str)
this.receive_data=str;
prompt.showToast({
message:str,
duration:1000
});
});
tcp.on('connect', () => {
console.log("on connect")
});
tcp.on('close', () => {
console.log("on close")
});

// 绑定IP地址和端口。
let bindAddress = {
address: wifi.getIpInfo().ipAddress,
port: 1234,
family: 1
};
tcp.bind(bindAddress, err => {
if (err) {
console.log('bind fail');
return;
}
console.log('bind success');
prompt.showToast({
message:"bind success",
})
});
},

第二个按钮用于连接Hi3861:

 tcpConnect()
{
prompt.showToast({
message:'wifiAddr'+wifi.isConnected()+wifi.getIpInfo().ipAddress,
});
// let promise = tcp.connect({ address: {address:'192.168.137.92', port: 8888, family: 1} , timeout: 6000});
// promise.then(() => {
// console.log('connect success')
// prompt.showToast({
// message:"connect success",
// });
// }).catch(err => {
// prompt.showToast({
// message:"connect fail",
// });
// console.log('connect fail');
// });
tcp.connect({ address: {address: '192.168.137.92', port: 8888, family: 1} , timeout: 6000}, err => {
if (err) {
console.log('connect fail');
prompt.showToast({
message:"connect fail",
});
return;
}
console.log('connect success');
prompt.showToast({
message:"connect success",
});
})
},

第三个按钮实现发送数据:

tcpSend()
{
tcp.send({
data: this.app_msg,
}, err => {
if (err) {
console.log('send fail');
prompt.showToast({
message:"send fail",
});
return;
}
prompt.showToast({
message:"send successful"
})
});
},

2、Hi3861 TCP

(1)初始化

参考小熊派开发板TCP server案例。主要任务是开启wifi,获取周围wifi列表。

#define SELECT_WLAN_PORT "wlan0"
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;
osDelay(200);
printf("<--System Init-->\r\n");
//初始化WIFI
WiFiInit();
//使能WIFI
if (EnableWifi() != WIFI_SUCCESS)
{
printf("EnableWifi failed, error = %d\r\n", error);
return -1;
}
//判断WIFI是否激活
if (IsWifiActive() == 0)
{
printf("Wifi station is not actived.\r\n");
return -1;
}
//分配空间,保存WiFi信息
info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
if (info == NULL)
{
return -1;
}
//轮询查找WiFi列表
do{
//重置标志位
ssid_count = 0;
g_staScanSuccess = 0;
//开始扫描
Scan();
//等待扫描结果
WaitSacnResult();
//获取扫描列表
error = GetScanInfoList(info, &size);
}while(g_staScanSuccess != 1);

//连接指定的WiFi热点
for(uint8_t i = 0; i < ssid_count; i++)
{
if (strcmp(ssid, info[i].ssid) == 0)
{
int result;

printf("Select:%3d wireless, Waiting...\r\n", i+1);

//拷贝要连接的热点信息
WifiDeviceConfig select_ap_config = {0};
strcpy(select_ap_config.ssid, info[i].ssid);
strcpy(select_ap_config.preSharedKey, psk);
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");
g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);
break;
}
}
}

if(i == ssid_count-1)
{
printf("ERROR: No wifi as expected\r\n");
while(1) osDelay(100);
}
}
//启动DHCP
if (g_lwip_netif)
{
dhcp_start(g_lwip_netif);
printf("begain to dhcp\r\n");
}
//等待DHCP
for(;;)
{
if(dhcp_is_bound(g_lwip_netif) == ERR_OK)
{
printf("<-- DHCP state:OK -->\r\n");
//打印获取到的IP信息
netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
break;
}
printf("<-- DHCP state:Inprogress -->\r\n");
osDelay(100);
}
osDelay(100);
return 0;
}

(2)作为TCP Server

连接指定wifi,创建socket server,监听指定IP 端口。

char *buf = "Hello! I'm BearPi-HM_Nano TCP Server!";
static void TCPServerTask(void)
{
//服务端地址信息
struct sockaddr_in server_sock;

//客户端地址信息
struct sockaddr_in client_sock;
int sin_size;

struct sockaddr_in *cli_addr;

//连接Wifi
WifiConnect("r1", "88888889");

//创建socket
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket is error\r\n");
exit(1);
}

bzero(&server_sock, sizeof(server_sock));
server_sock.sin_family = AF_INET;
server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
server_sock.sin_port = htons(_PROT_);

//调用bind函数绑定socket和地址
if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
{
perror("bind is error\r\n");
exit(1);
}

//调用listen函数监听(指定port监听)
if (listen(sock_fd, TCP_BACKLOG) == -1)
{
perror("listen is error\r\n");
exit(1);
}

printf("start accept\n");

//调用accept函数从队列中
while (1)
{
sin_size = sizeof(struct sockaddr_in);

if ((new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1)
{
perror("accept");
continue;
}

cli_addr = malloc(sizeof(struct sockaddr));

printf("accept addr\r\n");

if (cli_addr != NULL)
{
memcpy(cli_addr, &client_sock, sizeof(struct sockaddr));
}

//处理目标
ssize_t ret;

while (1)
{
if ((ret = recv(new_fd, recvbuf, sizeof(recvbuf), 0)) == -1)
{
printf("recv error \r\n");
}
printf("recv :%s\r\n", recvbuf);
sleep(2);
if ((ret = send(new_fd, buf, strlen(buf) + 1, 0)) == -1)
{
perror("send : ");
}

sleep(2);
}

close(new_fd);
}
}

3、测试

将Hi3861、Dayu200都连接到同一个wifi下,事先匹配好IP地址和端口:

#DAYU200体验官# Dayu200与Hi3861 TCP通信(JS)-开源基础软件社区

连接后Hi3861只要接收到数据就会返回一段字符串,Hi3861接收到的数据可以使用串口查看:

#DAYU200体验官# Dayu200与Hi3861 TCP通信(JS)-开源基础软件社区

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐
点赞
收藏

51CTO技术栈公众号