package device import ( "fmt" "strconv" "strings" ) // ProcessCommand handles incoming BLE commands and returns the response func (s *DeviceState) ProcessCommand(cmd string) string { cmd = strings.TrimSpace(cmd) // Handle global commands switch cmd { case "PROG_ON": s.SetProgMode(true) return "PROG_MODE: ON" case "PROG_OFF": s.SetProgMode(false) return "PROG_MODE: OFF" case "RESET": s.ResetAlarm() return "INFO: Uscita allarme resettata (BT)." case "CALI": active := s.ToggleCaliMode() if active { return "--- MODALITA CALIBRAZIONE ATTIVA ---" } return "--- MODALITA CALIBRAZIONE DISATTIVA ---" case "FACTORY": s.ResetToDefaults() return "FACTORY RESET DONE" } // Handle write commands (W1, W2, etc.) if strings.HasPrefix(cmd, "W") { return s.handleWriteCommand(cmd) } // Handle read commands (R1, R2, etc.) if strings.HasPrefix(cmd, "R") { return s.handleReadCommand(cmd) } return "ERRORE: Formato comando non valido" } // handleWriteCommand processes Wxx commands func (s *DeviceState) handleWriteCommand(cmd string) string { // Check if in programming mode if !s.GetProgMode() { return "ERRORE: I comandi 'W' sono accettati solo in modalità programmazione." } // Parse command format: "W " parts := strings.Fields(cmd) if len(parts) != 2 { return "ERRORE: Formato comando non valido" } // Extract parameter ID idStr := strings.TrimPrefix(parts[0], "W") id, err := strconv.Atoi(idStr) if err != nil { return "ERRORE: Formato comando non valido" } // Check if parameter ID is valid if !isValidParamID(id) { return "ERRORE: ID Sconosciuto" } // Parse value value, err := strconv.Atoi(parts[1]) if err != nil { return "ERRORE: Formato comando non valido" } // Validate range based on parameter ID if !validateParamRange(id, value) { return fmt.Sprintf("ERRORE: Valore fuori range per W%d", id) } // Set the parameter s.SetParam(id, value) return fmt.Sprintf("PARAM: W%d=%d", id, value) } // handleReadCommand processes Rxx commands func (s *DeviceState) handleReadCommand(cmd string) string { // Check if in programming mode if !s.GetProgMode() { return "ERRORE: I comandi 'W' sono accettati solo in modalità programmazione." } // Extract parameter ID idStr := strings.TrimPrefix(cmd, "R") id, err := strconv.Atoi(idStr) if err != nil { return "ERRORE: Formato comando non valido" } // Check if parameter ID is valid for reading if !isReadableParamID(id) { return "ERRORE: ID Sconosciuto" } // Get the parameter value value, ok := s.GetParam(id) if !ok { return "ERRORE: ID Sconosciuto" } return fmt.Sprintf("PARAM: W%d=%d", id, value) } // isValidParamID checks if the parameter ID is writable func isValidParamID(id int) bool { validIDs := []int{1, 2, 3, 4, 11, 12, 20} for _, v := range validIDs { if id == v { return true } } return false } // isReadableParamID checks if the parameter ID is readable func isReadableParamID(id int) bool { // According to docs.toon, only R1, R2, R20 are documented readableIDs := []int{1, 2, 20} for _, v := range readableIDs { if id == v { return true } } return false } // validateParamRange checks if value is within acceptable range for parameter func validateParamRange(id, value int) bool { ranges := map[int][2]int{ 1: {0, 2000}, // W1 - Min Threshold 2: {0, 4095}, // W2 - Max Threshold 3: {1, 50}, // W3 - Pulse Count 4: {10, 1000}, // W4 - Time Window 11: {0, 1000}, // W11 - Min Pulse Duration 12: {0, 1000}, // W12 - Max Pulse Duration 20: {0, 255}, // W20 - Gain (Wiper) } r, ok := ranges[id] if !ok { return false } return value >= r[0] && value <= r[1] }