Files
BLE_emulator/internal/device/logic.go
2026-02-19 11:43:56 +01:00

182 lines
4.2 KiB
Go

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 <value> 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."
}
// Handle special WNC command
if strings.HasPrefix(cmd, "WNC=") {
valueStr := strings.TrimPrefix(cmd, "WNC=")
value, err := strconv.Atoi(valueStr)
if err != nil || (value != 0 && value != 1) {
return "ERRORE: Valore fuori range per WNC"
}
s.SetNCParam(value == 1)
return fmt.Sprintf("OK: Parametro WNC impostato e salvato: %d", value)
}
// Parse command format: "W<id>=<value>"
parts := strings.SplitN(cmd, "=", 2)
if len(parts) != 2 {
return "ERRORE: Formato comando non valido"
}
// Extract parameter ID (remove "W" prefix from first part)
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."
}
// Handle special RNC command
if cmd == "RNC" {
value := 0
if s.GetNCParam() {
value = 1
}
return fmt.Sprintf("PARAM: WNC=%d", value)
}
// 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]
}