Completed AT command library

This commit is contained in:
David Cermak
2021-04-19 11:28:53 +02:00
parent 26bde89834
commit 9e8ffbc760
20 changed files with 335 additions and 65 deletions

View File

@ -128,6 +128,12 @@ extern "C" void app_main(void)
CHECK_ERR(dce->get_module_name(module_name), ESP_LOGI(TAG, "OK. Module name: %s", module_name.c_str()));
});
const ConsoleCommand GetOperatorName("get_operator_name", "reads the operator name", no_args, [&](ConsoleCommand *c){
std::string operator_name;
ESP_LOGI(TAG, "Reading operator name...");
CHECK_ERR(dce->get_operator_name(operator_name), ESP_LOGI(TAG, "OK. Operator name: %s", operator_name.c_str()));
});
const struct GenericCommandArgs {
GenericCommandArgs():
cmd(STR1, nullptr, nullptr, "<command>", "AT command to send to the modem"),
@ -163,6 +169,19 @@ extern "C" void app_main(void)
int rssi, ber;
CHECK_ERR(dce->get_signal_quality(rssi, ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber));
});
const ConsoleCommand GetBatteryStatus("get_battery_status", "Reads voltage/battery status", no_args, [&](ConsoleCommand *c){
int volt, bcl, bcs;
CHECK_ERR(dce->get_battery_status(volt, bcl, bcs), ESP_LOGI(TAG, "OK. volt=%d, bcl=%d, bcs=%d", volt, bcl, bcs));
});
const ConsoleCommand PowerDown("power_down", "power down the module", no_args, [&](ConsoleCommand *c){
ESP_LOGI(TAG, "Power down the module...");
CHECK_ERR(dce->power_down(), ESP_LOGI(TAG, "OK"));
});
const ConsoleCommand Reset("reset", "reset the module", no_args, [&](ConsoleCommand *c){
ESP_LOGI(TAG, "Resetting the module...");
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
});
signal_group exit_signal;
const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand *c){
ESP_LOGI(TAG, "Exiting...");

View File

@ -41,6 +41,14 @@ namespace dce_commands {
#undef ESP_MODEM_DECLARE_DCE_COMMAND
/**
* @brief Following commands that are different for some specific modules
*/
command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl);
command_result power_down_sim7xxx(CommandableIf* t);
command_result power_down_sim8xx(CommandableIf* t);
command_result set_data_mode_sim8xx(CommandableIf* t);
/**
* @}
*/

View File

@ -84,7 +84,7 @@ protected:
std::unique_ptr<PdpContext> pdp;
};
// Definitions of other modules
// Definitions of other supported modules with some specific commands overwritten
/**
* @brief Specific definition of the SIM7600 module
@ -93,6 +93,8 @@ class SIM7600: public GenericModule {
using GenericModule::GenericModule;
public:
command_result get_module_name(std::string& name) override;
command_result get_battery_status(int& voltage, int &bcs, int &bcl) override;
command_result power_down() override;
};
/**
@ -102,6 +104,8 @@ class SIM800: public GenericModule {
using GenericModule::GenericModule;
public:
command_result get_module_name(std::string& name) override;
command_result power_down() override;
command_result set_data_mode() override;
};
/**

View File

@ -48,6 +48,7 @@ public:
* @param t unique-ptr to Terminal
*/
explicit DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> t);
explicit DTE(std::unique_ptr<Terminal> t);
~DTE() = default;

View File

@ -20,6 +20,7 @@
// * handle different parameters for C++ and C API
// * make parameter unique names, so they could be easily referenced and forwarded
#define _ARG(param, name) param
#define INT_IN(param, name) int _ARG(param, name)
#ifdef __cplusplus
#include <string>
#define STRING_IN(param, name) const std::string& _ARG(param, name)
@ -39,13 +40,31 @@
#endif
#define DECLARE_ALL_COMMAND_APIS(...) \
/**
* @brief Sends the initial AT sequence to sync up with the device
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(sync, command_result, 0) \
/**
* @brief Reads the operator name
* @param[out] name module name
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_operator_name, command_result, 1, STRING_OUT(x, name)) \
\
/**
* @brief Stores current user profile
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(store_profile, command_result, 0) \
\
/**
* @brief Sets the supplied PIN code
* @param[in] pin Pin
* @return OK, FAIL or TIMEOUT
*/\
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(x, pin)) \
\
\
/**
* @brief Checks if the SIM needs a PIN
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
@ -126,20 +145,63 @@ ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, STRING_OUT(x, imei))
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, STRING_OUT(x, name)) \
\
\
/**
* @brief Sets the modem to data mode
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0) \
\
\
/**
* @brief Get Signal quality
* @param[out] rssi signal strength indication
* @param[out] ber channel bit error rate
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(x, rssi), INT_OUT(y, ber))
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(x, rssi), INT_OUT(y, ber)) \
\
/**
* @brief Sets HW control flow
* @param[in] dce_flow 0=none, 2=RTS hw flow control of DCE
* @param[in] dte_flow 0=none, 2=CTS hw flow control of DTE
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_flow_control, command_result, 2, INT_IN(x, dce_flow), INT_IN(y, dte_flow)) \
\
/**
* @brief Hangs up current data call
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(hang_up, command_result, 0) \
\
/**
* @brief Get voltage levels of modem power up circuitry
* @param[out] voltage Current status in mV
* @param[out] bcs charge status (-1-Not available, 0-Not charging, 1-Charging, 2-Charging done)
* @param[out] bcl 1-100% battery capacity, -1-Not available
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_battery_status, command_result, 3, INT_OUT(x, voltage), INT_OUT(y, bcs), INT_OUT(z, bcl)) \
\
/**
* @brief Power down the module
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(power_down, command_result, 0) \
\
/**
* @brief Reset the module
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(reset, command_result, 0)\
\
/**
* @brief Configures the baudrate
* @param[in] baud Desired baud rate of the DTE
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_baud, command_result, 1, INT_IN(x, baud))
#ifdef GENERATE_DOCS
// cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p'

View File

@ -214,7 +214,6 @@ bool CMux::init()
frame_header_offset = 0;
state = cmux_state::INIT;
term->set_read_cb([this](uint8_t *data, size_t len) {
Scoped<Lock> l(lock);
this->on_cmux(data, len);
return false;
});

View File

@ -40,7 +40,7 @@ static inline command_result generic_command(CommandableIf* t, const std::string
}, timeout_ms);
}
static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string& output, uint32_t timeout_ms)
static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string& output, uint32_t timeout_ms = 500)
{
return t->command(command, [&](uint8_t *data, size_t len) {
size_t pos = 0;
@ -69,12 +69,99 @@ static inline command_result generic_command_common(CommandableIf* t, std::strin
return generic_command(t, command, "OK", "ERROR", timeout);
}
command_result sync(CommandableIf* t)
{
return generic_command_common(t, "AT\r");
}
command_result store_profile(CommandableIf* t)
{
return generic_command_common(t, "AT&W\r");
}
command_result power_down(CommandableIf* t)
{
return generic_command(t, "AT+QPOWD=1\r", "POWERED DOWN", "ERROR", 1000);
}
command_result power_down_sim7xxx(CommandableIf* t)
{
return generic_command_common(t, "AT+CPOF\r", 1000);
}
command_result power_down_sim8xx(CommandableIf* t)
{
return generic_command(t, "AT+CPOWD=1\r", "POWER DOWN", "ERROR", 1000);
}
command_result reset(CommandableIf* t)
{
return generic_command(t, "AT+CRESET\r", "PB DONE", "ERROR", 60000);
}
command_result set_baud(CommandableIf* t, int baud)
{
return generic_command_common(t, "AT+IPR=" + std::to_string(baud) + "\r");
}
command_result hang_up(CommandableIf* t)
{
return generic_command_common(t, "ATH\r", 90000);
}
command_result get_battery_status(CommandableIf* t, int& voltage, int &bcs, int &bcl)
{
std::string out;
auto ret = generic_get_string(t, "AT+CBC\r", out);
if (ret != command_result::OK)
return ret;
if (out.find("+CBC") == std::string::npos)
return command_result::FAIL;
// Parsing +CBC: <bcs>,<bcl>,<voltage>
sscanf(out.c_str(), "%*s%d,%d,%d", &bcs, &bcl, &voltage);
return command_result::OK;
}
command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl)
{
std::string out;
auto ret = generic_get_string(t, "AT+CBC\r", out);
if (ret != command_result::OK)
return ret;
if (out.find("+CBC") == std::string::npos)
return command_result::FAIL;
// Parsing +CBC: <voltage in Volts> V
int volt, fraction;
sscanf(out.c_str(), "+CBC: %d.%dV", &volt, &fraction);
bcl = bcs = -1; // not available for these models
voltage = 1000*volt + fraction;
return command_result::OK;
}
command_result set_flow_control(CommandableIf* t, int dce_flow, int dte_flow)
{
return generic_command_common(t, "AT+IFC=" + std::to_string(dce_flow) + ", " + std::to_string(dte_flow) + "\r");
}
command_result get_operator_name(CommandableIf* t, std::string& operator_name)
{
std::string out;
auto ret = generic_get_string(t, "AT+COPS?\r", out, 75000);
if (ret != command_result::OK)
return ret;
auto pos = out.find("+COPS");
auto property = 0;
while (pos != std::string::npos) {
// Looking for: +COPS: <mode>[, <format>[, <oper>]]
if (property++ == 2) { // operator name is after second comma (as a 3rd property of COPS string)
operator_name = out.substr(++pos);
return command_result::OK;
}
pos = out.find(',', ++pos);
}
return command_result::FAIL;
}
command_result set_echo(CommandableIf* t, bool on)
{
if (on)
@ -94,6 +181,11 @@ command_result set_data_mode(CommandableIf* t)
return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
}
command_result set_data_mode_sim8xx(CommandableIf* t)
{
return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
}
command_result resume_data_mode(CommandableIf* t)
{
return generic_command(t, "ATO\r", "CONNECT", "ERROR", 5000);

View File

@ -19,12 +19,20 @@
using namespace esp_modem;
static const size_t dte_default_buffer_size = 1000;
DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> terminal):
buffer_size(config->dte_buffer_size), consumed(0),
buffer(std::make_unique<uint8_t[]>(buffer_size)),
term(std::move(terminal)), command_term(term.get()), other_term(nullptr),
mode(modem_mode::UNDEF) {}
DTE::DTE(std::unique_ptr<Terminal> terminal):
buffer_size(dte_default_buffer_size), consumed(0),
buffer(std::make_unique<uint8_t[]>(buffer_size)),
term(std::move(terminal)), command_term(term.get()), other_term(nullptr),
mode(modem_mode::UNDEF) {}
command_result DTE::command(const std::string &command, got_line_cb got_line, uint32_t time_ms, const char separator)
{
Scoped<Lock> l(lock);

View File

@ -21,35 +21,57 @@ namespace esp_modem {
GenericModule::GenericModule(std::shared_ptr<DTE> dte, const dce_config *config) :
dte(std::move(dte)), pdp(std::make_unique<PdpContext>(config->apn)) {}
//
// Define preprocessor's forwarding to dce_commands definitions
//
// Helper macros to handle multiple arguments of declared API
#define ARGS0
#define ARGS1 , x
#define ARGS2 , x , y
#define ARGS3 , x , y , z
#define _ARGS(x) ARGS ## x
#define ARGS(x) _ARGS(x)
#define TEMPLATE_ARG
//
// Repeat all declarations and forward to the AT commands defined in esp_modem::dce_commands:: namespace
//
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, ...) \
return_type GenericModule::name(__VA_ARGS__) { return esp_modem::dce_commands::name(dte.get() ARGS(arg_nr) ); }
DECLARE_ALL_COMMAND_APIS(return_type name(...) {
forwards
to
esp_modem::dce_commands::name(...)
})
DECLARE_ALL_COMMAND_APIS(return_type name(...) )
#undef ESP_MODEM_DECLARE_DCE_COMMAND
//
// Handle specific commands for specific supported modems
//
command_result SIM7600::get_module_name(std::string &name) {
name = "7600";
return command_result::OK;
}
command_result SIM7600::get_battery_status(int& voltage, int &bcs, int &bcl) {
return dce_commands::get_battery_status_sim7xxx(dte.get(), voltage, bcs, bcl);
}
command_result SIM7600::power_down() {
return dce_commands::power_down_sim7xxx(dte.get());
}
command_result SIM800::get_module_name(std::string &name) {
name = "800L";
return command_result::OK;
}
command_result SIM800::power_down() {
return dce_commands::power_down_sim8xx(dte.get());
}
command_result SIM800::set_data_mode() {
return dce_commands::set_data_mode_sim8xx(dte.get());
}
command_result BG96::get_module_name(std::string &name) {
name = "BG96";
return command_result::OK;

View File

@ -1,11 +1,19 @@
//
// Created by david on 2/11/21.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_err.h"
#include "esp_event.h"
const char * WIFI_EVENT = "WIFI_EVENT";
const char * IP_EVENT = "IP_EVENT";
@ -14,7 +22,6 @@ esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id,
return ESP_OK;
}
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler)
{
return ESP_OK;

View File

@ -1,16 +1,24 @@
//
// Created by david on 2/9/21.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MDNS_HOST_ESP_EVENT_H
#define MDNS_HOST_ESP_EVENT_H
#include <stdint.h>
#include "esp_netif_ip_addr.h"
#include "esp_netif.h"
#include "esp_err.h"
typedef void * esp_event_base_t;
typedef void * system_event_t;
extern const char * WIFI_EVENT;
@ -19,7 +27,6 @@ extern const char * IP_EVENT;
#define ESP_EVENT_ANY_BASE NULL /**< register handler for any event base */
#define ESP_EVENT_ANY_ID -1 /**< register handler for any event id */
typedef struct {
int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */
esp_netif_t *esp_netif; /*!< Pointer to corresponding esp-netif object */
@ -27,7 +34,6 @@ typedef struct {
int ip_index; /*!< IPv6 address index */
} ip_event_got_ip6_t;
esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg);
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler);

View File

@ -1,6 +1,15 @@
//
// Created by david on 2/9/21.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MDNS_HOST_ESP_EVENT_BASE_H
#define MDNS_HOST_ESP_EVENT_BASE_H
@ -14,4 +23,6 @@ typedef enum {
IP_EVENT_GOT_IP6
} mdns_used_event_t;
typedef void * esp_event_base_t;
#endif //MDNS_HOST_ESP_EVENT_BASE_H

View File

@ -1,16 +1,24 @@
//
// Created by david on 2/7/21.
//
#include<stdio.h>
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
#include "esp_netif.h"
#include "esp_err.h"
#include<string.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include <sys/types.h>
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include<stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
#include "esp_netif.h"
#include "esp_err.h"
esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key)
{
@ -31,19 +39,12 @@ esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_stat
esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
{
struct ifaddrs *addrs, *tmp;
getifaddrs(&addrs);
tmp = addrs;
while (tmp)
{
// if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET)
// {
// struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
// printf("%s: %s\n", tmp->ifa_name, inet_ntoa(pAddr->sin_addr));
// } else
if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) {
char addr[64];
struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr;

View File

@ -15,12 +15,14 @@
#define _HOST_ESP_NETIF_H_
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "esp_netif_ip_addr.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_event_base.h"
struct esp_netif_obj {};
typedef struct esp_netif_obj esp_netif_t;
typedef struct esp_netif_driver_base_s {
esp_err_t (*post_attach)(esp_netif_t *netif, void* h);
@ -34,8 +36,6 @@ struct esp_netif_driver_ifconfig {
void (*driver_free_rx_buffer)(void *h, void* buffer);
};
typedef struct esp_netif_obj esp_netif_t;
/** @brief Status of DHCP client or DHCP server */
typedef enum {
ESP_NETIF_DHCP_INIT = 0, /**< DHCP client/server is in initial state (not yet started) */

View File

@ -1,3 +1,16 @@
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
typedef int uart_port_t;

View File

@ -1,6 +1,15 @@
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
#include "esp_system_common_declares.h"
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
typedef int esp_err_t;
@ -14,4 +23,3 @@ typedef int esp_err_t;
#define ESP_ERR_NOT_FOUND 0x105
#define ESP_ERR_NOT_SUPPORTED 0x106
#define ESP_ERR_TIMEOUT 0x107
#define ESP_ERR_INVALID_RESPONSE 0x

View File

@ -1,6 +1,15 @@
//
// Created by david on 2/10/21.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MDNS_HOST_ESP_LOG_H
#define MDNS_HOST_ESP_LOG_H

View File

@ -1,13 +0,0 @@
//
// Created by david on 2/17/21.
//
#ifndef MDNS_HOST_ESP_SYSTEM_COMMON_DECLARES_H
#define MDNS_HOST_ESP_SYSTEM_COMMON_DECLARES_H
struct esp_netif_obj;
typedef struct esp_netif_obj esp_netif_t;
#endif //MDNS_HOST_ESP_SYSTEM_COMMON_DECLARES_H

View File

@ -1,6 +1,15 @@
//
// Created by david on 2/17/21.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MDNS_HOST_ENDIAN_H
#define MDNS_HOST_ENDIAN_H

View File

@ -42,8 +42,12 @@ public:
return len;
}
}
if (len > 2 && data[0] == 0xf9 && data[2] == 0xef) { // Simple CMUX responder
data[2] = 0xff; // turn the request into a reply -> implements CMUX loopback
if (len > 2 && data[0] == 0xf9) { // Simple CMUX responder
// turn the request into a reply -> implements CMUX loopback
if (data[2] == 0x3f) // SABM command
data[2] = 0x73;
else if (data[2] == 0xef) // Generic request
data[2] = 0xff; // generic reply
}
loopback_data.resize(data_len + len);
memcpy(&loopback_data[data_len], data, len);
@ -82,7 +86,7 @@ TEST_CASE("DTE send/receive command", "[esp_modem]")
const auto test_command = "Test\n";
CHECK(term == nullptr);
dte->set_mode(esp_modem::modem_mode::COMMAND_MODE);
CHECK(dte->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true);
auto ret = dte->command(test_command, [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);