功能说明:Neptune w800作为接入设备(STA)连接wifi(AP),用开发板上的按键(PB9)来控制WIFI的连接与断开。
知识点:
AP(Access point): 也就是无线接入点,是一个无线网络的创建者,是网络的中心节点。一般家庭或办公室使用的无线路由器就一个AP。STA(Station)站点: 每一个连接到无线网络中的终端(如笔记本电脑、PDA及其它可以联网的用户设备)都可称为一个站点。SSID(Service Set Identifier):每个无线AP都应该有一个标示用于识别,SSID就是这个用于识别的的名字,也就是我们经常说到的wifi名。BSSID(Basic Service Set):每一个网络设备都有其用于识别的物理地址,即MAC地址,48位,也是设备识别的标识符。对于STA的设备来说,拿到AP接入点的MAC地址就是这个BSSID。RSSI(Received Signal Strength Indicator):通过STA扫描到AP站点的信号强度。只是简要的说了下主要的知识点(并不全面),不然理解下面的代码会有障碍,多学学计算机网络,还有很多有趣的知识。
wifi设置相关的函数定义在wifi_device.c文件中,包括wifi连接、断开、扫描等功能,该文件的位置在device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_device.c,感兴趣的可以打开研究,我们使用他的头文件就行了。
而关于Neptune开发版的引脚定义、操作设备的API分别在iot_gpio_w800.h和iot_gpio_neptune.h中,如下:
#include "wifi_device.h" //Provides functions for the Wi-Fi station and hotspot modes.即wif连接、断开、参数配置等功能
#include "lwip/netifapi.h"
// #include "lwip/api_shell.h"
#include "iot_gpio_w800.h" //定义了w800引脚,例:IOT_GPIO_PA_00 为PA0
#include "iot_gpio_neptune.h" //提供了操作设备的API:flash, GPIO, I2C, PWM, UART, and watchdog APIs.可进入查看函数简介、参数、返回等信息
#define LOG_TAG "Wifista: " //日志标签
#define LOGI(fmt, ...) printf("[%d] INFO %s " fmt "\r\n", osKernelGetTickCount(), LOG_TAG, ##__VA_ARGS__) //变参log打印
说明:
fmt:格式,即printf("[%d] INFO %s " fmt "\r\n", osKernelGetTickCount(), LOG_TAG,这一部分,输出固定格式内容:[内核计数值] INFO Wifista:
...:缺省号代表一个可以变化的参数表。使用保留名 VA_ARGS 把参数传递给宏。当宏的调用展开时,实际的参数就传递给 printf()了。osKernelGetTickCount():获取 RTOS 内核计数效果展示:
调用:
LOGI("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s",
macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); //log打印连接信息
输出:
[8163] INFO Wifista: bssid: 02:5A:13:D2:C5:8F, rssi: 34, connState: 1, reason: 0, ssid: jaychou
很好理解,没用过snprintf()函数的注意一下就好了。
static void PrintLinkedInfo(WifiLinkedInfo* info) //打印连接信息,在bssid上右键即可打开对应的头文件,查看具体的参数含义
{
if (!info) return;
static char macAddress[32] = {0}; //暂时存疑,mac地址是6个字节,即6个char,此处为什么用32个char呢?
unsigned char* mac = info->bssid; //在基础设施BSS中,BSSID是无线接入点(WAP)的MAC地址.
snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", //格式化mac地址赋值给macAddress
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
LOGI("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s",
macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); //log打印连接信息
}
输入是一个结构体指针,定义如下:
typedef struct {
char ssid[WIFI_MAX_SSID_LEN];
unsigned char bssid[WIFI_MAC_LEN];
int rssi;
WifiConnState connState;
unsigned short disconnectedReason;
} WifiLinkedInfo;
随便打开一个wifi热点,设置里面可以看到这些选项。注意函数指针。
static char* SecurityTypeName(WifiSecurityType type) //返回扫描到的wifi热点的安全类型,同样在对应的头文件中有定义
{
switch (type)
{
case WIFI_SEC_TYPE_OPEN:
return "OPEN";
case WIFI_SEC_TYPE_WEP:
return "WEP";
case WIFI_SEC_TYPE_PSK:
return "PSK";
case WIFI_SEC_TYPE_SAE:
return "SAE";
default:
break;
}
LOGI("unknow type = %x\r\n", type);
return "Unknow";
}
static char* FormatMacAddress(char* buffer, unsigned char* mac) //格式化mac地址,这里使用了snprintf()函数,后面直接调用该函数即可,不用写下面这很长一段
{
snprintf(buffer, sizeof(buffer), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return buffer;
}
static void PrintScanResult(void) //打印热点扫描的结果 ,周围有哪些热点,及其类型,名称等
{
WifiScanInfo scanResult[WIFI_SCAN_HOTSPOT_LIMIT] = {0}; //默认显示最多64个结果,见头文件的定义
uint32_t resultSize = WIFI_SCAN_HOTSPOT_LIMIT;
memset(&scanResult, 0, sizeof(scanResult));
WifiErrorCode errCode = GetScanInfoList(scanResult, &resultSize);
if (errCode != WIFI_SUCCESS) { //打印错误信息
LOGI("GetScanInfoList failed: %d", errCode);
}
for (uint32_t i = 0; i < resultSize; i++) {
char buffer[32] = {0};
WifiScanInfo info = scanResult[i];
LOGI("Result[%d]: %s, %4s, %d, %d, %d, %s", i,
FormatMacAddress(buffer, info.bssid), SecurityTypeName(info.securityType),
info.rssi, info.band, info.frequency, info.ssid);
}
}
static int g_connected = 0; //连接状态,1表示连接成功
static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
if (!info) return;
LOGI("%s %d, state = %d, info = ", __FUNCTION__, __LINE__, state);
PrintLinkedInfo(info);
if (state == WIFI_STATE_AVALIABLE) {
g_connected = 1;
} else {
g_connected = 0;
}
}
可以猜测:当扫描结束后,就可以调用3.5中的结果打印函数了。事实的确如此,请看完整代码。
static int g_scanDone = 0; //扫描状态,1表示扫描完毕
static void OnWifiScanStateChanged(int state, int size)
{
LOGI("%s %d, state = %X, size = %d", __FUNCTION__, __LINE__, state, size);
if (state == WIFI_STATE_AVALIABLE && size > 0) {
g_scanDone = 1;
}
}
static void hexdump(void* data, int size) //hexdump一般用来查看"二进制"文件的十六进制编码
{
unsigned char* ptr = data;
printf("hexdump: %p %d: ", data, size);
for (int i = 0; i < size; i++) {
printf("%02X%c", ptr[i], (i+1) % 8 == 0 ? '\n' : ' ');
}
printf("\n");
}
这个函数主要用在打印连接到的AP ip地址、子网掩码、网关信息,其中:
netif:LwIP抽象出来的各网络接口,协议栈可以使用多个不同的接口,而ethernetif则提供了netif访问硬件的各接口,每个不同的接口有不同的ethernetif。
inet_ntoa()是编程语言,功能是将网络地址转换成“.”点隔的字符串格式(ip地址显示)。
LWIP:一个轻量级TCP/IP协议栈。
int i = 0;
for (struct netif* p = netif_list; p; p = p->next, i++) { //打印ip地址,网关地址,子网掩码
hexdump(p->name, sizeof(p->name));
LOGI("[%d]: ip = %s", i, inet_ntoa(p->ip_addr));
LOGI("[%d]: gateway = %s", i, inet_ntoa(p->gw));
LOGI("[%d]: netmask = %s", i, inet_ntoa(p->netmask));
}
输出:
[20:37:18:948] hexdump: 0x2000dfda 2: 65 6E
[20:37:18:948] [8276] INFO Wifista: [0]: ip = 192.168.43.102
[20:37:18:959] [8278] INFO Wifista: [0]: gateway = 192.168.43.1
[20:37:18:959] [8280] INFO Wifista: [0]: netmask = 255.255.255.0
[20:37:18:971] hexdump: 0x2000df7e 2: 65 6E
[20:37:18:971] [8284] INFO Wifista: [1]: ip = 0.0.0.0
[20:37:18:971] [8286] INFO Wifista: [1]: gateway = 0.0.0.0
[20:37:18:985] [8288] INFO Wifista: [1]: netmask = 0.0.0.0
[20:37:18:985] hexdump: 0x20032436 2: 6C 6F
[20:37:18:985] [8291] INFO Wifista: [2]: ip = 127.0.0.1
[20:37:18:996] [8293] INFO Wifista: [2]: gateway = 127.0.0.1
[20:37:18:996] [8295] INFO Wifista: [2]: netmask = 255.0.0.0
看192.168.43.102这个地址就行了,另外两个事环回地址和本网络上的本主机地址,没学过计网的可以了解一下。
static void GpioIsr(char* arg) //GPIO中断函数,PB9中断控制wifi连接状态
{
(void)arg;
IoTGpioSetIsrMask(IOT_GPIO_PB_09, 0); //不屏蔽PB9的中断功能(因为用它的中断功能确定LED的状态)
control_flag = control_flag == 0 ? 1 : 0; //按一次按键切换一次状态
printf(" Wifi state changed! Now control_flag=%d\n",control_flag); //打印当前flag值
}
其中:control_flag = control_flag == 0 ? 1 : 0为三目表达式。
while里面的状态切换,大家或许可以写的更好。
/*
版本:修改版,使用开发版的PB9按键控制wifi的连接与断开
说明:Neptune w800作为接入设备(STA)连接wifi(AP),WIFI名称和密码需要在程序中配置
知识点: AP: 也就是无线接入点,是一个无线网络的创建者,是网络的中心节点。一般家庭或办公室使用的无线路由器就一个AP。
STA站点: 每一个连接到无线网络中的终端(如笔记本电脑、PDA及其它可以联网的用户设备)都可称为一个站点。
运行流程:
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_device.h" //Provides functions for the Wi-Fi station and hotspot modes.即wif连接、断开、参数配置等功能
#include "lwip/netifapi.h"
// #include "lwip/api_shell.h"
#include "iot_gpio_w800.h" //定义了w800引脚,例:IOT_GPIO_PA_00 为PA0
#include "iot_gpio_neptune.h" //提供了操作设备的API:flash, GPIO, I2C, PWM, UART, and watchdog APIs.可进入查看函数简介、参数、返回等信息
#define LOG_TAG "Wifista: " //日志标签
#define LOGI(fmt, ...) printf("[%d] INFO %s " fmt "\r\n", osKernelGetTickCount(), LOG_TAG, ##__VA_ARGS__) //变参log打印
static bool control_flag = 0; //按键控制标志
static void PrintLinkedInfo(WifiLinkedInfo* info) //打印连接信息,在bssid上右键即可打开对应的头文件,查看具体的参数含义
{
if (!info) return;
static char macAddress[32] = {0}; //暂时存疑,mac地址是6个字节,即6个char,此处为什么用32个char呢?
unsigned char* mac = info->bssid; //在基础设施BSS中,BSSID是无线接入点(WAP)的MAC地址.
snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", //格式化mac地址赋值给macAddress
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
LOGI("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s",
macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); //log打印连接信息
}
static char* SecurityTypeName(WifiSecurityType type) //返回扫描到的wifi热点的加密方式,同样在对应的头文件中有定义
{
switch (type)
{
case WIFI_SEC_TYPE_OPEN:
return "OPEN";
case WIFI_SEC_TYPE_WEP:
return "WEP";
case WIFI_SEC_TYPE_PSK:
return "PSK";
case WIFI_SEC_TYPE_SAE:
return "SAE";
default:
break;
}
LOGI("unknow type = %x\r\n", type);
return "Unknow";
}
static char* FormatMacAddress(char* buffer, unsigned char* mac) //格式化mac地址,这里使用了snprintf()函数,后面直接调用该函数即可,不用写下面这很长一段
{
snprintf(buffer, sizeof(buffer), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return buffer;
}
static void PrintScanResult(void) //打印热点扫描的结果 ,周围有哪些热点,及其类型,名称等
{
WifiScanInfo scanResult[WIFI_SCAN_HOTSPOT_LIMIT] = {0}; //默认显示最多64个结果,见头文件的定义
uint32_t resultSize = WIFI_SCAN_HOTSPOT_LIMIT;
memset(&scanResult, 0, sizeof(scanResult));
WifiErrorCode errCode = GetScanInfoList(scanResult, &resultSize);
if (errCode != WIFI_SUCCESS) { //打印错误信息
LOGI("GetScanInfoList failed: %d", errCode);
}
for (uint32_t i = 0; i < resultSize; i++) {
char buffer[32] = {0};
WifiScanInfo info = scanResult[i];
LOGI("Result[%d]: %s, %4s, %d, %d, %d, %s", i,
FormatMacAddress(buffer, info.bssid), SecurityTypeName(info.securityType),
info.rssi, info.band, info.frequency, info.ssid);
}
}
static int g_connected = 0; //连接状态,1表示连接成功
static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
if (!info) return;
LOGI("%s %d, state = %d, info = ", __FUNCTION__, __LINE__, state);
PrintLinkedInfo(info);
if (state == WIFI_STATE_AVALIABLE) {
g_connected = 1;
} else {
g_connected = 0;
}
}
static int g_scanDone = 0; //扫描状态,1表示扫描完毕
static void OnWifiScanStateChanged(int state, int size)
{
LOGI("%s %d, state = %X, size = %d", __FUNCTION__, __LINE__, state, size);
if (state == WIFI_STATE_AVALIABLE && size > 0) {
g_scanDone = 1;
}
}
static void hexdump(void* data, int size) //hexdump一般用来查看"二进制"文件的十六进制编码
{
unsigned char* ptr = data;
printf("hexdump: %p %d: ", data, size);
for (int i = 0; i < size; i++) {
printf("%02X%c", ptr[i], (i+1) % 8 == 0 ? '\n' : ' ');
}
printf("\n");
}
static void GpioIsr(char* arg) //GPIO中断函数,PB9中断控制wifi连接状态
{
(void)arg;
IoTGpioSetIsrMask(IOT_GPIO_PB_09, 0); //不屏蔽PB9的中断功能(因为用它的中断功能确定LED的状态)
control_flag = control_flag == 0 ? 1 : 0; //按一次按键切换一次状态
printf(" Wifi state changed! Now control_flag=%d\n",control_flag); //打印当前flag值
}
static void WifiConnectTask(void *arg) //WIFI连接任务(static静态函数,函数名只在本文件生效)
{
(void)arg;
WifiErrorCode errCode; //WifiErrorCode类型结构体变量errCode,其成员是WIFI的各种状态
WifiEvent eventListener = { //wif事件(连接状态改变、扫描状态改变)监听,WifiEvent类型结构体变量eventListener,成员如下
.OnWifiConnectionChanged = OnWifiConnectionChanged,
.OnWifiScanStateChanged = OnWifiScanStateChanged
};
WifiDeviceConfig apConfig = {}; //连接到指定wifi AP的配置,是结构体,下面会对其成员变量赋值(ssid等)
int netId = -1;
osDelay(100);
errCode = RegisterWifiEvent(&eventListener);
LOGI("RegisterWifiEvent: %d", errCode);
// 设置热点参数(可以自行修改蓝牙穿参、串口传参)
strcpy(apConfig.ssid, "jaychou");
strcpy(apConfig.preSharedKey, "12345679");
apConfig.securityType = WIFI_SEC_TYPE_PSK;
while (1)
{
switch (control_flag)
{
case 0:
{
LOGI("sysTicks: %u, kernelTicks: %u", osKernelGetSysTimerCount(), osKernelGetTickCount());
LOGI("IsWifiActive: %d", IsWifiActive()); //此处wifi状态为未连接,0
errCode = EnableWifi(); //激活开发板的wifi,成功后EnableWifi()返回:WIFI_SUCCESS
LOGI("EnableWifi: %d", errCode); //激活成功此处输出0,WIFI_SUCCESS=0
LOGI("IsWifiActive: %d", IsWifiActive()); //此处为1
osDelay(10);
char buffer[32] = {0};
unsigned char mac[6] = {0};
errCode = GetDeviceMacAddress(mac);
LOGI("GetDeviceMacAddress: errCode:%d, FormatMacAddress:%s", errCode, FormatMacAddress(buffer, mac));
g_scanDone = 0; //扫描完毕会置为1,否则while循环扫等待描
errCode = Scan(); //扫描wifi热点
LOGI("Scan: %d", errCode);
LOGI("waiting for scan done...");
while (!g_scanDone) {
osDelay(5);
}
PrintScanResult(); //之前定义的函数,打印扫描结果
osDelay(100);
errCode = AddDeviceConfig(&apConfig, &netId); //添加wifi配置信息,返回netID=0即WIFI_SUCCESS
LOGI("AddDeviceConfig: %d", errCode);
g_connected = 0;
errCode = ConnectTo(netId); //连接到选定的热点
LOGI("ConnectTo netID: %d,errCode: %d", netId, errCode);
LOGI("waiting for connect success...");
while (!g_connected) {
osDelay(10);
}
LOGI("g_connected: %d", g_connected);
osDelay(100);
int i = 0; //联网业务开始
for (struct netif* p = netif_list; p; p = p->next, i++) { //打印ip地址,网关地址,子网掩码
hexdump(p->name, sizeof(p->name));
LOGI("[%d]: ip = %s", i, inet_ntoa(p->ip_addr));
LOGI("[%d]: gateway = %s", i, inet_ntoa(p->gw));
LOGI("[%d]: netmask = %s", i, inet_ntoa(p->netmask));
}
bool flag_1=true;
while(flag_1)
{
switch(control_flag)
{
case 0:break;
case 1:printf("\n===============1============\n\n");flag_1=false;break;
}
osDelay(100);
//break;
}
continue;
}
case 1:
{
errCode = Disconnect(); // disconnect with your AP
LOGI("Disconnect: %d", errCode);
errCode = RemoveDevice(netId); // remove AP config
LOGI("RemoveDevice: %d", errCode);
errCode = DisableWifi();
LOGI("DisableWifi: %d", errCode);
bool flag_2=1;
while (flag_2)
{
switch(control_flag)
{
case 1:break;
case 0:printf("\n===============0============\n\n");flag_2=false;break;
}
osDelay(100);
//break;
}
continue;
}
}
osDelay(100);
}
}
static void WifiConnectDemo(void) //开启一个线程运行wifitask
{
osThreadAttr_t attr;
IoTGpioInit(IOT_GPIO_PB_09); //初始化PB9引脚
IoTGpioSetDir(IOT_GPIO_PB_09,IOT_GPIO_DIR_IN); // input is PB09
IoTIoSetPull(IOT_GPIO_PB_09,IOT_GPIO_PULLHIGH); //PB9上拉输入,上拉输入的好处就是输入的电平不会上下浮动而导致输入信号不稳定,在没有信号输入的情况下可以稳定在高电平。
IoTGpioRegisterIsrFunc(IOT_GPIO_PB_09,IOT_INT_TYPE_EDGE,IOT_GPIO_EDGE_FALL_LEVEL_LOW, GpioIsr, NULL); //中断使能,PB9,边缘触发、下降沿或低电平
attr.name = "WifiConnectTask";
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(WifiConnectTask, NULL, &attr) == NULL) {
LOGI("[WifiConnectDemo] Falied to create WifiConnectTask!");
}
}
//SYS_RUN是标识用于初始化和启动系统运行阶段的入口
//PP_FEATURE_INIT标识用于初始化和启动应用层功能的入口
APP_FEATURE_INIT(WifiConnectDemo);
static_library("wifi_test") {
sources = [
# "wifi_scan_demo.c",
# "wifi_connect_demo.c",
# "wifi_hotspot_demo.c",
"wifi_control.c",
]
include_dirs = [
"//utils/native/lite/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
#按键控制
"//domains/iot/link/libbuild",
"//base/iot_hardware/peripheral/interfaces/kits"
]
if (board_name == "w800") {
include_dirs += [
"//vendor/winnermicro/w800/src/network/lwip2.0.3/include",
"//vendor/winnermicro/w800/include/arch/xt804/csi_core",
"//vendor/winnermicro/w800/include/arch/xt804",
"//vendor/winnermicro/w800/include/platform",
"//vendor/winnermicro/w800/include/os",
"//vendor/winnermicro/w800/include/net",
"//vendor/winnermicro/w800/include/app",
"//vendor/winnermicro/w800/include/wifi",
"//vendor/winnermicro/w800/include",
]
}
}
import("//build/lite/config/component/lite_component.gni")
lite_component("app") {
features = [
#格式:文件夹名称:文件夹下面BUILD文件中静态库的名称
# "my_test_gn:my_test_gn",
# "demolink:example_demolink",
# "wifi_bt:wifi_bt_test",
"wifitest:wifi_test"
]
}
[20:37:02:761] [183] INFO Wifista: RegisterWifiEvent: 0
[20:37:02:764] [184] INFO Wifista: sysTicks: 29585326, kernelTicks: 184
[20:37:02:775] [187] INFO Wifista: IsWifiActive: 0
[20:37:02:775] [189] INFO Wifista: EnableWifi: 0
[20:37:02:775] [190] INFO Wifista: IsWifiActive: 1
[20:37:02:803] [202] INFO Wifista: GetDeviceMacAddress: errCode:0, FormatMacAddress:28:
[20:37:02:805] [205] INFO Wifista: OnWifiScanStateChanged 101, state = 0, size = 0
[20:37:04:412] [wifi_service]: dispatch scan event.
[20:37:04:414] [1009] INFO Wifista: OnWifiScanStateChanged 101, state = 1, size = 10
[20:37:04:424] [1013] INFO Wifista: Scan: 0
[20:37:04:424] [1014] INFO Wifista: waiting for scan done...
[20:37:04:429] [1016] INFO Wifista: Result[0]: CC:, OPEN, -84, 0, 144, CQUPT-2.4G
[20:37:04:434] [1019] INFO Wifista: Result[1]: 52:, PSK, -70, 0, 72, vivo iQOO Neo
[20:37:04:440] [1022] INFO Wifista: Result[2]: CC:, OPEN, -80, 0, 144, CQUPT-2.4G
[20:37:04:445] [1026] INFO Wifista: Result[3]: CC:, OPEN, -78, 0, 144, CQUPT-2.4G
[20:37:04:451] [1029] INFO Wifista: Result[4]: 02:, PSK, -22, 0, 72, jaychou
[20:37:04:456] [1031] INFO Wifista: Result[5]: CC:, OPEN, -62, 0, 144, CQUPT-2.4G
[20:37:04:465] [1035] INFO Wifista: Result[6]: CC:, OPEN, -60, 0, 144, CQUPT-2.4G
[20:37:04:470] [1038] INFO Wifista: Result[7]: CC:, OPEN, -52, 0, 144, CQUPT-2.4G
[20:37:04:476] [1041] INFO Wifista: Result[8]: EE:, PSK, -74, 0, 144, Redmi K40
[20:37:04:482] [1044] INFO Wifista: Result[9]: 4A:, PSK, -78, 0, 144, CQUPT-8G
[20:37:04:689] [1147] INFO Wifista: AddDeviceConfig: 0
[20:37:04:692] InitWifiConfig, disconnect wifi...
[20:37:05:072] join net success
[20:37:05:072] WifiEventCallback status = WIFI_JOIN_SUCCESS
[20:37:05:081] [1341] INFO Wifista: OnWifiConnectionChanged 88, state = 1, info =
[20:37:05:085] [1344] INFO Wifista: bssid: 02:5A:13:D2:C5:8F, rssi: 36, connState: 1, reason: 0, ssid: jaychou
[20:37:05:091] Connect to jaychou done, status = 1!
[20:37:05:095] [1350] INFO Wifista: ConnectTo netID: 0,errCode: 0
[20:37:05:100] [1352] INFO Wifista: waiting for connect success...
[20:37:05:103] [1355] INFO Wifista: g_connected: 1
[20:37:05:132] WifiEventCallback status = NETIF_IP_NET_UP
[20:37:05:307] hexdump: 0x2000dfda 2: 65 6E
[20:37:05:307] [1457] INFO Wifista: [0]: ip = 192.168.43.102
[20:37:05:317] [1459] INFO Wifista: [0]: gateway = 192.168.43.1
[20:37:05:328] [1461] INFO Wifista: [0]: netmask = 255.255.255.0
[20:37:05:328] hexdump: 0x2000df7e 2: 65 6E
[20:37:05:328] [1465] INFO Wifista: [1]: ip = 0.0.0.0
[20:37:05:344] [1467] INFO Wifista: [1]: gateway = 0.0.0.0
[20:37:05:344] [1469] INFO Wifista: [1]: netmask = 0.0.0.0
[20:37:05:344] hexdump: 0x20032436 2: 6C 6F
[20:37:05:344] [1472] INFO Wifista: [2]: ip = 127.0.0.1
[20:37:05:344] [1474] INFO Wifista: [2]: gateway = 127.0.0.1
[20:37:05:358] [1476] INFO Wifista: [2]: netmask = 255.0.0.0
[20:37:09:101] Wifi state changed! Now control_flag=1
[20:37:09:153]
[20:37:09:153] ===============1============
[20:37:09:153]
[20:37:09:355] [3479] INFO Wifista: Disconnect: -9
[20:37:09:357] [3480] INFO Wifista: RemoveDevice: 0
[20:37:09:368] [3482] INFO Wifista: DisableWifi: 0
[20:37:16:118] Wifi state changed! Now control_flag=0
[20:37:16:118] Wifi state changed! Now control_flag=0
[20:37:16:168]
[20:37:16:168] ===============0============
[20:37:16:177]
[20:37:16:371] [6986] INFO Wifista: sysTicks: 1117762488, kernelTicks: 6986
[20:37:16:382] [6988] INFO Wifista: IsWifiActive: 0
[20:37:16:382] [6990] INFO Wifista: EnableWifi: 0
[20:37:16:382] [6992] INFO Wifista: IsWifiActive: 1
[20:37:16:405] [7003] INFO Wifista: GetDeviceMacAddress: errCode:0, FormatMacAddress:28:
[20:37:16:410] [7006] INFO Wifista: OnWifiScanStateChanged 101, state = 0, size = 0
[20:37:18:021] [wifi_service]: dispatch scan event.
[20:37:18:023] [7812] INFO Wifista: OnWifiScanStateChanged 101, state = 1, size = 9
后面和6.1输出一样的,不复制了。
大家可以做改进,比如第二次连接的时候不再输出那么多的信息,等等。我只做学习wifi功能用,就写到此。
在月光下弹琴
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时