BLE_TYQ_BJQ_CH32V303/bsp/src/at_device_ml307.c

1750 lines
52 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author : stark1898y 1658608470@qq.com
* @Date : 2024-09-04 13:33:49
* @LastEditors: mbw && 1600520629@qq.com
* @LastEditTime: 2024-12-05 16:31:00
* @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\at_device_ml307.c
* @Description :
*
* Copyright (c) 2024 by yzy, All Rights Reserved.
*/
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-12-13 qiyongzhong first version
*/
#include <stdio.h>
#include <string.h>
#include "bsp_flash.h"
#include <at_device_ml307.h>
#include "bsp_ml307.h"
#include "user_sys.h"
#include "bsp_rtc.h"
#include "bsp_led.h"
#define LOG_TAG "at.dev.ml307"
#include <at_log.h>
#include "pin.h"
#if IOT_MODULE_SWITCH == 1
#define ML307_POWER_OFF RT_FALSE
#define ML307_POWER_ON RT_TRUE
#define ML307_POWER_ON_TIME 3
#define ML307_POWER_OFF_TIME 4
#define AT_CLIENT_RECV_BUFF_LEN 512
#define AT_DEFAULT_TIMEOUT 1000
#ifdef AT_DEVICE_USING_ML307
#define ML307_WAIT_CONNECT_TIME 5000
#define ML307_THREAD_STACK_SIZE (4096)
#define ML307_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 2)
ml307_sys_info ml307 = {0};
struct rt_completion ml307_init_complate;
volatile rt_uint8_t socket_id = 0;
static rt_bool_t ml307_get_power_state(struct at_device *device)
{
struct at_device_ml307 *ml307 = RT_NULL;
ml307 = (struct at_device_ml307 *)device->user_data;
return (!rt_pin_read(ml307->power_status_pin)) ? ML307_POWER_ON : ML307_POWER_OFF;
}
static rt_err_t ml307_power_on(struct at_device *device)
{
struct at_device_ml307 *ml307 = RT_NULL;
ml307 = (struct at_device_ml307 *)device->user_data;
/* not nead to set pin configuration for ml307 device power on */
if (ml307->power_pin == -1 || ml307->power_status_pin == -1)
{
return -1;
}
if (ml307_get_power_state(device) == ML307_POWER_ON)
{
return RT_EOK;
}
rt_pin_write(ml307->power_pin, PIN_HIGH);
rt_thread_mdelay(ML307_POWER_ON_TIME * RT_TICK_PER_SECOND);
rt_pin_write(ml307->power_pin, PIN_LOW);
return RT_EOK;
}
static rt_err_t ml307_power_off(struct at_device *device)
{
struct at_device_ml307 *ml307 = RT_NULL;
ml307 = (struct at_device_ml307 *)device->user_data;
rt_pin_write(ml307->power_pin, PIN_HIGH);
rt_thread_mdelay(ML307_POWER_OFF_TIME * RT_TICK_PER_SECOND);
rt_pin_write(ml307->power_pin, PIN_LOW);
rt_thread_mdelay(100);
return RT_EOK;
}
rt_err_t Ml307_Reset(struct at_device *device)
{
at_client_send("AT+MREBOOT\r\n", rt_strlen("AT+MREBOOT\r\n"));
// struct at_device_ml307 *ml307 = RT_NULL;
// ml307 = (struct at_device_ml307 *) device->user_data;
// do{
/* not nead to set pin configuration for ml307 device power on */
// if (ml307->power_status_pin == -1 || ml307->rst_pin == -1)
// {
// return;
// }
// if(ml307_get_power_state(device) == ML307_POWER_OFF)
// {
// return;
// }
// rt_pin_write(ml307->rst_pin, PIN_HIGH);
// rt_thread_mdelay(RT_TICK_PER_SECOND/2);
// rt_pin_write(ml307->rst_pin, PIN_LOW);
// rt_thread_mdelay(100);
// }while(ml307_get_power_state(device) != ML307_POWER_OFF);
return RT_EOK;
}
#ifdef TEST_ENABLE
void TEST_Ml307_Reset()
{
Ml307_Reset(RT_NULL);
}
MSH_CMD_EXPORT(TEST_Ml307_Reset, "test_ml307_reset");
#endif
#if 0
static int ml307_sleep(struct at_device *device)
{
at_response_t resp = RT_NULL;
struct at_device_ml307 *ml307 = RT_NULL;
ml307 = (struct at_device_ml307 *)device->user_data;
if (!ml307->power_status) // power off
{
return (RT_EOK);
}
if (ml307->sleep_status) // is sleep status
{
return (RT_EOK);
}
resp = at_create_resp(64, 0, rt_tick_from_millisecond(300));
if (resp == RT_NULL)
{
LOG_D("no memory for resp create.");
at_delete_resp(resp);
return (-RT_ERROR);
}
/* enable sleep mode */
// Sleep 轻度睡眠
if (at_obj_exec_cmd(device->client, resp, "AAT+MLPMCFG=\"sleepmode\",1,1") != RT_EOK)
{
LOG_D("enable sleep set.\"AT+MLPMCFG=\"sleepmode\",1,1\" execute fail.");
at_delete_resp(resp);
return (-RT_ERROR);
}
/* enable PSM mode */
if (at_obj_exec_cmd(device->client, resp, "AT+MLPMCFG=\"psind\",1") != RT_EOK)//启用配置协议栈低功耗状态是否上报URC)
{
LOG_D("enable sleep URC.\"AAT+MLPMCFG=\"psind\",1\" execute fail.");
at_delete_resp(resp);
return (-RT_ERROR);
}
ml307->sleep_status = RT_TRUE;
at_delete_resp(resp);
return (RT_EOK);
}
#endif
#if 0
static int ml307_wakeup(struct at_device *device)
{
at_response_t resp = RT_NULL;
struct at_device_ml307 *ml307 = RT_NULL;
ml307 = (struct at_device_ml307 *)device->user_data;
if (!ml307->power_status) // power off
{
LOG_E("the power is off and the wake-up cannot be performed");
return (-RT_ERROR);
}
if (!ml307->sleep_status) // no sleep status
{
return (RT_EOK);
}
resp = at_create_resp(64, 0, rt_tick_from_millisecond(300));
if (resp == RT_NULL)
{
LOG_D("no memory for resp create.");
at_delete_resp(resp);
return (-RT_ERROR);
}
if (ml307->wkp_pin != -1)
{
rt_pin_write(ml307->wkp_pin, PIN_LOW);
rt_thread_mdelay(100);
rt_pin_write(ml307->wkp_pin, PIN_HIGH);
rt_thread_mdelay(100);
rt_pin_write(ml307->wkp_pin, PIN_LOW);
}
/* disable sleep mode */
if (at_obj_exec_cmd(device->client, resp, "AT+MLPMCFG=\"sleepmode\",0,1") != RT_EOK)
{
LOG_D("wake up fail. \"AT+MLPMCFG=\"sleepmode\",0,1\" execute fail.");
at_delete_resp(resp);
return (-RT_ERROR);
}
ml307->sleep_status = RT_FALSE;
at_delete_resp(resp);
return (RT_EOK);
}
#endif
static void urc_tcp_recv(struct at_client *client, const char *data, rt_size_t size)
{
int id;
int len = 0;
rt_uint16_t crc16 = 0;
rt_uint16_t rec_crc16 = 0;
char crc16_buf[6] = {0};
char data_buf[AT_CLIENT_RECV_BUFF_LEN] = {0};
rt_uint8_t recv_byte_buf[AT_CLIENT_RECV_BUFF_LEN] = {0};
rt_memset(data_buf, 0, sizeof(data_buf));
LOG_D("ml307 recv data: %s", data);
/*+MIPURC: "rtcp",<connect_id>,<recv_length>,<data>*/
if (sscanf(data, "+MIPURC: \"rtcp\",%d,%d,%s\r\n", &id, &len, data_buf) == 3)
{
if (id == socket_id)
{
HexStrToBytes(data_buf, recv_byte_buf, len * 2);
LOG_D("ml307 recv data: %s", data_buf);
crc16 = crc1021(data_buf, len * 2 - 10); // 去掉帧尾三个字节和2个字节的校验值字符长度为10
rt_strncpy(crc16_buf, data_buf + len * 2 - 10, 4);
LOG_D("ml307 crc16: %04s", crc16_buf);
rec_crc16 = strtol(crc16_buf, NULL, 16);
if (crc16 != rec_crc16) // 看下数据接收的是否正确
{
LOG_E("ml307 recv data error {crc16 [%x]!= rec_crc16[%x]}", crc16, rec_crc16);
}
else
{
/*比较数组的长度和结构体的长度是否一致,如果不一致则数据解析错误,如果一致复制数组值到结构体中*/
if (len == sizeof(struct Ml307RecvData))
{
rt_memset(ml307_ops.recv, 0, sizeof(struct Ml307RecvData)); // 清空结构体
rt_memcpy(ml307_ops.recv, recv_byte_buf, sizeof(struct Ml307RecvData));
rt_sem_release(ml307_recv_sem);
}
else
{
LOG_E("ml307 recv data error {len [%d]!= sizeof(struct Ml307RecvData)[%d]}", len, sizeof(struct Ml307RecvData));
}
}
}
}
}
static void urc_device_reset(struct at_client *client, const char *data, rt_size_t size)
{
LOG_D("device reset");
ml307_conncet_tcp_flag = 0;
if (SysControl.status == kNormalDetectionEvents)
{
LED_G_NORMAL;
}
}
static void urc_tcp_connect_state(struct at_client *client, const char *data, rt_size_t size)
{
size_t err_code = 0, id;
if (sscanf(data, "+MIPOPEN:%d,%d", &id, &err_code) == 2)
{
if ((id == socket_id) && (err_code == 0))
{
LOG_D("ml307 connect to tcp server success");
ml307_conncet_tcp_flag = 1;
}
}
}
static void urc_tcp_disconnect(struct at_client *client, const char *data, rt_size_t size)
{
size_t state = 0, id;
LOG_D("ml307 disconnect to tcp server");
if (sscanf(data, "+MIPURC: \"disconn\",%d,%d", &id, &state) == 2)
{
if (id == socket_id)
{
ml307_conncet_tcp_flag = 0;
if (SysControl.status == kNormalDetectionEvents)
{
LED_G_NORMAL;
}
switch (state)
{
case 1:
LOG_D("ml307 tcp server disconnect");
break;
case 2: // 连接异常
LOG_D("ml307 tcp server connect error");
break;
case 3: // PDP去激活
LOG_D("ml307 tcp server PDP deactivate");
break;
default:
break;
}
}
}
}
// static void urc_tcp_send_check(struct at_client *client, const char *data, rt_size_t size)
// {
// size_t id, len;
// if (sscanf(data, "+MIPSEND:%d,%d", &id, &len) == 2)
// {
// if (id == socket_id)
// {
// if (len == )
// {
// }
// LOG_D("ml307 send data success");
// }
// }
// }
static const struct at_urc urc_table[] = {
// {"+NSONMI:", "\r\n", urc_tcp_recv},
{"REBOOTING", "\r\n", urc_device_reset}, // 这个是软件复位时,
{"+MIPOPEN:", "\r\n", urc_tcp_connect_state},
{"+MIPURC: \"disconn\"", "\r\n", urc_tcp_disconnect},
{"+MIPURC: \"rtcp\"", "\r\n", urc_tcp_recv},
// {"+MIPSEND:", "\r\n", urc_tcp_send_check},
};
static void show_resp_info(at_response_t resp)
{
RT_ASSERT(resp);
/* Print response line buffer */
const char *line_buffer = RT_NULL;
for (rt_size_t line_num = 1; line_num <= resp->line_counts; line_num++)
{
if ((line_buffer = at_resp_get_line(resp, line_num)) != RT_NULL)
LOG_I("line %d buffer : %s", line_num, line_buffer);
else
LOG_I("Parse line buffer error!");
}
return;
}
int at_device_ml307_disconnect_tcp(struct at_device *device)
{
#define ML307_CLOSE_REP_TIME (5 * AT_DEFAULT_TIMEOUT)
if (ml307_conncet_tcp_flag)
{
at_response_t resp = at_create_resp(AT_CLIENT_RECV_BUFF_LEN, 0, ML307_CLOSE_REP_TIME);
if (resp == RT_NULL)
{
LOG_E("No memory for response structure!");
at_delete_resp(resp);
return -RT_ENOMEM;
}
if (at_obj_exec_cmd(device->client, resp, TCP_CLOSE_SOCKET, socket_id) != RT_EOK)
{
at_delete_resp(resp);
return -RT_ERROR;
}
ml307_conncet_tcp_flag = 0;
if (SysControl.status == kNormalDetectionEvents)
{
LED_G_NORMAL;
}
show_resp_info(resp);
at_delete_resp(resp);
}
return RT_EOK;
}
#if 0
int at_device_ml307_socket_creat(struct at_device *device)
{
rt_uint8_t retry = (rt_uint8_t)Flash_Get_SysCfg(kIotRetryId);
at_response_t resp = at_create_resp(AT_CLIENT_RECV_BUFF_LEN, 4, AT_DEFAULT_TIMEOUT);
if (resp == RT_NULL)
{
LOG_E("No memory for response structure!");
at_delete_resp(resp);
return -RT_ENOMEM;
}
while (retry--)
{
if (at_obj_exec_cmd(device->client, resp, TCP_SOCKET_CREAT, TCP_SERVER_PORT) == RT_EOK)
{
if (at_resp_parse_line_args(resp, 2, "%d", &socket_id) > 0)
{
LOG_D("ml307 create tcp socket:%d", socket_id);
at_delete_resp(resp);
return RT_EOK;
}
else
{
LOG_E("ml307 create tcp socket failed. retry %d", retry);
}
}
}
at_delete_resp(resp);
Ml307_Reset(device);
return RT_ERROR;
}
#endif // 0
static int at_device_ml307_connect_tcp(struct at_device *device)
{
rt_err_t ret = RT_EOK;
ASSERT(device);
rt_uint8_t retry = (rt_uint8_t)Flash_Get_SysCfg(kIotRetryId);
at_response_t resp = at_create_resp(64, 2, 2000);
if (resp == RT_NULL)
{
LOG_E("No memory for response structure!");
at_delete_resp(resp);
return -RT_ENOMEM;
}
#if 0
if (at_device_ml307_socket_creat(device) != RT_EOK)
{
LOG_E("ml307 connect to tcp server failed.");
at_delete_resp(resp);
return -RT_ERROR;
}
// /* read data from tcp server */
// if (at_obj_exec_cmd(device->client, resp, TCP_READ_SET_CMD, socket_id, AT_CLIENT_RECV_BUFF_LEN) != RT_EOK)
// {
// at_delete_resp(resp);
// return RT_ERROR;
// }
/* enable tcp notification */
if (at_obj_exec_cmd(device->client, resp, TCP_SET_NSONMI, AT_NSONMI_MODE_DEFAULT) != RT_EOK)
{
at_delete_resp(resp);
return RT_ERROR;
}
#endif
if (Flash_Get_Sever_Addr_Info(&sever_info) != RT_EOK)
{
LOG_E("Get Sever Data Failed");
at_delete_resp(resp);
return RT_ERROR;
}
// rt_uint16_t sever_port = strtol(sever_info.server_port, RT_NULL, 10); // 将字符串转为十进制
LOG_D("sever_info.server_url:%s sever_info.server_port:%s", sever_info.server_url, sever_info.server_port);
for (size_t i = 0; i < retry; i++)
{
if (at_obj_exec_cmd(device->client, resp, TCP_CONNECT_CMD, socket_id, (char *)sever_info.server_url, (char *)sever_info.server_port) == RT_EOK)
{
if (at_resp_get_line_by_kw(resp, "OK") != RT_NULL)
{
rt_thread_mdelay(2000);
if (ml307_conncet_tcp_flag == RT_TRUE)
{
LOG_D("ml307 connect to tcp server success");
break;
}
}
else
{
ml307_conncet_tcp_flag = 0;
LOG_E("ml307 connect to tcp server failed.");
ret = -RT_ERROR;
}
}
rt_thread_mdelay(3000);
}
if ((SysControl.status == kNormalDetectionEvents) && (ml307_conncet_tcp_flag == RT_FALSE))
{
LED_G_NORMAL;
}
at_delete_resp(resp);
return ret;
}
int at_send_data(struct at_device *device, const char *data, rt_size_t send_len)
{
#define ML307_SEND_RESP_TIME (5000)
if (ml307_conncet_tcp_flag)
{
if (SysControl.status == kNormalDetectionEvents)
{
LED_G_INTERNET;
}
rt_uint8_t retry = 0;
rt_uint8_t max_retry_count = (rt_uint8_t)Flash_Get_SysCfg(kIotRetryId);
LOG_D("max_retry_count:%d", max_retry_count);
at_response_t resp = at_create_resp(AT_CLIENT_RECV_BUFF_LEN / 4, 0, ML307_SEND_RESP_TIME);
if (resp == RT_NULL)
{
LOG_E("no memory for ml307 device(%s) response structure.", device->name);
at_delete_resp(resp);
return -RT_ERROR;
}
while (retry < max_retry_count)
{
if (at_obj_exec_cmd(device->client, resp, TCP_SEND_DATA, socket_id, send_len, data) == RT_EOK)
{
size_t len = 0;
if (at_resp_parse_line_args_by_kw(resp, "+MIPSEND:", "+MIPSEND:%*d,%d", &len) > 0)
{
if(len == send_len)
{
LOG_D("send data success, len:%d", len);
at_delete_resp(resp);
if (SysControl.status == kNormalDetectionEvents)
{
LED_G_NORMAL;
}
return RT_EOK;
}
}
else
{
LOG_E("send data error, retry %d times, socket_id: %d", retry + 1, socket_id);
retry++;
}
}
rt_thread_mdelay(2000);
retry++;
}
at_delete_resp(resp);
return -RT_ERROR;
}
else
{
LOG_D("not connected tcp sever!");
if (SysControl.status == kNormalDetectionEvents)
{
LED_G_NORMAL;
}
return -RT_ERROR;
}
}
static int ml307_check_link_status(struct at_device *device)
{
at_response_t resp = RT_NULL;
// struct at_device_ml307 *ml307 = RT_NULL;
int result = -RT_ERROR;
int link_stat = 0;
RT_ASSERT(device);
// ml307 = (struct at_device_ml307 *)device->user_data;
resp = at_create_resp(96, 0, rt_tick_from_millisecond(300));
if (resp == RT_NULL)
{
LOG_E("no memory for resp create.");
return -RT_ERROR;
}
// if (at_obj_exec_cmd(device->client, resp, "AT+MIPCALL?") < 0) // 建立模组应用层拨号连接
// {
// result = -RT_ERROR;
// goto __exit;
// }
// if (at_resp_parse_line_args_by_kw(resp, "+MIPCALL:", "+MIPCALL: %d,%*d,%*s", &link_stat) > 0)
// {
// if (link_stat == 1)
// {
// result = RT_EOK;
// }
// }
if (at_obj_exec_cmd(device->client, resp, "AT+CGACT?") < 0)
{
result = -RT_ERROR;
goto __exit;
}
//+CGACT: 1,1
if (at_resp_parse_line_args_by_kw(resp, "+CGACT:", "+CGACT: %d,%*d", &link_stat) > 0)
{
result = link_stat;
}
__exit:
if (resp)
{
at_delete_resp(resp);
}
return (result);
}
/* ============================= ml307 network interface operations ============================= */
/* set ml307 network interface device status and address information */
static int ml307_netdev_set_info(struct netdev *netdev)
{
#define ML307_IMEI_RESP_SIZE 32
#define ML307_IPADDR_RESP_SIZE 64
#define ML307_DNS_RESP_SIZE 96
#define ML307_INFO_RESP_TIMO rt_tick_from_millisecond(2000)
#define ML307_CONNECT_TIME rt_tick_from_millisecond(2000)
int result = RT_EOK;
ip_addr_t addr;
at_response_t resp = RT_NULL;
struct at_device *device = RT_NULL;
RT_ASSERT(netdev);
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
LOG_E("get device(%s) failed.", netdev->name);
return -RT_ERROR;
}
/* set network interface device status */
netdev_low_level_set_status(netdev, RT_TRUE);
netdev_low_level_set_link_status(netdev, RT_TRUE);
netdev_low_level_set_dhcp_status(netdev, RT_TRUE);
resp = at_create_resp(ML307_IMEI_RESP_SIZE, 0, ML307_INFO_RESP_TIMO);
if (resp == RT_NULL)
{
LOG_E("no memory for resp create.");
result = -RT_ENOMEM;
goto __exit;
}
/* set network interface device IP address */
{
#define IP_ADDR_SIZE_MAX 16
char ipaddr[IP_ADDR_SIZE_MAX] = {0};
at_resp_set_info(resp, ML307_IPADDR_RESP_SIZE * 2, 2, ML307_INFO_RESP_TIMO);
/* send "AT+CIFSR" commond to get IP address */
if (at_obj_exec_cmd(device->client, resp, "AT+CGPADDR=1") < 0)
{
result = -RT_ERROR;
goto __exit;
}
if (at_resp_parse_line_args_by_kw(resp, "+CGPADDR:", "+CGPADDR: %*d,\"%[^\"]", ipaddr) <= 0)
{
LOG_E("ml307 device(%s) prase \"AT+CGPADDR=1\" commands resposne data error!", device->name);
result = -RT_ERROR;
goto __exit;
}
LOG_D("ml307 device(%s) IP address: %s", device->name, ipaddr);
/* set network interface address information */
inet_aton(ipaddr, &addr);
netdev_low_level_set_ipaddr(netdev, &addr);
}
#if 0
/* set network interface device dns server */
{
#define DNS_ADDR_SIZE_MAX 16
char dns_server1[DNS_ADDR_SIZE_MAX] = {0}, dns_server2[DNS_ADDR_SIZE_MAX] = {0};
char dns_str[DNS_ADDR_SIZE_MAX*3] = {0};
at_resp_set_info(resp, ML307_DNS_RESP_SIZE, 0, ML307_INFO_RESP_TIMO);
/* send "AT+MDNSCFG=\"priority\",0" commond to set resolve IPV4 address priority */
if (at_obj_exec_cmd(device->client, resp, "AT+MDNSCFG=\"priority\",0") < 0)
{
result = -RT_ERROR;
goto __exit;
}
/* send "AT+MDNSCFG=\"ip\"" commond to get DNS servers address */
if (at_obj_exec_cmd(device->client, resp, "AT+MDNSCFG=\"ip\"") < 0)
{
result = -RT_ERROR;
goto __exit;
}
//+MDNSCFG: "ip","183.230.126.224",,"183.230.126.225"
if (at_resp_parse_line_args_by_kw(resp, "+MDNSCFG:", "+MDNSCFG: \"ip\",%s", dns_str) < 0)
{
result = -RT_ERROR;
goto __exit;
}
const char *dns1_str = strstr(dns_str, "\"");
sscanf(dns1_str, "\"%[^\"]", dns_server1);
const char *dns2_str = strstr(dns_str, "\",\"");
sscanf(dns2_str, "\",\"%[^\"]", dns_server2);
LOG_D("ml307 device(%s) primary DNS server address: %s", device->name, dns_server1);
LOG_D("ml307 device(%s) secondary DNS server address: %s", device->name, dns_server2);
inet_aton(dns_server1, &addr);
netdev_low_level_set_dns_server(netdev, 0, &addr);
inet_aton(dns_server2, &addr);
netdev_low_level_set_dns_server(netdev, 1, &addr);
}
#endif //
__exit:
if (resp)
{
at_delete_resp(resp);
}
return result;
}
/**
* @brief check ml307 network interface device status
*
* @param netdev: ml307 network interface device
*/
static void ml307_check_link_status_entry(void *parameter)
{
#define ML307_LINK_DELAY_TIME (60 * RT_TICK_PER_SECOND)
#define ML307_LINK_STATUS_OK 1
int link_status;
struct at_device *device = RT_NULL;
struct netdev *netdev = (struct netdev *)parameter;
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
LOG_E("get device(%s) failed.", netdev->name);
return;
}
while (1)
{
link_status = ml307_check_link_status(device);
if (link_status < 0)
{
rt_thread_mdelay(ML307_LINK_DELAY_TIME);
continue;
}
/* check the network interface device link status */
if ((ML307_LINK_STATUS_OK == link_status) != netdev_is_link_up(netdev))
{
netdev_low_level_set_link_status(netdev, (ML307_LINK_STATUS_OK == link_status));
}
rt_thread_delay(ML307_LINK_DELAY_TIME);
}
}
static int ml307_netdev_check_link_status(struct netdev *netdev)
{
#define ML307_LINK_THREAD_TICK 20
#define ML307_LINK_THREAD_STACK_SIZE (1024)
#define ML307_LINK_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX - 2)
rt_thread_t tid;
char tname[RT_NAME_MAX] = {0};
if (netdev == RT_NULL)
{
LOG_E("input network interface device is NULL.\n");
return -RT_ERROR;
}
// RT_ASSERT(netdev);
rt_snprintf(tname, RT_NAME_MAX, "%s", netdev->name);
/* create ml307 link status polling thread */
tid = rt_thread_create(tname, ml307_check_link_status_entry, (void *)netdev,
ML307_LINK_THREAD_STACK_SIZE, ML307_LINK_THREAD_PRIORITY, ML307_LINK_THREAD_TICK);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
return RT_EOK;
}
static int ml307_net_init(struct at_device *device);
static int ml307_netdev_set_up(struct netdev *netdev)
{
struct at_device *device = RT_NULL;
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
LOG_E("get device(%s) failed.", netdev->name);
return -RT_ERROR;
}
if (device->is_init == RT_FALSE)
{
ml307_net_init(device);
device->is_init = RT_TRUE;
netdev_low_level_set_status(netdev, RT_TRUE);
LOG_D("network interface device(%s) set up status.", netdev->name);
}
return RT_EOK;
}
static int ml307_netdev_set_down(struct netdev *netdev)
{
struct at_device *device = RT_NULL;
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
LOG_E("get device(%s) failed.", netdev->name);
return -RT_ERROR;
}
if (device->is_init == RT_TRUE)
{
ml307_power_off(device);
device->is_init = RT_FALSE;
netdev_low_level_set_status(netdev, RT_FALSE);
LOG_D("network interface device(%s) set down status.", netdev->name);
}
return RT_EOK;
}
static int ml307_netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server)
{
#define ML307_DNS_RESP_LEN 8
#define ML307_DNS_RESP_TIMEO rt_tick_from_millisecond(300)
int result = RT_EOK;
at_response_t resp = RT_NULL;
struct at_device *device = RT_NULL;
RT_ASSERT(netdev);
RT_ASSERT(dns_server);
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
LOG_E("get ml307 device by netdev name(%s) failed.", netdev->name);
return -RT_ERROR;
}
resp = at_create_resp(ML307_DNS_RESP_LEN, 0, ML307_DNS_RESP_TIMEO);
if (resp == RT_NULL)
{
LOG_D("ml307 set dns server failed, no memory for response object.");
result = -RT_ENOMEM;
goto __exit;
}
/* send "AT+CDNSCFG=<pri_dns>[,<sec_dns>]" commond to set dns servers */
if (at_obj_exec_cmd(device->client, resp, "AT+MDNSCFG=\"%s\"", inet_ntoa(*dns_server)) < 0)
{
result = -RT_ERROR;
goto __exit;
}
netdev_low_level_set_dns_server(netdev, dns_num, dns_server);
__exit:
if (resp)
{
at_delete_resp(resp);
}
return result;
}
#ifdef NETDEV_USING_PING
static int ml307_netdev_ping(struct netdev *netdev, const char *host, size_t data_len,
uint32_t timeout, struct netdev_ping_resp *ping_resp
#if RT_VER_NUM >= 0x50100
,
rt_bool_t is_bind
#endif
)
{
#define ML307_PING_RESP_SIZE 128
#define ML307_PING_IP_SIZE 16
#define ML307_PING_TIMEO (ML307_CON_REP_TIME)
rt_err_t result = RT_EOK;
int response = -1, recv_data_len, ping_time, ttl;
char ip_addr[ML307_PING_IP_SIZE] = {0};
at_response_t resp = RT_NULL;
struct at_device *device = RT_NULL;
#if RT_VER_NUM >= 0x50100
RT_UNUSED(is_bind);
#endif
RT_ASSERT(netdev);
RT_ASSERT(host);
RT_ASSERT(ping_resp);
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
LOG_E("get device(%s) failed.", netdev->name);
return -RT_ERROR;
}
resp = at_create_resp(ML307_PING_RESP_SIZE, 4, ML307_PING_TIMEO);
if (resp == RT_NULL)
{
LOG_E("no memory for resp create");
at_delete_resp(resp);
return -RT_ENOMEM;
}
/* send "AT+QPING=<contextID>"<host>"[,[<timeout>][,<pingnum>]]" commond to send ping request */
if (at_obj_exec_cmd(device->client, resp, "AT+QPING=1,\"%s\",%d,1", host, timeout / RT_TICK_PER_SECOND) < 0)
{
result = -RT_ERROR;
goto __exit;
}
at_resp_parse_line_args_by_kw(resp, "+QPING:", "+QPING:%d", &response);
/* Received the ping response from the server */
if (response == 0)
{
if (at_resp_parse_line_args_by_kw(resp, "+QPING:", "+QPING:%d,\"%[^\"]\",%d,%d,%d",
&response, ip_addr, &recv_data_len, &ping_time, &ttl) <= 0)
{
result = -RT_ERROR;
goto __exit;
}
}
/* prase response number */
switch (response)
{
case 0:
inet_aton(ip_addr, &(ping_resp->ip_addr));
ping_resp->data_len = recv_data_len;
ping_resp->ticks = ping_time;
ping_resp->ttl = ttl;
result = RT_EOK;
break;
case 569:
result = -RT_ETIMEOUT;
break;
default:
result = -RT_ERROR;
break;
}
__exit:
if (resp)
{
at_delete_resp(resp);
}
return result;
}
#endif /* NETDEV_USING_PING */
const struct netdev_ops ml307_netdev_ops =
{
ml307_netdev_set_up,
ml307_netdev_set_down,
RT_NULL,
ml307_netdev_set_dns_server,
RT_NULL,
#ifdef NETDEV_USING_PING
ml307_netdev_ping,
#endif
RT_NULL,
};
// 增加网卡设备
static struct netdev *ml307_netdev_add(const char *netdev_name)
{
#define ETHERNET_MTU 1380
#define HWADDR_LEN 8
struct netdev *netdev = RT_NULL;
netdev = netdev_get_by_name(netdev_name);
if (netdev != RT_NULL)
{
return (netdev);
}
netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev));
if (netdev == RT_NULL)
{
LOG_E("no memory for netdev create.");
return RT_NULL;
}
netdev->mtu = ETHERNET_MTU;
netdev->ops = &ml307_netdev_ops;
netdev->hwaddr_len = HWADDR_LEN;
#ifdef SAL_USING_AT
extern int sal_at_netdev_set_pf_info(struct netdev * netdev);
/* set the network interface socket/netdb operations */
sal_at_netdev_set_pf_info(netdev);
#endif
netdev_register(netdev, netdev_name, RT_NULL);
return netdev;
}
/* ============================= ml307 device operations ============================= */
// #define AT_SEND_CMD(client, resp, resp_line, timeout, cmd) \
// do { \
// (resp) = at_resp_set_info((resp), 128, (resp_line), rt_tick_from_millisecond(timeout)); \
// if (at_obj_exec_cmd((client), (resp), (cmd)) < 0) \
// { \
// result = -RT_ERROR; \
// goto __exit; \
// } \
// } while(0)
/* initialize for ml307 */
static void ml307_init_thread_entry(void *parameter)
{
#define INIT_RETRY 5
#define CPIN_RETRY 5
#define CSQ_RETRY 20
#define CEREG_RETRY 50
#define IPADDR_RETRY 10
#define ML307_AT_DEFAULT_TIMEOUT 1000
int i;
rt_uint8_t retry_num = INIT_RETRY;
rt_err_t result = RT_EOK;
at_response_t resp = RT_NULL;
struct at_device *device = (struct at_device *)parameter;
struct at_client *client = device->client;
resp = at_create_resp(128, 0, rt_tick_from_millisecond(ML307_AT_DEFAULT_TIMEOUT * 2));
if (resp == RT_NULL)
{
LOG_E("no memory for resp create.");
at_delete_resp(resp);
return;
}
LOG_D("start init %s device.", device->name);
ml307_power_off(device);
while (retry_num--)
{
/* power on the ml307 device */
rt_thread_mdelay(500);
ml307_power_on(device);
rt_thread_mdelay(1000);
LOG_D("power on %s device.", device->name);
/* wait ml307 startup finish, send AT every 500ms, if receive OK, SYNC success*/
if (at_client_obj_wait_connect(client, ML307_WAIT_CONNECT_TIME))
{
result = -RT_ETIMEOUT;
goto __exit;
}
/* disable echo */
if (at_obj_exec_cmd(device->client, resp, "ATE0") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/* get module version */
if (at_obj_exec_cmd(device->client, resp, "ATI") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
for (i = 0; i < (int)resp->line_counts - 1; i++)
{
LOG_D("%s", at_resp_get_line(resp, i + 1));
}
/*disable sleep mode */
if (at_obj_exec_cmd(device->client, resp, "AT+MLPMCFG=\"sleepmode\",0,1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/*设置心跳包*/
if (at_obj_exec_cmd(device->client, resp, "AT+MIPTKA=0,1,120,60,1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/*设置包模式*/
if (at_obj_exec_cmd(device->client, resp, "AT+MIPCFG=\"encoding\",0,1,1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
{
#define ML307_NETDEV_HWADDR_LEN 8
#define ML307_IMEI_LEN 15
char imei[ML307_IMEI_LEN] = {0};
/* send "AT+GSN" commond to get device IMEI */
if (at_obj_exec_cmd(device->client, resp, "AT+GSN=1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
if (at_resp_parse_line_args_by_kw(resp, "+GSN:", "+GSN:%s", imei) <= 0)
{
LOG_E("%s device prase \"AT+GSN=1\" cmd error.", device->name);
result = -RT_ERROR;
goto __exit;
}
LOG_D("%s device IMEI number: %s", device->name, imei);
rt_memcpy(ml307.imei, imei, ML307_IMEI_LEN);
Flash_Sys_Cfg(kIotImeiId, ml307.imei, ML307_IMEI_LEN);
}
/* check SIM card */
for (i = 0; i < CPIN_RETRY; i++)
{
if (at_obj_exec_cmd(device->client, resp, "AT+CPIN?") == RT_EOK)
{
char code[8] = {0};
if (at_resp_parse_line_args_by_kw(resp, "+CPIN:", "+CPIN: %s", code) > 0)
{
if (rt_strcmp(code, "READY") == 0)
{
LOG_D("%s device SIM card detection success.", device->name);
break;
}
else
{
LOG_E("%s device SIM card detection failed.", device->name);
result = -RT_ERROR;
goto __exit;
}
}
}
rt_thread_mdelay(1000);
}
if (i == CPIN_RETRY)
{
LOG_E("%s device SIM card detection failed.", device->name);
result = -RT_ERROR;
goto __exit;
}
// /*网络注册 */
// for (i = 0; i < CSQ_RETRY; i++)
// {
// if (at_obj_exec_cmd(device->client, resp, "AT+CREG=1") == RT_EOK)
// {
// rt_uint8_t state;
// if (at_resp_parse_line_args_by_kw(resp, "+CREG:", "+CREG:%d", &state) > 0)
// {
// if (state == 1)
// {
// LOG_D("%s device network registration success.", device->name);
// /* code */
// }
// else
// {
// LOG_E("%s device network registration failed.", device->name);
// result = -RT_ERROR;
// goto __exit;
// }
// }
// else
// {
// LOG_D("%s device prase \"AT+CREG=1\" cmd error.", device->name);
// result = -RT_ERROR;
// goto __exit;
// }
// }
// rt_thread_mdelay(1000);
// }
// if (i == CSQ_RETRY)
// {
// LOG_D("%s device network registration failed.", device->name);
// result = -RT_ERROR;
// goto __exit;
// }
/* set network interface device hardware iccid */
{
#define ML307_ICCID_LEN 20
char iccid[ML307_ICCID_LEN] = {0};
/* send "AT+ECICCID" commond to get device iccid */
if (at_obj_exec_cmd(device->client, resp, "AT+MCCID") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
if (at_resp_parse_line_args_by_kw(resp, "+MCCID:", "+MCCID:%s", iccid) <= 0)
{
LOG_E("%s device prase \"AT+ECICCID\" cmd error.", device->name);
result = -RT_ERROR;
goto __exit;
}
LOG_D("%s device iccid number: %s", device->name, iccid);
rt_memcpy(ml307.iccid, iccid, ML307_ICCID_LEN);
Flash_Sys_Cfg(kIotIccidId, ml307.iccid, ML307_ICCID_LEN);
}
/* set network interface device hardware imsi */
{
#define ML307_IMSI_LEN 15
char imsi[ML307_IMSI_LEN] = {0};
/* send "AT+CIMI" commond to get device imsi */
if (at_obj_exec_cmd(device->client, resp, "AT+CIMI") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
if (at_resp_parse_line_args_by_kw(resp, "46", "%s", imsi) <= 0)
{
LOG_E("%s device prase \"AT+CIMI\" cmd error.", device->name);
result = -RT_ERROR;
goto __exit;
}
LOG_D("%s device imsi number: %s", device->name, imsi);
rt_memcpy(ml307.imsi, imsi, ML307_IMSI_LEN);
Flash_Sys_Cfg(kIotImsiId, ml307.imsi, ML307_IMSI_LEN);
}
/* check signal strength */
for (i = 0; i < CSQ_RETRY; i++)
{
if (at_obj_exec_cmd(device->client, resp, "AT+CSQ") == RT_EOK)
{
int signal_strength = 0, err_rate = 0;
if (at_resp_parse_line_args_by_kw(resp, "+CSQ:", "+CSQ: %d,%d", &signal_strength, &err_rate) > 0)
{
if ((signal_strength != 99) && (signal_strength != 0))
{
LOG_D("%s device signal strength: %d, channel bit err_rate: %d",
device->name, signal_strength, err_rate);
ml307.rssi = signal_strength;
break;
}
}
}
rt_thread_mdelay(1000);
}
if (i == CSQ_RETRY)
{
LOG_E("%s device signal strength check failed", device->name);
result = -RT_ERROR;
goto __exit;
}
/* check the GPRS network is registered */
for (i = 0; i < CEREG_RETRY; i++)
{
if (at_obj_exec_cmd(device->client, resp, "AT+CEREG?") == RT_EOK)
{
int link_stat = 0;
if (at_resp_parse_line_args_by_kw(resp, "+CEREG:", "+CEREG: %*d,%d", &link_stat) > 0)
{
if ((link_stat == 1) || (link_stat == 5))
{
LOG_D("%s device GPRS is registered", device->name);
break;
}
}
}
rt_thread_mdelay(1000);
}
if (i == CEREG_RETRY)
{
LOG_E("%s device GPRS is register failed", device->name);
result = -RT_ERROR;
goto __exit;
}
#if defined(AT_DEBUG)
/* check the GPRS network IP address */
for (i = 0; i < IPADDR_RETRY; i++)
{
if (at_obj_exec_cmd(client, resp, "AT+MIPCALL?") == RT_EOK)
{
#define IP_ADDR_SIZE_MAX 16
char ipaddr_str[8 * IP_ADDR_SIZE_MAX] = {0};
char ipaddr_v4[IP_ADDR_SIZE_MAX] = {0};
char ipaddr_v6[4 * IP_ADDR_SIZE_MAX] = {0};
/* parse response data "+CGPADDR: 1,<IP_address>" */
if (at_resp_parse_line_args_by_kw(resp, "+MIPCALL:", "+MIPCALL: %*d,%*d,%s", ipaddr_str) > 0)
{
const char *ipaddr_v4_str = strstr(ipaddr_str, "\"");
sscanf(ipaddr_v4_str, "\"%[^\"]", ipaddr_v4);
const char *ipaddr_v6_str = strstr(ipaddr_str, "\",\"");
sscanf(ipaddr_v6_str, "\",\"%[^\"]", ipaddr_v6);
LOG_D("%s device IP address: %s - %s", device->name, ipaddr_v4, ipaddr_v6);
break;
}
}
rt_thread_mdelay(1000);
}
if (i == IPADDR_RETRY)
{
LOG_E("%s device GPRS is get IP address failed", device->name);
result = -RT_ERROR;
goto __exit;
}
#endif
/* initialize successfully */
result = RT_EOK;
break;
__exit:
if (result != RT_EOK)
{
/* power off the ml307 device */
// ml307_power_off(device);
rt_thread_mdelay(1000);
LOG_I("%s device initialize retry...", device->name);
}
}
if (resp)
{
at_delete_resp(resp);
}
if (result == RT_EOK)
{
/* set network interface device status and address information */
ml307_netdev_set_info(device->netdev);
/* check and create link staus sync thread */
// ml307_netdev_check_link_status(device->netdev);
LOG_I("%s device network initialize success.", device->name);
rt_completion_done(&ml307_init_complate); // 通知初始化完成
}
else
{
LOG_E("%s device network initialize failed(%d).", device->name, result);
}
}
/* ml307 device network initialize */
static int ml307_net_init(struct at_device *device)
{
#ifdef AT_DEVICE_ML307_INIT_ASYN
rt_thread_t tid;
/* 初始化完成量对象 */
rt_completion_init(&ml307_init_complate);
tid = rt_thread_create("ml307_net", ml307_init_thread_entry, (void *)device,
ML307_THREAD_STACK_SIZE, ML307_THREAD_PRIORITY, 20);
if (tid)
{
rt_thread_startup(tid);
}
else
{
LOG_E("create %s device init thread failed.", device->name);
return -RT_ERROR;
}
#else
ml307_init_thread_entry(device);
#endif /* AT_DEVICE_ML307_INIT_ASYN */
return RT_EOK;
}
// 去除字符串中的 \r 和 \n
void remove_crlf(char *str)
{
char *p = str;
while (*p)
{
if (*p == '\r' || *p == '\n')
{
memmove(p, p + 1, strlen(p));
}
else
{
p++;
}
}
}
rt_err_t Ml307_Get_Signal_Info(struct at_device *device)
{
#define RETRY 20
rt_err_t result = RT_EOK;
at_response_t resp = RT_NULL;
rt_uint8_t i;
RT_ASSERT(device);
resp = at_create_resp(1024, 4, rt_tick_from_millisecond(2000));
if (resp == RT_NULL)
{
LOG_E("no memory for resp create.");
at_delete_resp(resp);
return RT_ERROR;
}
/* check signal strength */
for (i = 0; i < RETRY; i++)
{
if (at_obj_exec_cmd(device->client, resp, "AT+CSQ") == RT_EOK)
{
int signal_strength = 0, err_rate = 0;
if (at_resp_parse_line_args_by_kw(resp, "+CSQ:", "+CSQ: %d,%d", &signal_strength, &err_rate) > 0)
{
if ((signal_strength != 99) && (signal_strength != 0))
{
LOG_D("%s device signal strength: %d, channel bit err_rate: %d",
device->name, signal_strength, err_rate);
ml307.rssi = signal_strength;
break;
}
}
}
rt_thread_mdelay(1000);
}
if (i == RETRY)
{
LOG_E("%s device signal strength check failed", device->name);
result = -RT_ERROR;
}
/* check signal strength */
//+CESQ:99,99,255,255,28,44
for (i = 0; i < RETRY; i++)
{
if (at_obj_exec_cmd(device->client, resp, "AT+CESQ") == RT_EOK)
{
rt_uint8_t rsrp = 0;
if (at_resp_parse_line_args_by_kw(resp, "+CESQ:", "+CESQ:%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%d", &rsrp) > 0)
{
if ((rsrp < 97) && (rsrp > 0))
{
LOG_D("%s device signal rsrp: %d",
device->name, rsrp);
ml307.rsrp = rsrp;
break;
}
}
}
rt_thread_mdelay(1000);
}
if (i == RETRY)
{
LOG_E("%s device signal data failed", device->name);
result = -RT_ERROR;
}
// /* get signal snr, pci */
// for (int i = 0; i < RETRY; i++)
// {
// if (at_obj_exec_cmd(device->client, resp, "AT+NUESTATS") == RT_EOK)
// {
// const char *key1 = "SNR:";
// const char *key2 = "PCI:";
// int pci = 0, snr = 0;
// // show_resp_info(resp);
// // 获取第 2 行的响应
// const char *line = at_resp_get_line(resp, 2);
// if (line != NULL)
// {
// snr = Extract_Value(line, key1);
// pci = Extract_Value(line, key2);
// if (snr != 0 && pci != 0)
// {
// ml307.pci = pci;
// ml307.snr = snr;
// LOG_D("pci:%d,snr:%d", ml307.pci, ml307.snr);
// break;
// }
// else
// {
// LOG_D("Extracted values are invalid: SNR=%d, PCI=%d", snr, pci);
// }
// }
// else
// {
// LOG_D("Failed to get line 2 from response");
// }
// }
// else
// {
// LOG_D("Failed to execute AT command");
// }
// rt_thread_mdelay(2000);
// }
// if (i == RETRY)
// {
// LOG_E("%s device signal data failed", device->name);
// result = -RT_ERROR;
// }
at_delete_resp(resp);
return result;
}
/* ml307 device network interface attach
* - set network interface device link status
*/
static int ml307_init(struct at_device *device)
{
RT_ASSERT(device);
struct at_device_ml307 *ml307 = (struct at_device_ml307 *)device->user_data;
ml307->power_status = RT_FALSE; // default power is off.
ml307->sleep_status = RT_FALSE; // default sleep is disabled.
rt_device_t serial = rt_device_find(ml307->client_name);
if (serial == RT_NULL)
{
LOG_E("device(%s) initialize failed, get AT client(%s) failed.", ml307->device_name, ml307->client_name);
return -RT_ERROR;
}
/* initialize AT client */
#if RT_VER_NUM >= 0x50100
at_client_init(ml307->client_name, ml307->recv_line_num, ml307->recv_line_num);
#else
at_client_init(ml307->client_name, ml307->recv_line_num);
#endif
device->client = at_client_get(ml307->client_name);
if (device->client == RT_NULL)
{
LOG_E("get AT client(%s) failed.", ml307->client_name);
return -RT_ERROR;
}
/* register URC data execution function */
at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
#ifdef AT_USING_SOCKET
ml307_socket_init(device);
#endif
/* add ml307 device to the netdev list */
device->netdev = ml307_netdev_add(ml307->device_name);
if (device->netdev == RT_NULL)
{
LOG_E("add netdev(%s) failed.", ml307->device_name);
return -RT_ERROR;
}
/* initialize ml307 pin configuration */
if (ml307->pwr_en_pin != -1)
{
rt_pin_mode(ml307->pwr_en_pin, PIN_MODE_OUTPUT);
rt_pin_write(ml307->pwr_en_pin, PIN_HIGH); // 打开3_8v供电
}
if (ml307->power_pin != -1)
{
rt_pin_mode(ml307->power_pin, PIN_MODE_OUTPUT);
}
if (ml307->power_status_pin != -1)
{
rt_pin_mode(ml307->power_status_pin, PIN_MODE_INPUT);
}
if (ml307->rst_pin != -1)
{
rt_pin_mode(ml307->rst_pin, PIN_MODE_OUTPUT);
}
/* initialize ml307 device network */
return ml307_netdev_set_up(device->netdev);
}
static int ml307_deinit(struct at_device *device)
{
RT_ASSERT(device);
return ml307_netdev_set_down(device->netdev);
}
static int ml307_control(struct at_device *device, int cmd, void *arg)
{
int result = -RT_ERROR;
RT_ASSERT(device);
switch (cmd)
{
case AT_DEVICE_CTRL_NET_CONN:
result = at_device_ml307_connect_tcp(device);
break;
case AT_DEVICE_CTRL_NET_DISCONN:
result = at_device_ml307_disconnect_tcp(device); // 直接删除Socket
break;
case AT_DEVICE_CTRL_GET_SIGNAL:
result = Ml307_Get_Signal_Info(device);
break;
case AT_DEVICE_CTRL_RESET:
result = Ml307_Reset(device);
break;
case AT_DEVICE_CTRL_POWER_ON:
result = ml307_power_on(device);
break;
case AT_DEVICE_CTRL_POWER_OFF:
result = ml307_power_off(device);
break;
case AT_DEVICE_CTRL_SLEEP:
// result = ml307_sleep(device);
// break;
case AT_DEVICE_CTRL_WAKEUP:
// result = ml307_wakeup(device);
// break;
case AT_DEVICE_CTRL_LOW_POWER:
case AT_DEVICE_CTRL_SET_WIFI_INFO:
case AT_DEVICE_CTRL_GET_GPS:
case AT_DEVICE_CTRL_GET_VER:
LOG_W("not support the control command(%d).", cmd);
break;
default:
LOG_E("input error control command(%d).", cmd);
break;
}
return result;
}
// 将本地时间转换为对应时区时间
void Time_Zone_Conversion(TsRtcDateTime *timeInfo)
{
// 根据时区差异进行转换这里时区差为8小时没有分钟差异。
timeInfo->hour += RT_LIBC_DEFAULT_TIMEZONE; // 小时部分加8小时
if (timeInfo->hour >= 24)
{ // 如果超过24小时则天数加1小时数减24。
timeInfo->day++;
timeInfo->hour -= 24;
if (timeInfo->day > 365)
{
timeInfo->year += 1;
}
}
}
int Time_Calibration(struct at_device *device)
{
at_response_t resp = RT_NULL;
RT_ASSERT(device);
resp = at_create_resp(64, 2, rt_tick_from_millisecond(2000));
if (resp == RT_NULL)
{
LOG_E("no memory for resp create.");
at_delete_resp(resp);
return RT_ERROR;
}
if (at_obj_exec_cmd(device->client, resp, "AT+CCLK?") == RT_EOK)
{
TsRtcDateTime rtc_dt;
; // 网络时间
int year, mounth, days, hous, min, sec;
/*+CCLK:24/11/12,06:08:19+32*/
if (at_resp_parse_line_args_by_kw(resp, "+CCLK:", "+CCLK: \"%d/%d/%d,%d:%d:%d+32\"", &year, &mounth, &days, &hous, &min, &sec) > 0)
{
rtc_dt.year = (2000 + year);
rtc_dt.month = mounth;
rtc_dt.day = days;
rtc_dt.hour = hous; // 此时为零区时间,需要转化为东八区
rtc_dt.minute = min;
rtc_dt.second = sec;
Time_Zone_Conversion(&rtc_dt); // 时区设置
rtc_dt.week = RTC_GetWeek(rtc_dt.year, rtc_dt.month, rtc_dt.day);
RTC_SetTime(rtc_dt.year, rtc_dt.month, rtc_dt.day,
rtc_dt.hour, rtc_dt.minute, rtc_dt.second); // 设置时间
LOG_I("RTC时间: %04d-%02d-%02d %02d:%02d:%02d \n",
rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, rtc_dt.second);
at_delete_resp(resp);
return RT_EOK;
}
}
at_delete_resp(resp);
return RT_ERROR;
}
const struct at_device_ops ml307_device_ops =
{
ml307_init,
ml307_deinit,
ml307_control,
};
static int ml307_device_class_register(void)
{
struct at_device_class *class = RT_NULL;
class = (struct at_device_class *)rt_calloc(1, sizeof(struct at_device_class));
if (class == RT_NULL)
{
LOG_E("no memory for device class create.");
rt_free(class);
return -RT_ENOMEM;
}
class->device_ops = &ml307_device_ops;
return at_device_class_register(class, AT_DEVICE_CLASS_ML307);
}
INIT_DEVICE_EXPORT(ml307_device_class_register);
#endif //! IOT_MODULE_SWITCH
#endif /* AT_DEVICE_USING_ML307 */