DEV: contains() data path added to sequencer (as else) and to cli_device

This commit is contained in:
2021-10-25 15:58:47 +03:00
parent 887bbf391e
commit fce49ee963
2 changed files with 105 additions and 70 deletions
+65 -61
View File
@@ -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);
}
/*!