feat(display): show cloud connection status

This commit is contained in:
Siyuan Miao 2025-04-12 22:46:48 +02:00
parent f712cb1719
commit edba5c94f5
6 changed files with 78 additions and 12 deletions

View File

@ -140,10 +140,22 @@ var (
)
var (
cloudConnectionAlive bool
cloudConnectionAliveLock = &sync.Mutex{}
cloudDisconnectChan chan error
cloudDisconnectLock = &sync.Mutex{}
)
func setCloudConnectionAlive(alive bool) {
cloudConnectionAliveLock.Lock()
defer cloudConnectionAliveLock.Unlock()
cloudConnectionAlive = alive
go waitCtrlAndRequestDisplayUpdate()
}
func wsResetMetrics(established bool, sourceType string, source string) {
metricConnectionLastPingTimestamp.WithLabelValues(sourceType, source).Set(-1)
metricConnectionLastPingDuration.WithLabelValues(sourceType, source).Set(-1)
@ -307,6 +319,8 @@ func runWebsocketClient() error {
metricConnectionTotalPingReceivedCount.WithLabelValues("cloud", wsURL.Host).Inc()
metricConnectionLastPingReceivedTimestamp.WithLabelValues("cloud", wsURL.Host).SetToCurrentTime()
setCloudConnectionAlive(true)
return true
},
})
@ -336,6 +350,8 @@ func runWebsocketClient() error {
if err != nil {
if errors.Is(err, context.Canceled) {
cloudLogger.Info().Msg("websocket connection canceled")
setCloudConnectionAlive(false)
return nil
}
return err

View File

@ -33,9 +33,37 @@ func switchToScreen(screen string) {
var displayedTexts = make(map[string]string)
func lvObjSetState(objName string, state string) (*CtrlResponse, error) {
return CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": objName, "state": state})
}
func lvObjAddFlag(objName string, flag string) (*CtrlResponse, error) {
return CallCtrlAction("lv_obj_add_flag", map[string]interface{}{"obj": objName, "flag": flag})
}
func lvObjClearFlag(objName string, flag string) (*CtrlResponse, error) {
return CallCtrlAction("lv_obj_clear_flag", map[string]interface{}{"obj": objName, "flag": flag})
}
func lvObjHide(objName string) (*CtrlResponse, error) {
return lvObjAddFlag(objName, "LV_OBJ_FLAG_HIDDEN")
}
func lvObjShow(objName string) (*CtrlResponse, error) {
return lvObjClearFlag(objName, "LV_OBJ_FLAG_HIDDEN")
}
func lvLabelSetText(objName string, text string) (*CtrlResponse, error) {
return CallCtrlAction("lv_label_set_text", map[string]interface{}{"obj": objName, "text": text})
}
func lvImgSetSrc(objName string, src string) (*CtrlResponse, error) {
return CallCtrlAction("lv_img_set_src", map[string]interface{}{"obj": objName, "src": src})
}
func updateLabelIfChanged(objName string, newText string) {
if newText != "" && newText != displayedTexts[objName] {
_, _ = CallCtrlAction("lv_label_set_text", map[string]interface{}{"obj": objName, "text": newText})
_, _ = lvLabelSetText(objName, newText)
displayedTexts[objName] = newText
}
}
@ -51,29 +79,43 @@ func updateDisplay() {
updateLabelIfChanged("ui_Home_Content_Ip", networkState.IPv4String())
if usbState == "configured" {
updateLabelIfChanged("ui_Home_Footer_Usb_Status_Label", "Connected")
_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Usb_Status_Label", "state": "LV_STATE_DEFAULT"})
_, _ = lvObjSetState("ui_Home_Footer_Usb_Status_Label", "LV_STATE_DEFAULT")
} else {
updateLabelIfChanged("ui_Home_Footer_Usb_Status_Label", "Disconnected")
_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Usb_Status_Label", "state": "LV_STATE_USER_2"})
_, _ = lvObjSetState("ui_Home_Footer_Usb_Status_Label", "LV_STATE_USER_2")
}
if lastVideoState.Ready {
updateLabelIfChanged("ui_Home_Footer_Hdmi_Status_Label", "Connected")
_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Hdmi_Status_Label", "state": "LV_STATE_DEFAULT"})
_, _ = lvObjSetState("ui_Home_Footer_Hdmi_Status_Label", "LV_STATE_DEFAULT")
} else {
updateLabelIfChanged("ui_Home_Footer_Hdmi_Status_Label", "Disconnected")
_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Hdmi_Status_Label", "state": "LV_STATE_USER_2"})
_, _ = lvObjSetState("ui_Home_Footer_Hdmi_Status_Label", "LV_STATE_USER_2")
}
updateLabelIfChanged("ui_Home_Header_Cloud_Status_Label", fmt.Sprintf("%d active", actionSessions))
if networkState.IsUp() {
switchToScreenIfDifferent("ui_Home_Screen")
} else {
switchToScreenIfDifferent("ui_No_Network_Screen")
}
if config.CloudToken == "" || config.CloudURL == "" {
lvObjHide("ui_Home_Header_Cloud_Status_Icon")
} else {
lvObjShow("ui_Home_Header_Cloud_Status_Icon")
// TODO: blink the icon if establishing connection
if cloudConnectionAlive {
_, _ = lvImgSetSrc("ui_Home_Header_Cloud_Status_Icon", "cloud.png")
} else {
_, _ = lvImgSetSrc("ui_Home_Header_Cloud_Status_Icon", "cloud_disconnected.png")
}
}
}
var (
displayInited = false
displayUpdateLock = sync.Mutex{}
waitDisplayUpdate = sync.Mutex{}
)
func requestDisplayUpdate() {
@ -92,6 +134,14 @@ func requestDisplayUpdate() {
}()
}
func waitCtrlAndRequestDisplayUpdate() {
waitDisplayUpdate.Lock()
defer waitDisplayUpdate.Unlock()
waitCtrlClientConnected()
requestDisplayUpdate()
}
func updateStaticContents() {
//contents that never change
updateLabelIfChanged("ui_Home_Content_Mac", networkState.MACString())

View File

@ -325,7 +325,6 @@ func initNetwork() {
}
go func() {
waitCtrlClientConnected()
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
@ -340,8 +339,4 @@ func initNetwork() {
}
}
}()
err := startMDNS()
if err != nil {
logger.Warn().Err(err).Msg("failed to run mDNS")
}
}

Binary file not shown.

View File

@ -1 +1 @@
c0803a9185298398eff9a925de69bd0ca882cd5983b989a45b748648146475c6
b556ac0d6f38518f20dcf212ba65fe97981aa169ae418c68b2cbb155447affda

7
web.go
View File

@ -242,7 +242,12 @@ func handleWebRTCSignalWsMessages(
scopedLogger *zerolog.Logger,
) error {
runCtx, cancelRun := context.WithCancel(context.Background())
defer cancelRun()
defer func() {
if isCloudConnection {
setCloudConnectionAlive(false)
}
cancelRun()
}()
// connection type
var sourceType string