diff --git a/goTool/README.md b/goTool/README.md index 249f5fa..8fc0971 100644 --- a/goTool/README.md +++ b/goTool/README.md @@ -31,6 +31,7 @@ go run . -port /dev/ttyUSB0 clients | `ota-progress` | 21 | Query per-slave ESP-NOW OTA progress on the master (`-client N`, default all) | | `led-ring` | 8 | LED ring: `-mode clear\|progress\|digit\|blink\|find-me`, … | | `find-me` | 22 | Locate pod (`-client 0` master, `>0` slave via ESP-NOW) | +| `restart` | 23 | Reboot master or slave (`-client 0` / `>0`) | `clients` requires slaves to have responded to master discover broadcasts first. @@ -73,7 +74,7 @@ The dashboard can configure nodes using the same UART commands as the CLI: | Alle Slaves | per-slave ESP-NOW (Master bleibt unverändert; CLI `-all` setzt auch den Master) | | Unicast test | `unicast-test -client ID` | -HTTP API (used by the web UI): `GET/POST /api/deadzone`, `POST /api/unicast-test`, `POST /api/find-me`, `POST /api/ota` (multipart field `firmware`, max 2 MiB). +HTTP API (used by the web UI): `GET/POST /api/deadzone`, `POST /api/unicast-test`, `POST /api/find-me`, `POST /api/restart`, `POST /api/ota` (multipart field `firmware`, max 2 MiB). | UI / API | Behaviour | |----------|-----------| diff --git a/goTool/api_serve.go b/goTool/api_serve.go index bb637d7..b7dc7e4 100644 --- a/goTool/api_serve.go +++ b/goTool/api_serve.go @@ -50,6 +50,16 @@ type findMeAPIResponse struct { Error string `json:"error,omitempty"` } +type restartAPIRequest struct { + ClientID uint32 `json:"client_id"` +} + +type restartAPIResponse struct { + Success bool `json:"success"` + ClientID uint32 `json:"client_id,omitempty"` + Error string `json:"error,omitempty"` +} + type otaAPIResponse struct { Success bool `json:"success"` BytesWritten uint32 `json:"bytes_written,omitempty"` @@ -82,6 +92,13 @@ func mountServeAPI(mux *http.ServeMux, link *managedSerial, hub *wsHub) { } serveFindMe(w, r, link) }) + mux.HandleFunc("/api/restart", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + serveRestart(w, r, link) + }) mux.HandleFunc("/api/ota", func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) @@ -233,6 +250,22 @@ func applyDeadzoneToSlaves(link *managedSerial, deadzone uint32) (uint32, error) return updated, nil } +func serveRestart(w http.ResponseWriter, r *http.Request, link *managedSerial) { + var body restartAPIRequest + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + writeJSON(w, http.StatusBadRequest, restartAPIResponse{Error: "invalid JSON"}) + return + } + if err := link.Restart(body.ClientID); err != nil { + writeJSON(w, http.StatusServiceUnavailable, restartAPIResponse{ + ClientID: body.ClientID, + Error: err.Error(), + }) + return + } + writeJSON(w, http.StatusOK, restartAPIResponse{Success: true, ClientID: body.ClientID}) +} + func serveFindMe(w http.ResponseWriter, r *http.Request, link *managedSerial) { var body findMeAPIRequest if err := json.NewDecoder(r.Body).Decode(&body); err != nil { diff --git a/goTool/client_api.go b/goTool/client_api.go index b36aae3..cd851ca 100644 --- a/goTool/client_api.go +++ b/goTool/client_api.go @@ -178,6 +178,12 @@ func (m *managedSerial) FindMe(clientID uint32) error { }) } +func (m *managedSerial) Restart(clientID uint32) error { + return m.withPort(func(sp *serialPort) error { + return runRestartClient(sp, clientID) + }) +} + func (s *serialPort) ledRingProgress(req *pb.LedRingProgressRequest) (*pb.LedRingProgressResponse, error) { msg := &pb.UartMessage{ Type: pb.MessageType_LED_RING, diff --git a/goTool/cmd_restart.go b/goTool/cmd_restart.go new file mode 100644 index 0000000..89abceb --- /dev/null +++ b/goTool/cmd_restart.go @@ -0,0 +1,61 @@ +package main + +import ( + "flag" + "fmt" + + "google.golang.org/protobuf/proto" + "powerpod/gotool/pb" +) + +func runRestart(sp *serialPort, args []string) error { + fs := flag.NewFlagSet("restart", flag.ExitOnError) + clientID := fs.Uint("client", 0, "0=master, >0=ESP-NOW unicast to slave id") + if err := fs.Parse(args); err != nil { + return err + } + return runRestartClient(sp, uint32(*clientID)) +} + +func runRestartClient(sp *serialPort, clientID uint32) error { + resp, err := sp.restart(clientID) + if err != nil { + return err + } + if !resp.GetSuccess() { + return fmt.Errorf("restart rejected (client_id=%d)", resp.GetClientId()) + } + if clientID == 0 { + fmt.Println("restart scheduled on master") + } else { + fmt.Printf("restart sent to slave %d\n", clientID) + } + return nil +} + +func (s *serialPort) restart(clientID uint32) (*pb.RestartResponse, error) { + msg := &pb.UartMessage{ + Type: pb.MessageType_RESTART, + Payload: &pb.UartMessage_RestartRequest{ + RestartRequest: &pb.RestartRequest{ClientId: clientID}, + }, + } + body, err := proto.Marshal(msg) + if err != nil { + return nil, fmt.Errorf("encode: %w", err) + } + payload := append([]byte{byte(pb.MessageType_RESTART)}, body...) + respPayload, err := s.exchangePayload(payload, "RESTART") + if err != nil { + return nil, err + } + var respMsg pb.UartMessage + if err := proto.Unmarshal(respPayload[1:], &respMsg); err != nil { + return nil, fmt.Errorf("decode: %w", err) + } + r := respMsg.GetRestartResponse() + if r == nil { + return nil, fmt.Errorf("missing restart_response") + } + return r, nil +} diff --git a/goTool/main.go b/goTool/main.go index c7e24a6..bc73576 100644 --- a/goTool/main.go +++ b/goTool/main.go @@ -22,7 +22,8 @@ func usage() { fmt.Fprintf(os.Stderr, " ota UART OTA upload (A/B partitions)\n") fmt.Fprintf(os.Stderr, " ota-progress query per-slave ESP-NOW OTA progress on master\n") fmt.Fprintf(os.Stderr, " led-ring set LED ring progress bar (0–100%%, rgb, intensity)\n") - fmt.Fprintf(os.Stderr, " find-me blink LED ring red/green/blue (3× each, full brightness)\n\n") + fmt.Fprintf(os.Stderr, " find-me blink LED ring red/green/blue (3× each, full brightness)\n") + fmt.Fprintf(os.Stderr, " restart reboot master or slave (ESP-NOW)\n\n") flag.PrintDefaults() } @@ -49,7 +50,7 @@ func main() { os.Exit(2) } runErr = runServe(*portName, *baud, flag.Args()[1:]) - case "version", "clients", "client-info", "deadzone", "accel-deadzone", "unicast-test", "unicast_test", "led-ring", "led_ring", "find-me", "find_me", "ota", "ota-progress", "ota_progress": + case "version", "clients", "client-info", "deadzone", "accel-deadzone", "unicast-test", "unicast_test", "led-ring", "led_ring", "find-me", "find_me", "restart", "ota", "ota-progress", "ota_progress": if *portName == "" { fmt.Fprintf(os.Stderr, "command %q requires -port\n\n", cmd) usage() @@ -73,6 +74,8 @@ func main() { runErr = runLedRing(sp, flag.Args()[1:]) case "find-me", "find_me": runErr = runFindMe(sp, flag.Args()[1:]) + case "restart": + runErr = runRestart(sp, flag.Args()[1:]) case "ota": runErr = runOTA(sp, flag.Args()[1:]) case "ota-progress", "ota_progress": diff --git a/goTool/pb/uart_messages.pb.go b/goTool/pb/uart_messages.pb.go index a7ff111..3236dfb 100644 --- a/goTool/pb/uart_messages.pb.go +++ b/goTool/pb/uart_messages.pb.go @@ -40,6 +40,7 @@ const ( MessageType_OTA_START_ESPNOW MessageType = 20 MessageType_OTA_SLAVE_PROGRESS MessageType = 21 MessageType_FIND_ME MessageType = 22 + MessageType_RESTART MessageType = 23 ) // Enum value maps for MessageType. @@ -61,6 +62,7 @@ var ( 20: "OTA_START_ESPNOW", 21: "OTA_SLAVE_PROGRESS", 22: "FIND_ME", + 23: "RESTART", } MessageType_value = map[string]int32{ "UNKNOWN": 0, @@ -79,6 +81,7 @@ var ( "OTA_START_ESPNOW": 20, "OTA_SLAVE_PROGRESS": 21, "FIND_ME": 22, + "RESTART": 23, } ) @@ -133,6 +136,8 @@ type UartMessage struct { // *UartMessage_LedRingProgressResponse // *UartMessage_EspnowFindMeRequest // *UartMessage_EspnowFindMeResponse + // *UartMessage_RestartRequest + // *UartMessage_RestartResponse Payload isUartMessage_Payload `protobuf_oneof:"payload"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -353,6 +358,24 @@ func (x *UartMessage) GetEspnowFindMeResponse() *EspNowFindMeResponse { return nil } +func (x *UartMessage) GetRestartRequest() *RestartRequest { + if x != nil { + if x, ok := x.Payload.(*UartMessage_RestartRequest); ok { + return x.RestartRequest + } + } + return nil +} + +func (x *UartMessage) GetRestartResponse() *RestartResponse { + if x != nil { + if x, ok := x.Payload.(*UartMessage_RestartResponse); ok { + return x.RestartResponse + } + } + return nil +} + type isUartMessage_Payload interface { isUartMessage_Payload() } @@ -433,6 +456,14 @@ type UartMessage_EspnowFindMeResponse struct { EspnowFindMeResponse *EspNowFindMeResponse `protobuf:"bytes,20,opt,name=espnow_find_me_response,json=espnowFindMeResponse,proto3,oneof"` } +type UartMessage_RestartRequest struct { + RestartRequest *RestartRequest `protobuf:"bytes,21,opt,name=restart_request,json=restartRequest,proto3,oneof"` +} + +type UartMessage_RestartResponse struct { + RestartResponse *RestartResponse `protobuf:"bytes,22,opt,name=restart_response,json=restartResponse,proto3,oneof"` +} + func (*UartMessage_AckPayload) isUartMessage_Payload() {} func (*UartMessage_EchoPayload) isUartMessage_Payload() {} @@ -471,6 +502,10 @@ func (*UartMessage_EspnowFindMeRequest) isUartMessage_Payload() {} func (*UartMessage_EspnowFindMeResponse) isUartMessage_Payload() {} +func (*UartMessage_RestartRequest) isUartMessage_Payload() {} + +func (*UartMessage_RestartResponse) isUartMessage_Payload() {} + type Ack struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1383,6 +1418,103 @@ func (x *EspNowFindMeResponse) GetClientId() uint32 { return 0 } +// * Host → master: restart local node (client_id=0) or ESP-NOW unicast to one slave. +type RestartRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ClientId uint32 `protobuf:"varint,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RestartRequest) Reset() { + *x = RestartRequest{} + mi := &file_uart_messages_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RestartRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RestartRequest) ProtoMessage() {} + +func (x *RestartRequest) ProtoReflect() protoreflect.Message { + mi := &file_uart_messages_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RestartRequest.ProtoReflect.Descriptor instead. +func (*RestartRequest) Descriptor() ([]byte, []int) { + return file_uart_messages_proto_rawDescGZIP(), []int{16} +} + +func (x *RestartRequest) GetClientId() uint32 { + if x != nil { + return x.ClientId + } + return 0 +} + +type RestartResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + ClientId uint32 `protobuf:"varint,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RestartResponse) Reset() { + *x = RestartResponse{} + mi := &file_uart_messages_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RestartResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RestartResponse) ProtoMessage() {} + +func (x *RestartResponse) ProtoReflect() protoreflect.Message { + mi := &file_uart_messages_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RestartResponse.ProtoReflect.Descriptor instead. +func (*RestartResponse) Descriptor() ([]byte, []int) { + return file_uart_messages_proto_rawDescGZIP(), []int{17} +} + +func (x *RestartResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *RestartResponse) GetClientId() uint32 { + if x != nil { + return x.ClientId + } + return 0 +} + // Host → device: begin UART OTA (erase inactive OTA slot; device replies OTA_STATUS). type OtaStartPayload struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1393,7 +1525,7 @@ type OtaStartPayload struct { func (x *OtaStartPayload) Reset() { *x = OtaStartPayload{} - mi := &file_uart_messages_proto_msgTypes[16] + mi := &file_uart_messages_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1405,7 +1537,7 @@ func (x *OtaStartPayload) String() string { func (*OtaStartPayload) ProtoMessage() {} func (x *OtaStartPayload) ProtoReflect() protoreflect.Message { - mi := &file_uart_messages_proto_msgTypes[16] + mi := &file_uart_messages_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1418,7 +1550,7 @@ func (x *OtaStartPayload) ProtoReflect() protoreflect.Message { // Deprecated: Use OtaStartPayload.ProtoReflect.Descriptor instead. func (*OtaStartPayload) Descriptor() ([]byte, []int) { - return file_uart_messages_proto_rawDescGZIP(), []int{16} + return file_uart_messages_proto_rawDescGZIP(), []int{18} } func (x *OtaStartPayload) GetTotalSize() uint32 { @@ -1439,7 +1571,7 @@ type OtaPayload struct { func (x *OtaPayload) Reset() { *x = OtaPayload{} - mi := &file_uart_messages_proto_msgTypes[17] + mi := &file_uart_messages_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1451,7 +1583,7 @@ func (x *OtaPayload) String() string { func (*OtaPayload) ProtoMessage() {} func (x *OtaPayload) ProtoReflect() protoreflect.Message { - mi := &file_uart_messages_proto_msgTypes[17] + mi := &file_uart_messages_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1464,7 +1596,7 @@ func (x *OtaPayload) ProtoReflect() protoreflect.Message { // Deprecated: Use OtaPayload.ProtoReflect.Descriptor instead. func (*OtaPayload) Descriptor() ([]byte, []int) { - return file_uart_messages_proto_rawDescGZIP(), []int{17} + return file_uart_messages_proto_rawDescGZIP(), []int{19} } func (x *OtaPayload) GetSeq() uint32 { @@ -1490,7 +1622,7 @@ type OtaEndPayload struct { func (x *OtaEndPayload) Reset() { *x = OtaEndPayload{} - mi := &file_uart_messages_proto_msgTypes[18] + mi := &file_uart_messages_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1502,7 +1634,7 @@ func (x *OtaEndPayload) String() string { func (*OtaEndPayload) ProtoMessage() {} func (x *OtaEndPayload) ProtoReflect() protoreflect.Message { - mi := &file_uart_messages_proto_msgTypes[18] + mi := &file_uart_messages_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1515,7 +1647,7 @@ func (x *OtaEndPayload) ProtoReflect() protoreflect.Message { // Deprecated: Use OtaEndPayload.ProtoReflect.Descriptor instead. func (*OtaEndPayload) Descriptor() ([]byte, []int) { - return file_uart_messages_proto_rawDescGZIP(), []int{18} + return file_uart_messages_proto_rawDescGZIP(), []int{20} } // Device → host status (also used as ACK after each 4 KiB written). @@ -1532,7 +1664,7 @@ type OtaStatusPayload struct { func (x *OtaStatusPayload) Reset() { *x = OtaStatusPayload{} - mi := &file_uart_messages_proto_msgTypes[19] + mi := &file_uart_messages_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1544,7 +1676,7 @@ func (x *OtaStatusPayload) String() string { func (*OtaStatusPayload) ProtoMessage() {} func (x *OtaStatusPayload) ProtoReflect() protoreflect.Message { - mi := &file_uart_messages_proto_msgTypes[19] + mi := &file_uart_messages_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1557,7 +1689,7 @@ func (x *OtaStatusPayload) ProtoReflect() protoreflect.Message { // Deprecated: Use OtaStatusPayload.ProtoReflect.Descriptor instead. func (*OtaStatusPayload) Descriptor() ([]byte, []int) { - return file_uart_messages_proto_rawDescGZIP(), []int{19} + return file_uart_messages_proto_rawDescGZIP(), []int{21} } func (x *OtaStatusPayload) GetStatus() uint32 { @@ -1598,7 +1730,7 @@ type OtaSlaveProgressRequest struct { func (x *OtaSlaveProgressRequest) Reset() { *x = OtaSlaveProgressRequest{} - mi := &file_uart_messages_proto_msgTypes[20] + mi := &file_uart_messages_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1610,7 +1742,7 @@ func (x *OtaSlaveProgressRequest) String() string { func (*OtaSlaveProgressRequest) ProtoMessage() {} func (x *OtaSlaveProgressRequest) ProtoReflect() protoreflect.Message { - mi := &file_uart_messages_proto_msgTypes[20] + mi := &file_uart_messages_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1623,7 +1755,7 @@ func (x *OtaSlaveProgressRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use OtaSlaveProgressRequest.ProtoReflect.Descriptor instead. func (*OtaSlaveProgressRequest) Descriptor() ([]byte, []int) { - return file_uart_messages_proto_rawDescGZIP(), []int{20} + return file_uart_messages_proto_rawDescGZIP(), []int{22} } func (x *OtaSlaveProgressRequest) GetClientId() uint32 { @@ -1647,7 +1779,7 @@ type OtaSlaveProgressEntry struct { func (x *OtaSlaveProgressEntry) Reset() { *x = OtaSlaveProgressEntry{} - mi := &file_uart_messages_proto_msgTypes[21] + mi := &file_uart_messages_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1659,7 +1791,7 @@ func (x *OtaSlaveProgressEntry) String() string { func (*OtaSlaveProgressEntry) ProtoMessage() {} func (x *OtaSlaveProgressEntry) ProtoReflect() protoreflect.Message { - mi := &file_uart_messages_proto_msgTypes[21] + mi := &file_uart_messages_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1672,7 +1804,7 @@ func (x *OtaSlaveProgressEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use OtaSlaveProgressEntry.ProtoReflect.Descriptor instead. func (*OtaSlaveProgressEntry) Descriptor() ([]byte, []int) { - return file_uart_messages_proto_rawDescGZIP(), []int{21} + return file_uart_messages_proto_rawDescGZIP(), []int{23} } func (x *OtaSlaveProgressEntry) GetClientId() uint32 { @@ -1723,7 +1855,7 @@ type OtaSlaveProgressResponse struct { func (x *OtaSlaveProgressResponse) Reset() { *x = OtaSlaveProgressResponse{} - mi := &file_uart_messages_proto_msgTypes[22] + mi := &file_uart_messages_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1735,7 +1867,7 @@ func (x *OtaSlaveProgressResponse) String() string { func (*OtaSlaveProgressResponse) ProtoMessage() {} func (x *OtaSlaveProgressResponse) ProtoReflect() protoreflect.Message { - mi := &file_uart_messages_proto_msgTypes[22] + mi := &file_uart_messages_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1748,7 +1880,7 @@ func (x *OtaSlaveProgressResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use OtaSlaveProgressResponse.ProtoReflect.Descriptor instead. func (*OtaSlaveProgressResponse) Descriptor() ([]byte, []int) { - return file_uart_messages_proto_rawDescGZIP(), []int{22} + return file_uart_messages_proto_rawDescGZIP(), []int{24} } func (x *OtaSlaveProgressResponse) GetActive() bool { @@ -1790,7 +1922,7 @@ var File_uart_messages_proto protoreflect.FileDescriptor const file_uart_messages_proto_rawDesc = "" + "\n" + - "\x13uart_messages.proto\x12\x04alox\x1a\fnanopb.proto\"\xeb\v\n" + + "\x13uart_messages.proto\x12\x04alox\x1a\fnanopb.proto\"\xf0\f\n" + "\vUartMessage\x12%\n" + "\x04type\x18\x01 \x01(\x0e2\x11.alox.MessageTypeR\x04type\x12,\n" + "\vack_payload\x18\x02 \x01(\v2\t.alox.AckH\x00R\n" + @@ -1815,7 +1947,9 @@ const file_uart_messages_proto_rawDesc = "" + "\x19led_ring_progress_request\x18\x11 \x01(\v2\x1c.alox.LedRingProgressRequestH\x00R\x16ledRingProgressRequest\x12\\\n" + "\x1aled_ring_progress_response\x18\x12 \x01(\v2\x1d.alox.LedRingProgressResponseH\x00R\x17ledRingProgressResponse\x12P\n" + "\x16espnow_find_me_request\x18\x13 \x01(\v2\x19.alox.EspNowFindMeRequestH\x00R\x13espnowFindMeRequest\x12S\n" + - "\x17espnow_find_me_response\x18\x14 \x01(\v2\x1a.alox.EspNowFindMeResponseH\x00R\x14espnowFindMeResponseB\t\n" + + "\x17espnow_find_me_response\x18\x14 \x01(\v2\x1a.alox.EspNowFindMeResponseH\x00R\x14espnowFindMeResponse\x12?\n" + + "\x0frestart_request\x18\x15 \x01(\v2\x14.alox.RestartRequestH\x00R\x0erestartRequest\x12B\n" + + "\x10restart_response\x18\x16 \x01(\v2\x15.alox.RestartResponseH\x00R\x0frestartResponseB\t\n" + "\apayload\"\x05\n" + "\x03Ack\"!\n" + "\vEchoPayload\x12\x12\n" + @@ -1879,6 +2013,11 @@ const file_uart_messages_proto_rawDesc = "" + "\tclient_id\x18\x01 \x01(\rR\bclientId\"M\n" + "\x14EspNowFindMeResponse\x12\x18\n" + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x1b\n" + + "\tclient_id\x18\x02 \x01(\rR\bclientId\"-\n" + + "\x0eRestartRequest\x12\x1b\n" + + "\tclient_id\x18\x01 \x01(\rR\bclientId\"H\n" + + "\x0fRestartResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x1b\n" + "\tclient_id\x18\x02 \x01(\rR\bclientId\"0\n" + "\x0fOtaStartPayload\x12\x1d\n" + "\n" + @@ -1910,7 +2049,7 @@ const file_uart_messages_proto_rawDesc = "" + "\x0faggregate_bytes\x18\x03 \x01(\rR\x0eaggregateBytes\x12\x1f\n" + "\vslave_count\x18\x04 \x01(\rR\n" + "slaveCount\x12:\n" + - "\x06slaves\x18\x05 \x03(\v2\x1b.alox.OtaSlaveProgressEntryB\x05\x92?\x02\x10\x10R\x06slaves*\x90\x02\n" + + "\x06slaves\x18\x05 \x03(\v2\x1b.alox.OtaSlaveProgressEntryB\x05\x92?\x02\x10\x10R\x06slaves*\x9d\x02\n" + "\vMessageType\x12\v\n" + "\aUNKNOWN\x10\x00\x12\a\n" + "\x03ACK\x10\x01\x12\b\n" + @@ -1928,7 +2067,8 @@ const file_uart_messages_proto_rawDesc = "" + "OTA_STATUS\x10\x13\x12\x14\n" + "\x10OTA_START_ESPNOW\x10\x14\x12\x16\n" + "\x12OTA_SLAVE_PROGRESS\x10\x15\x12\v\n" + - "\aFIND_ME\x10\x16b\x06proto3" + "\aFIND_ME\x10\x16\x12\v\n" + + "\aRESTART\x10\x17b\x06proto3" var ( file_uart_messages_proto_rawDescOnce sync.Once @@ -1943,7 +2083,7 @@ func file_uart_messages_proto_rawDescGZIP() []byte { } var file_uart_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_uart_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_uart_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_uart_messages_proto_goTypes = []any{ (MessageType)(0), // 0: alox.MessageType (*UartMessage)(nil), // 1: alox.UartMessage @@ -1962,13 +2102,15 @@ var file_uart_messages_proto_goTypes = []any{ (*LedRingProgressResponse)(nil), // 14: alox.LedRingProgressResponse (*EspNowFindMeRequest)(nil), // 15: alox.EspNowFindMeRequest (*EspNowFindMeResponse)(nil), // 16: alox.EspNowFindMeResponse - (*OtaStartPayload)(nil), // 17: alox.OtaStartPayload - (*OtaPayload)(nil), // 18: alox.OtaPayload - (*OtaEndPayload)(nil), // 19: alox.OtaEndPayload - (*OtaStatusPayload)(nil), // 20: alox.OtaStatusPayload - (*OtaSlaveProgressRequest)(nil), // 21: alox.OtaSlaveProgressRequest - (*OtaSlaveProgressEntry)(nil), // 22: alox.OtaSlaveProgressEntry - (*OtaSlaveProgressResponse)(nil), // 23: alox.OtaSlaveProgressResponse + (*RestartRequest)(nil), // 17: alox.RestartRequest + (*RestartResponse)(nil), // 18: alox.RestartResponse + (*OtaStartPayload)(nil), // 19: alox.OtaStartPayload + (*OtaPayload)(nil), // 20: alox.OtaPayload + (*OtaEndPayload)(nil), // 21: alox.OtaEndPayload + (*OtaStatusPayload)(nil), // 22: alox.OtaStatusPayload + (*OtaSlaveProgressRequest)(nil), // 23: alox.OtaSlaveProgressRequest + (*OtaSlaveProgressEntry)(nil), // 24: alox.OtaSlaveProgressEntry + (*OtaSlaveProgressResponse)(nil), // 25: alox.OtaSlaveProgressResponse } var file_uart_messages_proto_depIdxs = []int32{ 0, // 0: alox.UartMessage.type:type_name -> alox.MessageType @@ -1977,28 +2119,30 @@ var file_uart_messages_proto_depIdxs = []int32{ 4, // 3: alox.UartMessage.version_response:type_name -> alox.VersionResponse 6, // 4: alox.UartMessage.client_info_response:type_name -> alox.ClientInfoResponse 8, // 5: alox.UartMessage.client_input_response:type_name -> alox.ClientInputResponse - 17, // 6: alox.UartMessage.ota_start:type_name -> alox.OtaStartPayload - 18, // 7: alox.UartMessage.ota_payload:type_name -> alox.OtaPayload - 19, // 8: alox.UartMessage.ota_end:type_name -> alox.OtaEndPayload - 20, // 9: alox.UartMessage.ota_status:type_name -> alox.OtaStatusPayload + 19, // 6: alox.UartMessage.ota_start:type_name -> alox.OtaStartPayload + 20, // 7: alox.UartMessage.ota_payload:type_name -> alox.OtaPayload + 21, // 8: alox.UartMessage.ota_end:type_name -> alox.OtaEndPayload + 22, // 9: alox.UartMessage.ota_status:type_name -> alox.OtaStatusPayload 9, // 10: alox.UartMessage.accel_deadzone_request:type_name -> alox.AccelDeadzoneRequest 10, // 11: alox.UartMessage.accel_deadzone_response:type_name -> alox.AccelDeadzoneResponse 11, // 12: alox.UartMessage.espnow_unicast_test_request:type_name -> alox.EspNowUnicastTestRequest 12, // 13: alox.UartMessage.espnow_unicast_test_response:type_name -> alox.EspNowUnicastTestResponse - 21, // 14: alox.UartMessage.ota_slave_progress_request:type_name -> alox.OtaSlaveProgressRequest - 23, // 15: alox.UartMessage.ota_slave_progress_response:type_name -> alox.OtaSlaveProgressResponse + 23, // 14: alox.UartMessage.ota_slave_progress_request:type_name -> alox.OtaSlaveProgressRequest + 25, // 15: alox.UartMessage.ota_slave_progress_response:type_name -> alox.OtaSlaveProgressResponse 13, // 16: alox.UartMessage.led_ring_progress_request:type_name -> alox.LedRingProgressRequest 14, // 17: alox.UartMessage.led_ring_progress_response:type_name -> alox.LedRingProgressResponse 15, // 18: alox.UartMessage.espnow_find_me_request:type_name -> alox.EspNowFindMeRequest 16, // 19: alox.UartMessage.espnow_find_me_response:type_name -> alox.EspNowFindMeResponse - 5, // 20: alox.ClientInfoResponse.clients:type_name -> alox.ClientInfo - 7, // 21: alox.ClientInputResponse.clients:type_name -> alox.ClientInput - 22, // 22: alox.OtaSlaveProgressResponse.slaves:type_name -> alox.OtaSlaveProgressEntry - 23, // [23:23] is the sub-list for method output_type - 23, // [23:23] is the sub-list for method input_type - 23, // [23:23] is the sub-list for extension type_name - 23, // [23:23] is the sub-list for extension extendee - 0, // [0:23] is the sub-list for field type_name + 17, // 20: alox.UartMessage.restart_request:type_name -> alox.RestartRequest + 18, // 21: alox.UartMessage.restart_response:type_name -> alox.RestartResponse + 5, // 22: alox.ClientInfoResponse.clients:type_name -> alox.ClientInfo + 7, // 23: alox.ClientInputResponse.clients:type_name -> alox.ClientInput + 24, // 24: alox.OtaSlaveProgressResponse.slaves:type_name -> alox.OtaSlaveProgressEntry + 25, // [25:25] is the sub-list for method output_type + 25, // [25:25] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name } func init() { file_uart_messages_proto_init() } @@ -2026,6 +2170,8 @@ func file_uart_messages_proto_init() { (*UartMessage_LedRingProgressResponse)(nil), (*UartMessage_EspnowFindMeRequest)(nil), (*UartMessage_EspnowFindMeResponse)(nil), + (*UartMessage_RestartRequest)(nil), + (*UartMessage_RestartResponse)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -2033,7 +2179,7 @@ func file_uart_messages_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_uart_messages_proto_rawDesc), len(file_uart_messages_proto_rawDesc)), NumEnums: 1, - NumMessages: 23, + NumMessages: 25, NumExtensions: 0, NumServices: 0, }, diff --git a/goTool/webui/index.html b/goTool/webui/index.html index ea9cbd4..9a34b47 100644 --- a/goTool/webui/index.html +++ b/goTool/webui/index.html @@ -233,6 +233,12 @@ title="LED-Ring: Rot/Grün/Blau je 3×"> Find me +
UART nicht verbunden — Eingabe gesperrt. @@ -312,6 +318,12 @@ title="LED-Ring Find me (ESP-NOW)"> Find me + @@ -366,7 +378,11 @@ x-text="ota.masterMessage || (ota.step === 'master' ? ota.message : '')">