Sidebar Connectivity Status (#1268)

* store athena connected-at time

* refactor

* deref

* dt import

* Athena status based on last ping time param

* upd test for pingtime

* lower error timeout
old-commit-hash: 41bb3ac7ca
This commit is contained in:
Andy 2020-04-05 11:06:49 -07:00 committed by GitHub
parent 613e84efe0
commit e43b40540d
8 changed files with 94 additions and 35 deletions

2
apks

@ -1 +1 @@
Subproject commit ac26fd4a343b6a202dc3ddaac6e00feabcf3a506 Subproject commit d94f8663913f12142754b2501b174c8bcd5996ce

View File

@ -78,6 +78,7 @@ keys = {
"IsTakingSnapshot": [TxType.CLEAR_ON_MANAGER_START], "IsTakingSnapshot": [TxType.CLEAR_ON_MANAGER_START],
"IsUpdateAvailable": [TxType.CLEAR_ON_MANAGER_START], "IsUpdateAvailable": [TxType.CLEAR_ON_MANAGER_START],
"IsUploadRawEnabled": [TxType.PERSISTENT], "IsUploadRawEnabled": [TxType.PERSISTENT],
"LastAthenaPingTime": [TxType.PERSISTENT],
"LastUpdateTime": [TxType.PERSISTENT], "LastUpdateTime": [TxType.PERSISTENT],
"LimitSetSpeed": [TxType.PERSISTENT], "LimitSetSpeed": [TxType.PERSISTENT],
"LimitSetSpeedNeural": [TxType.PERSISTENT], "LimitSetSpeedNeural": [TxType.PERSISTENT],

View File

@ -22,6 +22,7 @@ from common import android
from common.basedir import PERSIST from common.basedir import PERSIST
from common.api import Api from common.api import Api
from common.params import Params from common.params import Params
from common.realtime import sec_since_boot
from cereal.services import service_list from cereal.services import service_list
from selfdrive.swaglog import cloudlog from selfdrive.swaglog import cloudlog
@ -272,8 +273,13 @@ def ws_proxy_send(ws, local_sock, signal_sock, end_event):
def ws_recv(ws, end_event): def ws_recv(ws, end_event):
while not end_event.is_set(): while not end_event.is_set():
try: try:
data = ws.recv() opcode, data = ws.recv_data(control_frame=True)
payload_queue.put_nowait(data) if opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY):
if opcode == ABNF.OPCODE_TEXT:
data = data.decode("utf-8")
payload_queue.put_nowait(data)
elif opcode == ABNF.OPCODE_PING:
Params().put("LastAthenaPingTime", str(int(sec_since_boot()*1e9)))
except WebSocketTimeoutException: except WebSocketTimeoutException:
pass pass
except Exception: except Exception:
@ -316,6 +322,7 @@ def main():
except Exception: except Exception:
cloudlog.exception("athenad.main.exception") cloudlog.exception("athenad.main.exception")
conn_retries += 1 conn_retries += 1
params.delete("LastAthenaPingTime")
time.sleep(backoff(conn_retries)) time.sleep(backoff(conn_retries))

View File

@ -4,6 +4,7 @@ os.environ['FAKEUPLOAD'] = "1"
from common.apk import update_apks, start_offroad, pm_apply_packages, android_packages from common.apk import update_apks, start_offroad, pm_apply_packages, android_packages
from common.params import Params from common.params import Params
from common.realtime import sec_since_boot
from common.testing import phone_only from common.testing import phone_only
from selfdrive.manager import manager_init, manager_prepare from selfdrive.manager import manager_init, manager_prepare
from selfdrive.manager import start_managed_process, kill_managed_process, get_running from selfdrive.manager import start_managed_process, kill_managed_process, get_running
@ -14,6 +15,7 @@ import requests
import signal import signal
import subprocess import subprocess
import time import time
from datetime import datetime, timedelta
DID_INIT = False DID_INIT = False
@ -108,6 +110,7 @@ def test_uploader():
@phone_only @phone_only
def test_athena(): def test_athena():
print("ATHENA") print("ATHENA")
start = sec_since_boot()
start_daemon_process("manage_athenad") start_daemon_process("manage_athenad")
params = Params() params = Params()
manage_athenad_pid = params.get("AthenadPid") manage_athenad_pid = params.get("AthenadPid")
@ -155,7 +158,7 @@ def test_athena():
else: else:
print(f'athena_post failed {e}. retrying...') print(f'athena_post failed {e}. retrying...')
def expect_athena_registers(): def expect_athena_registers(test_t0):
resp = athena_post({ resp = athena_post({
"method": "echo", "method": "echo",
"params": ["hello"], "params": ["hello"],
@ -164,6 +167,10 @@ def test_athena():
}, max_retries=12, wait=5) }, max_retries=12, wait=5)
assert resp.get('result') == "hello", f'Athena failed to register ({resp})' assert resp.get('result') == "hello", f'Athena failed to register ({resp})'
last_pingtime = params.get("LastAthenaPingTime", encoding='utf8')
assert last_pingtime, last_pingtime
assert ((int(last_pingtime)/1e9) - test_t0) < (sec_since_boot() - test_t0)
try: try:
athenad_pid = expect_athena_starts() athenad_pid = expect_athena_starts()
# kill athenad and ensure it is restarted (check_output will throw if it is not) # kill athenad and ensure it is restarted (check_output will throw if it is not)
@ -174,7 +181,7 @@ def test_athena():
print('WARNING: COMMA_JWT env not set, will not test requests to athena.comma.ai') print('WARNING: COMMA_JWT env not set, will not test requests to athena.comma.ai')
return return
expect_athena_registers() expect_athena_registers(start)
print("ATHENA: getSimInfo") print("ATHENA: getSimInfo")
resp = athena_post({ resp = athena_post({

View File

@ -771,8 +771,8 @@ void ui_draw_vision_alert(UIState *s, int va_size, int va_color,
const UIScene *scene = &s->scene; const UIScene *scene = &s->scene;
int ui_viz_rx = scene->ui_viz_rx; int ui_viz_rx = scene->ui_viz_rx;
int ui_viz_rw = scene->ui_viz_rw; int ui_viz_rw = scene->ui_viz_rw;
bool hasSidebar = !s->scene.uilayout_sidebarcollapsed; const bool hasSidebar = !scene->uilayout_sidebarcollapsed;
bool mapEnabled = s->scene.uilayout_mapenabled; const bool mapEnabled = scene->uilayout_mapenabled;
bool longAlert1 = strlen(va_text1) > 15; bool longAlert1 = strlen(va_text1) > 15;
const uint8_t *color = alert_colors[va_color]; const uint8_t *color = alert_colors[va_color];

View File

@ -3,8 +3,8 @@
#include <math.h> #include <math.h>
#include "ui.hpp" #include "ui.hpp"
static void ui_draw_sidebar_background(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_background(UIState *s) {
int sbr_x = hasSidebar ? 0 : -(sbr_w) + bdr_s * 2; int sbr_x = !s->scene.uilayout_sidebarcollapsed ? 0 : -(sbr_w) + bdr_s * 2;
nvgBeginPath(s->vg); nvgBeginPath(s->vg);
nvgRect(s->vg, sbr_x, 0, sbr_w, vwp_h); nvgRect(s->vg, sbr_x, 0, sbr_w, vwp_h);
@ -12,9 +12,9 @@ static void ui_draw_sidebar_background(UIState *s, bool hasSidebar) {
nvgFill(s->vg); nvgFill(s->vg);
} }
static void ui_draw_sidebar_settings_button(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_settings_button(UIState *s) {
bool settingsActive = s->active_app == cereal_UiLayoutState_App_settings; bool settingsActive = s->active_app == cereal_UiLayoutState_App_settings;
const int settings_btn_xr = hasSidebar ? settings_btn_x : -(sbr_w); const int settings_btn_xr = !s->scene.uilayout_sidebarcollapsed ? settings_btn_x : -(sbr_w);
nvgBeginPath(s->vg); nvgBeginPath(s->vg);
NVGpaint imgPaint = nvgImagePattern(s->vg, settings_btn_xr, settings_btn_y, NVGpaint imgPaint = nvgImagePattern(s->vg, settings_btn_xr, settings_btn_y,
@ -24,9 +24,9 @@ static void ui_draw_sidebar_settings_button(UIState *s, bool hasSidebar) {
nvgFill(s->vg); nvgFill(s->vg);
} }
static void ui_draw_sidebar_home_button(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_home_button(UIState *s) {
bool homeActive = s->active_app == cereal_UiLayoutState_App_home; bool homeActive = s->active_app == cereal_UiLayoutState_App_home;
const int home_btn_xr = hasSidebar ? home_btn_x : -(sbr_w); const int home_btn_xr = !s->scene.uilayout_sidebarcollapsed ? home_btn_x : -(sbr_w);
nvgBeginPath(s->vg); nvgBeginPath(s->vg);
NVGpaint imgPaint = nvgImagePattern(s->vg, home_btn_xr, home_btn_y, NVGpaint imgPaint = nvgImagePattern(s->vg, home_btn_xr, home_btn_y,
@ -36,10 +36,10 @@ static void ui_draw_sidebar_home_button(UIState *s, bool hasSidebar) {
nvgFill(s->vg); nvgFill(s->vg);
} }
static void ui_draw_sidebar_network_strength(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_network_strength(UIState *s) {
const int network_img_h = 27; const int network_img_h = 27;
const int network_img_w = 176; const int network_img_w = 176;
const int network_img_x = hasSidebar ? 58 : -(sbr_w); const int network_img_x = !s->scene.uilayout_sidebarcollapsed ? 58 : -(sbr_w);
const int network_img_y = 196; const int network_img_y = 196;
const int network_img = s->scene.networkType == cereal_ThermalData_NetworkType_none ? const int network_img = s->scene.networkType == cereal_ThermalData_NetworkType_none ?
s->img_network[0] : s->img_network[s->scene.networkStrength + 1]; s->img_network[0] : s->img_network[s->scene.networkStrength + 1];
@ -52,10 +52,10 @@ static void ui_draw_sidebar_network_strength(UIState *s, bool hasSidebar) {
nvgFill(s->vg); nvgFill(s->vg);
} }
static void ui_draw_sidebar_battery_icon(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_battery_icon(UIState *s) {
const int battery_img_h = 36; const int battery_img_h = 36;
const int battery_img_w = 76; const int battery_img_w = 76;
const int battery_img_x = hasSidebar ? 160 : -(sbr_w); const int battery_img_x = !s->scene.uilayout_sidebarcollapsed ? 160 : -(sbr_w);
const int battery_img_y = 255; const int battery_img_y = 255;
int battery_img = strcmp(s->scene.batteryStatus, "Charging") == 0 ? int battery_img = strcmp(s->scene.batteryStatus, "Charging") == 0 ?
@ -75,8 +75,8 @@ static void ui_draw_sidebar_battery_icon(UIState *s, bool hasSidebar) {
nvgFill(s->vg); nvgFill(s->vg);
} }
static void ui_draw_sidebar_network_type(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_network_type(UIState *s) {
const int network_x = hasSidebar ? 50 : -(sbr_w); const int network_x = !s->scene.uilayout_sidebarcollapsed ? 50 : -(sbr_w);
const int network_y = 273; const int network_y = 273;
const int network_w = 100; const int network_w = 100;
const int network_h = 100; const int network_h = 100;
@ -94,8 +94,8 @@ static void ui_draw_sidebar_network_type(UIState *s, bool hasSidebar) {
nvgTextBox(s->vg, network_x, network_y, network_w, network_type_str, NULL); nvgTextBox(s->vg, network_x, network_y, network_w, network_type_str, NULL);
} }
static void ui_draw_sidebar_metric(UIState *s, const char* label_str, const char* value_str, const int severity, const int y_offset, const char* message_str, bool hasSidebar) { static void ui_draw_sidebar_metric(UIState *s, const char* label_str, const char* value_str, const int severity, const int y_offset, const char* message_str) {
const int metric_x = hasSidebar ? 30 : -(sbr_w); const int metric_x = !s->scene.uilayout_sidebarcollapsed ? 30 : -(sbr_w);
const int metric_y = 338 + y_offset; const int metric_y = 338 + y_offset;
const int metric_w = 240; const int metric_w = 240;
const int metric_h = message_str ? strchr(message_str, '\n') ? 124 : 100 : 148; const int metric_h = message_str ? strchr(message_str, '\n') ? 124 : 100 : 148;
@ -142,7 +142,7 @@ static void ui_draw_sidebar_metric(UIState *s, const char* label_str, const char
} }
} }
static void ui_draw_sidebar_temp_metric(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_temp_metric(UIState *s) {
int temp_severity; int temp_severity;
char temp_label_str[32]; char temp_label_str[32];
char temp_value_str[32]; char temp_value_str[32];
@ -164,10 +164,10 @@ static void ui_draw_sidebar_temp_metric(UIState *s, bool hasSidebar) {
snprintf(temp_label_str, sizeof(temp_label_str), "%s", "TEMP"); snprintf(temp_label_str, sizeof(temp_label_str), "%s", "TEMP");
strcat(temp_value_str, temp_value_unit); strcat(temp_value_str, temp_value_unit);
ui_draw_sidebar_metric(s, temp_label_str, temp_value_str, temp_severity, temp_y_offset, NULL, hasSidebar); ui_draw_sidebar_metric(s, temp_label_str, temp_value_str, temp_severity, temp_y_offset, NULL);
} }
static void ui_draw_sidebar_panda_metric(UIState *s, bool hasSidebar) { static void ui_draw_sidebar_panda_metric(UIState *s) {
int panda_severity; int panda_severity;
char panda_message_str[32]; char panda_message_str[32];
const int panda_y_offset = 32 + 148; const int panda_y_offset = 32 + 148;
@ -194,17 +194,27 @@ static void ui_draw_sidebar_panda_metric(UIState *s, bool hasSidebar) {
} }
} }
ui_draw_sidebar_metric(s, NULL, NULL, panda_severity, panda_y_offset, panda_message_str, hasSidebar); ui_draw_sidebar_metric(s, NULL, NULL, panda_severity, panda_y_offset, panda_message_str);
}
static void ui_draw_sidebar_connectivity(UIState *s) {
if (s->scene.athenaStatus == NET_DISCONNECTED) {
ui_draw_sidebar_metric(s, NULL, NULL, 1, 180+158, "ATHENA\nOFFLINE");
} else if (s->scene.athenaStatus == NET_CONNECTED) {
ui_draw_sidebar_metric(s, NULL, NULL, 0, 180+158, "ATHENA\nONLINE");
} else {
ui_draw_sidebar_metric(s, NULL, NULL, 2, 180+158, "ATHENA\nERROR");
}
} }
void ui_draw_sidebar(UIState *s) { void ui_draw_sidebar(UIState *s) {
bool hasSidebar = !s->scene.uilayout_sidebarcollapsed; ui_draw_sidebar_background(s);
ui_draw_sidebar_background(s, hasSidebar); ui_draw_sidebar_settings_button(s);
ui_draw_sidebar_settings_button(s, hasSidebar); ui_draw_sidebar_home_button(s);
ui_draw_sidebar_home_button(s, hasSidebar); ui_draw_sidebar_network_strength(s);
ui_draw_sidebar_network_strength(s, hasSidebar); ui_draw_sidebar_battery_icon(s);
ui_draw_sidebar_battery_icon(s, hasSidebar); ui_draw_sidebar_network_type(s);
ui_draw_sidebar_network_type(s, hasSidebar); ui_draw_sidebar_temp_metric(s);
ui_draw_sidebar_temp_metric(s, hasSidebar); ui_draw_sidebar_panda_metric(s);
ui_draw_sidebar_panda_metric(s, hasSidebar); ui_draw_sidebar_connectivity(s);
} }

View File

@ -132,6 +132,16 @@ static void read_param_float(float* param, const char* param_name) {
} }
} }
static int read_param_uint64(uint64_t* dest, const char* param_name) {
char *s;
const int result = read_db_value(NULL, param_name, &s, NULL);
if (result == 0) {
*dest = strtoull(s, NULL, 0);
free(s);
}
return result;
}
static void read_param_bool_timeout(bool* param, const char* param_name, int* timeout) { static void read_param_bool_timeout(bool* param, const char* param_name, int* timeout) {
if (*timeout > 0){ if (*timeout > 0){
(*timeout)--; (*timeout)--;
@ -150,6 +160,16 @@ static void read_param_float_timeout(float* param, const char* param_name, int*
} }
} }
static int read_param_uint64_timeout(uint64_t* dest, const char* param_name, int* timeout) {
if (*timeout > 0){
(*timeout)--;
return 0;
} else {
return read_param_uint64(dest, param_name);
*timeout = 2 * UI_FREQ; // 0.5Hz
}
}
static void ui_init(UIState *s) { static void ui_init(UIState *s) {
memset(s, 0, sizeof(UIState)); memset(s, 0, sizeof(UIState));
@ -1026,7 +1046,14 @@ int main(int argc, char* argv[]) {
read_param_bool_timeout(&s->longitudinal_control, "LongitudinalControl", &s->longitudinal_control_timeout); read_param_bool_timeout(&s->longitudinal_control, "LongitudinalControl", &s->longitudinal_control_timeout);
read_param_bool_timeout(&s->limit_set_speed, "LimitSetSpeed", &s->limit_set_speed_timeout); read_param_bool_timeout(&s->limit_set_speed, "LimitSetSpeed", &s->limit_set_speed_timeout);
read_param_float_timeout(&s->speed_lim_off, "SpeedLimitOffset", &s->limit_set_speed_timeout); read_param_float_timeout(&s->speed_lim_off, "SpeedLimitOffset", &s->limit_set_speed_timeout);
int param_read = read_param_uint64_timeout(&s->last_athena_ping, "LastAthenaPingTime", &s->last_athena_ping_timeout);
if (param_read != 0) {
s->scene.athenaStatus = NET_DISCONNECTED;
} else if (nanos_since_boot() - s->last_athena_ping < 70e9) {
s->scene.athenaStatus = NET_CONNECTED;
} else {
s->scene.athenaStatus = NET_ERROR;
}
pthread_mutex_unlock(&s->lock); pthread_mutex_unlock(&s->lock);
// the bg thread needs to be scheduled, so the main thread needs time without the lock // the bg thread needs to be scheduled, so the main thread needs time without the lock

View File

@ -33,6 +33,10 @@
#define STATUS_WARNING 3 #define STATUS_WARNING 3
#define STATUS_ALERT 4 #define STATUS_ALERT 4
#define NET_CONNECTED 0
#define NET_DISCONNECTED 1
#define NET_ERROR 2
#define ALERTSIZE_NONE 0 #define ALERTSIZE_NONE 0
#define ALERTSIZE_SMALL 1 #define ALERTSIZE_SMALL 1
#define ALERTSIZE_MID 2 #define ALERTSIZE_MID 2
@ -157,6 +161,7 @@ typedef struct UIScene {
int paTemp; int paTemp;
int hwType; int hwType;
int satelliteCount; int satelliteCount;
uint8_t athenaStatus;
} UIScene; } UIScene;
typedef struct { typedef struct {
@ -257,9 +262,11 @@ typedef struct UIState {
int longitudinal_control_timeout; int longitudinal_control_timeout;
int limit_set_speed_timeout; int limit_set_speed_timeout;
int hardware_timeout; int hardware_timeout;
int last_athena_ping_timeout;
bool controls_seen; bool controls_seen;
uint64_t last_athena_ping;
int status; int status;
bool is_metric; bool is_metric;
bool longitudinal_control; bool longitudinal_control;