mirror of https://github.com/commaai/openpilot.git
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:
parent
613e84efe0
commit
e43b40540d
2
apks
2
apks
|
@ -1 +1 @@
|
||||||
Subproject commit ac26fd4a343b6a202dc3ddaac6e00feabcf3a506
|
Subproject commit d94f8663913f12142754b2501b174c8bcd5996ce
|
|
@ -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],
|
||||||
|
|
|
@ -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)
|
||||||
|
if opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY):
|
||||||
|
if opcode == ABNF.OPCODE_TEXT:
|
||||||
|
data = data.decode("utf-8")
|
||||||
payload_queue.put_nowait(data)
|
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))
|
||||||
|
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue