这是一个基于HiSpark_WiFi_IoT智能家居项目实战1-灯光控制例程, 之前有看下润和许老师以及连志安老师视频和开源码,HiSpark_WiFi_IoT Hi3861的底层驱动,和一些移植案例做都非常好,如MQTT,OLED 等,非常感谢他们的付出. 他们的案例很值得我们去学习参考 ,在此,我就不必重复造轮子. 下列是我一个智能家居项目实战1-灯光控制例程, 客户APP端的软件包含一个UDP 服务器, Hi3861只要请求连接成功就可以通讯了,如下图:
具体看源码:
//----------------------------------------------------------------------
//#include "MQTTPacket.h"
#include "transport.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "wifi_device.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"
#include "net_common.h"
#define PARAM_HOTSPOT_SSID "Honor" // your AP SSID
#define PARAM_HOTSPOT_PSK "12345678" // your AP PSK
#define PARAM_SERVER_ADDR "192.168.43.36"
#define PARAM_SERVER_PORT 6201
#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK // defined in wifi_device_config.h
#define R_LED WIFI_IOT_GPIO_IDX_10
#define B_LED WIFI_IOT_GPIO_IDX_12
#define G_LED WIFI_IOT_GPIO_IDX_11
static char request[] = "light:0\r\n";
static char response[128] = "";
static char light_status = 0;
void UdpClient(const char* host, unsigned short port);
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);
}
static volatile int g_connected = 0;
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);
}
static WifiEvent g_defaultWifiEventListener = {
.OnWifiConnectionChanged = OnWifiConnectionChanged,
.OnWifiScanStateChanged = OnWifiScanStateChanged
};
static struct netif* g_iface = NULL;
int ConnectToHotspot(WifiDeviceConfig* apConfig)
{
WifiErrorCode errCode;
int netId = -1;
errCode = RegisterWifiEvent(&g_defaultWifiEventListener);
printf("RegisterWifiEvent: %d\r\n", errCode);
errCode = EnableWifi();
printf("EnableWifi: %d\r\n", errCode);
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) { // wait until connect to AP
osDelay(10);
}
printf("g_connected: %d\r\n", g_connected);
g_iface = netifapi_netif_find("wlan0");
if (g_iface) {
err_t ret = netifapi_dhcp_start(g_iface);
printf("netifapi_dhcp_start: %d\r\n", ret);
osDelay(100); // wait DHCP server give me IP
ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL);
printf("netifapi_netif_common: %d\r\n", ret);
}
return netId;
}
void DisconnectWithHotspot(int netId)
{
if (g_iface) {
err_t ret = netifapi_dhcp_stop(g_iface);
printf("netifapi_dhcp_stop: %d\r\n", ret);
}
WifiErrorCode errCode = Disconnect(); // disconnect with your AP
printf("Disconnect: %d\r\n", errCode);
errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener);
printf("UnRegisterWifiEvent: %d\r\n", errCode);
RemoveDevice(netId); // remove AP config
printf("RemoveDevice: %d\r\n", errCode);
errCode = DisableWifi();
printf("DisableWifi: %d\r\n", errCode);
}
static void NetDemoTask(void *arg)
{
(void)arg;
WifiDeviceConfig config = {0};
// 准备AP的配置参数
strcpy(config.ssid, PARAM_HOTSPOT_SSID);
strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
config.securityType = PARAM_HOTSPOT_TYPE;
for(;;){
osDelay(10);
int netId = ConnectToHotspot(&config);
int timeout = 2;
while (timeout--) {
printf("After %d seconds, I will start\r\n", timeout);
osDelay(100);
}
UdpClient(PARAM_SERVER_ADDR, PARAM_SERVER_PORT);
// mqtt_connect();
printf("disconnect to AP ...\r\n");
DisconnectWithHotspot(netId);
printf("disconnect to AP done!\r\n");
}
}
static void NetDemoEntry(void)
{
GpioInit();
//设置红色,蓝 色,绿色 LED IO为输出状态
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_GPIO);
GpioSetDir(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_DIR_OUT);
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_11, WIFI_IOT_IO_FUNC_GPIO_11_GPIO);
GpioSetDir(WIFI_IOT_IO_NAME_GPIO_11, WIFI_IOT_GPIO_DIR_OUT);
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_12, WIFI_IOT_IO_FUNC_GPIO_12_GPIO);
GpioSetDir(WIFI_IOT_IO_NAME_GPIO_12, WIFI_IOT_GPIO_DIR_OUT);
osThreadAttr_t attr;
attr.name = "NetDemoTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 40960;
attr.priority = osPriorityNormal;
if (osThreadNew(NetDemoTask, NULL, &attr) == NULL) {
printf("[NetDemoEntry] Falied to create NetDemoTask!\n");
}
}
SYS_RUN(NetDemoEntry);
//=================================================
void UdpClient(const char* host, unsigned short port)
{
ssize_t retval = 0;
GpioSetOutputVal(R_LED, 1);
GpioSetOutputVal(B_LED, 1);
GpioSetOutputVal(G_LED, 1);
light_status = 1;
while (g_connected){
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP socket
printf("ip%s:%d\r\n",host,port);
struct sockaddr_in toAddr = {0};
toAddr.sin_family = AF_INET;
toAddr.sin_port = htons(port);
if (inet_pton(AF_INET, host, &toAddr.sin_addr) <= 0) {
printf("inet_pton failed!\r\n");
goto do_cleanup;
}
if(light_status == 1){
request[6] = '1';
}else{
request[6] = '0';
}
retval = sendto(sockfd, request, sizeof(request), 0, (struct sockaddr *)&toAddr, sizeof(toAddr));
if (retval < 0) {
printf("sendto failed!\r\n");
goto do_cleanup;
}
printf("send UDP message {%s} %ld done!\r\n", request, retval);
struct sockaddr_in fromAddr = {0};
socklen_t fromLen = sizeof(fromAddr);
retval = recvfrom(sockfd, &response, sizeof(response), 0, (struct sockaddr *)&fromAddr, &fromLen);
if (retval <= 0) {
printf("recvfrom failed or abort, %ld, %d!\r\n", retval, errno);
goto do_cleanup;
}
response[retval] = '\0';
printf("recv UDP message {%s} %ld done!\r\n", response, retval);
printf("peer info: ipaddr = %s, port = %d\r\n", inet_ntoa(fromAddr.sin_addr), ntohs(fromAddr.sin_port));
if (strncmp((char *)response, (char *)"light", 5) == 0){
printf("response[6]= %c\n",response[6]);
if(response[6]=='1'){
GpioSetOutputVal(R_LED, 1);
GpioSetOutputVal(B_LED, 1);
GpioSetOutputVal(G_LED, 1);
light_status = 1;
}
else{
GpioSetOutputVal(R_LED, 0);
GpioSetOutputVal(B_LED, 0);
GpioSetOutputVal(G_LED, 0);
light_status = 0;
}
}
do_cleanup:
printf("do_cleanup...\r\n");
close(sockfd);
}
}
具体源码和测试软件可以点击下面阅读原文下载!
扫二维码|关注我们
HarmonyOS技术社区
电子发烧友与华为官方共建