257 lines
6.6 KiB
Go
257 lines
6.6 KiB
Go
package main
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/huh"
|
|
)
|
|
|
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
|
|
case tea.KeyMsg:
|
|
if msg.Type == tea.KeyCtrlC {
|
|
return m, tea.Quit
|
|
}
|
|
|
|
if m.state == StateSettings {
|
|
if m.scanning {
|
|
return m, nil
|
|
}
|
|
if msg.Type == tea.KeyEsc {
|
|
if m.settingSubState != SubMenu {
|
|
m.settingSubState = SubMenu
|
|
m.initSettingsMenu()
|
|
return m, m.settingsForm.Init()
|
|
}
|
|
m.state = StateDashboard
|
|
m.err = nil
|
|
return m, nil
|
|
}
|
|
}
|
|
|
|
if m.state == StateDashboard {
|
|
switch msg.String() {
|
|
case "enter":
|
|
m.state = StateTerminal
|
|
return m, tea.Sequence(tea.ExitAltScreen, startRawTerminal(&m))
|
|
case "s":
|
|
return m, fetchSettings(*m.connDetails)
|
|
case "u":
|
|
return m, toggleLoad(*m.connDetails, "load_5v_on", !m.status.Sw.UsbOn)
|
|
case "m":
|
|
return m, toggleLoad(*m.connDetails, "load_12v_on", !m.status.Sw.MainOn)
|
|
case "q":
|
|
return m, tea.Quit
|
|
}
|
|
}
|
|
|
|
case tea.WindowSizeMsg:
|
|
m.width = msg.Width
|
|
m.height = msg.Height
|
|
|
|
case LoginSuccessMsg:
|
|
m.connDetails.Token = string(msg)
|
|
m.state = StateDashboard
|
|
return m, tea.Batch(
|
|
connectWebSocket(*m.connDetails),
|
|
fetchInitialState(*m.connDetails),
|
|
)
|
|
|
|
case InitStateMsg:
|
|
m.status.Sw.MainOn = msg.MainOn
|
|
m.status.Sw.UsbOn = msg.UsbOn
|
|
return m, nil
|
|
|
|
case SettingsFetchedMsg:
|
|
m.settingsData = SettingsPayload(msg)
|
|
if m.settingsData.CurIP.IP != "" {
|
|
m.settingsData.IP = m.settingsData.CurIP.IP
|
|
m.settingsData.Gateway = m.settingsData.CurIP.Gateway
|
|
m.settingsData.Subnet = m.settingsData.CurIP.Subnet
|
|
m.settingsData.DNS1 = m.settingsData.CurIP.DNS1
|
|
m.settingsData.DNS2 = m.settingsData.CurIP.DNS2
|
|
}
|
|
|
|
m.settingSubState = SubMenu
|
|
m.initSettingsMenu()
|
|
m.state = StateSettings
|
|
return m, m.settingsForm.Init()
|
|
|
|
case WifiScanListMsg:
|
|
m.scanning = false
|
|
m.wifiScanList = []WifiAP(msg)
|
|
m.settingSubState = SubWifiScanList
|
|
m.initWifiScanForm()
|
|
return m, m.settingsForm.Init()
|
|
|
|
case ActionDoneMsg:
|
|
m.err = nil
|
|
return m, fetchSettings(*m.connDetails)
|
|
|
|
case WsPartialMsg:
|
|
if msg.Vin != nil {
|
|
m.status.Vin = *msg.Vin
|
|
}
|
|
if msg.Main != nil {
|
|
m.status.Main = *msg.Main
|
|
}
|
|
if msg.Usb != nil {
|
|
m.status.Usb = *msg.Usb
|
|
}
|
|
if msg.Wifi != nil {
|
|
m.status.Wifi = *msg.Wifi
|
|
}
|
|
if msg.Sw != nil {
|
|
m.status.Sw = *msg.Sw
|
|
}
|
|
return m, waitForWebSocketMessage(msg.Conn)
|
|
|
|
case TerminalFinishedMsg:
|
|
m.state = StateDashboard
|
|
return m, tea.Sequence(tea.EnterAltScreen, tea.ClearScreen)
|
|
|
|
case error:
|
|
m.scanning = false
|
|
m.err = msg
|
|
if m.state == StateLogin {
|
|
if m.loginForm == nil {
|
|
m.initLoginForm()
|
|
}
|
|
return m, m.loginForm.Init()
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
// 1. Login Form Update
|
|
if m.state == StateLogin && m.loginForm != nil {
|
|
form, cmd := m.loginForm.Update(msg)
|
|
if f, ok := form.(*huh.Form); ok {
|
|
m.loginForm = f
|
|
if m.loginForm.State == huh.StateCompleted {
|
|
*m.connDetails = *m.formData
|
|
return m, performLogin(*m.connDetails)
|
|
}
|
|
}
|
|
return m, cmd
|
|
}
|
|
|
|
// 2. Settings Form Update
|
|
if m.state == StateSettings && m.settingsForm != nil {
|
|
form, cmd := m.settingsForm.Update(msg)
|
|
if f, ok := form.(*huh.Form); ok {
|
|
m.settingsForm = f
|
|
|
|
if m.settingsForm.State == huh.StateCompleted {
|
|
|
|
if m.settingSubState == SubMenu {
|
|
selection := f.GetString("menu_select")
|
|
|
|
switch selection {
|
|
case "scan":
|
|
m.scanning = true
|
|
return m, scanWifi(*m.connDetails)
|
|
case "manual":
|
|
m.settingSubState = SubWifiConnect
|
|
m.initWifiForm()
|
|
case "ip":
|
|
m.settingSubState = SubIPConfig
|
|
m.initIPForm()
|
|
case "ap":
|
|
m.settingSubState = SubAPMode
|
|
m.initAPForm()
|
|
case "system":
|
|
m.settingSubState = SubSystem
|
|
m.initSystemForm()
|
|
case "safety":
|
|
m.settingSubState = SubSafety
|
|
m.initSafetyForm()
|
|
case "account":
|
|
m.settingSubState = SubAccount
|
|
m.initAccountForm()
|
|
case "reboot":
|
|
return m, rebootDevice(*m.connDetails)
|
|
case "exit":
|
|
m.state = StateDashboard
|
|
return m, nil
|
|
}
|
|
return m, m.settingsForm.Init()
|
|
}
|
|
|
|
if m.settingSubState == SubWifiScanList {
|
|
selectedSSID := f.GetString("scan_ssid")
|
|
if selectedSSID == "" {
|
|
m.settingSubState = SubMenu
|
|
m.initSettingsMenu()
|
|
return m, m.settingsForm.Init()
|
|
}
|
|
m.settingsData.WifiSSID = selectedSSID
|
|
m.settingSubState = SubWifiConnect
|
|
m.initWifiForm()
|
|
return m, m.settingsForm.Init()
|
|
}
|
|
|
|
switch m.settingSubState {
|
|
case SubWifiConnect:
|
|
payload := map[string]string{
|
|
"ssid": m.settingsData.WifiSSID,
|
|
"password": m.settingsData.WifiPass,
|
|
}
|
|
return m, saveSettingsMap(*m.connDetails, payload)
|
|
|
|
case SubIPConfig:
|
|
payload := map[string]interface{}{"net_type": m.settingsData.NetType}
|
|
if m.settingsData.NetType == "static" {
|
|
payload["ip"] = m.settingsData.IP
|
|
payload["gateway"] = m.settingsData.Gateway
|
|
payload["subnet"] = m.settingsData.Subnet
|
|
payload["dns1"] = m.settingsData.DNS1
|
|
payload["dns2"] = m.settingsData.DNS2
|
|
}
|
|
return m, saveSettingsMap(*m.connDetails, payload)
|
|
|
|
case SubAPMode:
|
|
payload := map[string]string{"mode": m.settingsData.Mode}
|
|
if m.settingsData.Mode == "apsta" {
|
|
payload["ap_ssid"] = m.settingsData.APSSID
|
|
payload["ap_password"] = m.settingsData.APPass
|
|
}
|
|
return m, saveSettingsMap(*m.connDetails, payload)
|
|
|
|
case SubSystem:
|
|
// [수정] 백엔드 한계로 인해 순차적(Sequential) 전송 필수
|
|
// baudrate 변경 요청 -> period 변경 요청
|
|
return m, tea.Sequence(
|
|
saveSettingsMap(*m.connDetails, map[string]interface{}{"baudrate": m.settingsData.Baudrate}),
|
|
saveSettingsMap(*m.connDetails, map[string]interface{}{"period": m.settingsData.Period}),
|
|
)
|
|
|
|
case SubSafety:
|
|
// Safety 설정은 백엔드에서 한 번에 처리가 가능하므로 하나로 묶음
|
|
valVin, _ := strconv.ParseFloat(f.GetString("vin_limit"), 64)
|
|
valMain, _ := strconv.ParseFloat(f.GetString("main_limit"), 64)
|
|
valUsb, _ := strconv.ParseFloat(f.GetString("usb_limit"), 64)
|
|
|
|
payload := map[string]interface{}{
|
|
"vin_current_limit": valVin,
|
|
"main_current_limit": valMain,
|
|
"usb_current_limit": valUsb,
|
|
}
|
|
return m, saveSettingsMap(*m.connDetails, payload)
|
|
|
|
case SubAccount:
|
|
payload := map[string]string{
|
|
"new_username": m.settingsData.NewUser,
|
|
"new_password": m.settingsData.NewPass,
|
|
}
|
|
return m, saveSettingsMap(*m.connDetails, payload)
|
|
}
|
|
}
|
|
}
|
|
return m, cmd
|
|
}
|
|
|
|
return m, nil
|
|
}
|