鸿蒙Hi3861学习十三-Huawei LiteOS-M(STA模式)

news2024/11/20 7:20:12

一、简介

AP(Access Point)无线接入点

        AP是无线接入点,是一个无线网络的创建者,是网络的中心节点。一般家庭或办公室使用的无线路由器就是一个AP

STA(Station)站点

        STA也可以理解为终端的意思,每一个连接到无线网络中的终端(例如笔记本电脑,手机等其他可以联网的设备)都可以成为一个STA站点

SSID(Service Set Identifier)服务集标识符

        每个无线AP都应该有一个SSID用于识别,就是通常所说的WIFI名

BSSID(Basic Service Set Identifier)基本服务集标识符

        每一个网络设备都有其用于识别的物理地址,这个东西就是MAC地址。一般在出厂后会有一个默认MAC,可更改。MAC地址作为设备识别的标识符。BSSID是针对STA而言。对于STA来说,获取到AP接入点的MAC地址就是BSSID

        例如:某个AP释放一个名为A的WIFI热点,同一区域内另一个AP也释放一个名为A的WIFI热点,当手机连接A热点时,如何辨别连接的是哪个AP呢?此时就要用到BSSID。一般情况下BSSID可以理解为无线路由器的MAC地址,通过查看手机连接WIFI的MAC地址即可知道连接的是哪个AP。

ESSID(Extended Service Set Identifier)扩展服务集标识符

        ESSID是一个比较抽象的概念,它实际上和SSID相同,只是如果有好几个AP热点名字相同,此时就相当于把这个SSID扩大了,这几个AP共同的名字就叫ESSID

        例如:某个AP释放一个名为A的WIFI热点,同一区域内另一个AP也释放一个名为A的WIFI热点,那么A就是ESSID

二、API介绍

      RegisterWifiEvent

        函数功能:

        为指定的WIFI事件注册回调函数。当wifiEvent中定义的wifi事件发生时,将调用已注册的回调函数。

        函数原型:

WifiErrorCode RegisterWifiEvent(WifiEvent* event)

        参数:

        event:

        事件类型。其类型为WifiEvent。看该类型的定义。

typedef struct {
    /** Connection state change */
    void (*OnWifiConnectionChanged)(int state, WifiLinkedInfo* info);
    /** Scan state change */
    void (*OnWifiScanStateChanged)(int state, int size);
    /** Hotspot state change */
    void (*OnHotspotStateChanged)(int state);
    /** Station connected */
    void (*OnHotspotStaJoin)(StationInfo* info);
    /** Station disconnected */
    void (*OnHotspotStaLeave)(StationInfo* info);
} WifiEvent;

         OnWifiConnectionChangedWIFI连接状态改变回调。针对STA。其参数state表示连接的状态。state>0表示连接成功,0 连接失败(密码错误或连接断开)。info 为更加详细的连接信息。看其对应的结构体。

typedef struct {
    /** Service set ID (SSID). For its length, see {@link WIFI_MAX_SSID_LEN}. */
    char ssid[WIFI_MAX_SSID_LEN];
    /** Basic service set ID (BSSID). For its length, see {@link WIFI_MAC_LEN}. */
    unsigned char bssid[WIFI_MAC_LEN];
    /** Received signal strength indicator (RSSI) */
    int rssi;
    /** Wi-Fi connection state, which is defined in {@link WifiConnState} */
    WifiConnState connState;
    /** Reason for Wi-Fi disconnection */
    unsigned short disconnectedReason;
} WifiLinkedInfo;

        ssid:连接的SSID。只在连接成功时有用。

        bssid:链接的路由器的MAC。只在连接成功时有用。

        rssi:信号强度。只在连接成功时有用。

        connState:连接状态。0 断开,1 连接。

typedef enum {
    /** Disconnected */
    WIFI_DISCONNECTED,
    /** Connected */
    WIFI_CONNECTED
} WifiConnState;

         disconnectedReason:断开连接原因。

        OnWifiScanStateChanged扫描结果回调。针对STA。其参数有两个,state和size。state 表示扫描的结果,0 失败,1 成功。size表示扫描到的AP数量。

        OnHotspotStateChanged热点状态改变针对AP。详细参数介绍见下一章。

        OnHotspotStaJoin有STA链接针对AP。详细参数介绍见下一章。

        OnHotspotStaLeave有STA断开连接针对AP。详细参数介绍见下一章。

        返回值:

        WIFI_SUCCESS:成功

        其他值:失败

        实例:

static WifiEvent g_wifiEventHandler = {0};
static WifiErrorCode error;

    g_wifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChangedHandler;  //扫描状态改变,扫描到了AP
    g_wifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChangedHandler;    //WIFI连接状态改变回调
    g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;  //STA连接回调
    g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;    //STA断开回调
    g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;    //热点状态改变的回调
    error = RegisterWifiEvent(&g_wifiEventHandler); //注册事件

      EnableWifi

        函数功能:

        使能WIFI,启用STA模式

        函数原型:

WifiErrorCode EnableWifi(void)

        参数:

        无

        返回值:

        WIFI_SUCCESS:成功

        其他值:失败

        实例:

    if (EnableWifi() != WIFI_SUCCESS)
    {
        LOG_E("EnableWifi failed, error = %d\n", error);
    }

      IsWifiActive

        函数功能:

        检查STA模式是否启用

        函数原型:

int IsWifiActive(void)

        参数:

        无

        返回值:

#define WIFI_STA_NOT_ACTIVE 0    //STA未启动
#define WIFI_STA_ACTIVE 1    //STA启动

        实例:

if (IsWifiActive() == 0)
{}

      Scan

        函数功能:

        开启扫描热点信息。开启后,设备开始扫描设备。如果扫描完成,则会调用RegisterWifiEvent注册的OnWifiScanStateChanged事件

        函数原型:

WifiErrorCode Scan(void)

        参数:

        无

        返回值:

        WIFI_SUCCESS:成功

        其他值:失败

        实例:

Scan();

      GetScanInfoList

        函数功能:

        获取所有扫描到的热点列表

        函数原型:

WifiErrorCode GetScanInfoList(WifiScanInfo* result, unsigned int* size)

        参数:

        result:输出参数。扫描到的热点列表信息。其结构体信息为WifiScanInfo。

typedef struct {
    /** Service set ID (SSID). For its length, see {@link WIFI_MAX_SSID_LEN}. */
    char ssid[WIFI_MAX_SSID_LEN];
    /** Basic service set ID (BSSID). For its length, see {@link WIFI_MAC_LEN}. */
    unsigned char bssid[WIFI_MAC_LEN];
    /** Security type. For details, see {@link WifiSecurityType}. */
    int securityType;
    /** Received signal strength indicator (RSSI) */
    int rssi;
    /** Frequency band */
    int band;
    /** Frequency in MHz */
    int frequency;
} WifiScanInfo;

         ssid:WIFI名

        bssid:AP的MAC

        securityType:加密类型

        rssi:信号强度

        band:2.4G还是5G

        frequency:频率(信道)

        size:扫描到的AP个数。

        返回值:

        WIFI_SUCCESS:成功

        其他值:失败

        实例:

WifiScanInfo *info = NULL;
unsigned int size = 0;
WifiErrorCode error;

error = GetScanInfoList(info, &size);   //获取扫描列表

      AddDeviceConfig

        函数功能:

        配置要连接的AP信息,此函数生成一个networkID

        函数原型:

WifiErrorCode AddDeviceConfig(const WifiDeviceConfig* config, int* result)

        参数:

        config:配置参数,要连接的热点信息。结构体为WifiDeviceConfig。

typedef struct WifiDeviceConfig {
    /** Service set ID (SSID). For its length, see {@link WIFI_MAX_SSID_LEN}. */
    char ssid[WIFI_MAX_SSID_LEN];
    /** Basic service set ID (BSSID). For its length, see {@link WIFI_MAC_LEN}. */
    unsigned char bssid[WIFI_MAC_LEN];
    /** Key. For its length, see {@link WIFI_MAX_KEY_LEN}. */
    char preSharedKey[WIFI_MAX_KEY_LEN];
    /** Security type. It is defined in {@link WifiSecurityType}. */
    int securityType;
    /** Allocated <b>networkId</b> */
    int netId;
    /** Frequency */
    unsigned int freq;
    /** PSK type, see {@link WifiPskType}. */
    int wapiPskType;
} WifiDeviceConfig;

         ssid:AP名。必填

        bssid:AP MAC。非必填

        preSharedKey:AP密码。必填

        securityType:加密类型,必填

typedef enum {
    /** Invalid security type */
    WIFI_SEC_TYPE_INVALID = -1,
    /** Open */
    WIFI_SEC_TYPE_OPEN,
    /** Wired Equivalent Privacy (WEP) */
    WIFI_SEC_TYPE_WEP,
    /** Pre-shared key (PSK) */
    WIFI_SEC_TYPE_PSK,
    /** Simultaneous Authentication of Equals (SAE) */
    WIFI_SEC_TYPE_SAE,
} WifiSecurityType;

        netId:网络ID,非必填

        freq:频率,非必填

        wapiPskType:psk 加密类型,非必填

        result:输出生成的networkID每个网络ID匹配一个热点配置

        返回值:

        WIFI_SUCCESS:成功

        其他值:失败

        实例:

WifiDeviceConfig select_ap_config = {0};
strcpy(select_ap_config.ssid,"harmony_test_ap");
strcpy(select_ap_config.preSharedKey, "123456789");
select_ap_config.securityType = WIFI_SEC_TYPE_PSK;   //加密类型

if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS)    //添加连接对象
{}

      ConnectTo

        函数功能:

        连接到指定AP。连接结果会触发由RegisterWifiEvent注册的OnWifiConnectionChanged回调。

        函数原型:

WifiErrorCode ConnectTo(int networkId)

        参数:

        networkId:网络ID。AddDeviceConfig 返回得到

        返回值:

        WIFI_SUCCESS:成功

        其他值:失败

        实例:

int result;
if (ConnectTo(result) == WIFI_SUCCESS)
{}

      netifapi_netif_find

        函数功能:

        获取网络接口用于IP操作

        函数原型:

struct netif *netifapi_netif_find(const char *name);

        参数:

        name:网络接口名称。STA为“wlan0”,AP为“ap0”。为什么是这俩,还没搞清楚。搞清楚后会回来补充。

        返回值:

        NULL:失败

        其他值:网络接口值。netif:LwIP网络接口

        实例:

struct netif *g_lwip_netif = NULL;
g_lwip_netif = netifapi_netif_find("wlan0");   //获取网络接口

      dhcp_start

        函数功能:

        启动DHCP,获取IP

        函数原型:

err_t dhcp_start(struct netif *netif)

        参数:

        netif:网络接口值。netifapi_netif_find 获得。

        返回值:

        ERR_OK:成功

        其他值:失败

        实例:

struct netif *g_lwip_netif = NULL;
dhcp_start(g_lwip_netif);

      dhcp_is_bound

        函数功能:

        查询DHCP状态,成功后返回OK。

        函数原型:

err_t dhcp_is_bound(struct netif *netif)

        参数:

        netif:网络接口值。netifapi_netif_find 获得。

        返回值:

        ERR_OK:成功

        其他值:失败

        实例:

struct netif *g_lwip_netif = NULL;
if(dhcp_is_bound(g_lwip_netif) == ERR_OK)
{}

      netifapi_netif_common

        函数功能:

        以线程安全的方式调用与netif相关的API

        函数原型:

err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
                      netifapi_errt_fn errtfunc)

        参数:

        netif:网络接口值。netifapi_netif_find 获得。

        voidfunc:要调用的API。

        errtfunc:失败时的回调。默认为NULL。

        返回值:

        ERR_OK:成功

        其他值:失败

        实例:

struct netif *g_lwip_netif = NULL;
netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);

      dhcp_clients_info_show

        函数功能:

        打印DHCP客户端的相关信息。

        函数原型:

void dhcp_clients_info_show(struct netif *netif_p);

        参数:

        netif:网络接口值。netifapi_netif_find 获得。

        返回值:

        无

        实例:

netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);

四、实例

        这里创建一个STA去连接指定的AP,并且打印相关链接的信息。

        修改BUILD.gn文件如下:

include_dirs = [
        "//utild/native/lite/include",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
        "src",
    ]
#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 LOG_I(fmt, args...)   printf("<%8ld> - [STA]:"fmt"\r\n",osKernelGetTickCount(),##args);
#define LOG_E(fmt, args...)   printf("<%8ld>-[STA_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);

#define DEF_TIMEOUT 15
#define ONE_SECOND 1

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 int g_staScanSuccess = 0;
static int g_ConnectSuccess = 0;
static int ssid_count = 0;
static WifiEvent g_wifiEventHandler = {0};
static WifiErrorCode error;

#define SELECT_WLAN_PORT "wlan0"

#define SELECT_WIFI_SSID "harmony_test_ap"
#define SELECT_WIFI_PASSWORD "123456789"
#define SELECT_WIFI_SECURITYTYPE WIFI_SEC_TYPE_PSK


/*扫描结果回调*/
static void OnWifiScanStateChangedHandler(int state, int size)
{
    (void)state;
    LOG_I("OnWifiScanStateChangedHandler,state:%d,size:%d",state,size);
    if (size > 0)
    {
        ssid_count = size;
        g_staScanSuccess = 1;
    }
    return;
}

/*WIFI连接状态改变*/
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info)
{
    (void)info;

    LOG_I("bssid:%02x:%02x:%02x:%02x:%02x:%02x",info->bssid[0],info->bssid[1],info->bssid[2],info->bssid[3],info->bssid[4],info->bssid[5]);
    LOG_I("OnWifiConnectionChangedHandler.state:%d,ssid:%s,rssi:%d,connstate:%d,disconnReason:%d",state,info->ssid,info->rssi,info->connState,info->disconnectedReason);

    if (state > 0)
    {
        g_ConnectSuccess = 1;
        LOG_I("callback function for wifi connect\r\n");
    }
    else
    {
        LOG_I("connect error,please check password\r\n");
    }
    return;
}


/*等待扫描结果,在扫描结果回调中置标志*/
static void WaitSacnResult(void)
{
    int scanTimeout = DEF_TIMEOUT;
    while (scanTimeout > 0)
    {
        sleep(ONE_SECOND);
        scanTimeout--;
        if (g_staScanSuccess == 1)
        {
            LOG_I("WaitSacnResult:wait success[%d]s\n", (DEF_TIMEOUT - scanTimeout));
            break;
        }
    }
    if (scanTimeout <= 0)
    {
        LOG_I("WaitSacnResult:timeout!\n");
    }
}

/*等待连接结果*/
static int WaitConnectResult(void)
{
    int ConnectTimeout = DEF_TIMEOUT;
    while (ConnectTimeout > 0)
    {
        sleep(1);
        ConnectTimeout--;
        if (g_ConnectSuccess == 1)
        {
            LOG_I("WaitConnectResult:wait success[%d]s\n", (DEF_TIMEOUT - ConnectTimeout));
            break;
        }
    }
    if (ConnectTimeout <= 0)
    {
        LOG_I("WaitConnectResult:timeout!\n");
        return 0;
    }

    return 1;
}

/*WIFI初始化*/
static void WiFiInit(void)
{
    LOG_I("<--Wifi Init-->\r\n");
    g_wifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChangedHandler;  //扫描状态改变,扫描到了AP
    g_wifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChangedHandler;    //WIFI连接状态改变回调

    error = RegisterWifiEvent(&g_wifiEventHandler); //注册事件
    if (error != WIFI_SUCCESS)
    {
        LOG_I("register wifi event fail!\r\n");
    }
    else
    {
        LOG_I("register wifi event succeed!\r\n");
    }
}

/*STA任务*/
static BOOL WifiSTATask(void)
{
    WifiScanInfo *info = NULL;
    unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;
    static struct netif *g_lwip_netif = NULL;
    WifiDeviceConfig select_ap_config = {0};

    osDelay(200);
    LOG_I("<--System Init-->\r\n");

    //初始化WIFI
    WiFiInit();

    //使能WIFI
    if (EnableWifi() != WIFI_SUCCESS)
    {
        LOG_E("EnableWifi failed, error = %d\n", error);
        return -1;
    }

    //判断WIFI是否激活
    if (IsWifiActive() == 0)
    {
        LOG_E("Wifi station is not actived.\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列表
    LOG_I("********************\r\n");
    for(uint8_t i = 0; i < ssid_count; i++)
    {
        LOG_I("no:%.3d, ssid:%-30s, rssi:%5d, freq:%d\r\n", i+1, info[i].ssid, info[i].rssi/100,info[i].frequency);
    }
    LOG_I("********************\r\n");

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

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

            //拷贝要连接的热点信息
            strcpy(select_ap_config.ssid, info[i].ssid);
            strcpy(select_ap_config.preSharedKey, SELECT_WIFI_PASSWORD);
            select_ap_config.securityType = SELECT_WIFI_SECURITYTYPE;   //加密类型

            if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS)    //添加连接对象
            {
                if (ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1)  //开始连接
                {
                    LOG_I("WiFi connect succeed!\r\n");
                    g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);   //获取网络接口
                    break;
                }
            }
        }

        if(i == ssid_count-1)
        {
            LOG_I("ERROR: No wifi as expected\r\n");
            while(1) osDelay(100);
        }
    }

    //启动DHCP
    if (g_lwip_netif)
    {
        dhcp_start(g_lwip_netif);
        LOG_I("begain to dhcp\r\n");
    }


    //等待DHCP
    for(;;)
    {
        if(dhcp_is_bound(g_lwip_netif) == ERR_OK)
        {
            LOG_I("<-- DHCP state:OK -->\r\n");

            //打印获取到的IP信息
            netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
            break;
        }

        LOG_I("<-- DHCP state:Inprogress -->\r\n");
        osDelay(100);
    }

    //执行其他操作
    for(;;)
    {
        osDelay(100);
    }

}

/*STA任务初始化*/
void drv_sta_task_init(void)
{
    osThreadAttr_t attr;

    attr.name = "WifiSTATask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 24;

    if (osThreadNew((osThreadFunc_t)WifiSTATask, NULL, &attr) == NULL)
    {
        LOG_I("Falied to create WifiSTATask!\n");
    }
}

        看结果: 

         可以看到,扫描结束后,触发了OnWifiScanStateChanged回调。STA连接上AP之后,触发了OnWifiConnectionChanged回调。且在回调中都打印了链接相关信息。

        dhcp_clients_info_show会把serverclient的相关信息都打印出来。包括MAC和IP地址等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/541230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高性能零售IT系统的建设10-一个系统日志记录搞崩了整个公司的O2O交易系统

背景 绝大多数业务系统其实都是一座屎山&#xff0c;本人接手的这座屎山目前已经成了一座金山。这其中的幸酸只有那些从0参与过并活到现在的一些“老人”们心中自知其中的滋味。 在3年半前&#xff0c;本以为买来的一套将近600万行代码、达800张表、几乎用到了所有的互联网中间…

分布式系统:高并发

目录 1.什么是高并发 2.术语 3.如何应对处理高并发 3.1.提升系统的并发能力 3.3.1.垂直扩展 3.3.2.水平扩展 3.2.流量控制 4.削峰 4.1.怎样来实现流量削峰方案 4.2.限流 5.总结 1.什么是高并发 高并发是指系统在同一时间内处理大量请求的能力。在软件开发中&a…

CRM管理系统在线用

一、CRM管理系统是什么 CRM是客户关系管理的缩写&#xff0c;是指企业通过建立客户档案、跟进客户需求、提供优质服务来维系客户关系的一种管理模式。是企业以客户关系为重点&#xff0c;通过开展系统化的客户研究&#xff0c;优化企业组织体系和业务流程&#xff0c;提高客户…

Jina AI全新Inference服务,LangChain开发体验从未如此丝滑

由于 Token 的限制&#xff0c;在开发 LangChain 问答机器人应用时&#xff0c;我们经常需要将文档切割&#xff0c;接着使用 Embedding 引擎 分别将分割后的 Document 变成 Embeddings&#xff0c;即向量表示。 同时输入的问题&#xff0c;也需要用到 Embedding 引擎 变成向量…

linux调试知识:手把手教你SSH怎么链接

在机器装机后&#xff0c;如果没有显示&#xff0c;有没有串口&#xff0c;通常很难区操作调试&#xff0c;本文总结一篇通过搭建SSH链接去为调试做服务&#xff1a; 首先第一步&#xff1a;安装必要的软件&#xff0c;CRT或者XSHELL。 下面将举实际案例&#xff0c;手把手搭…

Axure rp9 引入Echarts图表 |手动引入图表 Apache Echarts

Axure rp9 引入Echarts图表 |手动引入图表 Apache Echarts 1.拖入一个矩形lable&#xff0c;调整合适大小,并命名为test 2.给test新建交互载入时&#xff0c;打开链接&#xff0c;并将下方code贴入 如果想在无网的情况下运行&#xff0c;需要在axure软件的安装目录DefaultSet…

深度学习笔记之递归网络(三)递归神经网络

深度学习笔记之递归网络——递归神经网络 引言回顾&#xff1a;潜变量自回归模型递归神经网络思想困惑度 引言 上一节介绍了基于统计算法的语言模型。本节将介绍基于神经网络的序列模型——递归神经网络。 回顾&#xff1a;潜变量自回归模型 关于潜变量自回归模型&#xff0…

记一次 Visual Studio 2022 卡死分析

一&#xff1a;背景 1. 讲故事 最近不知道咋了&#xff0c;各种程序有问题都寻上我了&#xff0c;你说 .NET 程序有问题找我能理解&#xff0c;Windows 崩溃找我&#xff0c;我也可以试试看&#xff0c;毕竟对 Windows 内核也知道一丢丢&#xff0c;那 Visual Studio 有问题找…

揭秘市场热销的4款问卷调查工具

当谈到进行在线问卷调查时&#xff0c;选择正确的工具可以使调查过程完全不同。市场上有这么多可供选择的产品&#xff0c;要找到一款符合我们需求的工具不是一件容易的事儿。在本文中&#xff0c;小编将和大家一起讨论4款市面上好用的问卷调查工具盘点&#xff0c;并比较它们的…

基于C语言设计一个叫号系统

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 这道题的重点在于怎么处理患者的治疗过程。大二上学期的理论课上&#xff0c;我们在第一节的研讨课上对于这道题的实现进行了探讨。本题的患者排队与数据结构中的队列结构完全符合&#xff0c;当患者挂号后&#xff0c;检查该…

语音工牌:从线下沟通过程入手,实现运营商上门安装流程监管

近年来&#xff0c;随着网络的飞速发展&#xff0c;宽带越来越成为人们生活中必不可少的一部分&#xff0c;相应的&#xff0c;宽带上门安装、迁机及检修服务也成为运营商业务场景里重要的一环。 随着业务需求的增加和上门服务工程师队伍的壮大&#xff0c;以及消费者对服务质…

印度也开始自研 CPU ,5nm工艺、功耗是i9好几倍

前两天的新闻估计大家都看了&#xff0c;国内又一个科技巨头公司终止「造芯」。 OPPO 子公司哲库从成立到解散用了4年时间&#xff0c;这期间做出的马里亚纳X影像芯片也小有名气。 显然其目标不只是影像这一点&#xff0c;今年年初就有消息称 OPPO 自研 Soc 已经快到流片&…

Go语言中sync.Cond、atomic原子性和sync.Once的用法

目录 【sync.Cond】 【atomic原子性】 【sync.Once】 使用sync.Once实现单例模式 在 上一篇文章 中分析了Go语言sync 包中 sync.Mutex、sync.RWMutex和sync.WaitGroup的用法&#xff0c;这篇文章继续来讨论下sync包中关于 sync.Cond 、atomic原子性 和 sync.Once 的用法。…

23 KVM管理虚拟机-使用VNC密码登录虚拟机

文章目录 23 KVM管理虚拟机-使用VNC密码登录虚拟机23.1 概述23.2 前提条件23.3 操作步骤 23 KVM管理虚拟机-使用VNC密码登录虚拟机 本章介绍使用VNC密码登录虚拟机的方法。 23.1 概述 当虚拟机操作系统安装部署完成之后&#xff0c;用户可以通过VNC协议远程登录虚拟机&#…

【数据分享】2014-2023年全国监测站点的逐月空气质量数据(15个指标\shp\excel格式)

空气质量的好坏反映了空气的污染程度&#xff0c;在各项涉及城市环境的研究中&#xff0c;空气质量都是一个十分重要的指标。空气质量是依据空气中污染物浓度的高低来判断的。 我们发现学者王晓磊在自己的主页里面分享了2014年5月以来的全国范围的到站点的逐时空气质量数据&am…

2023年5月18日,ChatGPT还是能接收到验证码完成注册

前言 从昨天开始&#xff0c;有不少网友加我微信&#xff0c;问的基本都是同一个问题&#xff0c;应该注册ChatGPT账号的时候&#xff0c;应该都收到了如下的报错内容&#xff0c;主要是ChatGPT开始检测滥用问题了。 问题 一&#xff1a;The carrier associated with this p…

nodejs简易的token更新模型

1. 什么是JWT JWT全称为(JSON WEB TOKEN)&#xff0c;是目前流行做登录认证的工具之一&#xff0c;它是一个非常轻巧的规范 2.库安装 npm install jsonwebtoken github地址: jsonwebtoken 3.更新策略1 假设一个token的有效时间为T&#xff1b; 当超过T小时没有请求过接口则失…

docker 安装mongo数据库

1.pull镜像 docker pull mongo:4 2.创建目录 mkdir -p /mongodb/datadb chmod 777 /mongodb/datadb 3.运行 准备好目录之后&#xff0c; 就可以开始运行 Docker 镜像了&#xff1a; docker run -d --name mongodb -v /mongodb/datadb:/data/db -p 27017:27017 -e MONGO_INITDB…

【Axure教程】轮盘滑动控制元件移动

轮盘控制元件移动是一种通过轮盘来控制元件位置或参数的方式。轮盘通常是一个圆形或半圆形的旋转控制器&#xff0c;用户可以通过旋转轮盘来实现元件的移动。轮盘滑动控制元件移动广泛应用于各种设备和系统中&#xff0c;例如移动端操作内的游戏&#xff0c;通过旋转轮盘&#…

神经网络:Zero2Hero 3 - Gradient calculation

Zero2Hero 4 - Gradient 创建一个Value类&#xff0c;属性包含变量的值和梯度信息&#xff0c;并支持梯度计算。举例说明梯度反向计算过程。基于Value类构建MLP模型、并实现参数的更新。 import numpy as np import matplotlib.pyplot as plt %matplotlib inlineValue类 支持…