-
Notifications
You must be signed in to change notification settings - Fork 0
/
atcom.go
148 lines (122 loc) · 2.69 KB
/
atcom.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
Created by: Yasin Kaya (selengalp), [email protected], 2023
Copyright (c) 2023 Sixfab Inc.
*/
package atcom
import (
"bufio"
"context"
"errors"
"strings"
"time"
"github.com/tarm/serial"
)
func open(args map[string]interface{}) (port *serial.Port, err error) {
portname := "/dev/ttyUSB2"
baudrate := 115200
for key, value := range args {
switch key {
case "port":
portname = value.(string)
case "baud":
baudrate = value.(int)
}
}
config := &serial.Config{
Name: portname,
Baud: baudrate,
ReadTimeout: time.Millisecond * 100,
}
return serial.OpenPort(config)
}
func SendAT(command string, args map[string]interface{}) ([]string, error) {
var lineEnd bool = true
var desired []string = nil
var fault []string = nil
var timeout int = 5
for key, value := range args {
switch key {
case "desired":
desired = value.([]string)
case "fault":
fault = value.([]string)
case "timeout":
timeout = value.(int)
case "lineEnd":
lineEnd = value.(bool)
}
}
serialPort, err := open(args)
if err != nil {
return nil, err
}
defer serialPort.Close()
if lineEnd {
command += "\r\n"
}
_, err = serialPort.Write([]byte(command))
if err != nil {
return nil, err
}
scanner := bufio.NewScanner(serialPort)
response := make([]string, 0)
timeoutDuration := time.Duration(timeout) * time.Second
found := make(chan error)
defer close(found)
ctxScan, cancelScan := context.WithCancel(context.Background())
defer cancelScan()
go func(ctx context.Context) {
for {
if !scanner.Scan() {
return
}
line := scanner.Text()
line = strings.TrimSpace(line)
line = strings.Trim(line, "\r")
line = strings.Trim(line, "\n")
if line != "" {
response = append(response, line)
}
if line == "OK" {
// make response string to check desired and fault
data := ""
for _, word := range response {
if word != "OK" {
data += word
}
}
// check desired and fault existed in response
if desired != nil || fault != nil {
for _, desiredStr := range desired {
if strings.Contains(data, desiredStr) {
found <- nil
return
}
}
for _, faultStr := range fault {
if strings.Contains(data, faultStr) {
found <- errors.New("faulty response detected")
return
}
}
} else {
found <- nil
return
}
} else if line == "ERROR" || strings.Contains(line, "+CME ERROR") {
found <- errors.New("modem error")
return
}
}
}(ctxScan)
timeoutCh := time.After(timeoutDuration)
for {
select {
case err := <-found:
return response, err
case <-timeoutCh:
cancelScan()
return response, errors.New("timeout")
}
}
}