ublox: new +UGCNTRD? response parser

The parser returns only the results for the CID being specified as input. This
is so that we can just query the statistics of the CID currently in use by the
bearer.
This commit is contained in:
Aleksander Morgado
2016-08-15 12:14:19 +02:00
parent 1775544dbc
commit e6e53467ee
3 changed files with 181 additions and 0 deletions

View File

@@ -956,3 +956,93 @@ mm_ublox_build_urat_set_command (MMModemMode allowed,
return g_string_free (command, FALSE);
}
/*****************************************************************************/
/* +UGCNTRD response parser */
gboolean
mm_ublox_parse_ugcntrd_response_for_cid (const gchar *response,
guint in_cid,
guint *out_session_tx_bytes,
guint *out_session_rx_bytes,
guint *out_total_tx_bytes,
guint *out_total_rx_bytes,
GError **error)
{
GRegex *r;
GMatchInfo *match_info;
GError *inner_error = NULL;
guint session_tx_bytes = 0;
guint session_rx_bytes = 0;
guint total_tx_bytes = 0;
guint total_rx_bytes = 0;
gboolean matched = FALSE;
/* Response may be e.g.:
* +UGCNTRD: 31,2704,1819,2724,1839
* We assume only ONE line is returned.
*/
r = g_regex_new ("\\+UGCNTRD:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)",
G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL);
g_assert (r != NULL);
g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
while (!inner_error && g_match_info_matches (match_info)) {
guint cid = 0;
/* Matched CID? */
if (!mm_get_uint_from_match_info (match_info, 1, &cid) || cid != in_cid) {
g_match_info_next (match_info, &inner_error);
continue;
}
if (out_session_tx_bytes && !mm_get_uint_from_match_info (match_info, 2, &session_tx_bytes)) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing session TX bytes");
goto out;
}
if (out_session_rx_bytes && !mm_get_uint_from_match_info (match_info, 3, &session_rx_bytes)) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing session RX bytes");
goto out;
}
if (out_total_tx_bytes && !mm_get_uint_from_match_info (match_info, 4, &total_tx_bytes)) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing total TX bytes");
goto out;
}
if (out_total_rx_bytes && !mm_get_uint_from_match_info (match_info, 5, &total_rx_bytes)) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing total RX bytes");
goto out;
}
matched = TRUE;
break;
}
if (!matched) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "No statistics found for CID %u", in_cid);
goto out;
}
out:
if (match_info)
g_match_info_free (match_info);
g_regex_unref (r);
if (inner_error) {
g_propagate_error (error, inner_error);
return FALSE;
}
if (out_session_tx_bytes)
*out_session_tx_bytes = session_tx_bytes;
if (out_session_rx_bytes)
*out_session_rx_bytes = session_rx_bytes;
if (out_total_tx_bytes)
*out_total_tx_bytes = total_tx_bytes;
if (out_total_rx_bytes)
*out_total_rx_bytes = total_rx_bytes;
return TRUE;
}

View File

@@ -126,4 +126,15 @@ gchar *mm_ublox_build_urat_set_command (MMModemMode allowed,
MMModemMode preferred,
GError **error);
/*****************************************************************************/
/* +UGCNTRD response parser */
gboolean mm_ublox_parse_ugcntrd_response_for_cid (const gchar *response,
guint in_cid,
guint *session_tx_bytes,
guint *session_rx_bytes,
guint *total_tx_bytes,
guint *total_rx_bytes,
GError **error);
#endif /* MM_MODEM_HELPERS_UBLOX_H */

View File

@@ -724,6 +724,84 @@ test_ubandsel_request_1800 (void)
common_validate_ubandsel_request (bands, G_N_ELEMENTS (bands), "+UBANDSEL=1800");
}
/*****************************************************************************/
/* Test +UGCNTRD responses */
typedef struct {
const gchar *str;
guint cid;
guint session_tx_bytes;
guint session_rx_bytes;
guint total_tx_bytes;
guint total_rx_bytes;
} UgcntrdResponseTest;
static const UgcntrdResponseTest ugcntrd_response_tests[] = {
{
.str = "+UGCNTRD: 1, 100, 0, 100, 0",
.cid = 1,
.session_tx_bytes = 100,
.session_rx_bytes = 0,
.total_tx_bytes = 100,
.total_rx_bytes = 0
},
{
.str = "+UGCNTRD: 31,2704,1819,2724,1839",
.cid = 31,
.session_tx_bytes = 2704,
.session_rx_bytes = 1819,
.total_tx_bytes = 2724,
.total_rx_bytes = 1839
},
{
.str = "+UGCNTRD: 1, 100, 0, 100, 0\r\n"
"+UGCNTRD: 31,2704,1819,2724,1839\r\n",
.cid = 1,
.session_tx_bytes = 100,
.session_rx_bytes = 0,
.total_tx_bytes = 100,
.total_rx_bytes = 0
},
{
.str = "+UGCNTRD: 1, 100, 0, 100, 0\r\n"
"+UGCNTRD: 31,2704,1819,2724,1839\r\n",
.cid = 31,
.session_tx_bytes = 2704,
.session_rx_bytes = 1819,
.total_tx_bytes = 2724,
.total_rx_bytes = 1839
}
};
static void
test_ugcntrd_response (void)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (ugcntrd_response_tests); i++) {
GError *error = NULL;
gboolean success;
guint session_tx_bytes = G_MAXUINT;
guint session_rx_bytes = G_MAXUINT;
guint total_tx_bytes = G_MAXUINT;
guint total_rx_bytes = G_MAXUINT;
success = mm_ublox_parse_ugcntrd_response_for_cid (ugcntrd_response_tests[i].str,
ugcntrd_response_tests[i].cid,
&session_tx_bytes,
&session_rx_bytes,
&total_tx_bytes,
&total_rx_bytes,
&error);
g_assert_no_error (error);
g_assert (success);
g_assert_cmpuint (ugcntrd_response_tests[i].session_tx_bytes, ==, session_tx_bytes);
g_assert_cmpuint (ugcntrd_response_tests[i].session_rx_bytes, ==, session_rx_bytes);
g_assert_cmpuint (ugcntrd_response_tests[i].total_tx_bytes, ==, total_tx_bytes);
g_assert_cmpuint (ugcntrd_response_tests[i].total_rx_bytes, ==, total_rx_bytes);
}
}
/*****************************************************************************/
void
@@ -780,5 +858,7 @@ int main (int argc, char **argv)
g_test_add_func ("/MM/ublox/ubandsel/request/2g", test_ubandsel_request_2g);
g_test_add_func ("/MM/ublox/ubandsel/request/1800", test_ubandsel_request_1800);
g_test_add_func ("/MM/ublox/ugcntrd/response", test_ugcntrd_response);
return g_test_run ();
}