Compare commits

...

2 Commits

Author SHA1 Message Date
deadprogram 26aa664c80 espat: add Debug field to driver, and the associated behavior you would expect
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-02-03 19:56:27 +01:00
deadprogram 2d644c8b60 espat: some improvements for response handling
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-02-02 12:20:16 +01:00
4 changed files with 154 additions and 47 deletions
+4 -1
View File
@@ -11,7 +11,10 @@ func (d *Device) ConnectToAccessPoint(ssid, pass string, timeout time.Duration)
return net.ErrWiFiMissingSSID return net.ErrWiFiMissingSSID
} }
d.SetWifiMode(WifiModeClient) if err := d.SetWifiMode(WifiModeClient); err != nil {
return err
}
return d.ConnectToAP(ssid, pass, 10) return d.ConnectToAP(ssid, pass, 10)
} }
+47 -26
View File
@@ -28,6 +28,8 @@ import (
"tinygo.org/x/drivers/net" "tinygo.org/x/drivers/net"
) )
const CRLF = "\r\n"
// Device wraps UART connection to the ESP8266/ESP32. // Device wraps UART connection to the ESP8266/ESP32.
type Device struct { type Device struct {
bus drivers.UART bus drivers.UART
@@ -37,10 +39,10 @@ type Device struct {
// data received from a TCP/UDP connection forwarded by the ESP8266/ESP32 // data received from a TCP/UDP connection forwarded by the ESP8266/ESP32
socketdata []byte socketdata []byte
}
// ActiveDevice is the currently configured Device in use. There can only be one. // dump extra data to console?
var ActiveDevice *Device Debug bool
}
// New returns a new espat driver. Pass in a fully configured UART bus. // New returns a new espat driver. Pass in a fully configured UART bus.
func New(b drivers.UART) *Device { func New(b drivers.UART) *Device {
@@ -48,9 +50,9 @@ func New(b drivers.UART) *Device {
} }
// Configure sets up the device for communication. // Configure sets up the device for communication.
func (d Device) Configure() { func (d *Device) Configure() {
ActiveDevice = &d // set the configured Device in use. There can only be one.
net.ActiveDevice = ActiveDevice net.UseDriver(d)
} }
// Connected checks if there is communication with the ESP8266/ESP32. // Connected checks if there is communication with the ESP8266/ESP32.
@@ -59,10 +61,7 @@ func (d *Device) Connected() bool {
// handle response here, should include "OK" // handle response here, should include "OK"
_, err := d.Response(100) _, err := d.Response(100)
if err != nil { return err == nil
return false
}
return true
} }
// Write raw bytes to the UART. // Write raw bytes to the UART.
@@ -80,21 +79,33 @@ const pause = 300
// Execute sends an AT command to the ESP8266/ESP32. // Execute sends an AT command to the ESP8266/ESP32.
func (d Device) Execute(cmd string) error { func (d Device) Execute(cmd string) error {
_, err := d.Write([]byte("AT" + cmd + "\r\n")) data := "AT" + cmd
if d.Debug {
debugprintln(data)
}
_, err := d.Write([]byte(data + CRLF))
return err return err
} }
// Query sends an AT command to the ESP8266/ESP32 that returns the // Query sends an AT command to the ESP8266/ESP32 that returns the
// current value for some configuration parameter. // current value for some configuration parameter.
func (d Device) Query(cmd string) (string, error) { func (d Device) Query(cmd string) (string, error) {
_, err := d.Write([]byte("AT" + cmd + "?\r\n")) data := "AT" + cmd + "?"
if d.Debug {
debugprintln(data)
}
_, err := d.Write([]byte(data + CRLF))
return "", err return "", err
} }
// Set sends an AT command with params to the ESP8266/ESP32 for a // Set sends an AT command with params to the ESP8266/ESP32 for a
// configuration value to be set. // configuration value to be set.
func (d Device) Set(cmd, params string) error { func (d Device) Set(cmd, params string) error {
_, err := d.Write([]byte("AT" + cmd + "=" + params + "\r\n")) data := "AT" + cmd + "=" + params
if d.Debug {
debugprintln(data)
}
_, err := d.Write([]byte(data + CRLF))
return err return err
} }
@@ -103,6 +114,10 @@ func (d Device) Version() []byte {
d.Execute(Version) d.Execute(Version)
r, err := d.Response(100) r, err := d.Response(100)
if err != nil { if err != nil {
if d.Debug {
debugprintln(string(r))
}
return []byte("unknown") return []byte("unknown")
} }
return r return r
@@ -152,17 +167,17 @@ func (d *Device) ReadSocket(b []byte) (n int, err error) {
// The call will retry for up to timeout milliseconds before returning nothing. // The call will retry for up to timeout milliseconds before returning nothing.
func (d *Device) Response(timeout int) ([]byte, error) { func (d *Device) Response(timeout int) ([]byte, error) {
// read data // read data
var size int
var start, end int var start, end int
pause := 100 // pause to wait for 100 ms pause := 10 * time.Millisecond
retries := timeout / pause starting := time.Now()
for { for {
size = d.bus.Buffered() if size := d.bus.Buffered(); size > 0 {
if size > 0 {
end += size end += size
d.bus.Read(d.response[start:end]) _, err := d.bus.Read(d.response[start:end])
if err != nil {
return nil, err
}
// if "+IPD" then read socket data // if "+IPD" then read socket data
if strings.Contains(string(d.response[:end]), "+IPD") { if strings.Contains(string(d.response[:end]), "+IPD") {
@@ -172,12 +187,15 @@ func (d *Device) Response(timeout int) ([]byte, error) {
// if "OK" then the command worked // if "OK" then the command worked
if strings.Contains(string(d.response[:end]), "OK") { if strings.Contains(string(d.response[:end]), "OK") {
return d.response[start:end], nil if d.Debug {
debugprintln(string(d.response[:end]))
}
return d.response[:end], nil
} }
// if "Error" then the command failed // if "Error" then the command failed
if strings.Contains(string(d.response[:end]), "ERROR") { if strings.Contains(string(d.response[:end]), "ERROR") {
return d.response[start:end], errors.New("response error:" + string(d.response[start:end])) return d.response[:end], errors.New("response error:" + string(d.response[:end]))
} }
// if anything else, then keep reading data in? // if anything else, then keep reading data in?
@@ -185,12 +203,11 @@ func (d *Device) Response(timeout int) ([]byte, error) {
} }
// wait longer? // wait longer?
retries-- if time.Since(starting) > time.Duration(timeout)*time.Millisecond {
if retries == 0 { return nil, errors.New("response timeout error:" + string(d.response[:end]))
return nil, errors.New("response timeout error:" + string(d.response[start:end]))
} }
time.Sleep(time.Duration(pause) * time.Millisecond) time.Sleep(pause)
} }
} }
@@ -220,3 +237,7 @@ func (d *Device) parseIPD(end int) error {
func (d *Device) IsSocketDataAvailable() bool { func (d *Device) IsSocketDataAvailable() bool {
return len(d.socketdata) > 0 || d.bus.Buffered() > 0 return len(d.socketdata) > 0 || d.bus.Buffered() > 0
} }
func debugprintln(msg string) {
println("[DEBUG] " + msg)
}
+50 -12
View File
@@ -19,6 +19,9 @@ func (d *Device) GetDNS(domain string) (string, error) {
d.Set(TCPDNSLookup, "\""+domain+"\"") d.Set(TCPDNSLookup, "\""+domain+"\"")
resp, err := d.Response(1000) resp, err := d.Response(1000)
if err != nil { if err != nil {
if d.Debug {
println(string(resp))
}
return "", err return "", err
} }
if !strings.Contains(string(resp), ":") { if !strings.Contains(string(resp), ":") {
@@ -36,13 +39,17 @@ func (d *Device) GetDNS(domain string) (string, error) {
// Currently only supports single connection mode. // Currently only supports single connection mode.
func (d *Device) ConnectTCPSocket(addr, port string) error { func (d *Device) ConnectTCPSocket(addr, port string) error {
protocol := "TCP" protocol := "TCP"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120" val := "\"" + protocol + "\"," + addr + "," + port + ",120"
err := d.Set(TCPConnect, val) err := d.Set(TCPConnect, val)
if err != nil { if err != nil {
return err return err
} }
_, e := d.Response(3000) r, e := d.Response(3000)
if e != nil { if e != nil {
if d.Debug {
println(string(r))
}
return e return e
} }
return nil return nil
@@ -51,13 +58,17 @@ func (d *Device) ConnectTCPSocket(addr, port string) error {
// ConnectUDPSocket creates a new UDP connection for the ESP8266/ESP32. // ConnectUDPSocket creates a new UDP connection for the ESP8266/ESP32.
func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error { func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
protocol := "UDP" protocol := "UDP"
val := "\"" + protocol + "\",\"" + addr + "\"," + sendport + "," + listenport + ",2" val := "\"" + protocol + "\"," + addr + "," + sendport + "," + listenport + ",2"
err := d.Set(TCPConnect, val) err := d.Set(TCPConnect, val)
if err != nil { if err != nil {
return err return err
} }
_, e := d.Response(3000) r, e := d.Response(3000)
if e != nil { if e != nil {
if d.Debug {
println(string(r))
}
return e return e
} }
return nil return nil
@@ -67,11 +78,15 @@ func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
// Currently only supports single connection mode. // Currently only supports single connection mode.
func (d *Device) ConnectSSLSocket(addr, port string) error { func (d *Device) ConnectSSLSocket(addr, port string) error {
protocol := "SSL" protocol := "SSL"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120" val := "\"" + protocol + "\"," + addr + "," + port + ",120"
d.Set(TCPConnect, val) d.Set(TCPConnect, val)
// this operation takes longer, so wait up to 6 seconds to complete. // this operation takes longer, so wait up to 6 seconds to complete.
_, err := d.Response(6000) r, err := d.Response(6000)
if err != nil { if err != nil {
if d.Debug {
println(string(r))
}
return err return err
} }
return nil return nil
@@ -83,8 +98,12 @@ func (d *Device) DisconnectSocket() error {
if err != nil { if err != nil {
return err return err
} }
_, e := d.Response(pause) r, e := d.Response(pause)
if e != nil { if e != nil {
if d.Debug {
println(string(r))
}
return e return e
} }
return nil return nil
@@ -95,7 +114,11 @@ func (d *Device) DisconnectSocket() error {
func (d *Device) SetMux(mode int) error { func (d *Device) SetMux(mode int) error {
val := strconv.Itoa(mode) val := strconv.Itoa(mode)
d.Set(TCPMultiple, val) d.Set(TCPMultiple, val)
_, err := d.Response(pause) r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err return err
} }
@@ -110,7 +133,11 @@ func (d *Device) GetMux() ([]byte, error) {
func (d *Device) SetTCPTransferMode(mode int) error { func (d *Device) SetTCPTransferMode(mode int) error {
val := strconv.Itoa(mode) val := strconv.Itoa(mode)
d.Set(TransmissionMode, val) d.Set(TransmissionMode, val)
_, err := d.Response(pause) r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err return err
} }
@@ -123,12 +150,19 @@ func (d *Device) GetTCPTransferMode() ([]byte, error) {
// StartSocketSend gets the ESP8266/ESP32 ready to receive TCP/UDP socket data. // StartSocketSend gets the ESP8266/ESP32 ready to receive TCP/UDP socket data.
func (d *Device) StartSocketSend(size int) error { func (d *Device) StartSocketSend(size int) error {
val := strconv.Itoa(size) val := strconv.Itoa(size)
d.Set(TCPSend, val) err := d.Set(TCPSend, val)
if err != nil {
return err
}
// when ">" is received, it indicates // when ">" is received, it indicates
// ready to receive data // ready to receive data
r, err := d.Response(2000) r, err := d.Response(500)
if err != nil { if err != nil {
if d.Debug {
println(string(r))
}
return err return err
} }
if strings.Contains(string(r), ">") { if strings.Contains(string(r), ">") {
@@ -142,6 +176,10 @@ func (d *Device) StartSocketSend(size int) error {
func (d *Device) EndSocketSend() error { func (d *Device) EndSocketSend() error {
d.Write([]byte("+++")) d.Write([]byte("+++"))
_, err := d.Response(pause) r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err return err
} }
+53 -8
View File
@@ -25,7 +25,11 @@ func (d *Device) GetWifiMode() ([]byte, error) {
func (d *Device) SetWifiMode(mode int) error { func (d *Device) SetWifiMode(mode int) error {
val := strconv.Itoa(mode) val := strconv.Itoa(mode)
d.Set(WifiMode, val) d.Set(WifiMode, val)
_, err := d.Response(pause) r, err := d.Response(pause)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err return err
} }
@@ -43,8 +47,12 @@ func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
val := "\"" + ssid + "\",\"" + pwd + "\"" val := "\"" + ssid + "\",\"" + pwd + "\""
d.Set(ConnectAP, val) d.Set(ConnectAP, val)
_, err := d.Response(ws * 1000) r, err := d.Response(ws * 1000)
if err != nil { if err != nil {
if d.Debug {
debugprintln(string(r))
}
return err return err
} }
return nil return nil
@@ -53,7 +61,11 @@ func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
// DisconnectFromAP disconnects the ESP8266/ESP32 from the current access point. // DisconnectFromAP disconnects the ESP8266/ESP32 from the current access point.
func (d *Device) DisconnectFromAP() error { func (d *Device) DisconnectFromAP() error {
d.Execute(Disconnect) d.Execute(Disconnect)
_, err := d.Response(1000) r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err return err
} }
@@ -68,7 +80,11 @@ func (d *Device) GetClientIP() (string, error) {
func (d *Device) SetClientIP(ipaddr string) error { func (d *Device) SetClientIP(ipaddr string) error {
val := "\"" + ipaddr + "\"" val := "\"" + ipaddr + "\""
d.Set(ConnectAP, val) d.Set(ConnectAP, val)
_, err := d.Response(500) r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err return err
} }
@@ -78,6 +94,10 @@ func (d *Device) SetClientIP(ipaddr string) error {
func (d *Device) GetAPConfig() (string, error) { func (d *Device) GetAPConfig() (string, error) {
d.Query(SoftAPConfigCurrent) d.Query(SoftAPConfigCurrent)
r, err := d.Response(100) r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err return string(r), err
} }
@@ -89,7 +109,11 @@ func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
ecnval := strconv.Itoa(security) ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigCurrent, val) d.Set(SoftAPConfigCurrent, val)
_, err := d.Response(1000) r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err return err
} }
@@ -97,6 +121,9 @@ func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
func (d *Device) GetAPClients() (string, error) { func (d *Device) GetAPClients() (string, error) {
d.Query(ListConnectedIP) d.Query(ListConnectedIP)
r, err := d.Response(100) r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err return string(r), err
} }
@@ -104,6 +131,9 @@ func (d *Device) GetAPClients() (string, error) {
func (d *Device) GetAPIP() (string, error) { func (d *Device) GetAPIP() (string, error) {
d.Query(SetSoftAPIPCurrent) d.Query(SetSoftAPIPCurrent)
r, err := d.Response(100) r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err return string(r), err
} }
@@ -111,7 +141,10 @@ func (d *Device) GetAPIP() (string, error) {
func (d *Device) SetAPIP(ipaddr string) error { func (d *Device) SetAPIP(ipaddr string) error {
val := "\"" + ipaddr + "\"" val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPCurrent, val) d.Set(SetSoftAPIPCurrent, val)
_, err := d.Response(500) r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err return err
} }
@@ -120,6 +153,9 @@ func (d *Device) SetAPIP(ipaddr string) error {
func (d *Device) GetAPConfigFlash() (string, error) { func (d *Device) GetAPConfigFlash() (string, error) {
d.Query(SoftAPConfigFlash) d.Query(SoftAPConfigFlash)
r, err := d.Response(100) r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err return string(r), err
} }
@@ -132,7 +168,10 @@ func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
ecnval := strconv.Itoa(security) ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigFlash, val) d.Set(SoftAPConfigFlash, val)
_, err := d.Response(1000) r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err return err
} }
@@ -141,6 +180,9 @@ func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
func (d *Device) GetAPIPFlash() (string, error) { func (d *Device) GetAPIPFlash() (string, error) {
d.Query(SetSoftAPIPFlash) d.Query(SetSoftAPIPFlash)
r, err := d.Response(100) r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err return string(r), err
} }
@@ -149,6 +191,9 @@ func (d *Device) GetAPIPFlash() (string, error) {
func (d *Device) SetAPIPFlash(ipaddr string) error { func (d *Device) SetAPIPFlash(ipaddr string) error {
val := "\"" + ipaddr + "\"" val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPFlash, val) d.Set(SetSoftAPIPFlash, val)
_, err := d.Response(500) r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err return err
} }