diff --git a/.gitignore b/.gitignore index 9f8ced0..b9161d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ out/ -Makefile go.sum .git/ *.swp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..85cdd17 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +export GOOS=linux +export GOARCH=arm +export GOARM=6 +export CGO_ENABLED=0 + +build: + @go build -o out/modem main.go diff --git a/api/modem/at/at.go b/api/modem/at/at.go index a258fe8..0c9dc0f 100644 --- a/api/modem/at/at.go +++ b/api/modem/at/at.go @@ -13,7 +13,7 @@ import ( // Some constants const ( ReadTimeout = time.Second - InputBufSize = 128 + InputBufSize = 2048 ) type atPort struct { diff --git a/api/modem/gps/gps.go b/api/modem/gps/gps.go index 2df03c3..2ff1115 100644 --- a/api/modem/gps/gps.go +++ b/api/modem/gps/gps.go @@ -18,8 +18,10 @@ type gps struct { type Gps interface { Init() error Update() error + GetData() Data - CheckStatus() (Status, error) + GetStatus() (Status, error) + io.Closer } @@ -56,6 +58,14 @@ func (g *gps) Update() error { return nil } +func (g *gps) GetData() Data { + return g.data +} + +func (g *gps) Close() error { + return nil +} + func (g *gps) switchGpsMode(on bool) error { onStr := "0" if on { @@ -94,11 +104,3 @@ func (g *gps) switchGpsMode(on bool) error { } return nil } - -func (g *gps) GetData() Data { - return g.data -} - -func (g *gps) Close() error { - return nil -} diff --git a/api/modem/gps/nmea.go b/api/modem/gps/nmea.go index b2d2ff8..061fc20 100644 --- a/api/modem/gps/nmea.go +++ b/api/modem/gps/nmea.go @@ -85,6 +85,9 @@ func (g *gps) rawCollect(flags nmeaFlags) (string, error) { if _, err := s.Write([]byte("AT+CGPSINFOCFG=0,31\r\n")); err != nil { return "", fmt.Errorf("serial port write 2: %w", err) } + if _, err := s.Write([]byte("AT+CGPSFTM=0\r\n")); err != nil { // For sure because sometimes it cannot stop... + return "", fmt.Errorf("serial port write 2: %w", err) + } time.Sleep(100 * time.Millisecond) // To enshure @@ -115,7 +118,7 @@ func (g *gps) collectNmeaReports(flags nmeaFlags) ([]string, error) { } // DEBUG - g.logger.Println("NMEA raw collect:", resp) + // g.logger.Println("NMEA raw collect:", resp) // Right responce struct: // \r\n diff --git a/api/modem/gps/check.go b/api/modem/gps/status.go similarity index 79% rename from api/modem/gps/check.go rename to api/modem/gps/status.go index b27a403..367b408 100644 --- a/api/modem/gps/check.go +++ b/api/modem/gps/status.go @@ -12,24 +12,13 @@ type Status struct { ActiveSatelitesCounte int `json:"activeSatelitesCount"` } -func (st Status) String() string { - got := "false" - if st.GotResponses { - got = "true" - } - return "" + - "GotResponses: " + got + "\n" + - "FoundSatelitesCount: " + string(st.FoundSatelitesCount) + "\n" + - "ActiveSatelitesCounte: " + string(st.ActiveSatelitesCounte) + "\n" -} - var StatusNil = Status{ GotResponses: false, FoundSatelitesCount: 0, ActiveSatelitesCounte: 0, } -func (g *gps) CheckStatus() (Status, error) { +func (g *gps) GetStatus() (Status, error) { // Provides more information about signal and possible problems using NMEA reports // Collect reports diff --git a/api/modem/modem.go b/api/modem/modem.go index 1ae7c48..0fbc05a 100644 --- a/api/modem/modem.go +++ b/api/modem/modem.go @@ -26,13 +26,12 @@ type modem struct { logger *log.Logger // Serial values - baudrate int - + baudrate int deviceName string port at.Port // Gpio values - onOffPin gpio.Pin + onOffPin gpio.Pin // For turning on and off // Other values lastUpdateTime time.Time @@ -44,19 +43,19 @@ type modem struct { ic internet.Conn // Sms and calls - sms sms.Dialer + sms sms.Sms } type Modem interface { Init() error - Validate() bool + IsConnected() bool Update() error GetData() ModemData - // Temp access to SMS, GPS, AT interfaces mostly for debug - At() at.Port - Gps() gps.Gps - Sms() sms.Dialer + // Access to SMS, GPS, AT interfaces mostly for debug + At() at.Port // Send + Gps() gps.Gps // Update, GetData, GetStatus + Sms() sms.Sms // Send, ReadNew io.Closer } @@ -77,7 +76,8 @@ func (m *modem) Init() error { if err := m.onOffPin.Init(); err != nil { return fmt.Errorf("gpio pin init: %w", err) } - // m.onOffPin.PowerOn() + m.logger.Println("TURNING ON IS COMMENTED NOW!!!") + // m.onOffPin.PowerOn() // DEBUG do not want to wait 30 seconds // Search m.logger.Println("=============================== Search") @@ -101,40 +101,44 @@ func (m *modem) Init() error { return fmt.Errorf("connect: %w", err) } - // // Establish internet connection - // m.logger.Println("=============================== Internet") - // m.ic = internet.New(log.New(m.logger.Writer(), "internet", log.LstdFlags), m.port) - // if err := m.ic.Init(); err != nil { - // return fmt.Errorf("internet connection init: %w", err) - // } - // Init submodules + // submodulesLogger := m.logger.Writer() // FOR more logs + submodulesLogger := io.Discard // FOR less logs + m.logger.Println("=============================== Init submodules") - m.sms = sms.New(log.New(m.logger.Writer(), "modem-sms", log.LstdFlags), m.port) + m.ic = internet.New(log.New(submodulesLogger, "modem-internet : ", log.LstdFlags), m.port) + if err := m.ic.Init(); err != nil { + m.logger.Printf("\x1b[38;2;255;0;0mInternet: %s\x1b[38;2;255;255;255m\n", err.Error()) + } else { + m.logger.Println("\x1b[38;2;0;255;0mInternet 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 { - return fmt.Errorf("sms dialer init %w", err) + 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(m.logger.Writer(), "modem-gps", log.LstdFlags), m.port) + + m.gps = gps.New(log.New(submodulesLogger, "modem-gps : ", log.LstdFlags), m.port) if err := m.gps.Init(); err != nil { - return fmt.Errorf("gps init %w", err) + m.logger.Printf("\x1b[38;2;255;0;0mgps init %w\x1b[38;2;255;255;255m\n", err) + } else { + m.logger.Println("\x1b[38;2;0;255;0mGPS OK\x1b[38;2;255;255;255m") } - m.logger.Println(m.gps, m) // Tests - m.logger.Println("=============================== Test") - if err := m.testGPS(); err != nil { - return fmt.Errorf("testGPS: %w", err) - } + // GPS works fine but almost always there is no signal + // m.logger.Println("=============================== Test") + // if err := m.testGPS(); err != nil { + // return fmt.Errorf("testGPS: %w", err) + // } return nil } -func (m *modem) Validate() bool { - return m.isConnected() -} - func (m *modem) Update() error { - if !m.isConnected() { + if !m.IsConnected() { m.logger.Println("No connection to module") return nil } @@ -142,6 +146,8 @@ func (m *modem) Update() error { if err := m.gps.Update(); err != nil { m.logger.Println("gps update:", err.Error()) } + // Read new messages + return nil } @@ -152,7 +158,7 @@ func (m *modem) GetData() ModemData { } } -func (m *modem) Sms() sms.Dialer { +func (m *modem) Sms() sms.Sms { return m.sms } @@ -164,25 +170,26 @@ func (m *modem) At() at.Port { return m.port } -func (m *modem) Close() error { +func (m *modem) Close() error { // I can't return error so I log it if err := m.sms.Close(); err != nil { - return fmt.Errorf("sms: %w", err) + m.logger.Printf("\x1b[38;2;255;0;0mclose sms error: %s\x1b[38;2;255;255;255m\n", err.Error()) } - // Not right way I think if err := m.port.Close(); err != nil { - return fmt.Errorf("serial port: %w", err) + m.logger.Printf("\x1b[38;2;255;0;0mclose serial port error: %s\x1b[38;2;255;255;255m\n", err.Error()) } if err := m.onOffPin.Close(); err != nil { - return fmt.Errorf("gpio pin: %w", err) + m.logger.Printf("\x1b[38;2;255;0;0mclose gpio pin error: %s\x1b[38;2;255;255;255m\n", err.Error()) } if err := m.ic.Close(); err != nil { - return fmt.Errorf("internet connection: %w", err) + m.logger.Printf("\x1b[38;2;255;0;0mclose internet connection error: %s\x1b[38;2;255;255;255m\n", err.Error()) } return nil } +///////////// Private functions + func (m *modem) connect() error { if m.port == nil { return fmt.Errorf("port is not defined") @@ -197,7 +204,7 @@ func (m *modem) disconnect() error { return m.port.Disconnect() } -func (m *modem) isConnected() bool { +func (m *modem) IsConnected() bool { if m.port != nil { return m.port.IsConnected() } @@ -234,22 +241,17 @@ func (m *modem) saveGPS(path string) error { return nil } -func (m *modem) testConsole() { - for { - var inStr string - fmt.Scanln(&inStr) - if inStr == "exit" { - return - } - resp, err := m.port.Send(inStr) - if err != nil { - m.logger.Println("ERROR:", err.Error()) - } - m.logger.Println(resp) - m.logger.Println("------------------") +// Short way to send command +func (m *modem) printCmd(cmd string) { + if resp, err := m.port.Send(cmd); err != nil { + m.logger.Println("FAILED TO SEND REQ", cmd, ":", err.Error()) + } else { + _ = resp + // m.logger.Println("CMD", cmd, ":", resp) } } +// Some required commands before checking port func (m *modem) setupPort() error { // Reset input if err := m.port.SerialPort().ResetInputBuffer(); err != nil { @@ -259,37 +261,11 @@ func (m *modem) setupPort() error { if err := m.port.SerialPort().ResetOutputBuffer(); err != nil { return fmt.Errorf("reset output buffer: %w", err) } - m.port.Send("ATE0") // This shit sometimes enables echo mode... why... when... but it can - // Turn on errors' describtion - if resp, err := m.port.Send("AT+CMEE=2"); err != nil || !resp.Check() { - if err != nil { - return fmt.Errorf("AT+CMEE=2 request: %w", err) - } - return fmt.Errorf("turn on errors: error response: %s", resp) - } - - // Display other values - m.logger.Println("DEBUG SIM VALUES:") - // ICCID - if resp, err := m.port.Send("AT+CCID"); err != nil || !resp.Check() { - if err != nil { - return fmt.Errorf("AT+CCID request: %w", err) - } - return fmt.Errorf("get ICCID: error response: %s", resp) - } else { - m.logger.Println("ICCID:", strings.Split(resp.String(), "\n")[0]) - } - - // ICCID - if resp, err := m.port.Send("AT+CNUM"); err != nil || !resp.Check() { - if err != nil { - return fmt.Errorf("AT+CNUM request: %w", err) - } - return fmt.Errorf("get CNUM: error response: %s", resp) - } else { - m.logger.Println("CNUM:", strings.Split(resp.String(), "\n")[0]) - } + // These commands ensure that correct modes are set + m.printCmd("ATE0") // Sometimes enables echo mode + m.printCmd("AT+CGPSFTM=0") // Sometimes does not turn off nmea + m.printCmd("AT+CMEE=2") // Turn on errors describtion return nil } diff --git a/api/modem/sms/sms.go b/api/modem/sms/sms.go index c7bddfb..3806516 100644 --- a/api/modem/sms/sms.go +++ b/api/modem/sms/sms.go @@ -14,14 +14,15 @@ type dialer struct { port at.Port } -type Dialer interface { +type Sms interface { Init() error - Send(number, msg string) error - ReadNew() ([]string, error) + Send(number, msg string) error // Send sms + ReadNew() ([]string, error) // Read new smses + io.Closer } -func New(logger *log.Logger, port at.Port) Dialer { +func New(logger *log.Logger, port at.Port) Sms { return &dialer{ logger: logger, port: port, @@ -45,13 +46,15 @@ func (d *dialer) Init() error { } func (d *dialer) Send(number, msg string) error { - d.port.Send(fmt.Sprintf("AT+CMGS=\"%s\"", number)) // Because it will throw error - resp, err := d.port.RawSend(fmt.Sprintf("%s\x1A", msg)) // Add additional \r\n because there is not supposed to be + d.port.Send(fmt.Sprintf(`AT+CMGS="%s"`, number)) // Because it will throw error + resp, err := d.port.RawSend(fmt.Sprintf("%s\n\r", msg)) // Add additional \r\n because there is not supposed to be if err != nil { return fmt.Errorf("message request: %w", err) } - if at.Resp(resp).Check() { - return nil + d.logger.Println("SEND RESPONSE:", resp) + resp, err = d.port.RawSend("\x1A") + if err != nil { + return fmt.Errorf("message request: %w", err) } d.logger.Println("SEND RESPONSE:", resp) errCode, err := GetError([]byte(resp)) diff --git a/main.go b/main.go index 6ed584f..6d09e7a 100644 --- a/main.go +++ b/main.go @@ -16,18 +16,18 @@ func main() { } func mainE() error { - logger := log.New(os.Stdout, "main:", log.LstdFlags) - m := modem.New(log.New(logger.Writer(), "modem:", log.LstdFlags)) + logger := log.New(os.Stdout, "main : ", log.LstdFlags) + m := modem.New(log.New(logger.Writer(), "modem : ", log.LstdFlags)) logger.Println("||||||||||||||||| INIT |||||||||||||||") if err := m.Init(); err != nil { return err } - if !m.Validate() { - logger.Println("AAAAAAAAAAAAAAA Validation failed") + if !m.IsConnected() { + logger.Println("AAAAAAAAAAAAAAA Modem is not connected") return nil } logger.Println("||||||||||||||||| GET INFO |||||||||||||||||") - logger.Println(m.GetData()) + logger.Printf("DATA: %+v\n", m.GetData()) // logger.Println("||||||||||||||||| SEND SMS |||||||||||||||||") // logger.Println(m.At().Send("AT+CNUM")) @@ -40,11 +40,11 @@ func mainE() error { // logger.Println("NEW:", ms) // } logger.Println("||||||||||||||||| Checking gps status |||||||||||||||||") - st, err := m.Gps().CheckStatus() + st, err := m.Gps().GetStatus() if err != nil { return err } - logger.Println("GPS Status:\n", st) + logger.Printf("GPS Status:%+v\n", st) return nil } diff --git a/readme.md b/readme.md deleted file mode 100644 index c128a3e..0000000 --- a/readme.md +++ /dev/null @@ -1,2 +0,0 @@ -ISSUES: - - create input buffer every at port creation \ No newline at end of file