基于TCP控制鴻蒙3861三色燈板亮滅(附Demo指導(dǎo))
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos.51cto.com/#zz
跟著許思維老師的腳步,在許大神的影響之下才誕生了這個(gè)demo。
首先把整個(gè)demo跑起來的演示視頻放上來,讓大家看看最終實(shí)現(xiàn)的一個(gè)效果,視頻鏈接(點(diǎn)擊可看):基于TCP來控制鴻蒙Hi3861三色燈板的燈的亮滅。
這玩意,說簡單也不簡單,說復(fù)雜吧也不復(fù)雜。
這里先說一下demo源碼如何使用:
這里我已經(jīng)把整個(gè)demo源碼作為附件上傳了,大家把文件解壓后放在源碼目錄中:applications/sample/wifi-iot/app文件夾下,然后修改該文件夾下的BUILD.gn,將其內(nèi)容修改為:
- import("//build/lite/config/component/lite_component.gni")
- lite_component("app") {
- features = [
- "iothardware:wifi_demo",
- ]
- }
這里我還是先按照老規(guī)矩說一下總體的大概思路:
1.PC和Hi3861開發(fā)板之間使用無線連接到同一個(gè)局域網(wǎng)中。
2.Hi3861作為客戶端,PC作為服務(wù)端建立TCP連接。
3.Hi3861作為客戶端接受到PC端發(fā)送的相應(yīng)指令來進(jìn)行相應(yīng)的控制三色燈板的操作。
說完了大概思路,就可以說操作需要注意的一個(gè)點(diǎn)了:在把Hi3861燒好之后進(jìn)行測試的時(shí)候,需要先開啟服務(wù)端(這里我是直接拿linux下的netcat,小伙伴完全可以換成自己熟悉的,都可以),然后在reset一下Hi3861開發(fā)板。
下面開始按照大概思路來分成三塊講解代碼
1.PC和Hi3861開發(fā)板之間使用無線連接到同一個(gè)局域網(wǎng)中
1.1 首先定義了wifi需要的兩個(gè)監(jiān)聽事件OnWifiConnectionChanged和OnWifiScanStateChanged
- 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);
- }
1.2 定義了一個(gè)打印wifi信息的輔助函數(shù)
- 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);
- }
1.3 開始真正的wifi連接流程
- (void)arg;
- WifiErrorCode errCode;
- WifiEvent eventListener = {
- .OnWifiConnectionChanged = OnWifiConnectionChanged,
- .OnWifiScanStateChanged = OnWifiScanStateChanged
- };
- WifiDeviceConfig apConfig = {0};
- int netId = -1;
- osDelay(10);
- errCode = RegisterWifiEvent(&eventListener);
- printf("RegisterWifiEvent: %d\r\n", errCode);
- strcpy(apConfig.ssid, "helloworld");
- strcpy(apConfig.preSharedKey, "12345678");
- apConfig.securityType = WIFI_SEC_TYPE_PSK;
- errCode = EnableWifi();
- printf("EnableWifi: %d\r\n", errCode);
- osDelay(10);
- 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) {
- osDelay(10);
- }
- printf("g_connected: %d\r\n", g_connected);
- osDelay(50);
- struct netif* iface = netifapi_netif_find("wlan0");
- if (iface) {
- err_t ret = netifapi_dhcp_start(iface);
- printf("netifapi_dhcp_start: %d\r\n", ret);
- osDelay(200); // wait DHCP server give me IP
- ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL);
- printf("netifapi_netif_common: %d\r\n", ret);
- }
2.Hi3861作為客戶端,PC作為服務(wù)端建立TCP連接。
2.1 先配置TCP協(xié)議
- ssize_t retval = 0;
- int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
- unsigned short port=5678;
- struct sockaddr_in serverAddr = {0};
- serverAddr.sin_family = AF_INET; // AF_INET表示IPv4協(xié)議
- serverAddr.sin_port = htons(port); // 端口號(hào),從主機(jī)字節(jié)序轉(zhuǎn)為網(wǎng)絡(luò)字節(jié)序
- if (inet_pton(AF_INET, PARAM_SERVER_ADDR, &serverAddr.sin_addr) <= 0) { // 將主機(jī)IP地址從“點(diǎn)分十進(jìn)制”字符串 轉(zhuǎn)化為 標(biāo)準(zhǔn)格式(32位整數(shù))
- printf("inet_pton failed!\r\n");
- goto do_cleanup;
2.2 調(diào)用connect函數(shù)進(jìn)行連接,這里確保連接之后,才可以
- if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
- printf("connect failed!\r\n");
- goto do_cleanup;
- }
- printf("connect to server %s success!\r\n", PARAM_SERVER_ADDR);
2.3 調(diào)用recv接口接收從PC服務(wù)端發(fā)來的消息
- retval = recv(sockfd, &response, sizeof(response), 0);
- if (retval <= 0) {
- printf("send response from server failed or done, %ld!\r\n", retval);
- goto do_cleanup;
- }
- response[retval] = '\0';
- printf("recv response{%s} %ld from server done!\r\n", response, retval);
3.Hi3861作為客戶端接受到PC端發(fā)送的相應(yīng)指令來進(jìn)行相應(yīng)的控制三色燈板的操作。
3.1 先進(jìn)行Hi3861控制三色開發(fā)板的基礎(chǔ)設(shè)置
- GpioInit();
- IoSetFunc(RED_LED_PIN_NAME,RED_LED_PIN_FUNCTION);
- IoSetFunc(GREEN_LED_PIN_NAME,GREEN_LED_PIN_FUNCTION);
- IoSetFunc(RELLOW_LED_PIN_NAME,RELLOW_LED_PIN_FUNCTION);
- GpioSetDir(RED_LED_PIN_NAME,WIFI_IOT_GPIO_DIR_OUT);
- GpioSetDir(GREEN_LED_PIN_NAME,WIFI_IOT_GPIO_DIR_OUT);
- GpioSetDir(RELLOW_LED_PIN_NAME,WIFI_IOT_GPIO_DIR_OUT);
3.2 根據(jù)TCP協(xié)議接收到的信息,判斷后選擇GpioSetOutputVal進(jìn)行三色燈開關(guān)控制
- if(strncmp(RED_ON,response,5) == 0){
- printf("red on----------------");
- GpioSetOutputVal(RED_LED_PIN_NAME,LED_BRIGHT);
- }
- else if(strncmp(RED_OFF,response,6) == 0){
- printf("red off--------------");
- GpioSetOutputVal(RED_LED_PIN_NAME,LED_DARK);
- }else if(strncmp(GREEN_ON,response,7) == 0){
- printf("red on----------------");
- GpioSetOutputVal(GREEN_LED_PIN_NAME,LED_BRIGHT);
- }
- else if(strncmp(GREEN_OFF,response,8) == 0){
- printf("red off--------------");
- GpioSetOutputVal(GREEN_LED_PIN_NAME,LED_DARK);
- }else
- if(strncmp(RELLOW_ON,response,8) == 0){
- printf("red on----------------");
- GpioSetOutputVal(RELLOW_LED_PIN_NAME,LED_BRIGHT);
- }
- else if(strncmp(RELLOW_OFF,response,9) == 0){
- printf("red off--------------");
- GpioSetOutputVal(RELLOW_LED_PIN_NAME,LED_DARK);
- }else
- {
- printf("error index");
- }
上述所有源碼見附件,有什么問題歡迎留言交流
ps:分享一個(gè)調(diào)試中困擾了我好長時(shí)間的一個(gè)問題,就是在調(diào)試過程中Hi3861的無線很不穩(wěn)定,連接上一會(huì)兒就會(huì)掉,然后又連接,我一度以為是代碼的問題,苦苦探求,之后才發(fā)現(xiàn)問題的根源是我公司的同時(shí)使用的wifi太多了,把無線信道都占了,導(dǎo)致我使用的只支持2.4G的小破路由器根本不穩(wěn)定,給大家分享這個(gè)坑,遇到的話直接跳過去,別重蹈我的覆轍了......
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos.51cto.com/#zz