-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample_test.go
More file actions
169 lines (141 loc) · 4.52 KB
/
example_test.go
File metadata and controls
169 lines (141 loc) · 4.52 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package at_test
import (
"context"
"fmt"
"io"
"time"
"github.com/flipb/at"
)
func openATDevice() io.ReadWriter {
fakeDevice, _ := at.NewFakeDeviceReadWriter(func(writes <-chan at.WriteRequest, reads <-chan at.ReadRequest) error {
lastWrite := ""
for {
select {
case wreq, ok := <-writes:
if !ok {
return nil
}
lastWrite = string(wreq.InData)
wreq.Response <- at.WriteResponse{} // responding with empty WriteResponse means Write was accepted by the fake device
case rreq, ok := <-reads:
if !ok {
return nil
}
// Always return OK when someone is reading from device, except if something was just written, then return what was just written
data := "OK\r\n"
if lastWrite != "" {
data = lastWrite
lastWrite = ""
}
rreq.Response <- at.ReadResponse{OutData: []byte(data)}
}
}
})
return fakeDevice
}
func ExampleNewAT() {
ctx := context.Background()
var rawDevice io.ReadWriter = openATDevice()
// create AT - note that specifying the DeviceProfile is optional
atDevice := at.NewAT(rawDevice, at.WithProfile(at.DefaultProfile{}))
// we want to set a timeout for the AT command we're about to send.
commandCtx, cancelFn := context.WithTimeout(ctx, time.Second*10)
defer cancelFn()
// Send the command "AT". Implementation of Send adds EOL automatically.
response, err := atDevice.Send(commandCtx, "AT")
if err != nil {
// there was an error sending the command.
// Could be io error, context timeout, or some AT error
switch err {
case at.ErrUnexpectedPrompt:
// handle
case context.DeadlineExceeded:
// handle
default:
panic(err)
}
}
// Print the response
println(response)
// NOTE: response here should be an empty string
// this is because command echoes, "OK" and error strings are stripped from the response.
// error strings are instead put in the err return value
// so, again, response is empty for AT commands that don't output anything (other than potential command echo and OK)
}
func ExampleNewScanWriter() {
ctx := context.Background()
var rawDevice io.ReadWriter = openATDevice()
// create a scanwriter over an io.ReadWriter
// after this point you should no longer use the rawDevice anywhere else
scanwriter := at.NewScanWriter(rawDevice, at.DefaultProfile{})
// initial state should be "ready"
state := scanwriter.State()
if state != at.ATReady {
panic("unexpected state")
}
scanContext, cancelFn := context.WithTimeout(ctx, time.Second*10)
defer cancelFn()
// in order to update scanwriter's state we have to either Scan or Write.
// Scan will block until there's enough output from the device, or until context is cancelled.
ok := scanwriter.Scan(scanContext)
// we expect "ok" to be false in this case as no output should have been written
// Scan only returned because the context timed out
if !ok {
// let's confirm our theory
err := scanwriter.Err()
switch err {
case context.DeadlineExceeded:
// well this was expected!
default:
panic("unexpected error")
}
} else {
panic("unexpected scan result")
}
// write a command to the AT device
err := scanwriter.Write([]byte("AT\r\n"))
if err != nil {
panic("error writing to scanwriter")
}
states := 0
// scan in a loop
for scanwriter.Scan(ctx) {
state := scanwriter.State()
switch state {
// We expect the first output after sending out command to be an Echo
case at.ATEcho:
states++
continue
case at.ATData:
// we got data - this is unexpected for the AT command
// AT normally only returns an echo (ATEcho) and an OK (ATReady)
// to get the data returned
data := scanwriter.Bytes()
println(data)
// String is the same as Bytes, only with a type conversion built in.
_ = scanwriter.String()
continue
case at.ATError:
// ATError means the command failed and returned an error
// lets see the error
err = scanwriter.Err()
fmt.Printf("error in AT command: %v\n", err)
// let's also inspect if the AT command returned any data before the error occurred
data := scanwriter.Bytes()
fmt.Printf("AT command output: %s", data)
break
case at.ATNotice:
// notice is very unexpected here - normally only sent on the Notification port on my device.
// An ATNotice is a notification pushed from the network, ie. ^BOOT, RING, etc.
// ATNotice and ATData classification might get be mixed up.
case at.ATReady:
// we got an "OK" - command finished successfully
println("Command completed successfully!")
break
}
}
err = scanwriter.Err()
if err != nil {
panic("error scanning")
}
}