forked from haxpax/gosms
-
Notifications
You must be signed in to change notification settings - Fork 1
/
gsm.go
104 lines (90 loc) · 2.31 KB
/
gsm.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
package gosms
import (
"github.com/haxpax/goserial"
"log"
"strings"
"time"
)
//TODO: should be configurable
const SMSRetryLimit = 3
type GSMModem struct {
Port string
Baud int
Status bool
Conn serial.ReadWriteFlushCloser
Devid string
}
func (m *GSMModem) Connect() error {
//log.Println("--- Connect")
c := &serial.Config{Name: m.Port, Baud: m.Baud, ReadTimeout: time.Second}
s, err := serial.OpenPort(c)
if err == nil {
m.Status = true
m.Conn = s
}
return err
}
func (m *GSMModem) SendCommand(command string, waitForOk bool) string {
log.Println("--- SendCommand: ", command)
var status string = ""
m.Conn.Flush()
_, err := m.Conn.Write([]byte(command))
if err != nil {
log.Fatal(err)
}
buf := make([]byte, 32)
var loop int = 1
if waitForOk {
loop = 10
}
for i := 0; i < loop; i++ {
// ignoring error as EOF raises error on Linux
n, _ := m.Conn.Read(buf)
if n > 0 {
status = string(buf[:n])
log.Printf("SendCommand: rcvd %d bytes: %s\n", n, status)
if strings.HasSuffix(status, "OK\r\n") || strings.HasSuffix(status, "ERROR\r\n") {
break
}
}
}
return status
}
func (m *GSMModem) SendSMS(mobile string, message string) int {
log.Println("--- SendSMS ", mobile, message)
// Put Modem in SMS Text Mode
m.SendCommand("AT+CMGF=1\r", false)
m.SendCommand("AT+CMGS=\""+mobile+"\"\r", false)
// EOM CTRL-Z = 26
status := m.SendCommand(message+string(26), true)
if strings.HasSuffix(status, "OK\r\n") {
return SMSProcessed
} else if strings.HasSuffix(status, "ERROR\r\n") {
return SMSError
} else {
return SMSPending
}
}
func (m *GSMModem) ProcessMessages() {
defer func() {
log.Println("--- deferring ProcessMessage")
m.Status = false
}()
//log.Println("--- ProcessMessage")
for {
message := <-messages
log.Println("processing: ", message.UUID, m.Devid)
message.Status = m.SendSMS(message.Mobile, message.Body)
message.Device = m.Devid
message.Retries++
updateMessageStatus(message)
if message.Status != SMSProcessed && message.Retries < SMSRetryLimit {
// push message back to queue until either it is sent successfully or
// retry count is reached
// I can't push it to channel directly. Doing so may cause the sms to be in
// the queue twice. I don't want that
EnqueueMessage(&message, false)
}
time.Sleep(5 * time.Microsecond)
}
}