diff --git a/api/modem/internet/ic.go b/api/modem/internet/ic.go index 285f9d0..32d4b85 100644 --- a/api/modem/internet/ic.go +++ b/api/modem/internet/ic.go @@ -4,11 +4,11 @@ import ( "fmt" "io" "log" - "os" "os/exec" "strings" "gitea.unprism.ru/KRBL/sim-modem/api/modem/at" + "gitea.unprism.ru/KRBL/sim-modem/api/modem/utils" ) var apns = map[string]string{ @@ -44,7 +44,8 @@ type conn struct { type Conn interface { Init() error - ConfigurePPP() error + Connect() error + Disconnect() error Ping() bool // Is connected io.Closer } @@ -56,121 +57,14 @@ func New(logger *log.Logger, port at.Port) Conn { } } -func (c *conn) checkPackageExist(pname string) bool { - resp, err := exec.Command("apt-mark", "showmanual", pname).Output() - c.logger.Println("CHECK:", resp) - if err != nil { - c.logger.Println("CHECK PACKAGE ERROR: ", err.Error()) - return false - } - return string(resp[:len(pname)]) == pname -} - -func (c *conn) ensurePackage(pname string) error { - if c.checkPackageExist(pname) { - return nil - } - return fmt.Errorf("package %s not installed", pname) - // c.logger.Println("Installing", pname, "package...") - // resp, err := exec.Command("apt-get", "install", pname).Output() - // if err != nil { - // return fmt.Errorf("execute install cmd: %w", err) - // } - // c.logger.Println(resp) - // c.logger.Println("\x1b[38;2;255;0;0mComplete\x1b[38;2;255;255;255m") - // return nil -} - -// Check requirenments -func (c *conn) checkReqs() error { - // Check AT port for sure - if c.port == nil || !c.port.IsConnected() { - return fmt.Errorf("AT port is not connect or nil") +func (c *conn) Connect() error { + if ok, err := utils.CheckService(c.port, c.logger); err != nil || !ok { + if err != nil { + return fmt.Errorf("check service: %w", err) + } + return fmt.Errorf("no service") } - // Ensure all necessary packages installed - if err := c.ensurePackage("ppp"); err != nil { - return fmt.Errorf("ensure ppp package: %w", err) - } - // if err := c.ensurePackage("net-tools"); err != nil { - // return fmt.Errorf("ensure net-tools package: %w", err) - // } - - // Check SIM is valid - // AT+CPIN? and just check - resp, err := c.port.Send("AT+CPIN?") - if err != nil { - return fmt.Errorf("AT+CPIN? request: %w", err) - } - if !resp.Check() { - return fmt.Errorf("validate SIM: error response: %s", resp) - } - return nil -} - -func (c *conn) ConfigurePPP() error { - // Get provider name and its APN - resp, err := c.port.Send("AT+CSPN?") - if err != nil { - return fmt.Errorf("AT+CSPN? request: %w", err) - } - if !resp.Check() { - return fmt.Errorf("get provider: error response: %s", resp) - } - strs := strings.Split(string(resp), "\"") - if len(strs) < 3 { - return fmt.Errorf("parse AT+CSPN response: %s", string(resp)) - } - provider := strs[1] - apn := apns[provider] - if apn == "" { - return fmt.Errorf("no apn for provider: %s", provider) - } - - // Make config - c.logger.Printf("Config values: %s, %s, %d", apn, c.port.GetName(), c.port.GetBaudrate()) - config := fmt.Sprintf(pppConfig, apn, c.port.GetName(), c.port.GetBaudrate()) - - // Write to file - f, err := os.OpenFile("/etc/ppp/peers/"+pppConfigName, os.O_CREATE|os.O_WRONLY, 0666) - if err != nil { - return fmt.Errorf("open ppp config file %w", err) - } - defer f.Close() - if _, err := f.Write([]byte(config)); err != nil { - return fmt.Errorf("write to ppp config file: %w", err) - } - return nil -} - -func (c *conn) setup() error { - c.logger.Println("Check requirenments...") - if err := c.checkReqs(); err != nil { - return fmt.Errorf("check requirenments: %w", err) - } - // DEBUG show networks and signal - resp, err := c.port.Send("AT+COPS?") - if err != nil { - return fmt.Errorf("AT+COPS? request: %w", err) - } - c.logger.Println("DEBUG networks:", resp) - - resp, err = c.port.Send("AT+CSQ") - if err != nil { - return fmt.Errorf("AT+CSQ request: %w", err) - } - c.logger.Println("DEBUG signal quality:", resp) - - // Configure ppp - // what is better ASK If /etc/ppp/peers/annalistnet not exists - c.logger.Println("Configure ppp...") - if err := c.ConfigurePPP(); err != nil { - return fmt.Errorf("configure ppp: %w", err) - } - return nil -} - -func (c *conn) connect() error { resp, err := exec.Command("pon", pppConfigName).Output() if err != nil { return fmt.Errorf("execute connect cmd: %w", err) @@ -179,7 +73,7 @@ func (c *conn) connect() error { return nil } -func (c *conn) diconnect() error { +func (c *conn) Disconnect() error { resp, err := exec.Command("poff", pppConfigName).Output() if err != nil { return fmt.Errorf("execute disconnect cmd: %w", err) @@ -190,28 +84,27 @@ func (c *conn) diconnect() error { func (c *conn) Init() error { // Setup - c.logger.Println("Setup...") if err := c.setup(); err != nil { return fmt.Errorf("setup: %w", err) } - // Connect - c.logger.Println("Connect...") - if err := c.connect(); err != nil { - return fmt.Errorf("connect: %w", err) - } + // // Connect + // c.logger.Println("Connect...") + // if err := c.Connect(); err != nil { + // return fmt.Errorf("connect: %w", err) + // } - //DEBUG - resp, err := exec.Command("ifconfig").Output() - if err != nil { - return fmt.Errorf("execute ifconfig cmd: %w", err) - } - c.logger.Println("DEBUG ifconfig resp:", string(resp)) + // //DEBUG + // resp, err := exec.Command("ifconfig").Output() + // if err != nil { + // return fmt.Errorf("execute ifconfig cmd: %w", err) + // } + // c.logger.Println("DEBUG ifconfig resp:", string(resp)) - // Test connectin using Ping - c.logger.Println("Test...") - if !c.Ping() { - return fmt.Errorf("ping failed") - } + // // Test connectin using Ping + // c.logger.Println("Test...") + // if !c.Ping() { + // return fmt.Errorf("ping failed") + // } return nil } @@ -234,7 +127,7 @@ func (c *conn) Ping() bool { } func (c *conn) Close() error { - if err := c.diconnect(); err != nil { + if err := c.Disconnect(); err != nil { return fmt.Errorf("diconnect: %w", err) } return nil diff --git a/api/modem/internet/setup.go b/api/modem/internet/setup.go new file mode 100644 index 0000000..09ccdf5 --- /dev/null +++ b/api/modem/internet/setup.go @@ -0,0 +1,119 @@ +package internet + +import ( + "fmt" + "os" + "os/exec" + "strings" + + "gitea.unprism.ru/KRBL/sim-modem/api/modem/utils" +) + +func (c *conn) setup() error { + c.logger.Println("Check requirenments...") + if err := c.checkReqs(); err != nil { + return fmt.Errorf("check requirenments: %w", err) + } + // DEBUG show networks and signal + resp, err := c.port.Send("AT+COPS?") + if err != nil { + return fmt.Errorf("AT+COPS? request: %w", err) + } + c.logger.Println("DEBUG networks:", resp) + + resp, err = c.port.Send("AT+CSQ") + if err != nil { + return fmt.Errorf("AT+CSQ request: %w", err) + } + c.logger.Println("DEBUG signal quality:", resp) + + // Configure ppp + // what is better ASK If /etc/ppp/peers/annalistnet not exists + c.logger.Println("Configure ppp...") + if err := c.configurePPP(); err != nil { + return fmt.Errorf("configure ppp: %w", err) + } + return nil +} + +// Check requirenments +func (c *conn) checkReqs() error { + // Check AT port for sure + if c.port == nil || !c.port.IsConnected() { + return fmt.Errorf("AT port is not connect or nil") + } + + // Ensure all necessary packages installed + if err := c.ensurePackage("ppp"); err != nil { + return fmt.Errorf("ensure ppp package: %w", err) + } + // if err := c.ensurePackage("net-tools"); err != nil { + // return fmt.Errorf("ensure net-tools package: %w", err) + // } + + // Check SIM is valid + if err := utils.CheckPIN(c.port, c.logger); err != nil { + return fmt.Errorf("PIN check: %w", err) + } + return nil +} + +func (c *conn) ensurePackage(pname string) error { + if c.checkPackageExist(pname) { + return nil + } + return fmt.Errorf("package %s not installed", pname) + // c.logger.Println("Installing", pname, "package...") + // resp, err := exec.Command("apt-get", "install", pname).Output() + // if err != nil { + // return fmt.Errorf("execute install cmd: %w", err) + // } + // c.logger.Println(resp) + // c.logger.Println("\x1b[38;2;255;0;0mComplete\x1b[38;2;255;255;255m") + // return nil +} + +func (c *conn) checkPackageExist(pname string) bool { + resp, err := exec.Command("apt-mark", "showmanual", pname).Output() + c.logger.Println("CHECK:", resp) + if err != nil { + c.logger.Println("CHECK PACKAGE ERROR: ", err.Error()) + return false + } + return string(resp[:len(pname)]) == pname +} + +func (c *conn) configurePPP() error { + // Get provider name and its APN + resp, err := c.port.Send("AT+CSPN?") + if err != nil { + return fmt.Errorf("AT+CSPN? request: %w", err) + } + if !resp.Check() { + return fmt.Errorf("get provider: error response: %s", resp) + } + strs := strings.Split(string(resp), "\"") + if len(strs) < 3 { + return fmt.Errorf("parse AT+CSPN response: %s", string(resp)) + } + provider := strs[1] + apn := apns[provider] + if apn == "" { + return fmt.Errorf("no apn for provider: %s", provider) + } + + // Make config + c.logger.Printf("Config values: %s, %s, %d", apn, c.port.GetName(), c.port.GetBaudrate()) + config := fmt.Sprintf(pppConfig, apn, c.port.GetName(), c.port.GetBaudrate()) + + // Write to file + f, err := os.OpenFile("/etc/ppp/peers/"+pppConfigName, os.O_CREATE|os.O_WRONLY, 0666) + if err != nil { + return fmt.Errorf("open ppp config file %w", err) + } + defer f.Close() + if _, err := f.Write([]byte(config)); err != nil { + return fmt.Errorf("write to ppp config file: %w", err) + } + return nil +} diff --git a/api/modem/modem.go b/api/modem/modem.go index 907b818..ec969e7 100644 --- a/api/modem/modem.go +++ b/api/modem/modem.go @@ -15,7 +15,6 @@ import ( "gitea.unprism.ru/KRBL/sim-modem/api/modem/gps" "gitea.unprism.ru/KRBL/sim-modem/api/modem/internet" "gitea.unprism.ru/KRBL/sim-modem/api/modem/sms" - "gitea.unprism.ru/KRBL/sim-modem/api/modem/utils" ) type ModemData struct { @@ -54,7 +53,6 @@ type Modem interface { IsConnected() bool Update() error GetData() ModemData - CheckSignal() error PowerOn() error PowerOff() error @@ -120,13 +118,19 @@ func (m *modem) Init() error { // } else { // m.logger.Println("\x1b[38;2;0;255;0mInternet OK\x1b[38;2;255;255;255m") // } + // + // if err := m.ic.Connect(); err != nil { + // m.logger.Println("connect to internet: %w", err) + // } else { + // m.logger.Println("internet connected") + // } - m.sms = sms.New(log.New(submodulesLogger, "modem-sms : ", log.LstdFlags), m.port) - if err := m.sms.Init(); err != nil { - m.logger.Printf("\x1b[38;2;255;0;0mSMS: %s\x1b[38;2;255;255;255m\n", err.Error()) - } else { - m.logger.Println("\x1b[38;2;0;255;0mSMS OK\x1b[38;2;255;255;255m") - } + // m.sms = sms.New(log.New(submodulesLogger, "modem-sms : ", log.LstdFlags), m.port) + // if err := m.sms.Init(); err != nil { + // m.logger.Printf("\x1b[38;2;255;0;0mSMS: %s\x1b[38;2;255;255;255m\n", err.Error()) + // } else { + // m.logger.Println("\x1b[38;2;0;255;0mSMS OK\x1b[38;2;255;255;255m") + // } m.gps = gps.New(log.New(submodulesLogger, "modem-gps : ", log.LstdFlags), m.port) if err := m.gps.Init(); err != nil { @@ -172,10 +176,6 @@ func (m *modem) GetData() ModemData { } } -func (m *modem) CheckSignal() error { - return utils.CheckSignal(m.port, m.logger) -} - func (m *modem) PowerOn() error { m.onOffPin.PowerOn() // DEBUG do not want to wait 30 seconds return nil diff --git a/api/modem/sms/setup.go b/api/modem/sms/setup.go index 1616668..01f7a6a 100644 --- a/api/modem/sms/setup.go +++ b/api/modem/sms/setup.go @@ -6,23 +6,6 @@ import ( "strings" ) -func (d *dialer) checkPIN() error { - // Get code - resp, err := d.port.Send("AT+CPIN?") - if err != nil { - return fmt.Errorf("AT+CPIN? request: %w", err) - } - if !resp.Check() || !resp.CheckFront("+CPIN:") { - return fmt.Errorf("AT+CPIN? error response: %s", resp) - } - code := strings.ReplaceAll(strings.ReplaceAll(strings.Split(resp.RmFront("+CPIN:").String(), "\n")[0], "\r", ""), " ", "") - if code != "READY" { - return fmt.Errorf("not READY code: %s", code) - } - d.logger.Println("PIN is ready") - return nil -} - func (d *dialer) setupMsgSt() error { // Check for free space for messages // !!! I use one! memory for all three bindings diff --git a/api/modem/sms/sms.go b/api/modem/sms/sms.go index df94c83..2926d89 100644 --- a/api/modem/sms/sms.go +++ b/api/modem/sms/sms.go @@ -8,6 +8,7 @@ import ( "time" "gitea.unprism.ru/KRBL/sim-modem/api/modem/at" + "gitea.unprism.ru/KRBL/sim-modem/api/modem/utils" ) type dialer struct { @@ -36,7 +37,7 @@ func (d *dialer) Init() error { return fmt.Errorf("serial port is not connected") } // Check ping - if err := d.checkPIN(); err != nil { + if err := utils.CheckPIN(d.port, d.logger); err != nil { return fmt.Errorf("check PIN: %w", err) } // Setup prefered message storage diff --git a/api/modem/utils/service.go b/api/modem/utils/service.go new file mode 100644 index 0000000..1a90de3 --- /dev/null +++ b/api/modem/utils/service.go @@ -0,0 +1,37 @@ +package utils + +import ( + "fmt" + "log" + "strings" + + "gitea.unprism.ru/KRBL/sim-modem/api/modem/at" +) + +func CheckService(port at.Port, logger *log.Logger) (bool, error) { + srv, err := getService(port) + if err != nil { + return false, fmt.Errorf("get service: %w", err) + } + if srv == "NO SERVICE" { + return false, nil + } + logger.Println("Current service:", srv) + return true, nil +} + +// Returns service +func getService(port at.Port) (string, error) { + resp, err := port.Send("AT+CPSI?") + if err != nil { + return "", err + } + if !resp.Check() || !resp.CheckFront("+CPSI: ") { + return "", fmt.Errorf("error response: %s", resp) + } + values := strings.Split(strings.ReplaceAll(strings.Split(resp.RmFront("+CPSI: ").String(), "\n")[0], "\r", ""), ",") + if len(values) < 2 { + return "", fmt.Errorf("invalid values(len): [% s]", values) + } + return values[0], nil +} diff --git a/api/modem/utils/signal.go b/api/modem/utils/signal.go index dfe1503..022762c 100644 --- a/api/modem/utils/signal.go +++ b/api/modem/utils/signal.go @@ -9,19 +9,19 @@ import ( "gitea.unprism.ru/KRBL/sim-modem/api/modem/at" ) -func CheckSignal(port at.Port, logger *log.Logger) error { +func CheckSignal(port at.Port, logger *log.Logger) (bool, error) { rssi, ber, err := getSignalQuality(port) if err != nil { - return fmt.Errorf("get signal quality: %w", err) + 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 fmt.Errorf("rssi: %w", err) + return false, nil } if err := checkBer(ber); err != nil { logger.Printf("bad ber(not critical): %s", err.Error()) // Happened not to be critical } - return nil + return true, nil } func checkRssi(rssi int) error { @@ -84,6 +84,7 @@ func checkBer(ber int) error { 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 { diff --git a/api/modem/utils/sim.go b/api/modem/utils/sim.go new file mode 100644 index 0000000..332fa38 --- /dev/null +++ b/api/modem/utils/sim.go @@ -0,0 +1,26 @@ +package utils + +import ( + "fmt" + "log" + "strings" + + "gitea.unprism.ru/KRBL/sim-modem/api/modem/at" +) + +func CheckPIN(port at.Port, logger *log.Logger) error { + // Get code + resp, err := port.Send("AT+CPIN?") + if err != nil { + return fmt.Errorf("AT+CPIN? request: %w", err) + } + if !resp.Check() || !resp.CheckFront("+CPIN:") { + return fmt.Errorf("AT+CPIN? error response: %s", resp) + } + code := strings.ReplaceAll(strings.ReplaceAll(strings.Split(resp.RmFront("+CPIN:").String(), "\n")[0], "\r", ""), " ", "") + if code != "READY" { + return fmt.Errorf("not READY code: %s", code) + } + logger.Println("PIN is ready") + return nil +} diff --git a/main.go b/main.go index f1f02d7..a14cde5 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,11 @@ package main import ( + "context" "log" "os" + "os/signal" + "syscall" "time" "gitea.unprism.ru/KRBL/sim-modem/api/modem" @@ -11,13 +14,17 @@ import ( func main() { log.Println("CGSG forever!!!") - if err := mainE(); err != nil { + + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer cancel() + + if err := mainE(ctx); err != nil { log.Println("MAIN finished with error:", err.Error()) } log.Println("END") } -func mainE() error { +func mainE(ctx context.Context) error { logger := log.New(os.Stdout, "main : ", log.LstdFlags) m := modem.New(log.New(logger.Writer(), "modem : ", log.LstdFlags)) @@ -61,30 +68,34 @@ func mainE() error { // logger.Println(m.Sms().Send("+79218937173", "CGSG forever!!!")) // m.At().RawSend("\r\n\x1A\r\n") - Cmd("AT+CREG?") - Cmd("AT+CNMI?") - Cmd("AT+CSQ") - Cmd("AT+CSCA?") - Cmd("AT+CPOL?") - Cmd("AT+COPS?") - // Cmd("AT+COPS=?") - Cmd("AT+CPSI?") - resp, err = m.At().Send("AT+CNMI=2,2") + // Cmd("AT+CREG?") + // Cmd("AT+CNMI?") + // Cmd("AT+CSQ") + // Cmd("AT+CSCA?") + // Cmd("AT+CPOL?") + // Cmd("AT+COPS?") + // // Cmd("AT+COPS=?") + // Cmd("AT+CPSI?") + // resp, err = m.At().Send("AT+CNMI=2,2") for { + // Cmd("AT+CSQ") + // Cmd("AT+COPS?") + + Cmd("AT+CPSI?") // if err := m.CheckSignal(); err != nil { // logger.Println(err) // } else { // logger.Println("AAAAAAAAAAA THERE IS SIGNAL") // } - // time.Sleep(250 * time.Millisecond) - readLen, err := m.At().SerialPort().Read(buf) - if err != nil { - return err - } - if readLen > 0 { - logger.Println(string(buf[:readLen])) - } + time.Sleep(500 * time.Millisecond) + // readLen, err := m.At().SerialPort().Read(buf) + // if err != nil { + // return err + // } + // if readLen > 0 { + // logger.Println(string(buf[:readLen])) + // } } // resp, err = m.At().Send("AT+CPMS?")