mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 00:09:46 +01:00
drivers/at: fix URC collision with command response
This commit is contained in:
parent
9ba6eb2aee
commit
e99cafba33
159
drivers/at/at.c
159
drivers/at/at.c
@ -6,6 +6,39 @@
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/* A note on URCs (Unsolicited Result Codes), regardless of whether URC handling
|
||||
* is enabled or not.
|
||||
*
|
||||
* Some DCEs (Data Circuit-terminating Equipment, aka modem), like the LTE
|
||||
* modules from uBlox define a grace period where URCs are guaranteed NOT to be
|
||||
* sent as the time span between:
|
||||
* - the command EOL character reception AND command being internally accepted
|
||||
* - the EOL character of the last response line
|
||||
*
|
||||
* As follows, there is an indeterminate amount of time between:
|
||||
* - the command EOL character being sent
|
||||
* - the command EOL character reception AND command being internally accepted,
|
||||
* i.e. the begin of the grace period
|
||||
*
|
||||
* In other words, we can get a URC (or more?) just after issuing the command
|
||||
* and before the first line of response. The net effect is that such URCs will
|
||||
* appear to be the first line of response to the last issued command.
|
||||
*
|
||||
* The current solution is to skip characters that don't match the expected
|
||||
* response, at the expense of losing these URCs. Note, we may already lose URCs
|
||||
* when calling at_drain() just before any at_send_cmd(). Success partially
|
||||
* depends on whether command echoing is enabled or not:
|
||||
* 1. echo enabled: by observation, it seems that the grace period begins
|
||||
* BEFORE the echoed command. This has the advantage that we ALWAYS know what
|
||||
* the first line of response must look like and so if it doesn't, then it's a
|
||||
* URC. Thus, any procedure that calls at_send_cmd() will catch and discard
|
||||
* these URCs.
|
||||
* 2. echo disabled: commands that expect a response (e.g. at_send_cmd_get_resp_wait_ok())
|
||||
* will catch and discard any URC (or, if MODULE_AT_URC enabled, hand it over
|
||||
* to the URC callbacks). For the rest, it is the application's responsibility
|
||||
* to handle it.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@ -32,6 +65,10 @@
|
||||
#define AT_EVENT_PRIO EVENT_PRIO_HIGHEST
|
||||
#endif
|
||||
|
||||
#if defined(MODULE_AT_URC)
|
||||
static int _check_urc(clist_node_t *node, void *arg);
|
||||
#endif
|
||||
|
||||
#if defined(MODULE_AT_URC_ISR)
|
||||
static void _event_process_urc(event_t *_event)
|
||||
{
|
||||
@ -62,8 +99,7 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t
|
||||
|
||||
isrpipe_init(&dev->isrpipe, (uint8_t *)buf, bufsize);
|
||||
|
||||
return uart_init(uart, baudrate, _isrpipe_write_one_wrapper,
|
||||
dev);
|
||||
return uart_init(uart, baudrate, _isrpipe_write_one_wrapper, dev);
|
||||
}
|
||||
|
||||
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
|
||||
@ -99,6 +135,15 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
int at_wait_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
|
||||
{
|
||||
int res;
|
||||
do {
|
||||
res = at_expect_bytes(dev, bytes, timeout);
|
||||
} while (res != 0 && res != -ETIMEDOUT);
|
||||
return res;
|
||||
}
|
||||
|
||||
void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len)
|
||||
{
|
||||
uart_write(dev->uart, (const uint8_t *)bytes, len);
|
||||
@ -175,11 +220,12 @@ int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout)
|
||||
uart_write(dev->uart, (const uint8_t *)CONFIG_AT_SEND_EOL, AT_SEND_EOL_LEN);
|
||||
|
||||
if (!IS_ACTIVE(CONFIG_AT_SEND_SKIP_ECHO)) {
|
||||
if (at_expect_bytes(dev, command, timeout)) {
|
||||
if (at_wait_bytes(dev, command, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL AT_RECV_EOL_1 AT_RECV_EOL_2, timeout)) {
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL AT_RECV_EOL_1 AT_RECV_EOL_2,
|
||||
timeout)) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
@ -218,11 +264,7 @@ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command,
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
if (res == 0) {
|
||||
/* skip possible empty line */
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
}
|
||||
res = at_readline_skip_empty(dev, resp_buf, len, false, timeout);
|
||||
|
||||
out:
|
||||
return res;
|
||||
@ -242,35 +284,35 @@ ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const c
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
if (res == 0) {
|
||||
/* skip possible empty line */
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
}
|
||||
/* URCs may occur right after the command has been sent and before the
|
||||
* expected response */
|
||||
do {
|
||||
res = at_readline_skip_empty(dev, resp_buf, len, false, timeout);
|
||||
|
||||
/* Strip the expected prefix */
|
||||
if (res > 0 && resp_prefix && *resp_prefix) {
|
||||
size_t prefix_len = strlen(resp_prefix);
|
||||
if (strncmp(resp_buf, resp_prefix, prefix_len) == 0) {
|
||||
size_t remaining_len = strlen(resp_buf) - prefix_len;
|
||||
/* The one extra byte in the copy is the terminating nul byte */
|
||||
memmove(resp_buf, resp_buf + prefix_len, remaining_len + 1);
|
||||
res -= prefix_len;
|
||||
/* Strip the expected prefix */
|
||||
if (res > 0 && resp_prefix && *resp_prefix) {
|
||||
size_t prefix_len = strlen(resp_prefix);
|
||||
if (strncmp(resp_buf, resp_prefix, prefix_len) == 0) {
|
||||
size_t remaining_len = strlen(resp_buf) - prefix_len;
|
||||
/* The one extra byte in the copy is the terminating nul byte */
|
||||
memmove(resp_buf, resp_buf + prefix_len, remaining_len + 1);
|
||||
res -= prefix_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (res >= 0);
|
||||
|
||||
/* wait for OK */
|
||||
if (res >= 0) {
|
||||
res_ok = at_readline(dev, ok_buf, sizeof(ok_buf), false, timeout);
|
||||
if (res_ok == 0) {
|
||||
/* skip possible empty line */
|
||||
res_ok = at_readline(dev, ok_buf, sizeof(ok_buf), false, timeout);
|
||||
res_ok = at_readline_skip_empty(dev, ok_buf, sizeof(ok_buf), false, timeout);
|
||||
if (res_ok < 0) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||
if ((len_ok != 0) && (strcmp(ok_buf, CONFIG_AT_RECV_OK) == 0)) {
|
||||
}
|
||||
else {
|
||||
/* Something else then OK */
|
||||
/* Something else than OK */
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
@ -295,8 +337,6 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* only clear the response buffer after sending the command,
|
||||
* so the same buffer can be used for command and response */
|
||||
memset(resp_buf, '\0', len);
|
||||
|
||||
while (1) {
|
||||
@ -358,19 +398,16 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout
|
||||
uart_write(dev->uart, (const uint8_t *)command, cmdlen);
|
||||
uart_write(dev->uart, (const uint8_t *)CONFIG_AT_SEND_EOL, AT_SEND_EOL_LEN);
|
||||
|
||||
if (at_expect_bytes(dev, command, timeout)) {
|
||||
return -1;
|
||||
if (!IS_ACTIVE(CONFIG_AT_SEND_SKIP_ECHO)) {
|
||||
if (at_wait_bytes(dev, command, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL, timeout)) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL AT_RECV_EOL_2, timeout)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (at_expect_bytes(dev, ">", timeout)) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return at_wait_bytes(dev, ">", timeout);
|
||||
}
|
||||
|
||||
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout)
|
||||
@ -378,16 +415,31 @@ int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout)
|
||||
int res;
|
||||
char resp_buf[64];
|
||||
|
||||
res = at_send_cmd_get_resp(dev, command, resp_buf, sizeof(resp_buf), timeout);
|
||||
res = at_send_cmd_get_resp(dev, command, resp_buf, sizeof(resp_buf),
|
||||
timeout);
|
||||
|
||||
if (res > 0) {
|
||||
ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||
if ((len_ok != 0) && (strcmp(resp_buf, CONFIG_AT_RECV_OK) == 0)) {
|
||||
res = 0;
|
||||
size_t const len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||
size_t const len_err = sizeof(CONFIG_AT_RECV_ERROR) - 1;
|
||||
size_t const len_cme_cms = sizeof("+CME ERROR:") - 1;
|
||||
|
||||
while (res >= 0) {
|
||||
if (strncmp(resp_buf, CONFIG_AT_RECV_OK, len_ok) == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
res = -1;
|
||||
else if (strncmp(resp_buf, CONFIG_AT_RECV_ERROR, len_err) == 0) {
|
||||
return -1;
|
||||
}
|
||||
else if (strncmp(resp_buf, "+CME ERROR:", len_cme_cms) == 0) {
|
||||
return -2;
|
||||
}
|
||||
else if (strncmp(resp_buf, "+CMS ERROR:", len_cme_cms) == 0) {
|
||||
return -2;
|
||||
}
|
||||
/* probably a sneaky URC */
|
||||
#ifdef MODULE_AT_URC
|
||||
clist_foreach(&dev->urc_list, _check_urc, resp_buf);
|
||||
#endif
|
||||
res = at_readline_skip_empty(dev, resp_buf, sizeof(resp_buf), false, timeout);
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -445,6 +497,17 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t at_readline_skip_empty(at_dev_t *dev, char *resp_buf, size_t len,
|
||||
bool keep_eol, uint32_t timeout)
|
||||
{
|
||||
ssize_t res = at_readline(dev, resp_buf, len, keep_eol, timeout);
|
||||
if (res == 0) {
|
||||
/* skip possible empty line */
|
||||
res = at_readline(dev, resp_buf, len, keep_eol, timeout);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef MODULE_AT_URC
|
||||
void at_add_urc(at_dev_t *dev, at_urc_t *urc)
|
||||
{
|
||||
|
@ -195,8 +195,8 @@ typedef struct {
|
||||
* @param[in] buf input buffer
|
||||
* @param[in] bufsize size of @p buf
|
||||
*
|
||||
* @returns success code UART_OK on success
|
||||
* @returns error code UART_NODEV or UART_NOBAUD otherwise
|
||||
* @retval success code UART_OK on success
|
||||
* @retval error code UART_NODEV or UART_NOBAUD otherwise
|
||||
*/
|
||||
int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t bufsize);
|
||||
|
||||
@ -209,8 +209,8 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t
|
||||
* @param[in] command command string to send
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns 0 when device answers "OK"
|
||||
* @returns <0 otherwise
|
||||
* @retval 0 when device answers "OK"
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
|
||||
@ -224,8 +224,8 @@ int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
* @param[in] command command string to send
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @return 0 when prompt is received
|
||||
* @return <0 otherwise
|
||||
* @retval 0 when prompt is received
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
|
||||
@ -243,8 +243,8 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout
|
||||
* @param[in] len len of @p buffer
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns length of response on success
|
||||
* @returns <0 on error
|
||||
* @retval n length of response on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout);
|
||||
|
||||
@ -263,8 +263,8 @@ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf,
|
||||
* @param[in] len len of @p buffer
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns length of response on success
|
||||
* @returns <0 on error
|
||||
* @retval n length of response on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const char *resp_prefix,
|
||||
char *resp_buf, size_t len, uint32_t timeout);
|
||||
@ -286,9 +286,9 @@ ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const c
|
||||
* @param[in] keep_eol true to keep the CR character in the response
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns length of response on success
|
||||
* @returns -1 on error
|
||||
* @returns -2 on CMS or CME error
|
||||
* @retval n length of response on success
|
||||
* @retval -1 on error
|
||||
* @retval -2 on CMS or CME error
|
||||
*/
|
||||
ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf,
|
||||
size_t len, bool keep_eol, uint32_t timeout);
|
||||
@ -300,11 +300,23 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf
|
||||
* @param[in] bytes buffer containing bytes to expect (NULL-terminated)
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns 0 on success
|
||||
* @returns <0 otherwise
|
||||
* @retval 0 on success
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Repeatedly calls at_expect_bytes() until a match or timeout occurs
|
||||
*
|
||||
* @param[in] dev device to operate on
|
||||
* @param[in] bytes buffer containing bytes to expect (NULL-terminated)
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_wait_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Receives bytes into @p bytes buffer until the string pattern
|
||||
* @p string is received or the buffer is full.
|
||||
@ -317,8 +329,8 @@ int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
|
||||
* bytes.
|
||||
* @param[in] timeout timeout (in usec) of inactivity to finish read
|
||||
*
|
||||
* @returns 0 on success
|
||||
* @returns <0 on error
|
||||
* @retval 0 on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
int at_recv_bytes_until_string(at_dev_t *dev, const char *string,
|
||||
char *bytes, size_t *bytes_len,
|
||||
@ -341,7 +353,7 @@ void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len);
|
||||
* @param[in] len maximum number of bytes to receive
|
||||
* @param[in] timeout timeout (in usec) of inactivity to finish read
|
||||
*
|
||||
* @returns Number of bytes read, eventually zero if no bytes available
|
||||
* @retval n Number of bytes read, eventually zero if no bytes available
|
||||
*/
|
||||
ssize_t at_recv_bytes(at_dev_t *dev, char *bytes, size_t len, uint32_t timeout);
|
||||
|
||||
@ -352,8 +364,8 @@ ssize_t at_recv_bytes(at_dev_t *dev, char *bytes, size_t len, uint32_t timeout);
|
||||
* @param[in] command command to send
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns 0 on success
|
||||
* @returns <0 otherwise
|
||||
* @retval 0 on success
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
|
||||
@ -366,11 +378,26 @@ int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
* @param[in] keep_eol true to keep the CR character in the response
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns line length on success
|
||||
* @returns <0 on error
|
||||
* @retval n line length on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Read a line from device, skipping a possibly empty line.
|
||||
*
|
||||
* @param[in] dev device to operate on
|
||||
* @param[in] resp_buf buffer to store line
|
||||
* @param[in] len size of @p resp_buf
|
||||
* @param[in] keep_eol true to keep the CR character in the response
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @retval n line length on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_readline_skip_empty(at_dev_t *dev, char *resp_buf, size_t len,
|
||||
bool keep_eol, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Drain device input buffer
|
||||
*
|
||||
|
@ -285,6 +285,67 @@ static int remove_urc(int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sneaky_urc(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
int res = 0;
|
||||
char resp_buf[128];
|
||||
|
||||
#ifdef MODULE_AT_URC
|
||||
at_urc_t urc = {.cb = _urc_cb, .code = "+CSCON"};
|
||||
at_add_urc(&at_dev, &urc);
|
||||
#endif
|
||||
|
||||
res = at_send_cmd_wait_ok(&at_dev, "AT+CFUN=1", US_PER_SEC);
|
||||
|
||||
if (res) {
|
||||
puts("Error AT+CFUN=1");
|
||||
res = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = at_send_cmd_get_resp_wait_ok(&at_dev, "AT+CEREG?",
|
||||
"+CEREG:", resp_buf,
|
||||
sizeof(resp_buf), US_PER_SEC);
|
||||
if (res < 0) {
|
||||
puts("Error AT+CEREG?");
|
||||
res = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = at_send_cmd_wait_prompt(&at_dev, "AT+USECMNG=0,0,\"cert\",128", US_PER_SEC);
|
||||
if (res) {
|
||||
puts("Error AT+USECMNG");
|
||||
res = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = at_send_cmd_wait_ok(&at_dev, "AT+CFUN=8", US_PER_SEC);
|
||||
|
||||
if (res != -1) {
|
||||
puts("Error AT+CFUN=8");
|
||||
res = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = at_send_cmd_wait_ok(&at_dev, "AT+CFUN=9", US_PER_SEC);
|
||||
|
||||
if (res != -2) {
|
||||
puts("Error AT+CFUN=9");
|
||||
res = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = 0;
|
||||
exit:
|
||||
#ifdef MODULE_AT_URC
|
||||
at_remove_urc(&at_dev, &urc);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "init", "Initialize AT device", init },
|
||||
{ "send", "Send a command and wait response", send },
|
||||
@ -296,6 +357,7 @@ static const shell_command_t shell_commands[] = {
|
||||
{ "drain", "Drain AT device", drain },
|
||||
{ "power_on", "Power on AT device", power_on },
|
||||
{ "power_off", "Power off AT device", power_off },
|
||||
{ "sneaky_urc", "Test sneaky URC interference", sneaky_urc},
|
||||
#ifdef MODULE_AT_URC
|
||||
{ "add_urc", "Register an URC", add_urc },
|
||||
{ "remove_urc", "De-register an URC", remove_urc },
|
||||
|
85
tests/drivers/at/tests-with-config/sneaky_urc.py
Executable file
85
tests/drivers/at/tests-with-config/sneaky_urc.py
Executable file
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This script simulates a modem sending a "sneaky URC", a URC that happens exactly
|
||||
# after the command is received, but before the first line of answer is sent. This
|
||||
# is possible behavior at least on the U-Blox LTE modules.
|
||||
#
|
||||
# Running this test requires the board to be connected twice
|
||||
# - one connection simulating the modem (e.g.: /dev/ttyUSB0), connected to the
|
||||
# serial device this script is listening to
|
||||
# - one to access the RIOT CLI (e.g.: debugger, USB or a second serial connection)
|
||||
#
|
||||
# How to get it running:
|
||||
# 1. Adapt the `EOL_IN`, `EOL_OUT`, `ECHO_ON` variables below to match your use case
|
||||
# 2. Run this script with the baud rate and the serial dev the device is connected
|
||||
# to, e.g.:
|
||||
# $ ./sneaky_urc 115200 /dev/ttyUSB0
|
||||
# 4. run the test (e.g. make term)
|
||||
# 5. inside the test console:
|
||||
# a) run the `init` command (e.g. init 0 115200)
|
||||
# b) run `sneaky_urc` command
|
||||
#
|
||||
# If the command echoing is enabled, you will miss the URCs, but the commands
|
||||
# should work (e.g. the URC should not interfere with response parsing).
|
||||
#
|
||||
# If command echoing is enabled AND `MODULE_AT_URC` is defined, you should see
|
||||
# *some* of the URCs being parsed.
|
||||
|
||||
import sys
|
||||
import pexpect
|
||||
|
||||
baud = sys.argv[1]
|
||||
ser = sys.argv[2]
|
||||
tty = pexpect.spawn(f'picocom --baud {baud} {ser}')
|
||||
|
||||
# EOL sent by the device
|
||||
EOL_IN = '\r'
|
||||
# EOL to send back to the device
|
||||
EOL_OUT = '\r\n'
|
||||
# Command echoing enabled
|
||||
ECHO_ON = False
|
||||
|
||||
CFUN_CMD = "AT+CFUN=1" + EOL_IN
|
||||
CFUN_ERR_CMD = "AT+CFUN=8" + EOL_IN
|
||||
CFUN_CME_CMD = "AT+CFUN=9" + EOL_IN
|
||||
CEREG_CMD = "AT+CEREG?" + EOL_IN
|
||||
USECMNG_CMD = "AT+USECMNG=0,0,\"cert\",128" + EOL_IN
|
||||
|
||||
while True:
|
||||
try:
|
||||
idx = tty.expect_exact([CFUN_CMD, CFUN_ERR_CMD, CFUN_CME_CMD, CEREG_CMD, USECMNG_CMD])
|
||||
if idx == 0:
|
||||
print(CFUN_CMD)
|
||||
tty.send(EOL_OUT + "+CSCON: 1" + EOL_OUT)
|
||||
if ECHO_ON:
|
||||
tty.send(CFUN_CMD)
|
||||
tty.send(EOL_OUT + "OK" + EOL_OUT)
|
||||
if idx == 1:
|
||||
print(CFUN_ERR_CMD)
|
||||
tty.send(EOL_OUT + "+CSCON: 1" + EOL_OUT)
|
||||
if ECHO_ON:
|
||||
tty.send(CFUN_ERR_CMD)
|
||||
tty.send(EOL_OUT + "ERROR" + EOL_OUT)
|
||||
if idx == 2:
|
||||
print(CFUN_CME_CMD)
|
||||
tty.send(EOL_OUT + "+CSCON: 1" + EOL_OUT)
|
||||
if ECHO_ON:
|
||||
tty.send(CFUN_CME_CMD)
|
||||
tty.send(EOL_OUT + "+CME ERROR:" + EOL_OUT)
|
||||
elif idx == 3:
|
||||
print(CEREG_CMD)
|
||||
tty.send(EOL_OUT + "+CSCON: 1" + EOL_OUT)
|
||||
if ECHO_ON:
|
||||
tty.send(CEREG_CMD)
|
||||
tty.send(EOL_OUT + "+CEREG: 0,1" + EOL_OUT)
|
||||
tty.send(EOL_OUT + "OK" + EOL_OUT)
|
||||
elif idx == 4:
|
||||
print(USECMNG_CMD)
|
||||
tty.send(EOL_OUT + "+CSCON: 1" + EOL_OUT)
|
||||
if ECHO_ON:
|
||||
tty.send(USECMNG_CMD)
|
||||
tty.send(">")
|
||||
except pexpect.EOF:
|
||||
print("ERROR: EOF")
|
||||
except pexpect.TIMEOUT:
|
||||
print("ERROR: TIMEOUT")
|
Loading…
Reference in New Issue
Block a user