109 lines
2.7 KiB
Go
109 lines
2.7 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"gitea.unprism.ru/KRBL/sim-modem/api/modem/at"
|
|
)
|
|
|
|
func CheckSignal(port at.Port, logger *log.Logger) error {
|
|
rssi, ber, err := getSignalQuality(port)
|
|
if err != nil {
|
|
return fmt.Errorf("get signal quality: %w", err)
|
|
}
|
|
logger.Printf("check signal: rssi=%d ber=%d\n", rssi, ber)
|
|
if err := checkRssi(rssi); err != nil {
|
|
return fmt.Errorf("rssi: %w", err)
|
|
}
|
|
if err := checkBer(ber); err != nil {
|
|
logger.Printf("bad ber(not critical): %s", err.Error()) // Happened not to be critical
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
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
|
|
}
|