at

package module
v0.0.0-...-379970a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2022 License: MIT Imports: 11 Imported by: 3

README

AT

Go Reference Build Status Coverage

Package at is a framework for communication with AT-compatible devices like Huawei modems via serial port. Currently this package is well-suited for Huawei devices and since AT-commands set may vary from device to device, sometimes you'll be forced to implement some logic by yourself.

Installation
go get github.com/xlab/at

Full documentation: godoc.

Features

This framework includes facilities for device monitoring, sending and receiving AT-commands, encoding and decoding SMS messages from or to PDU octet representation (as specified in 3GPP TS 23.040). An example of incoming SMS monitor application is given in example/daemon.

Examples

To get an SMS in a PDU octet representation:

smsSubmitGsm7 := Message{
	Text:                 "hello world",
	Encoding:             Encodings.Gsm7Bit,
	Type:                 MessageTypes.Submit,
	Address:              "+79261234567",
	ServiceCenterAddress: "+79262000331",
	VP:                   ValidityPeriod(time.Hour * 24 * 4),
	VPFormat:             ValidityPeriodFormats.Relative,
}
n, octets, err := smsSubmitGsm7.PDU()

To open a modem device:

dev = &Device{
	CommandPort: CommandPortPath,
	NotifyPort:  NotifyPortPath,
}
if err = dev.Open(); err != nil {
	return
}

If you're going to use this framework and its methods instead of plain R/W you should initialize the modem beforehand:

if err = dev.Init(DeviceE173()); err != nil {
	return
}

To use the wrapped version of a command:

err = dev.Commands.CUSD(UssdResultReporting.Enable, pdu.Encode7Bit(`*100#`), Encodings.Gsm7Bit)

Or to send a completely generic command:

str, err := dev.Send(`AT+GMM`)
log.Println(str, err)
Device-specific config

In order to introduce your own logic (i.e. custom modem Init function), you should derive your profile from the default DeviceProfile and override its methods.

License

MIT

Documentation

Overview

Package at is a framework for communication with AT-compatible devices like Huawei modems via serial port. Currently this package is well-suited for Huawei devices and since AT-commands set may vary from device to device, sometimes you'll be forced to implement some logic by yourself.

Framework

This framework includes facilities for device monitoring, sending and receiving AT-commands, encoding and decoding SMS messages from or to PDU octet representation (as specified in 3GPP TS 23.040). An example of incoming SMS monitor application is given.

Device-specific config

In order to introduce your own logic (i.e. custom modem Init function), you should derive your profile from the default DeviceProfile and override its methods.

About

Project page: https://github.com/xlab/at

Index

Constants

View Source
const DefaultTimeout = time.Minute

DefaultTimeout to close the connection in case of modem is being not responsive at all.

View Source
const KillCmd = "AT_KILL"

KillCmd is an artificial AT command that may be successfully sent to device in order to emulate the response from it. In other words, if a connection with device stalled and no bytes could be read, then this command is used to read something and then close the connection.

View Source
const NoopCmd = "AT"

NoopCmd is like a ping command that signals that the device is responsive.

View Source
const Sep = "\r\n"

<CR><LF> sequence.

View Source
const Sub = "\x1A"

Ctrl+Z code.

Variables

View Source
var (
	ErrTimeout         = errors.New("at: timeout")
	ErrUnknownEncoding = errors.New("at: unsupported encoding")
	ErrClosed          = errors.New("at: device ports are closed")
	ErrNotInitialized  = errors.New("at: not initialized")
	ErrWriteFailed     = errors.New("at: write failed")
	ErrParseReport     = errors.New("at: error while parsing report")
	ErrUnknownReport   = errors.New("at: got unknown report")
)

Common errors.

View Source
var CallerIDTypes = struct {
	Resolve func(int) Opt

	NetworkSpecific Opt
	International   Opt
}{
	func(id int) Opt { return callerIDType.Resolve(id) },

	callerIDType[129], callerIDType[145],
}

CallerIDTypes represent the possible caller id types.

View Source
var CallerIDValidityStates = struct {
	Resolve func(int) Opt

	Valid    Opt
	Rejected Opt
	Denied   Opt
}{
	func(id int) Opt { return callerIDValidity.Resolve(id) },

	callerIDValidity[0], callerIDValidity[1], callerIDValidity[2],
}

CallerIDValidityStates represent the possible caller id validity states.

View Source
var DeleteOptions = struct {
	Resolve func(int) Opt

	Index            Opt
	AllReadNotMO     Opt
	AllReadNotUnsent Opt
	AllNotUnread     Opt
	All              Opt
}{
	func(id int) Opt { return resultReporting.Resolve(id) },

	delOpts[0], delOpts[1], delOpts[2], delOpts[3], delOpts[4],
}

DeleteOptions represent the available options of message deletion masks.

View Source
var Encodings = struct {
	Gsm7Bit Encoding
	UCS2    Encoding
}{
	15, 72,
}

Encodings represents all the supported encodings.

View Source
var FinalResults = struct {
	Resolve func(string) StringOpt

	Noop              StringOpt
	Ok                StringOpt
	Connect           StringOpt
	Ring              StringOpt
	NoCarrier         StringOpt
	Error             StringOpt
	NoDialtone        StringOpt
	Busy              StringOpt
	NoAnswer          StringOpt
	CmeError          StringOpt
	CmsError          StringOpt
	NotSupported      StringOpt
	TooManyParameters StringOpt
	Timeout           StringOpt
}{
	func(str string) StringOpt { return result.Resolve(str) },

	result[0], result[1], result[2], result[3],
	result[4], result[5], result[6], result[7],
	result[8], result[9], result[10], result[11],
	result[12], result[13],
}

FinalResults represent the possible replies from a modem.

View Source
var MemoryTypes = struct {
	Resolve func(string) StringOpt

	NvRAM       StringOpt
	Associated  StringOpt
	Sim         StringOpt
	StateReport StringOpt
}{
	func(str string) StringOpt { return mem.Resolve(str) },

	mem[0], mem[1], mem[2], mem[3],
}

MemoryTypes represent the available options of message storage.

View Source
var MessageFlags = struct {
	Resolve func(int) Opt

	Unread Opt
	Read   Opt
	Unsent Opt
	Sent   Opt
	Any    Opt
}{
	func(id int) Opt { return resultReporting.Resolve(id) },

	msgFlags[0], msgFlags[1], msgFlags[2], msgFlags[3], msgFlags[4],
}

MessageFlags represent the available states of messages in memory.

View Source
var Reports = struct {
	Resolve func(string) StringOpt

	Ussd           StringOpt
	Message        StringOpt
	SignalStrength StringOpt
	BootHandshake  StringOpt
	Mode           StringOpt
	ServiceState   StringOpt
	SimState       StringOpt
	Stin           StringOpt
	CallerID       StringOpt
}{
	func(str string) StringOpt { return reports.Resolve(str) },

	reports[0], reports[1], reports[2], reports[3],
	reports[4], reports[5], reports[6], reports[7], reports[8],
}

Reports represent the possible state reports from a modem.

View Source
var RoamingStates = struct {
	Resolve func(int) Opt

	NotRoaming Opt
	Roaming    Opt
}{
	func(id int) Opt { return roaming.Resolve(id) },

	roaming[0], roaming[1],
}

RoamingStates represent the state of roaming.

View Source
var ServiceDomains = struct {
	Resolve func(int) Opt

	None               Opt
	Restricted         Opt
	Valid              Opt
	RestrictedRegional Opt
	PowerSaving        Opt
}{
	func(id int) Opt { return domain.Resolve(id) },

	domain[0], domain[1],
	domain[2], domain[3], domain[4],
}

ServiceDomains represent the possible service domains.

View Source
var ServiceStates = struct {
	Resolve func(int) Opt

	None               Opt
	Restricted         Opt
	Valid              Opt
	RestrictedRegional Opt
	PowerSaving        Opt
}{
	func(id int) Opt { return service.Resolve(id) },

	service[0], service[1], service[2], service[3], service[4],
}

ServiceStates represent the possible service states.

View Source
var SimStates = struct {
	Resolve func(int) Opt

	Invalid     Opt
	Valid       Opt
	InvalidCS   Opt
	InvalidPS   Opt
	InvalidCSPS Opt
	NoCard      Opt
}{
	func(id int) Opt { return sim.Resolve(id) },

	sim[0], sim[1], sim[2], sim[3], sim[4], sim[255],
}

SimStates represent the possible data card states.

View Source
var SystemModes = struct {
	Resolve func(int) Opt

	NoService Opt
	AMPS      Opt
	CDMA      Opt
	GsmGprs   Opt
	HDR       Opt
	WCDMA     Opt
	GPS       Opt
	GsmWcdma  Opt
	CdmaHdr   Opt
	SCDMA     Opt
}{
	func(id int) Opt { return mode.Resolve(id) },

	mode[0], mode[1], mode[2], mode[3], mode[4],
	mode[5], mode[6], mode[7], mode[8], mode[15],
}

SystemModes represent the possible system operating modes.

View Source
var SystemSubmodes = struct {
	Resolve func(int) Opt

	NoService  Opt
	GSM        Opt
	GPRS       Opt
	EDGE       Opt
	WCDMA      Opt
	HSDPA      Opt
	HSUPA      Opt
	HsdpaHsupa Opt
	SCDMA      Opt
	HspaPlus   Opt
	Hspa64QAM  Opt
	HspaMIMO   Opt
}{
	func(id int) Opt { return submode.Resolve(id) },

	submode[0], submode[1], submode[2], submode[3],
	submode[4], submode[5], submode[6], submode[7],
	submode[8], submode[9], submode[17], submode[18],
}

SystemSubmodes represent the possible system operating submodes.

View Source
var UnknownOpt = Opt{ID: -1, Description: "-"}

UnknownOpt represents an option that was parsed incorrectly or was not parsed at all.

View Source
var UnknownStringOpt = StringOpt{ID: "nil", Description: "Unknown"}

UnknownStringOpt represents a string option that was parsed incorrectly or was not parsed at all.

View Source
var UssdResultReporting = struct {
	Resolve func(int) Opt

	Disable Opt
	Enable  Opt
	Exit    Opt
}{
	func(id int) Opt { return resultReporting.Resolve(id) },

	resultReporting[0],
	resultReporting[1],
	resultReporting[2],
}

UssdResultReporting represents the available options of USSD reporting.

Functions

This section is empty.

Types

type DefaultProfile

type DefaultProfile struct {
	DeviceProfile
	// contains filtered or unexported fields
}

DefaultProfile is a reference implementation that could be embedded in any other custom implementation of the DeviceProfile interface.

func (*DefaultProfile) BOOT

func (p *DefaultProfile) BOOT(token uint64) (err error)

BOOT sends AT^BOOT with the given token to the device. This completes the handshaking procedure.

func (*DefaultProfile) CHUP

func (p *DefaultProfile) CHUP() (err error)

CHUP sends ATH+CHUP to the device. It hangs up an active incoming call

func (*DefaultProfile) CLIP

func (p *DefaultProfile) CLIP(text bool) (err error)

CLIP sends AT+CLIP with the given value to the device. It toggles the mode of periodic calling party ID notification

func (*DefaultProfile) CMGD

func (p *DefaultProfile) CMGD(index uint16, option Opt) (err error)

CMGD sends AT+CMGD with the given index and option to the device. Option defines the mode in which messages will be deleted. The default mode is to delete by index.

func (*DefaultProfile) CMGF

func (p *DefaultProfile) CMGF(text bool) (err error)

CMGF sends AT+CMGF with the given value to the device. It toggles the mode of message handling between PDU and TEXT.

Note, that the at package works only in PDU mode.

func (*DefaultProfile) CMGL

func (p *DefaultProfile) CMGL(flag Opt) (result []MessageSlot, err error)

CMGL sends AT+CMGL with the given filtering flag to the device and then parses the list of received messages that match their filter. See MessageFlags for the list of supported filters.

func (*DefaultProfile) CMGR

func (p *DefaultProfile) CMGR(index uint16) (octets []byte, err error)

CMGR sends AT+CMGR with the given index to the device and returns the message contents.

func (*DefaultProfile) CMGS

func (p *DefaultProfile) CMGS(length int, octets []byte) (byte, error)

CMGS sends AT+CMGS with the given parameters to the device. This is used to send SMS using the given PDU data. Length is a number of TPDU bytes. Returns the reference number of the sent message.

func (*DefaultProfile) CNMI

func (p *DefaultProfile) CNMI(mode, mt, bm, ds, bfr int) (err error)

CNMI sends AT+CNMI with the given parameters to the device. It's used to adjust the settings of the new message arrival notifications.

func (*DefaultProfile) COPS

func (p *DefaultProfile) COPS(auto bool, text bool) (err error)

COPS sends AT+COPS to the device with parameters that define autosearch and the operator's name representation. The default representation is numerical.

func (*DefaultProfile) CPMS

func (p *DefaultProfile) CPMS(mem1 StringOpt, mem2 StringOpt, mem3 StringOpt) (err error)

CPMS sends AT+CPMS with the given options to the device. It allows to select the storage type for different kinds of messages and message notifications.

func (*DefaultProfile) CUSD

func (p *DefaultProfile) CUSD(reporting Opt, octets []byte, enc Encoding) (err error)

CUSD sends AT+CUSD with the given parameters to the device. This will invoke an USSD request.

func (*DefaultProfile) FetchInbox

func (p *DefaultProfile) FetchInbox() error

func (*DefaultProfile) IMEI

func (p *DefaultProfile) IMEI() (str string, err error)

IMEI sends AT+GSN to the device and gets the modem's IMEI code.

func (*DefaultProfile) Init

func (p *DefaultProfile) Init(d *Device) (err error)

Init invokes a set of methods that will make the initial setup of the modem.

func (*DefaultProfile) ModelName

func (p *DefaultProfile) ModelName() (str string, err error)

ModelName sends AT+GMM to the device and gets the modem's model name.

func (*DefaultProfile) OperatorName

func (p *DefaultProfile) OperatorName() (str string, err error)

OperatorName sends AT+COPS? to the device and gets the operator's name.

func (*DefaultProfile) SYSCFG

func (p *DefaultProfile) SYSCFG(roaming, cellular bool) (err error)

SYSCFG sends AT^SYSCFG with the given parameters to the device. The arguments of this command may vary, so the options are limited to switchng roaming and cellular mode on/off.

func (*DefaultProfile) SYSINFO

func (p *DefaultProfile) SYSINFO() (info *SystemInfoReport, err error)

SYSINFO sends AT^SYSINFO to the device and parses the output.

type Device

type Device struct {
	// Name is the label to distinguish different devices.
	Name string
	// CommandPort is the path or name of command serial port.
	CommandPort string
	// CommandPort is the path or name of notification serial port.
	NotifyPort string
	// State holds the device state.
	State *DeviceState
	// Commands is a profile that provides implementation of Init and the other commands.
	Commands DeviceProfile
	// Timeout to override the default timeout (1m)
	Timeout time.Duration
	// contains filtered or unexported fields
}

Device represents a physical modem that supports Hayes AT-commands.

func (*Device) Close

func (d *Device) Close() (err error)

Close closes all the event channels and also closes both command and notification modem's ports. This function may block until the device will reply or the reply timeout timer will fire.

Close is a no-op if already closed.

func (*Device) Closed

func (d *Device) Closed() <-chan struct{}

Closed fires when the connection was closed.

func (*Device) IncomingCallerID

func (d *Device) IncomingCallerID() <-chan *calls.CallerID

IncomingCallerID fires when an incoming caller ID was received.

func (*Device) IncomingSms

func (d *Device) IncomingSms() <-chan *sms.Message

IncomingSms fires when an SMS was received.

func (*Device) Init

func (d *Device) Init(profile DeviceProfile) error

Init checks whether device is opened, initializes event channels and runs init procedure defined within the supplied DeviceProfile.

func (*Device) Open

func (d *Device) Open() (err error)

Open is used to open serial ports of the device. This should be used first. The method returns error if open was not succeed, i.e. if device is absent.

func (*Device) Send

func (d *Device) Send(req string) (reply string, err error)

Send writes a command to the device's command port and parses the output. Result will not contain any FinalReply since they're used to detect error status. Multiple lines will be joined with '\n'.

func (*Device) SendSMS

func (d *Device) SendSMS(text string, address sms.PhoneNumber) (err error)

SendSMS sends an SMS message with given text to the given address, the encoding and other parameters are default.

func (*Device) SendUSSD

func (d *Device) SendUSSD(req string) (err error)

SendUSSD sends an USSD request, the encoding and other parameters are default.

func (*Device) StateUpdate

func (d *Device) StateUpdate() <-chan struct{}

StateUpdate fires when DeviceState was updated by a received event.

func (*Device) UssdReply

func (d *Device) UssdReply() <-chan Ussd

UssdReply fires when an Ussd reply was received.

func (*Device) Watch

func (d *Device) Watch() error

Watch starts a monitoring process that will wait for events from the device's notification port.

type DeviceProfile

type DeviceProfile interface {
	Init(*Device) error
	CMGS(length int, octets []byte) (byte, error)
	CUSD(reporting Opt, octets []byte, enc Encoding) (err error)
	CMGR(index uint16) (octets []byte, err error)
	CMGD(index uint16, option Opt) (err error)
	CMGL(flag Opt) (octets []MessageSlot, err error)
	CMGF(text bool) (err error)
	CLIP(text bool) (err error)
	CHUP() (err error)
	CNMI(mode, mt, bm, ds, bfr int) (err error)
	CPMS(mem1 StringOpt, mem2 StringOpt, mem3 StringOpt) (err error)
	BOOT(token uint64) (err error)
	SYSCFG(roaming, cellular bool) (err error)
	SYSINFO() (info *SystemInfoReport, err error)
	COPS(auto bool, text bool) (err error)
	OperatorName() (str string, err error)
	ModelName() (str string, err error)
	IMEI() (str string, err error)
}

DeviceProfile hides the device-specific implementation and provides a set of methods that can be used on a device. Init should be called first.

func DeviceE173

func DeviceE173() DeviceProfile

DeviceE173 returns an instance of DeviceProfile implementation for Huawei E173, it's also the default one.

type DeviceState

type DeviceState struct {
	ServiceState   Opt
	ServiceDomain  Opt
	RoamingState   Opt
	SystemMode     Opt
	SystemSubmode  Opt
	SimState       Opt
	ModelName      string
	OperatorName   string
	IMEI           string
	SignalStrength int
}

DeviceState represents the device state including cellular options, signal quality, current operator name, service status.

func NewDeviceState

func NewDeviceState() *DeviceState

NewDeviceState returns a clean state with unknown options.

type Encoding

type Encoding byte

Encoding is an encoding option to use.

type MessageSlot

type MessageSlot struct {
	Index   uint16
	Payload []byte
}

type Opt

type Opt struct {
	// ID is usually used to detect an option from a number in string.
	ID int
	// Description contains a human-readable description of an option.
	Description string
}

Opt represents a numerical option.

type StringOpt

type StringOpt struct {
	// ID is usually used to detect an option from a substring in string.
	ID string
	// Description contains a human-readable description of an option.
	Description string
}

StringOpt represents a string option.

type SystemInfoReport

type SystemInfoReport struct {
	ServiceState  Opt
	ServiceDomain Opt
	RoamingState  Opt
	SystemMode    Opt
	SystemSubmode Opt
	SimState      Opt
}

SystemInfoReport represents the report from the AT^SYSINFO command.

func (*SystemInfoReport) Parse

func (s *SystemInfoReport) Parse(str string) (err error)

Parse scans the AT^SYSINFO report into a non-nil SystemInfoReport struct.

type Ussd

type Ussd string

Ussd type represents the USSD query string.

func (*Ussd) Encode

func (u *Ussd) Encode(enc Encoding) ([]byte, error)

Encode converts the query string into bytes according to the specified encoding.

func (*Ussd) String

func (u *Ussd) String() string

Directories

Path Synopsis
example
Package pdu implements data encoding schemes described in 3GPP TS 23.040.
Package pdu implements data encoding schemes described in 3GPP TS 23.040.
Package sms allows to encode and decode SMS messages into/from PDU format as described in 3GPP TS 23.040.
Package sms allows to encode and decode SMS messages into/from PDU format as described in 3GPP TS 23.040.
Package util provides some useful methods that are used within the 'at' package.
Package util provides some useful methods that are used within the 'at' package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL