|
|
@@ -124,7 +124,8 @@ class cli_device |
|
|
|
//! Publish delimiter
|
|
|
|
constexpr static char delimiter = Delimiter;
|
|
|
|
|
|
|
|
enum flush_type { keep =0, flush };
|
|
|
|
enum Flush_t { Keep =0, Flush };
|
|
|
|
enum Receive_t { Get =0, Detect };
|
|
|
|
|
|
|
|
//! Required types for inetd async handler operation
|
|
|
|
//! @{
|
|
|
@@ -247,7 +248,7 @@ class cli_device |
|
|
|
* \param token Pointer to store the parsed tokens
|
|
|
|
* \return A (number of characters parsed, marker found) pair
|
|
|
|
*/
|
|
|
|
template <char Marker = '%'>
|
|
|
|
template <char Marker>
|
|
|
|
std::pair<size_t, bool> parse_ (const char* expected, const string_view buffer, char* token) {
|
|
|
|
do {
|
|
|
|
if (*expected == Marker) {
|
|
|
@@ -273,53 +274,22 @@ class cli_device |
|
|
|
return std::make_pair(0, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Analyze the response of a command based on \c expected.
|
|
|
|
*
|
|
|
|
* Tries to receive data with timeout and match them against expected string_view.
|
|
|
|
* For each Marker inside the expected string the value gets extracted, converted and
|
|
|
|
* copied to \c vargs pointer array.
|
|
|
|
*
|
|
|
|
* \param expected The expected string view
|
|
|
|
* \param timeout the timeout in CPU time
|
|
|
|
* \param vargs Pointer to variable arguments array
|
|
|
|
* \param nargs Size of variable arguments array
|
|
|
|
* \return
|
|
|
|
*/
|
|
|
|
template<char Marker = '%', typename T>
|
|
|
|
bool response_ (const string_view expected, clock_t timeout, T* vargs, size_t nargs) {
|
|
|
|
char buffer[N], token[N], *pbuffer = buffer;
|
|
|
|
|
|
|
|
size_t v =0, sz =0;
|
|
|
|
for (auto ex = expected.begin() ; ex != expected.end() ; ) {
|
|
|
|
clock_t mark = clock(); // mark the time
|
|
|
|
while (sz <= 0) { // if buffer is empty get buffer with timeout
|
|
|
|
sz = receive(buffer);
|
|
|
|
pbuffer = buffer;
|
|
|
|
if ((timeout != 0 )&& ((clock() - mark) >= timeout))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// try to parse
|
|
|
|
auto [step, marker] = parse_<Marker> (ex, {pbuffer, sz}, token);
|
|
|
|
if (!step)
|
|
|
|
return false; // discard buffer and fail
|
|
|
|
|
|
|
|
if (marker && v < nargs)
|
|
|
|
extract_(token, vargs[v++]);
|
|
|
|
|
|
|
|
pbuffer += step;
|
|
|
|
sz -= (step <= sz) ? step: sz;
|
|
|
|
++ex;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//! @}
|
|
|
|
|
|
|
|
//! \name public functionality
|
|
|
|
//! @{
|
|
|
|
public:
|
|
|
|
|
|
|
|
//! Clears the incoming data buffer
|
|
|
|
void clear () noexcept {
|
|
|
|
rx_q.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
//! \return Returns the size of the incoming data buffer
|
|
|
|
size_t size() noexcept {
|
|
|
|
return rx_q.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief
|
|
|
|
* Transmit data to modem
|
|
|
@@ -370,14 +340,48 @@ class cli_device |
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Clears the incoming data buffer
|
|
|
|
void clear () noexcept {
|
|
|
|
rx_q.clear();
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* Analyze the response of a command based on \c expected.
|
|
|
|
*
|
|
|
|
* Tries to receive data via get() path with timeout and match them against expected string_view.
|
|
|
|
* For each Marker inside the expected string the value gets extracted, converted and
|
|
|
|
* copied to \c vargs pointer array.
|
|
|
|
*
|
|
|
|
* \param expected The expected string view
|
|
|
|
* \param timeout the timeout in CPU time
|
|
|
|
* \param vargs Pointer to variable arguments array
|
|
|
|
* \param nargs Size of variable arguments array
|
|
|
|
* \return
|
|
|
|
*/
|
|
|
|
template<Receive_t Recv, char Marker, typename T>
|
|
|
|
bool response (const string_view expected, clock_t timeout, T* vargs, size_t nargs) {
|
|
|
|
char buffer[N], token[N], *pbuffer = buffer;
|
|
|
|
|
|
|
|
//! \return Returns the size of the incoming data buffer
|
|
|
|
size_t size() noexcept {
|
|
|
|
return rx_q.size();
|
|
|
|
size_t v =0, sz =0;
|
|
|
|
for (auto ex = expected.begin() ; ex != expected.end() ; ) {
|
|
|
|
clock_t mark = clock(); // mark the time
|
|
|
|
while (sz <= 0) { // if buffer is empty get buffer with timeout
|
|
|
|
if constexpr (Recv == Get)
|
|
|
|
sz = receive(buffer);
|
|
|
|
else
|
|
|
|
sz = contents(buffer);
|
|
|
|
pbuffer = buffer;
|
|
|
|
if ((timeout != 0 )&& ((clock() - mark) >= timeout))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// try to parse
|
|
|
|
auto [step, marker] = parse_<Marker> (ex, {pbuffer, sz}, token);
|
|
|
|
if (!step)
|
|
|
|
return false; // discard buffer and fail
|
|
|
|
|
|
|
|
if (marker && v < nargs)
|
|
|
|
extract_(token, vargs[v++]);
|
|
|
|
|
|
|
|
pbuffer += step;
|
|
|
|
sz -= (step <= sz) ? step: sz;
|
|
|
|
++ex;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
@@ -387,7 +391,7 @@ class cli_device |
|
|
|
* This function executes 3 steps.
|
|
|
|
* - Clears the incoming buffer if requested by template parameter
|
|
|
|
* - Sends the command to device
|
|
|
|
* - Waits to get the response and parse it accordingly to \c expected \see response_()
|
|
|
|
* - Waits to get the response and parse it accordingly to \c expected \see response()
|
|
|
|
*
|
|
|
|
* The user can mark spots inside the expected string using the \c Marker ['%'] character.
|
|
|
|
* These spots will be extracted to tokens upon parsing. If the user passes \c values parameters,
|
|
|
@@ -399,7 +403,7 @@ class cli_device |
|
|
|
* \param timeout The timeout in CPU time (leave it for 0 - no timeout)
|
|
|
|
* \param values The value pointer arguments to get the converted tokens
|
|
|
|
*
|
|
|
|
* \tparam Flush Flag to indicate if we flush the buffer before command or not
|
|
|
|
* \tparam Flush Flag to indicate if we Flush the buffer before command or not
|
|
|
|
* \tparam Marker The marker character
|
|
|
|
* \tparam Ts The type of the values to read from response marked with \c Marker
|
|
|
|
* \warning The types MUST be the same
|
|
|
@@ -416,31 +420,31 @@ class cli_device |
|
|
|
* cli.command("AT+CREG?\r\n", "%%%OK\r\n", 1000);
|
|
|
|
*
|
|
|
|
* // extract a number from response without timeout (blocking)
|
|
|
|
* cli.command<flush>("AT+CREG?\r\n", "\r\n+CREG: 0,%\r\n\r\nOK\r\n", 0, &status);
|
|
|
|
* cli.command<Flush>("AT+CREG?\r\n", "\r\n+CREG: 0,%\r\n\r\nOK\r\n", 0, &status);
|
|
|
|
*
|
|
|
|
* // extract a number and discard the last 2 lines
|
|
|
|
* cli.command<flush>("AT+CREG?\r\n", "\r\n+CREG: 0,%\r\n%%", 1000, &status);
|
|
|
|
* cli.command<Flush>("AT+CREG?\r\n", "\r\n+CREG: 0,%\r\n%%", 1000, &status);
|
|
|
|
*
|
|
|
|
* // discard first line, read the 2nd to str, discard the 3rd line.
|
|
|
|
* // expect the last to be "OK\r\n"
|
|
|
|
* cli.command<flush>("AT+CREG?\r\n", "", 100000);
|
|
|
|
* cli.command<keep>("", "%", 1000);
|
|
|
|
* cli.command<keep>("", "%%", 1000, str);
|
|
|
|
* cli.command<keep>("", "OK\r\n", 1000);
|
|
|
|
* cli.command<Flush>("AT+CREG?\r\n", "", 100000);
|
|
|
|
* cli.command<Keep>("", "%", 1000);
|
|
|
|
* cli.command<Keep>("", "%%", 1000, str);
|
|
|
|
* cli.command<Keep>("", "OK\r\n", 1000);
|
|
|
|
* \endcode
|
|
|
|
*/
|
|
|
|
template<flush_type Flush =flush, char Marker = '%', typename ...Ts>
|
|
|
|
template<Receive_t Recv =Get, Flush_t Flsh =Flush, char Marker = '%', typename ...Ts>
|
|
|
|
bool command (const string_view cmd, const string_view expected, clock_t timeout, Ts* ...values) {
|
|
|
|
constexpr size_t Nr = sizeof...(Ts);
|
|
|
|
|
|
|
|
front<typelist<Ts...>>* vargs[Nr] = {values...}; // read all args to local buffer
|
|
|
|
if constexpr (Flush == flush) {
|
|
|
|
if constexpr (Flsh == Flush) {
|
|
|
|
clear ();
|
|
|
|
}
|
|
|
|
if (transmit(cmd.data(), cmd.size()) != cmd.size()) // send command
|
|
|
|
return false;
|
|
|
|
// parse the response and return the status
|
|
|
|
return response_<Marker>(expected, timeout, vargs, Nr);
|
|
|
|
return response<Recv, Marker>(expected, timeout, vargs, Nr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|