A low level Go driver for AT modems.
The at package provides a low level driver which sits between an io.ReadWriter, representing the physical modem, and a higher level driver or application.
The AT driver provides the ability to issue AT commands to the modem, and to receive the info and status returned by the modem, as synchronous function calls.
Handlers for asynchronous indications from the modem, such as received SMSs, can be registered with the driver.
Supports the following functionality:
- Simple synchronous interface for AT commands
- Serialises access to the modem from multiple goroutines
- Asynchronous indication handling
- Pluggable serial driver - any io.ReadWriter will suffice
The modem is constructed with New:
modem := at.New(ioWR)
Some modem behaviour can be controlled using optional parameters. This example sets the default timeout for AT commands to one second:
modem := at.New(ioWR, at.WithTimeout(time.Second))
The modem can be initialised to a known state using Init:
err := modem.Init()
By default the Init issues the ATZ and ATE0 commands. The set of commands performed can be replaced using the optional WithCmds parameter. This example replaces the ATE0 with AT^CURC=0:
err := modem.Init(at.WithCmds("Z","^CURC=0"))
Issue AT commands to the modem and receive the response using Command:
info, err := modem.Command("I")
This produces the following interaction with the modem (exact results will differ for your modem):
2018/05/17 20:39:56 w: ATI
2018/05/17 20:39:56 r:
Manufacturer: huawei
Model: E173
Revision: 21.017.09.00.314
IMEI: 1234567
+GCAP: +CGSM,+DS,+ES
OK
and returns this info:
info = []string{
"Manufacturer: huawei",
"Model: E173",
"Revision: 21.017.09.00.314",
"IMEI: 1234567",
"+GCAP: +CGSM,+DS,+ES",
}
SMS commands are a special case as they are a two stage process, with the modem prompting between stages. The SMSCommand performs the two stage handshake with the modem and returns any resulting info. This example sends an SMS with the modem in text mode:
info, err := modem.SMSCommand("+CMGS=\"12345\"", "hello world")
Handlers can be provided for asynchronous indications using AddIndication. This example provides a handler for +CMT events:
handler := func(info []string) {
// handle CMT info here
}
err := modem.AddIndication("+CMT:", handler)
The handler can be removed using CancelIndication:
modem.CancelIndication("+CMT:")
A number of the modem methods accept optional parameters. The following table comprises a list of the available options:
Option | Method | Description |
---|---|---|
WithTimeout(time.duration) | New, Init, Command, SMSCommand | Specify the timeout for commands. A value provided to New becomes the default for the other methods. |
WithCmds([]string) | New, Init | Override the set of commands issued by Init. |
WithEscTime(time.Duration) | New | Specifies the minimum period between issuing an escape and a subsequent command. |
WithIndication(prefix, handler) | New | Adds an indication handler at construction time. |
WithTrailingLines(int) | AddIndication, WithIndication | Specifies the number of lines to collect following the indicationline itself. |
WithTrailingLine | AddIndication, WithIndication | Simple case of one trailing line. |