RT-Thread 软件包-软件包分类-IoT-AT device①

发布时间:2023年12月27日

RT-Thread 软件包-软件包分类-IoT-AT device①

在这里插入图片描述

# AT device #

中文页 | 英文页

1. 简介

AT device 软件包是由 RT-Thread AT 组件针对不同 AT 设备的移植文件和示例代码组成,目前支持的 AT 设备有:ESP8266、ESP32、M26、MC20、RW007、MW31、SIM800C、W60X 、SIM76XX、A9/A9G、BC26 、AIR720、ME3616、M6315、BC28、EC200X、M5311、L610系列设备等,目前上述设备都完成对 AT socket 功能的移植,及设备通过 AT 命令实现标准 socket 编程接口,完成 socket 通讯的功能,具体功能介绍可参考 《RT-Thread 编程指南》AT 命令章节 。

1.1. 目录结构

名称说明
srcAT device 实现源码目录
incAT device 头文件目录
sample不同设备示例文件目录
class不同设备针对 AT 组件的移植适配目录
class/esp8266ESP8266 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/esp32ESP32 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/rw007RW007 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/sim800cSIM800C 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/sim76xxSIM76XX 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/m26M26/MC20 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/ec20EC20 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/mw31MW31 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/w60xW60X 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/a9gA9G 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/bc26bc26 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/air720air720 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/me3616me3616 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/m6315m6315 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/bc28bc28 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/ec200xEC200T、EC200S 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/n21N21 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/n58N58 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/m5311M5311 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/l610L610 设备针对 AT 组件的移植目录,实现 AT Socket 功能
class/ml305ML305 设备针对 AT 组件的移植目录,实现 AT Socket 功能

1.2 许可证

详见 LICENSE 文件。

1.3 依赖

  • RT_Thread 4.0.2+
  • RT_Thread AT 组件 1.3.0+
  • RT_Thread SAL 组件
  • RT-Thread netdev 组件

2. 获取方式

AT device 软件包是对 AT 组件和 AT socket 功能的移植,需开启 AT 组件库和 AT socket 功能来获取 AT device 软件包。

版本号说明

AT device 软件包目前已经发布多个版本,各个版本之间选项配置方式和其对应的系统版本有所不同,下面主要列出当前可使用的软件包版本信息:

  • V1.2.0:适用于 RT-Thread 版本小于 V3.1.3,AT 组件版本等于 V1.0.0;
  • V1.3.0:适用于 RT-Thread 版本小于 V3.1.3,AT 组件版本等于 V1.1.0;
  • V1.4.0:适用于 RT-Thread 版本小于 V3.1.3或等于 V4.0.0, AT 组件版本等于 V1.2.0;
  • V1.5.0:适用于 RT-Thread 版本小于 V3.1.3 或等于 V4.0.0, AT 组件版本等于 V1.2.0;
  • V1.6.0:适用于 RT-Thread 版本等于 V3.1.3 或等于 V4.0.1, AT 组件版本等于 V1.2.0;
  • V2.0.0/V2.0.1:适用于 RT-Thread 版本大于 V4.0.1 或者大于 3.1.3, AT 组件版本等于 V1.3.0;
  • latest:只适用于 RT-Thread 版本大于 V4.0.1 或者大于 3.1.3, AT 组件版本等于 V1.3.0;

上述 版本判断在 menuconfig 中自动完成,at_device 软件包选择版本时会根据当前系统环境给出最佳版本支持,这里版本介绍作为运行环境参考。

针对不同的版本号,在 ENV 中的选项配置也有所不同,主要分为如下几部分:

V1.X.X 版本配置选项介绍

开启 AT device 软件包,该版本只支持同时开启一种 AT 设备, 配置选项具体如下所示:

RT-Thread online packages  --->
     IoT - internet of things  --->
        -*- AT DEVICE: RT-Thread AT component porting or samples for different device  
        [ ]   Enable at device init by thread
              AT socket device modules (Not selected, please select)  --->    
              Version (V1.6.0)  --->
  • Enable at device init by thread: 配置开启设备网络初始化是否通过创建线程完成;
  • AT socket device modules: AT 设备选择,目前仅支持 RW007、ESP8266、M26/MC20、EC20、SIM800C、SIM76XX;更多的设备支持请选择 V2.X.X 分支。
  • Version: 下载软件包版本;

V2.X.X (latest) 版本配置选项介绍

开启 AT device 软件包,该版本支持同时开启多种 AT 设备配置选项具体如下所示:

RT-Thread online packages  --->
     IoT - internet of things  --->
        -*- AT DEVICE: RT-Thread AT component porting or samples for different device
        [*]   Quectel M26/MC20  --->
          [*]   Enable initialize by thread
          [*]   Enable sample
          (-1)    Power pin
          (-1)    Power status pin
          (uart3) AT client device name
          (512)   The maximum length of receive line buffer
        [ ]   Quectel EC20  --->
        [ ]   Espressif ESP32  --->
        [*]   Espressif ESP8266  --->
          [*]   Enable initialize by thread
          [*]   Enable sample
          (realthread) WIFI ssid
          (12345678) WIFI password
          (uart2) AT client device name
          (512)   The maximum length of receive line buffer
        [ ]   Realthread RW007  --->
        [ ]   SIMCom SIM800C  --->
        [ ]   SIMCom SIM76XX  --->
        [ ]   Notion MW31  --->
        [ ]   WinnerMicro W60X  --->
        [ ]   AiThink A9/A9G  --->
        [ ]   Quectel BC26  --->
        [ ]   Luat air720  --->
        [ ]   GOSUNCN ME3616  --->
        [ ]   ChinaMobile M6315  --->
        [ ]   Quectel BC28  --->
        [ ]   Quectel ec200x  --->
        [ ]   Neoway N21  --->
        [ ]   Neoway N58  --->
        [ ]   ChinaMobile M5311  --->
        [ ]   ChinaMobile ML305  --->
        Version (latest)  --->
  • Quectel M26/MC20:开启 M20/MC20(2G 模块)设备支持;
    • Enable initialize by thread:开启使用线程进行设备初始化功能(非阻塞模式初始化);
    • Enable sample:开启示例代码,该示例代码中有对示例设备的注册;
    • Power pin:配置该示例设备上电引脚;
    • Power status pin:配置该示例设备上电状态引脚;
    • AT client device name:配置该示例设备使用的串口设备名称;
    • The maximum length of receive line buffer:配置该示例设备最大一行接收的数据长度;
  • Quectel EC20:开启 EC20(4G 模块)设备支持;
  • Espressif ESP8266:开启 ESP8266 (WIFI 模块)设备支持;
    • Enable initialize by thread:开启使用线程进行设备初始化功能(非阻塞模式初始化);
    • Enable sample:开启示例代码,该示例代码中有对示例设备的注册;
    • WIFI ssid:配置该示例设备连接的 WIFI 用户名;
    • WIFI password:配置该示例设备连接的 WIFI 密码;
    • AT client device name:配置该示例设备使用的串口设备名称;
    • The maximum length of receive line buffer:配置该示例设备最大一行接收的数据长度;
  • Espressif ESP32:开启 ESP32 (WIFI 模块)设备支持;
  • Realthread RW007:开启 RW007 (WIFI 模块)设备支持;
  • SIMCom SIM800C:开启 SIM800C (2G 模块)设备支持;
  • SIMCom SIM76XX:开启 SIM76XX (4G 模块)设备支持;
  • Notion MW31:开启 MW31 (WIFI 模块)设备支持;
  • WinnerMicro W60X:开启 W60X (WIFI 模块)设备支持;
  • AiThink A9/A9G:开启 A9/A9G (2G 模块)设备支持;
  • Quectel BC26:开启 BC26(NB-IOT 模块)设备支持;
  • Luat Air720:开启 air720(4g 模块)设备支持;
  • GOSUNCN ME3616:开启 ME3616(NB-IOT 模块)设备支持;
  • ChinaMobile M6315:开启 M6315 (2G 模块)设备支持;
  • Quectel BC28:开启 BC28(NB-IoT 模块)设备支持;
  • Quectel EC200X:开启 EC200T、EC200S(4G 模块)设备支持;
  • Neoway N21:开启 N21(NB-IoT 模块)设备支持;
  • Neoway N58:开启 N58(4G 模块)设备支持;
  • ChinaMobile M5311:开启 M5311(NB-IoT 模块)设备支持;
  • ChinaMobile ML305:开启 ML305(4G 模块)设备支持;
  • Version 下载软件包版本;

上面配置选项以 2G 模块和 WIFI 模块选项为例,介绍了V2.X.X 版本 AT device 软件包配置方式,如下几点值得注意:

  • V2.X.X 版本支持同时开启多个 AT 设备,可以在 FinSH 中通过 ifocnfig 命令查看开启的设备信息;
  • V2.X.X 版本设备需要注册之后才可使用,目前在 samples 目录文件中完成设备注册,用户也可以在应用层自定义设备注册。
  • Power pinPower status pin 等引脚选项根据具体设备硬件连接情况配置,如果不使用硬件上电功能,可以配置为 -1
  • 一个 AT 设备对应一个串口名称,及每个设备配置的AT client device name 应该都不相同。

AT 组件相关配置选项介绍

选中 AT device 软件包并开启相关设备支持之后,会默认选中 AT 组件的客户端功能,下面是 AT 组件配置选项,

RT-Thread Components  --->
    Network  --->
        AT commands  --->
    [ ]   Enable debug log output
    [ ]   Enable AT commands server 
    -*-   Enable AT commands client
    (1)     The maximum number of supported clients
    -*-     Enable BSD Socket API support by AT commnads
    [*]     Enable CLI(Command-Line Interface) for AT commands
    [ ]     Enable print RAW format AT command communication data
    (128)   The maximum lenght of AT Commonds buffe

其中和 AT device 软件包相关的配置选项:

  • The maximum number of supported clients:最大支持的同时开启的 AT 客户端数量(AT device 软件包中选中多个设备需要配置该选项为对应数值);
  • Enable BSD Socket API support by AT commnads:开启 AT Socket 功能支持,选中 AT device 软件包默认选中该选项;
  • The maximum lenght of AT Commonds buffe:最大支持的发送命令数据的长度。

3. 注意事项

  • AT device 软件包适配的模块暂时不支持作为 TCP Server 完成服务器相关操作(如 accept 等);
  • AT device 软件包默认设备类型为未选择,使用时需要指定使用设备型号;
  • latest 版本支持多个选中多个 AT 设备接入实现 AT Socket 功能,V1.X.X 版本只支持单个 AT 设备接入。
  • AT device 软件包目前多个版本主要用于适配 AT 组件和系统的改动,推荐使用最新版本 RT-Thread 系统,并在 menuconfig 选项中选择 latest 版本;
  • 请参考 at_sample_xxx.c 中说明,部分功能需要增加AT_CMD_MAX_LENRT_SERIAL_RB_BUFSZ设定值大小。

4. 相关文档

示例代码

…\src\at_device.c

/*
 * Copyright (c) 2006-2023, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2019-05-08     chenyong     first version
 */

#include <stdlib.h>
#include <string.h>

#include <at_device.h>

#define DBG_TAG              "at.dev"
#define DBG_LVL              DBG_INFO
#include <rtdbg.h>

/* The global list of at device */
static rt_slist_t at_device_list = RT_SLIST_OBJECT_INIT(at_device_list);
/* The global list of at device class */
static rt_slist_t at_device_class_list = RT_SLIST_OBJECT_INIT(at_device_class_list);

/**
 * This function will get the first initialized AT device.
 *
 * @return the AT device structure pointer
 */
struct at_device *at_device_get_first_initialized(void)
{
    rt_base_t level;
    rt_slist_t *node = RT_NULL;
    struct at_device *device = RT_NULL;

    level = rt_hw_interrupt_disable();

    rt_slist_for_each(node, &at_device_list)
    {
        device = rt_slist_entry(node, struct at_device, list);
        if (device && device->is_init == RT_TRUE)
        {
           rt_hw_interrupt_enable(level);
           return device;
        }
    }

    rt_hw_interrupt_enable(level);

    return RT_NULL;
}

/**
 * This function will get AT device by device name.
 *
 * @param type the name type
 * @param name the device name or the client name
 *
 * @return the AT device structure pointer
 */
struct at_device *at_device_get_by_name(int type, const char *name)
{
    rt_base_t level;
    rt_slist_t *node = RT_NULL;
    struct at_device *device = RT_NULL;

    RT_ASSERT(name);

    level = rt_hw_interrupt_disable();

    rt_slist_for_each(node, &at_device_list)
    {
        device = rt_slist_entry(node, struct at_device, list);
        if (device)
        {
            if (((type == AT_DEVICE_NAMETYPE_DEVICE) || (type == AT_DEVICE_NAMETYPE_NETDEV)) &&
                (rt_strncmp(device->name, name, rt_strlen(name)) == 0))
            {
                rt_hw_interrupt_enable(level);
                return device;
            }
            else if ((type == AT_DEVICE_NAMETYPE_CLIENT) &&
                (rt_strncmp(device->client->device->parent.name, name, rt_strlen(name)) == 0))
            {
                rt_hw_interrupt_enable(level);
                return device;
            }
        }
    }

    rt_hw_interrupt_enable(level);

    return RT_NULL;
}

#ifdef AT_USING_SOCKET
/**
 * This function will get AT device by ip address.
 *
 * @param ip_addr input ip address
 * network
 * @return != NULL: network interface device object
 *            NULL: get failed
 */
struct at_device *at_device_get_by_ipaddr(ip_addr_t *ip_addr)
{
    rt_base_t level;
    rt_slist_t *node = RT_NULL;
    struct at_device *device = RT_NULL;

    level = rt_hw_interrupt_disable();

    rt_slist_for_each(node, &at_device_list)
    {
        device = rt_slist_entry(node, struct at_device, list);
        if (device && ip_addr_cmp(ip_addr, &(device->netdev->ip_addr)))
        {
           rt_hw_interrupt_enable(level);
           return device;
        }
    }

    rt_hw_interrupt_enable(level);

    return RT_NULL;

}
#endif /* AT_USING_SOCKET */


/**
 * This function will perform a variety of control functions on AT devices.
 *
 * @param device the pointer of AT device structure
 * @param cmd the command sent to AT device
 * @param arg the argument of command
 *
 * @return = 0: perform successfully
 *         < 0: perform failed
 */
int at_device_control(struct at_device *device, int cmd, void *arg)
{
    if (device->class->device_ops->control)
    {
        return device->class->device_ops->control(device, cmd, arg);
    }
    else
    {
        LOG_W("AT device(%s) not support control operations.", device->name);
        return RT_EOK;
    }
}

/**
 * This function registers an AT device class with specified device class ID.
 *
 * @param class the pointer of AT device class structure
 * @param class_id AT device class ID
 *
 * @return 0: register successfully
 */
int at_device_class_register(struct at_device_class *class, uint16_t class_id)
{
    rt_base_t level;

    RT_ASSERT(class);

    /* Fill AT device class */
    class->class_id = class_id;

    /* Initialize current AT device class single list */
    rt_slist_init(&(class->list));

    level = rt_hw_interrupt_disable();

    /* Add current AT device class to list */
    rt_slist_append(&at_device_class_list, &(class->list));

    rt_hw_interrupt_enable(level);

    return RT_EOK;
}

/* Get AT device class by client ID */
static struct at_device_class *at_device_class_get(uint16_t class_id)
{
    rt_base_t level;
    rt_slist_t *node = RT_NULL;
    struct at_device_class *class = RT_NULL;

    level = rt_hw_interrupt_disable();

    /* Get AT device class by class ID */
    rt_slist_for_each(node, &at_device_class_list)
    {
        class = rt_slist_entry(node, struct at_device_class, list);
        if (class && class->class_id == class_id)
        {
            rt_hw_interrupt_enable(level);
            return class;
        }
    }

    rt_hw_interrupt_enable(level);

    return RT_NULL;
}

/**
 * This function registers an AT device with specified device name and AT client name.
 *
 * @param device the pointer of AT device structure
 * @param device_name AT device name
 * @param at_client_name AT device client name
 * @param class_id AT device class ID
 * @param user_data user-specific data
 *
 * @return = 0: register successfully
 *         < 0: register failed
 */
int at_device_register(struct at_device *device, const char *device_name,
                        const char *at_client_name, uint16_t class_id, void *user_data)
{
    rt_base_t level;
    int result = 0;
    static int device_counts = 0;
    char name[RT_NAME_MAX] = {0};
    struct at_device_class *class = RT_NULL;

    RT_ASSERT(device);
    RT_ASSERT(device_name);
    RT_ASSERT(at_client_name);

    class = at_device_class_get(class_id);
    if (class == RT_NULL)
    {
        LOG_E("get AT device class(%d) failed.", class_id);
        result = -RT_ERROR;
        goto __exit;
    }

    /* Fill AT device object*/
#ifdef AT_USING_SOCKET
    device->sockets = (struct at_socket *) rt_calloc(class->socket_num, sizeof(struct at_socket));
    if (device->sockets == RT_NULL)
    {
        LOG_E("no memory for AT Socket number(%d) create.", class->socket_num);
        result = -RT_ENOMEM;
        goto __exit;
    }

    /* create AT device socket event */
    rt_snprintf(name, RT_NAME_MAX, "at_se%d", device_counts++);
    device->socket_event = rt_event_create(name, RT_IPC_FLAG_FIFO);
    if (device->socket_event == RT_NULL)
    {
        LOG_E("no memory for AT device(%s) socket event create.", device_name);
        result = -RT_ENOMEM;
        goto __exit;
    }
#endif /* AT_USING_SOCKET */

    rt_memcpy(device->name, device_name, rt_strlen(device_name));
    device->class = class;
    device->user_data = user_data;

    /* Initialize current AT device single list */
    rt_slist_init(&(device->list));

    level = rt_hw_interrupt_disable();

    /* Add current AT device to device list */
    rt_slist_append(&at_device_list, &(device->list));

    rt_hw_interrupt_enable(level);

    /* Initialize AT device */
    result = class->device_ops->init(device);
    if (result < 0)
    {
        goto __exit;
    }

__exit:
    if (result < 0)
    {
        device->is_init = RT_FALSE;
    }
    else
    {
        device->is_init = RT_TRUE;
    }

    return result;
}


维护人:

文章来源:https://blog.csdn.net/kingpower2018/article/details/135183917
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。