Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Diagnostics] Signal strength/quality #1423

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
56b2db0
FixedPointSQ should count sign bit as part of M bits
avtolstoy Nov 2, 2017
8908876
Adds RAT-specific parameters to NetStatus according to 3GPP TS 45.008…
avtolstoy Nov 2, 2017
6aee4d8
Fill in RAT-specific quality parameters according to the current RAT …
avtolstoy Nov 2, 2017
b70f91a
Adds new cellular_signal_t struct that exposes raw RAT-specific quali…
avtolstoy Nov 2, 2017
d14c19c
cellular_signal() should not take a reference, as it is a C function.…
avtolstoy Nov 2, 2017
6a1ab90
Adds SYSTEM_ERROR_INVALID_ARGUMENT
avtolstoy Nov 2, 2017
cba95fd
cellular_signal(): cellular_signal_t filling
avtolstoy Nov 2, 2017
9848ca3
NET_ACCESS_TECHONOLOGY_ enum
avtolstoy Nov 2, 2017
1938c26
Adds common Signal base class to be used by Cellular and WiFi classes…
avtolstoy Nov 2, 2017
aea33bc
Updates CellularSignal to use Signal as a base class and report signa…
avtolstoy Nov 2, 2017
07f6b17
wlan: adds wlan_connected_info() function definition
avtolstoy Nov 2, 2017
280d674
photon: Adds wlan_connected_info() implementation reporting RSSI, noi…
avtolstoy Nov 2, 2017
7d43a26
Adds WiFiSignal class
avtolstoy Nov 2, 2017
270fa29
core: wlan_connected_info() implementation
avtolstoy Nov 2, 2017
7fbf1a8
Adds wlan_connected_info stubs
avtolstoy Nov 2, 2017
6a691f4
Minor fixes
avtolstoy Nov 2, 2017
a7bb79a
Updates system_display_rssi() to use signal strength to calculate bar…
avtolstoy Nov 2, 2017
467f4a5
Superseding net.rssi diagnostic data source:
avtolstoy Nov 2, 2017
a103e88
Fixes diagnostics IDs
avtolstoy Nov 2, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hal/inc/cellular_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void cellular_cancel(bool cancel, bool calledFromISR, void* reserved);
/**
* Retrieve cellular signal strength info
*/
cellular_result_t cellular_signal(CellularSignalHal &signal, void* reserved);
cellular_result_t cellular_signal(CellularSignalHal* signal, cellular_signal_t* reserved);

/**
* Send an AT command and wait for response, optionally specify a callback function to parse the results
Expand Down
36 changes: 28 additions & 8 deletions hal/inc/cellular_hal_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,35 @@ struct CellularDevice
typedef struct CellularDevice CellularDevice;
#endif

#ifdef __cplusplus
struct CellularSignalHal
typedef struct
{
int rssi = 0;
int qual = 0;
};
#else
typedef struct CellularSignalHal CellularSignalHal;
#endif
int rssi;
int qual;
} CellularSignalHal;

typedef struct
{
uint16_t size;
uint16_t version;
uint8_t rat;
union {
int32_t rssi; // Generic accessor, GSM
int32_t rscp; // UMTS
int32_t rsrq; // LTE
};
// In % mapped to [0, 65535]
int32_t strength;

union {
int32_t qual; // Generic accessor
int32_t ber; // GSM
int32_t bep; // EDGE
int32_t ecno; // UMTS
int32_t rsrp; // LTE
};
// In % mapped to [0, 65535]
int32_t quality;
} cellular_signal_t;

#ifdef __cplusplus
struct CellularDataHal {
Expand Down
2 changes: 1 addition & 1 deletion hal/inc/hal_dynalib_cellular.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ DYNALIB_FN(13, hal_cellular, cellular_cancel, void(bool, bool, void*))
DYNALIB_FN(14, hal_cellular, HAL_NET_SetNetWatchDog, uint32_t(uint32_t))
DYNALIB_FN(15, hal_cellular, inet_gethostbyname, int(const char*, uint16_t, HAL_IPAddress*, network_interface_t, void*))
DYNALIB_FN(16, hal_cellular, inet_ping, int(const HAL_IPAddress*, network_interface_t, uint8_t, void*))
DYNALIB_FN(17, hal_cellular, cellular_signal, cellular_result_t(CellularSignalHal&, void*))
DYNALIB_FN(17, hal_cellular, cellular_signal, cellular_result_t(CellularSignalHal*, cellular_signal_t*))
DYNALIB_FN(18, hal_cellular, cellular_command, cellular_result_t(_CALLBACKPTR_MDM, void*, system_tick_t, const char*, ...))
DYNALIB_FN(19, hal_cellular, cellular_data_usage_set, cellular_result_t(CellularDataHal*,void*))
DYNALIB_FN(20, hal_cellular, cellular_data_usage_get, cellular_result_t(CellularDataHal*,void*))
Expand Down
1 change: 1 addition & 0 deletions hal/inc/hal_dynalib_wlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ DYNALIB_FN(25, hal_wlan, softap_set_application_page_handler, int(PageProvider*
DYNALIB_FN(26, hal_wlan, wlan_restart, int(void*))
DYNALIB_FN(27, hal_wlan, wlan_set_hostname, int(const char*, void*))
DYNALIB_FN(28, hal_wlan, wlan_get_hostname, int(char*, size_t, void*))
DYNALIB_FN(29, hal_wlan, wlan_connected_info, int(void*, wlan_connected_info_t*, void*))
DYNALIB_END(hal_wlan)

#endif // PLATFORM_ID != 10
Expand Down
12 changes: 12 additions & 0 deletions hal/inc/net_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ void HAL_NET_notify_dhcp(bool dhcp);

void HAL_NET_notify_can_shutdown();

typedef enum {
NET_ACCESS_TECHNOLOGY_UNKNOWN = 0,
NET_ACCESS_TECHNOLOGY_NONE = 0,
NET_ACCESS_TECHNOLOGY_WIFI = 1,
NET_ACCESS_TECHNOLOGY_GSM = 2,
NET_ACCESS_TECHNOLOGY_EDGE = 3,
NET_ACCESS_TECHNOLOGY_UMTS = 4,
NET_ACCESS_TECHNOLOGY_UTRAN = 4,
NET_ACCESS_TECHNOLOGY_WCDMA = 4,
NET_ACCESS_TECHNOLOGY_CDMA = 5,
NET_ACCESS_TECHNOLOGY_LTE = 6
} hal_net_access_tech_t;

#ifdef __cplusplus
}
Expand Down
16 changes: 16 additions & 0 deletions hal/inc/wlan_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@ wlan_result_t wlan_deactivate();
*/
int wlan_connected_rssi();

typedef struct {
uint16_t size;
uint16_t version;

int32_t rssi;
// In % mapped to [0, 65535]
int32_t strength;

int32_t snr;
int32_t noise;
// In % mapped to [0, 65535]
int32_t quality;
} wlan_connected_info_t;

int wlan_connected_info(void* reserved, wlan_connected_info_t* inf, void* reserved1);

int wlan_clear_credentials();
int wlan_has_credentials();

Expand Down
58 changes: 44 additions & 14 deletions hal/src/core/wlan_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@
#include "spark_macros.h"
#include "security.h"
#include "evnt_handler.h"

#include "timer_hal.h"
#include <sys/param.h>
#include "system_error.h"
#include <limits.h>

/* Smart Config Prefix */
static char aucCC3000_prefix[] = {'T', 'T', 'T'};
Expand Down Expand Up @@ -166,26 +169,53 @@ wlan_result_t wlan_disconnect_now()

int wlan_connected_rssi()
{
tNetappIpconfigRetArgs config;
netapp_ipconfig((void*)&config);

int _returnValue = 0;
int l;
for (l=0; l<16; l++)
{
char wlan_scan_results_table[50];
if(wlan_ioctl_get_scan_results(0, (unsigned char*)wlan_scan_results_table) != 0)
return(1);
if (wlan_scan_results_table[0] == 0)
break;
if (!strcmp(wlan_scan_results_table+12, config.uaSSID)) {
_returnValue = ((wlan_scan_results_table[8] >> 1) - 127);

system_tick_t _functionStart = HAL_Timer_Get_Milli_Seconds();
while ((HAL_Timer_Get_Milli_Seconds() - _functionStart) < 1000) {
tNetappIpconfigRetArgs config;
netapp_ipconfig((void*)&config);
int l;
for (l=0; l<16; l++)
{
char wlan_scan_results_table[50];
if(wlan_ioctl_get_scan_results(0, (unsigned char*)wlan_scan_results_table) != 0) {
_returnValue = 1;
break;
}
if (wlan_scan_results_table[0] == 0)
break;
if (!strcmp(wlan_scan_results_table+12, config.uaSSID)) {
_returnValue = ((wlan_scan_results_table[8] >> 1) - 127);
break;
}
}
if (_returnValue != 0) {
break;
}
}
return _returnValue;
}

int wlan_connected_info(void* reserved, wlan_connected_info_t* inf, void* reserved1)
{
system_error_t ret = SYSTEM_ERROR_NONE;

int32_t rssi = wlan_connected_rssi();
if (rssi >= 0) {
// Error
return SYSTEM_ERROR_UNKNOWN;
}

inf->rssi = rssi * 100;
inf->snr = INT_MIN;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should have flags to indicate which fields are supported.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add flags to explicitly indicate which fields are supported?

inf->noise = INT_MIN;

inf->strength = MIN(MAX(2 * (rssi + 100), 0L), 100L) * 65535 / 100;
inf->quality = INT_MIN;
return ret;
}

netapp_pingreport_args_t ping_report;
uint8_t ping_report_num;

Expand Down
92 changes: 88 additions & 4 deletions hal/src/electron/cellular_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#include "modem/mdm_hal.h"
#include "cellular_hal.h"
#include "cellular_internal.h"
#include "system_error.h"
#include <limits>
#include <cmath>
#include "net_hal.h"

#define CHECK_SUCCESS(x) { if (!(x)) return -1; }

Expand Down Expand Up @@ -176,13 +180,93 @@ void cellular_cancel(bool cancel, bool calledFromISR, void*)
}
}

cellular_result_t cellular_signal(CellularSignalHal &signal, void* reserved)
cellular_result_t cellular_signal(CellularSignalHal* signal, cellular_signal_t* signalext)
{
// % * 100, see 3GPP TS 45.008 8.2.4
// 0.14%, 0.28%, 0.57%, 1.13%, 2.26%, 4.53%, 9.05%, 18.10%
static const uint16_t berMapping[] = {14, 28, 57, 113, 226, 453, 905, 1810};

cellular_result_t res = SYSTEM_ERROR_NONE;
if (signal == nullptr && signalext == nullptr) {
return SYSTEM_ERROR_INVALID_ARGUMENT;
}
NetStatus status;
CHECK_SUCCESS(electronMDM.getSignalStrength(status));
signal.rssi = status.rssi;
signal.qual = status.qual;
return 0;
if (signal != nullptr) {
signal->rssi = status.rssi;
signal->qual = status.qual;
}

if (signalext != nullptr) {
switch (status.act) {
case ACT_GSM:
signalext->rat = NET_ACCESS_TECHNOLOGY_GSM;
break;
case ACT_EDGE:
signalext->rat = NET_ACCESS_TECHNOLOGY_EDGE;
break;
case ACT_UTRAN:
signalext->rat = NET_ACCESS_TECHNOLOGY_UTRAN;
break;
default:
signalext->rat = NET_ACCESS_TECHNOLOGY_NONE;
break;
}
switch (status.act) {
case ACT_GSM:
case ACT_EDGE:
// Convert to dBm [-111, -48], see 3GPP TS 45.008 8.1.4
// Reported multiplied by 100
signalext->rssi = ((status.rxlev != 99) ? status.rxlev - 111 : -111) * 100;

// NOTE: From u-blox AT Command Reference manual:
// SARA-U260-00S / SARA-U270-00S / SARA-U270-00X / SARA-U280-00S / LISA-U200-00S /
// LISA-U200-01S / LISA-U200-02S / LISA-U200-52S / LISA-U200-62S / LISA-U230 / LISA-U260 /
// LISA-U270 / LISA-U1
// The <qual> parameter is not updated in GPRS and EGPRS packet transfer mode
if (status.act == ACT_GSM) {
// Convert to BER (% * 100), see 3GPP TS 45.008 8.2.4
signalext->ber = (status.rxqual != 99) ? berMapping[status.rxqual] : std::numeric_limits<int32_t>::min();
} else /* status.act == ACT_EDGE */ {
// Convert to MEAN_BEP level first
// See u-blox AT Reference Manual:
// In 2G RAT EGPRS packet transfer mode indicates the Mean Bit Error Probability (BEP) of a radio
// block. 3GPP TS 45.008 [148] specifies the range 0-31 for the Mean BEP which is mapped to
// the range 0-7 of <qual>
int bepLevel = (status.rxqual != 99) ? (7 - status.rxqual) * 31 / 7 : std::numeric_limits<int32_t>::min();
// Convert to log10(MEAN_BEP) multiplied by 100, see 3GPP TS 45.008 10.2.3.3
// Uses QPSK table
signalext->bep = bepLevel >= 0 ? (-(bepLevel - 31) * 10 - 3.7) : bepLevel;
}

// RSSI in % [0, 100] based on [-111, -48] range mapped to [0, 65535] integer range
signalext->strength = (status.rxlev != 99) ? status.rxlev * 65535 / 63 : std::numeric_limits<int32_t>::min();
// Quality based on RXQUAL in % [0, 100] mapped to [0, 65535] integer range
signalext->quality = (status.rxqual != 99) ? (7 - status.rxqual) * 65535 / 7 : std::numeric_limits<int32_t>::min();
break;
case ACT_UTRAN:
// Convert to dBm [-121, -25], see 3GPP TS 25.133 9.1.1.3
// Reported multiplied by 100
signalext->rscp = ((status.rscp != 255) ? status.rscp - 116 : -121) * 100;
// Convert to Ec/Io (dB) [-24.5, 0], see 3GPP TS 25.133 9.1.2.3
// Report multiplied by 100
signalext->ecno = (status.ecno != 255) ? status.ecno * 50 - 2450 : -2450;

// RSCP in % [0, 100] based on [-121, -25] range mapped to [0, 65535] integer range
signalext->strength = (status.rscp != 255) ? (status.rscp + 5) * 65535 / 96 : std::numeric_limits<int32_t>::min();
// Quality based on Ec/Io in % [0, 100] mapped to [0,65535] integer range
signalext->quality = (status.ecno != 255) ? status.ecno * 65535 / 49 : std::numeric_limits<int32_t>::min();
break;
default:
res = SYSTEM_ERROR_UNKNOWN;
signalext->rssi = std::numeric_limits<int32_t>::min();
signalext->qual = std::numeric_limits<int32_t>::min();
signalext->strength = 0;
signalext->quality = 0;
break;
}
}
return res;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps factor out fetching the data from the modem from computing the percentages so that the computation can be more easily tested.

}

cellular_result_t cellular_command(_CALLBACKPTR_MDM cb, void* param,
Expand Down
14 changes: 14 additions & 0 deletions hal/src/electron/modem/enums_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ typedef struct {
int qual; //!< In UMTS RAT indicates the Energy per Chip/Noise ratio in dB levels
//!< of the current cell (see <ecn0_ lev> in +CGED command description),
//!< see 3GPP TS 45.008 [20] subclause 8.2.4
union {
int rxlev; //!< GSM RAT: RXLEV ([0, 63], 99), see 3GPP TS 45.008 subclause 8.1.4
int rscp; //!< UMTS RAT: RSCP ([-5, 91], 255), see 3GPP TS 25.133 subclause 9.1.1.3
int rsrp; //!< LTE RAT: RSRP ([0, 95], 255), see 3GPP TS 36.133 subclause 9.1.7
int asu; //!< Abstract accessor
};

union {
int rxqual; //!< GSM RAT: RXQUAL ([0, 7], 99), see 3GPP TS 45.008 subclause 8.2.4
int ecno; //!< UMTS RAT: ECNO ([0, 49], 255), see 3GPP TS 25.133 subclause 9.1.2.3
int rsrq; //!< LTE RAT: RSRQ ([0, 97], 255), see 3GPP TS 36.133 subclause 9.1.4
int aqual; //!< Abstract accessor
};

char opr[16+1]; //!< Operator Name
char num[32]; //!< Mobile Directory Number
unsigned short lac; //!< location area code in hexadecimal format (2 bytes in hex)
Expand Down
21 changes: 19 additions & 2 deletions hal/src/electron/modem/mdm_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "concurrent_hal.h"
#include <mutex>
#include "net_hal.h"
#include <limits>

std::recursive_mutex mdm_mutex;

Expand Down Expand Up @@ -864,8 +865,7 @@ bool MDMParser::getSignalStrength(NetStatus &status)
sendFormated("AT+CSQ\r\n");
if (RESP_OK == waitFinalResp(_cbCSQ, &_net)) {
ok = true;
status.rssi = _net.rssi;
status.qual = _net.qual;
status = _net;
}
}
UNLOCK();
Expand Down Expand Up @@ -1072,6 +1072,23 @@ int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status)
if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) {
if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps
if ((b != 99) && (b < (int)sizeof(_qual))) status->qual = _qual[b]; //

switch (status->act) {
case ACT_GSM:
case ACT_EDGE:
status->rxlev = (a != 99) ? (2 * a) : a;
status->rxqual = b;
break;
case ACT_UTRAN:
status->rscp = (a != 99) ? (status->rssi + 116) : 255;
status->ecno = (b != 99) ? std::min((7 + (7 - b) * 6), 44) : 255;
break;
default:
// Unknown access tecnhology
status->asu = std::numeric_limits<int32_t>::min();
status->aqual = std::numeric_limits<int32_t>::min();
break;
}
}
}
return WAIT;
Expand Down
5 changes: 5 additions & 0 deletions hal/src/gcc/wlan_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ wlan_result_t wlan_connected_rssi()
return 0;
}

int wlan_connected_info(void* reserved, wlan_connected_info_t* inf, void* reserved1)
{
return -1;
}

int wlan_set_credentials(WLanCredentials* c)
{
return -1;
Expand Down
Loading