forked from haxpax/gosms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
modem.go
123 lines (100 loc) · 2.89 KB
/
modem.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package modem
import (
"errors"
"log"
"strings"
"time"
"github.com/tarm/serial"
)
type GSMModem struct {
ComPort string
BaudRate int
Port *serial.Port
DeviceId string
}
func New(ComPort string, BaudRate int, DeviceId string) (modem *GSMModem) {
modem = &GSMModem{ComPort: ComPort, BaudRate: BaudRate, DeviceId: DeviceId}
return modem
}
func (m *GSMModem) Connect() (err error) {
config := &serial.Config{Name: m.ComPort, Baud: m.BaudRate, ReadTimeout: time.Second}
m.Port, err = serial.OpenPort(config)
if err == nil {
m.initModem()
}
return err
}
func (m *GSMModem) initModem() {
m.SendCommand("ATE0\r\n", true) // echo off
m.SendCommand("AT+CMEE=1\r\n", true) // useful error messages
m.SendCommand("AT+WIND=0\r\n", true) // disable notifications
m.SendCommand("AT+CMGF=1\r\n", true) // switch to TEXT mode
}
func (m *GSMModem) Expect(possibilities []string) (string, error) {
readMax := 0
for _, possibility := range possibilities {
length := len(possibility)
if length > readMax {
readMax = length
}
}
readMax = readMax + 2 // we need offset for \r\n sent by modem
var status string = ""
buf := make([]byte, readMax)
for i := 0; i < readMax; i++ {
// ignoring error as EOF raises error on Linux
n, _ := m.Port.Read(buf)
if n > 0 {
status = string(buf[:n])
for _, possibility := range possibilities {
if strings.HasSuffix(status, possibility) {
log.Println("--- Expect:", m.transposeLog(strings.Join(possibilities, "|")), "Got:", m.transposeLog(status))
return status, nil
}
}
}
}
log.Println("--- Expect:", m.transposeLog(strings.Join(possibilities, "|")), "Got:", m.transposeLog(status), "(match not found!)")
return status, errors.New("match not found")
}
func (m *GSMModem) Send(command string) {
log.Println("--- Send:", m.transposeLog(command))
m.Port.Flush()
_, err := m.Port.Write([]byte(command))
if err != nil {
log.Fatal(err)
}
}
func (m *GSMModem) Read(n int) string {
var output string = ""
buf := make([]byte, n)
for i := 0; i < n; i++ {
// ignoring error as EOF raises error on Linux
c, _ := m.Port.Read(buf)
if c > 0 {
output = string(buf[:c])
}
}
log.Printf("--- Read(%d): %v", n, m.transposeLog(output))
return output
}
func (m *GSMModem) SendCommand(command string, waitForOk bool) string {
m.Send(command)
if waitForOk {
output, _ := m.Expect([]string{"OK\r\n", "ERROR\r\n"}) // we will not change api so errors are ignored for now
return output
} else {
return m.Read(1)
}
}
func (m *GSMModem) SendSMS(mobile string, message string) string {
log.Println("--- SendSMS ", mobile, message)
m.Send("AT+CMGS=\"" + mobile + "\"\r") // should return ">"
m.Read(3)
// EOM CTRL-Z = 26
return m.SendCommand(message+string(26), true)
}
func (m *GSMModem) transposeLog(input string) string {
output := strings.Replace(input, "\r\n", "\\r\\n", -1)
return strings.Replace(output, "\r", "\\r", -1)
}