2024-07-28 18:01:18 +00:00
|
|
|
package sms
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"strings"
|
|
|
|
|
2024-08-08 10:32:55 +00:00
|
|
|
"gitea.unprism.ru/KRBL/sim-modem/api/modem/at"
|
2024-07-28 18:01:18 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type dialer struct {
|
|
|
|
logger *log.Logger
|
|
|
|
port at.Port
|
|
|
|
}
|
|
|
|
|
2024-08-06 17:37:20 +00:00
|
|
|
type Sms interface {
|
2024-07-28 18:01:18 +00:00
|
|
|
Init() error
|
2024-08-06 17:37:20 +00:00
|
|
|
Send(number, msg string) error // Send sms
|
|
|
|
ReadNew() ([]string, error) // Read new smses
|
|
|
|
|
2024-07-28 18:01:18 +00:00
|
|
|
io.Closer
|
|
|
|
}
|
|
|
|
|
2024-08-06 17:37:20 +00:00
|
|
|
func New(logger *log.Logger, port at.Port) Sms {
|
2024-07-29 13:51:54 +00:00
|
|
|
return &dialer{
|
|
|
|
logger: logger,
|
|
|
|
port: port,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-28 18:01:18 +00:00
|
|
|
func (d *dialer) Init() error {
|
2024-08-09 15:17:20 +00:00
|
|
|
// Ensure serial port is connected
|
2024-07-28 18:01:18 +00:00
|
|
|
if !d.port.IsConnected() {
|
|
|
|
return fmt.Errorf("serial port is not connected")
|
|
|
|
}
|
2024-08-09 15:17:20 +00:00
|
|
|
// Check ping
|
|
|
|
if err := d.checkPIN(); err != nil {
|
|
|
|
return fmt.Errorf("check PIN: %w", err)
|
2024-08-06 18:10:24 +00:00
|
|
|
}
|
2024-08-09 15:17:20 +00:00
|
|
|
// Setup prefered message storage
|
|
|
|
if err := d.setupMsgSt(); err != nil {
|
|
|
|
return fmt.Errorf("setup msg storage: %w", err)
|
|
|
|
}
|
|
|
|
// Check number
|
|
|
|
if resp, err := d.port.Send("AT+CNUM"); err != nil || !resp.Check() {
|
2024-07-28 18:01:18 +00:00
|
|
|
if err != nil {
|
2024-08-09 15:17:20 +00:00
|
|
|
return fmt.Errorf("AT+CNUM request ")
|
2024-07-28 18:01:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dialer) Send(number, msg string) error {
|
2024-08-09 15:17:20 +00:00
|
|
|
sresp, err := d.port.Send(fmt.Sprintf(`AT+CMGSEX="%s"`, number)) // Because it will throw error
|
2024-07-29 15:53:55 +00:00
|
|
|
if err != nil {
|
2024-08-09 15:17:20 +00:00
|
|
|
return err
|
2024-07-28 18:01:18 +00:00
|
|
|
}
|
2024-08-09 15:17:20 +00:00
|
|
|
d.logger.Println(sresp)
|
|
|
|
resp, err := d.port.RawSend(fmt.Sprintf("%s\x1A", msg)) // Add additional \r\n because there is not supposed to be
|
2024-08-06 17:37:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("message request: %w", err)
|
2024-07-29 15:53:55 +00:00
|
|
|
}
|
2024-08-09 15:17:20 +00:00
|
|
|
d.logger.Println("Send response:", resp)
|
|
|
|
if !at.Resp(resp).Check() {
|
|
|
|
return fmt.Errorf("error response: %s", resp)
|
2024-07-29 15:53:55 +00:00
|
|
|
}
|
2024-08-09 15:17:20 +00:00
|
|
|
return nil
|
2024-07-28 18:01:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reads all new messages
|
|
|
|
func (d *dialer) ReadNew() ([]string, error) {
|
2024-08-09 15:17:20 +00:00
|
|
|
resp, err := d.port.Send("AT+CMGL=\"ALL\"")
|
2024-07-28 18:01:18 +00:00
|
|
|
if err != nil {
|
2024-08-09 15:17:20 +00:00
|
|
|
return nil, err
|
2024-07-28 18:01:18 +00:00
|
|
|
}
|
2024-08-09 15:17:20 +00:00
|
|
|
d.logger.Println("raw sms:", resp)
|
2024-07-28 18:01:18 +00:00
|
|
|
msgs := strings.Split(strings.Replace(string(resp), "\r", "", -1), "\n")
|
2024-07-29 17:03:22 +00:00
|
|
|
|
|
|
|
outMsgs := make([]string, 0)
|
|
|
|
for _, s := range msgs {
|
|
|
|
if len(s) >= len("+CMGL:") && s[:len("+CMGL:")] == "+CMGL:" {
|
|
|
|
params := strings.Split(s[len("+CMGL:"):], ",")
|
|
|
|
d.logger.Println("GET MSG:", params)
|
|
|
|
} else {
|
|
|
|
outMsgs = append(outMsgs, s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return outMsgs, nil // TODO
|
2024-07-28 18:01:18 +00:00
|
|
|
}
|
2024-07-29 13:51:54 +00:00
|
|
|
|
|
|
|
func (d *dialer) Close() error {
|
|
|
|
return nil
|
|
|
|
}
|