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) { rssi, ber, err := getSignalQuality(port) if err != nil { return false, 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 false, nil } if err := checkBer(ber); err != nil { logger.Printf("bad ber(not critical): %s", err.Error()) // Happened not to be critical } return true, nil } func checkRssi(rssi int) error { // rssi - Received signal strength 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) 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 }