润和DAYU200与润和WIFI_IOT开发实现信息互通和很多种方式,老师在经典教程中用udp来实现数据的通讯,我前几天在徐建国老师的指导下,实现了TCP的通讯,现记录与分享如下:
1、DAYU200端,新建工程并修改index.ets代码如下:
import wifi from '@ohos.wifi';
import socket from '@ohos.net.socket';
import prompt from '@ohos.prompt';
import router from '@ohos.router';
let tcp = socket.constructTCPSocketInstance();
let targetAddr = {
address: '192.168.3.129',
family: 1,
port: 3861
}
enum MSG_CMD {
LED_ON = "LEDON",
LED_OFF = "LEDOFF",
};
@Entry
@Component
struct Index {
@State message_send: string = MSG_CMD.MOVE_STOP
@State message_recv: string = ''
@State status: string = '未连接'
@State private click_times: number = 0;
localAddr = {
address: this.resolveIP(wifi.getIpInfo().ipAddress)
}
tcpInit() {
tcp.on('connect', () => {
this.status = '已连接'
prompt.showToast({ message: "已连接" })
});
tcp.on('message', value => {
this.message_recv = this.resolveArrayBuffer(value.message)
prompt.showToast({ message: this.message_recv })
});
tcp.on('close', () => {
prompt.showToast({ message: "on tcp close success" })
});
tcp.bind({ address: this.localAddr.address, port: 3861, family: 1 })
.then(() => {
prompt.showToast({ message: "bind tcp success" })
}).catch(err => {
prompt.showToast({ message: `bind tcp failed ${err}` })
return
});
}
tcpConnect() {
tcp.getState()
.then((data) => {
console.info(`====${JSON.stringify(data)}`)
if (data.isClose) {
this.tcpInit()
}
tcp.connect(
{
address: { address: targetAddr.address, port: 3861, family: 1 }, timeout: 6000
}
).then(() => {
console.info(`connect success`);
}).catch((error) => {
console.info(`connect failed ${JSON.stringify(error)}`);
})
})
}
tcpSend() {
tcp.getState().then((data) => {
console.info(`====${JSON.stringify(data)}`)
if (data.isConnected) {
tcp.send(
{ data: this.message_send, }
).then(() => {
prompt.showToast({ message: "数据发送成功" + this.message_send })
}).catch((error) => {
prompt.showToast({ message: `send failed ${JSON.stringify(error)}` })
})
} else {
prompt.showToast({ message: "not connect" })
}
})
}
tcpClose() {
tcp.close().then(() => {
this.status = '已断开'
console.info(`tcp.close success`)
}).catch((err) => {
console.info(`tcp.close error:${JSON.stringify(err)}`)
})
tcp.off('close');
tcp.off('message');
tcp.off('connect');
}
resolveArrayBuffer(message: ArrayBuffer): string {
if (message instanceof ArrayBuffer) {
let dataView = new DataView(message)
console.info(`length ${dataView.byteLength}`)
let str = ""
for (let i = 0;i < dataView.byteLength; ++i) {
let c = String.fromCharCode(dataView.getUint8(i))
if (c !== "\n") {
str += c
}
}
console.info(`message aray buffer:${str}`)
return str;
}
}
resolveIP(ip) {
if (ip < 0 || ip > 0xFFFFFFFF) {
throw ("The number is not normal!");
}
return (ip >>> 24) + "." + (ip >> 16 & 0xFF) + "." + (ip >> 8 & 0xFF) + "." + (ip & 0xFF);
}
aboutToAppear(){
this.tcpConnect()
}
build() {
Column() {
Text(`H3861控制程序`)
.fontSize(30)
.width('100%')
.margin({ top: 50 })
.textAlign(TextAlign.Center)
Button('开灯')
.fancBtn()
.onClick(() => {
this.message_send = MSG_CMD.LED_ON
this.tcpSend()
})
Button('关灯')
.fancBtn()
.onClick(() => {
this.message_send = MSG_CMD.LED_OFF
this.tcpSend()
})
}
.height('100%')
.width('100%')
.backgroundColor(0xE1FFFF)
}
}
@Extend(Button) function fancBtn() {
.width('90%')
.height(60).fontSize(26)
.margin({ top: 20 })
.type(ButtonType.Capsule).backgroundColor(Color.Orange)
}
下载到DAYU200后界面如下:
2、Hi3861的tcp_server程序,我是借用小熊派的tcpserver的demo来修改的。主要是添加了接收到数据后的判断工作:
//判断接收到的数据
if (strstr(recvbuf,"LEDON")==0)
{
printf("Open LED \r\n");
Ledcontrl(1);
}
else if(strstr(recvbuf,"LEDOFF")==0)
{
printf("Close LED \r\n");
Ledcontrl(0);
}
其他的程序附如下:
wifi_connect.h
#ifndef __WIFI_CONNECT_H__
#define __WIFI_CONNECT_H__
int WifiConnect(const char *ssid,const char *psk);
#endif
wifi_connect.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "lwip/ip4_addr.h"
#include "lwip/api_shell.h"
#include "cmsis_os2.h"
#include "hos_types.h"
#include "wifi_device.h"
#include "wifiiot_errno.h"
#include "ohos_init.h"
#define DEF_TIMEOUT 15
#define ONE_SECOND 1
#define SELECT_WIFI_SECURITYTYPE WIFI_SEC_TYPE_PSK
static void WiFiInit(void);
static void WaitSacnResult(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);
static int g_staScanSuccess = 0;
static int g_ConnectSuccess = 0;
static int ssid_count = 0;
WifiEvent g_wifiEventHandler = {0};
WifiErrorCode error;
#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");
WiFiInit();
if (EnableWifi() != WIFI_SUCCESS)
{
printf("EnableWifi failed, error = %d\r\n", error);
return -1;
}
if (IsWifiActive() == 0)
{
printf("Wifi station is not actived.\r\n");
return -1;
}
info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
if (info == NULL)
{
return -1;
}
do{
ssid_count = 0;
g_staScanSuccess = 0;
Scan();
WaitSacnResult();
error = GetScanInfoList(info, &size);
}while(g_staScanSuccess != 1);
printf("********************\r\n");
for(uint8_t i = 0; i < ssid_count; i++)
{
printf("no:%03d, ssid:%-30s, rssi:%5d\r\n", i+1, info[i].ssid, info[i].rssi/100);
}
printf("********************\r\n");
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);
}
}
if (g_lwip_netif)
{
dhcp_start(g_lwip_netif);
printf("begain to dhcp\r\n");
}
for(;;)
{
if(dhcp_is_bound(g_lwip_netif) == ERR_OK)
{
printf("<-- DHCP state:OK -->\r\n");
netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
break;
}
printf("<-- DHCP state:Inprogress -->\r\n");
osDelay(100);
}
osDelay(100);
return 0;
}
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;
error = RegisterWifiEvent(&g_wifiEventHandler);
if (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)
{
if (size > 0)
{
ssid_count = size;
g_staScanSuccess = 1;
}
printf("callback function for wifi scan:%d, %d\r\n", state, size);
return;
}
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info)
{
if (info == NULL)
{
printf("WifiConnectionChanged:info is null, stat is %d.\n", state);
}
else
{
if (state == WIFI_STATE_AVALIABLE)
{
g_ConnectSuccess = 1;
}
else
{
g_ConnectSuccess = 0;
}
}
}
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 WaitSacnResult(void)
{
int scanTimeout = DEF_TIMEOUT;
while (scanTimeout > 0)
{
sleep(ONE_SECOND);
scanTimeout--;
if (g_staScanSuccess == 1)
{
printf("WaitSacnResult:wait success[%d]s\n", (DEF_TIMEOUT - scanTimeout));
break;
}
}
if (scanTimeout <= 0)
{
printf("WaitSacnResult:timeout!\n");
}
}
static int WaitConnectResult(void)
{
int ConnectTimeout = DEF_TIMEOUT;
while (ConnectTimeout > 0)
{
sleep(ONE_SECOND);
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;
}
tcp_server_demo.c
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "lwip/sockets.h"
#include "wifi_connect.h"
#define _PROT_ 3861
#define TCP_BACKLOG 10
int sock_fd, new_fd;
char recvbuf[512];
char *buf = "Hello! I'm BearPi-HM_Nano TCP Server!";
static void LedInit(void)
{
GpioInit();
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_GPIO);
GpioSetDir(WIFI_IOT_GPIO_IDX_9, WIFI_IOT_GPIO_DIR_OUT);
}
static void Ledcontrl(int sta)
{
if(sta == 1){
GpioSetOutputVal(WIFI_IOT_GPIO_IDX_9, 1);
}
else{
GpioSetOutputVal(WIFI_IOT_GPIO_IDX_9, 0);
}
}
static void TCPServerTask(void)
{
struct sockaddr_in server_sock;
struct sockaddr_in client_sock;
int sin_size;
struct sockaddr_in *cli_addr;
WifiConnect("HUAWEI-H10R9U", "18977381885@");
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_);
if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
{
perror("bind is error\r\n");
exit(1);
}
if (listen(sock_fd, TCP_BACKLOG) == -1)
{
perror("listen is error\r\n");
exit(1);
}
printf("start accept\n");
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);
if (strstr(recvbuf,"LEDON")==0)
{
printf("Open LED \r\n");
Ledcontrl(1);
}
else if(strstr(recvbuf,"LEDOFF")==0)
{
printf("Close LED \r\n");
Ledcontrl(0);
}
sleep(2);
if ((ret = send(new_fd, buf, strlen(buf) + 1, 0)) == -1)
{
perror("send : ");
}
sleep(2);
}
close(new_fd);
}
}
static void TCPServerDemo(void)
{
osThreadAttr_t attr;
LedInit();
attr.name = "TCPServerTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = osPriorityNormal;
if (osThreadNew((osThreadFunc_t)TCPServerTask, NULL, &attr) == NULL)
{
printf("[TCPServerDemo] Falied to create TCPServerTask!\n");
}
}
APP_FEATURE_INIT(TCPServerDemo);
下载程序后,两个开发板就可以实现通讯了,点击开关灯后,开发板的LED也随之打开与关闭。