sim-modem/api/modem/utils/signal.go

110 lines
2.7 KiB
Go
Raw Normal View History

2024-08-10 12:21:27 +00:00
package utils
import (
"fmt"
"log"
"strconv"
"strings"
"gitea.unprism.ru/KRBL/sim-modem/api/modem/at"
)
func CheckSignal(port at.Port, logger *log.Logger) (bool, error) {
2024-08-10 12:21:27 +00:00
rssi, ber, err := getSignalQuality(port)
if err != nil {
return false, fmt.Errorf("get signal quality: %w", err)
2024-08-10 12:21:27 +00:00
}
logger.Printf("check signal: rssi=%d ber=%d\n", rssi, ber)
if err := checkRssi(rssi); err != nil {
return false, nil
2024-08-10 12:21:27 +00:00
}
if err := checkBer(ber); err != nil {
logger.Printf("bad ber(not critical): %s", err.Error()) // Happened not to be critical
}
return true, nil
2024-08-10 12:21:27 +00:00
}
func checkRssi(rssi int) error {
// rssi - Received signal strenght indicator
// 0 -113 dBm or less
// 1 -111 dBm
// 2...30 -109... - 53 dBm
// 31 -51 dBm or greater
// 99 not known or not detectable
// 100 -116 dBm or less
// 101 -115 dBm
// 102…191 -114... - 26dBm
// 191 -25 dBm or greater
// 199 not known or not detectable
// 100…199 expand to TDSCDMA, indicate RSCPreceived
if rssi <= 2 { // Too poor
return fmt.Errorf("too poor <= -109dBm")
}
if rssi > 2 && rssi <= 31 {
return nil // Can live
}
if rssi == 99 {
return fmt.Errorf("not known or not detectable")
}
if rssi >= 100 && rssi <= 102 {
return fmt.Errorf("too poor <= -114dBm")
}
if rssi > 102 && rssi <= 191 {
return nil // Can live
}
if rssi == 199 {
return fmt.Errorf("not known or not detectable")
}
return fmt.Errorf("invalid code %d", rssi)
}
func checkBer(ber int) error {
// ber - Bit error rate
// 0 <0.01%
// 1 0.01% --- 0.1%
// 2 0.1% --- 0.5%
// 3 0.5% --- 1.0%
// 4 1.0% --- 2.0%
// 5 2.0% --- 4.0%
// 6 4.0% --- 8.0%
// 7 >=8.0%
// 99 not known or not detectable
if ber >= 0 && ber <= 3 {
// ber -> [0%;1%)
// Ok, can live
return nil
}
if ber >= 4 && ber <= 7 {
return fmt.Errorf("too high: %d code", ber)
}
if ber == 99 {
return fmt.Errorf("not known or not detectable")
}
return fmt.Errorf("invalid code %d", ber)
}
// Returns rssi and ber(look above)
2024-08-10 12:21:27 +00:00
func getSignalQuality(port at.Port) (int, int, error) {
resp, err := port.Send("AT+CSQ")
if err != nil {
return 99, 99, err
}
if !resp.Check() || !resp.CheckFront("+CSQ: ") {
return 99, 99, fmt.Errorf("error response: %s", resp)
}
values := strings.Split(strings.ReplaceAll(strings.Split(resp.RmFront("+CSQ: ").String(), "\n")[0], "\r", ""), ",")
if len(values) != 2 {
return 99, 99, fmt.Errorf("invalid values(len): [% s]", values)
}
rssi, err := strconv.Atoi(values[0])
if err != nil {
return 99, 99, fmt.Errorf("parse rssi: %w", err)
}
ber, err := strconv.Atoi(values[1])
if err != nil {
return 99, 99, fmt.Errorf("parse ber: %w", err)
}
return rssi, ber, nil
}