/*********************************************************************************
|
* Copyright: (C) 2023 LingYun IoT System Studio.
|
* All rights reserved.
|
*
|
* Filename: at-esp32.c
|
* Description: This file is ESP32 AT command low level API functions
|
*
|
* Version: 1.0.0(11/08/23)
|
* Author: Guo Wenxue <guowenxue@gmail.com>
|
* ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
|
*
|
********************************************************************************/
|
|
#include "logger.h"
|
#include "at-esp32.h"
|
|
/*+------------------------+
|
*| Baisc AT command |
|
*+------------------------+*/
|
|
static inline int check_at_ready(comport_t *comport)
|
{
|
int times = 6;
|
int ready = 0;
|
|
while( times-- )
|
{
|
if( 0 == send_atcmd_check_ok(comport, "AT", 500) )
|
{
|
ready = 1;
|
break;
|
}
|
}
|
|
return ready;
|
}
|
|
/* AT command: AT+RST */
|
int esp32_reset(comport_t *comport)
|
{
|
int rv;
|
|
rv = send_atcmd(comport, "AT+RST", 5000, "ready", AT_ERRSTR, NULL, 0);
|
if( rv < 0)
|
{
|
log_error("send AT command to reset ESP32 failed, rv=%d\n", rv);
|
return -1;
|
}
|
|
if( check_at_ready(comport) )
|
{
|
log_info("send AT to reset ESP32 and AT command ready\n");
|
return 0;
|
}
|
else
|
{
|
log_info("send AT to reset ESP32 but AT command not ready\n");
|
return -3;
|
}
|
}
|
|
/* AT command: AT+RESTORE */
|
int esp32_restore(comport_t *comport)
|
{
|
int rv;
|
|
//rv = send_atcmd_check_ok(comport, "AT+RESTORE", 5000);
|
rv = send_atcmd(comport, "AT+RESTORE", 5000, "ready", AT_ERRSTR, NULL, 0);
|
if( rv < 0)
|
{
|
log_error("send AT command to restore ESP32 failed, rv=%d\n", rv);
|
return -1;
|
}
|
|
if( check_at_ready(comport) )
|
{
|
log_info("send AT command to resstore ESP32 ready\n");
|
return 0;
|
}
|
else
|
{
|
log_error("send AT command to restore ESP32 but AT not ready\n");
|
return -3;
|
}
|
}
|
|
/* AT command: ATE1 or ATE0 */
|
int esp32_set_echo(comport_t *comport, int enable)
|
{
|
char *at = enable? "ATE1" : "ATE0";
|
|
return send_atcmd_check_ok(comport, at, 500);
|
}
|
|
/* AT command: AT+GMR */
|
int esp32_get_firmware(comport_t *comport, char *version, int size)
|
{
|
if( !version || size<=0 )
|
return -1;
|
|
return send_atcmd_check_value(comport, "AT+GMR", 2000, version, size);
|
}
|
|
/* AT command: AT+SYSSTORE */
|
int esp32_set_sysstore(comport_t *comport, int enable)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
snprintf(at, sizeof(at), "AT+SYSSTORE=%d", enable?1:0);
|
|
return send_atcmd_check_ok(comport, at, 1000);
|
}
|
|
/*+------------------------+
|
*| WiFi AT command |
|
*+------------------------+*/
|
|
/* AT command: AT+CWMODE */
|
int esp32_set_wmode(comport_t *comport, workmode_t mode, int autoconn)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
snprintf(at, sizeof(at), "AT+CWMODE=%d,%d", mode, autoconn?1:0);
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CIPSTAMAC/CIPAPMAC */
|
int esp32_get_macaddr(comport_t *comport, workmode_t mode, char *mac)
|
{
|
if( !mac )
|
return -1;
|
|
if( MODE_SOFTAP == mode )
|
return send_atcmd_check_request(comport, "AT+CIPAPMAC?", 3000, mac, MAC_LEN);
|
else
|
return send_atcmd_check_request(comport, "AT+CIPSTAMAC?", 3000, mac, MAC_LEN);
|
}
|
|
/* AT command: AT+CIPSTA/AT+CIPAP */
|
int esp32_set_ipaddr(comport_t *comport, workmode_t mode, char *ip, char *gateway)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( !ip || !gateway )
|
return -1;
|
|
if( MODE_SOFTAP == mode )
|
snprintf(at, sizeof(at), "AT+CIPAP=\"%s\",\"%s\"", ip, gateway);
|
else
|
snprintf(at, sizeof(at), "AT+CIPSTA=\"%s\",\"%s\"", ip, gateway);
|
|
return send_atcmd_check_ok(comport, at, 2000);
|
}
|
|
/* AT command: AT+CIPSTA/AT+CIPAP */
|
int esp32_get_ipaddr(comport_t *comport, workmode_t mode, char *ip, char *gateway)
|
{
|
char *at = MODE_SOFTAP==mode? "AT+CIPAP?" : "AT+CIPSTA?";
|
char buf[ATCMD_REPLY_LEN];
|
int rv;
|
|
if( !ip || !gateway )
|
return -1;
|
|
rv = send_atcmd_check_value(comport, at, 3000, buf, sizeof(buf));
|
if( rv < 0)
|
{
|
log_error("AT command query IP address failed, rv=%d\n", rv);
|
return rv;
|
}
|
|
rv = parser_request_value(buf, "ip", ip, IP_LEN);
|
if( rv < 0 )
|
{
|
log_error("Parser query IP address failed, rv=%d\n", rv);
|
return rv;
|
}
|
|
rv = parser_request_value(buf, "gateway", gateway, IP_LEN);
|
if( rv < 0 )
|
{
|
log_error("Parser query gateway address failed, rv=%d\n", rv);
|
return rv;
|
}
|
|
return 0;
|
}
|
|
/* AT command: AT+CWDHCP */
|
int esp32_set_dhcp(comport_t *comport, workmode_t mode, int enable)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
snprintf(at, sizeof(at), "AT+CWDHCP=%d,%d", enable?1:0, mode);
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CWAUTOCONN */
|
int esp32_set_autoconn(comport_t *comport, int enable)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
snprintf(at, sizeof(at), "AT+CWAUTOCONN=%d", enable?1:0);
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CWLAP */
|
int esp32_list_ap(comport_t *comport, char *buf, int size)
|
{
|
if( !buf || size<=0 )
|
return -1;
|
|
return send_atcmd_check_value(comport, "AT+CWLAP", 8000, buf, size);
|
}
|
|
/* AT command: AT+CWJAP */
|
int esp32_connect_ap(comport_t *comport, char *ssid, char *pwd)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( !ssid || !pwd )
|
return -1;
|
|
snprintf(at, sizeof(at), "AT+CWJAP=\"%s\",\"%s\"", ssid, pwd);
|
return send_atcmd_check_ok(comport, at, 15000);
|
}
|
|
/* AT command: AT+CWQAP */
|
int esp32_disconn_ap(comport_t *comport)
|
{
|
return send_atcmd_check_ok(comport, "AT+CWQAP", 5000);
|
}
|
|
|
/* AT command: AT+CWSTATE? status value:
|
* - 0: ESP32 station has not started any Wi-Fi connection.
|
* - 1: ESP32 station has connected to an AP, but does not get an IPv4 address yet.
|
* - 2: ESP32 station has connected to an AP, and got an IPv4 address.
|
* - 3: ESP32 station is in Wi-Fi connecting or reconnecting state.
|
* - 4: ESP32 station is in Wi-Fi disconnected state
|
*/
|
int esp32_join_status(comport_t *comport, int *status, char *ssid)
|
{
|
char buf[ATCMD_REPLY_LEN];
|
int rv;
|
|
if( !status || !ssid )
|
return -1;
|
|
rv = send_atcmd_check_request(comport, "AT+CWSTATE?", 3000, buf, sizeof(buf));
|
if( rv < 0)
|
{
|
log_error("AT command query join status failed, rv=%d\n", rv);
|
return rv;
|
}
|
|
sscanf(buf, "%d,%s", status, ssid);
|
|
return 0;
|
}
|
|
/* AT command: AT+PING */
|
int esp32_ping(comport_t *comport, char *host, int timeout)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( !host )
|
return -1;
|
|
snprintf(at, sizeof(at), "AT+PING=\"%s\"", host);
|
return send_atcmd_check_ok(comport, at, timeout);
|
}
|
|
/* AT command: AT+CWSAP */
|
int esp32_set_softap(comport_t *comport, char *ssid, char *pwd, int channel, encmode_t encmode)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( !ssid || !pwd )
|
return -1;
|
|
snprintf(at, sizeof(at), "AT+CWSAP=\"%s\",\"%s\",%d,%d", ssid, pwd, channel, encmode);
|
return send_atcmd_check_ok(comport, at, 5000);
|
}
|
|
/* AT command: AT+CWLIF */
|
int esp32_list_client(comport_t *comport, char *buf, int size)
|
{
|
if( !buf || size<=0 )
|
return -1;
|
|
return send_atcmd_check_value(comport, "AT+CWLIF", 8000, buf, size);
|
}
|
|
/*+------------------------+
|
*| Socket AT command |
|
*+------------------------+*/
|
|
/* AT command: AT+CIPMUX */
|
int esp32_set_socket_mux(comport_t *comport, int enable)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
snprintf(at, sizeof(at), "AT+CIPMUX=%d", enable?1:0);
|
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CIPSERVERMAXCONN */
|
int esp32_set_socket_clients(comport_t *comport, int max)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( max <= 0 )
|
return -1;
|
|
snprintf(at, sizeof(at), "AT+CIPSERVERMAXCONN=%d", max);
|
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CIPSTO, timeout unit second */
|
int esp32_set_socket_timeout(comport_t *comport, int timeout)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( timeout <= 0 )
|
return -1;
|
|
snprintf(at, sizeof(at), "AT+CIPSTO=%d", timeout);
|
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CIPSERVER */
|
int esp32_set_tcp_server(comport_t *comport, int port)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( port <= 0 )
|
return -1;
|
|
snprintf(at, sizeof(at), "AT+CIPSERVER=1,%d,\"TCP\"", port);
|
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CIPSERVER */
|
int esp32_del_tcp_server(comport_t *comport, int port)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
|
if( port <= 0 )
|
return -1;
|
|
snprintf(at, sizeof(at), "AT+CIPSERVER=0,%d,\"TCP\"", port);
|
|
return send_atcmd_check_ok(comport, at, 1500);
|
}
|
|
/* AT command: AT+CIPSTART */
|
int esp32_set_tcp_client(comport_t *comport, int mux, char *host, int port)
|
{
|
char at[ATCMD_LEN]={'\0'};
|
char buf[ATCMD_REPLY_LEN]={'\0'};
|
int keepalive = 60; /* unit second */
|
int rv,linkid = 0;
|
|
if( !host || port <= 0 )
|
return -1;
|
|
rv = esp32_set_socket_mux(comport, mux);
|
if(rv < 0)
|
return rv;
|
|
if( mux )
|
snprintf(at, sizeof(at), "AT+CIPSTART=1,\"TCP\",\"%s\",%d,%d", host, port, keepalive);
|
else
|
snprintf(at, sizeof(at), "AT+CIPSTART=\"TCP\",\"%s\",%d,%d", host, port, keepalive);
|
|
rv = send_atcmd_check_value(comport, at, 1500, buf, sizeof(buf));
|
if(rv < 0)
|
return rv;
|
|
sscanf(buf, "%d,", &linkid);
|
|
return linkid;
|
}
|