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
}
d.SetWifiMode(WifiModeClient)
if err := d.SetWifiMode(WifiModeClient); err != nil {
return err
}
return d.ConnectToAP(ssid, pass, 10)
}
+47 -26
View File
@@ -28,6 +28,8 @@ import (
"tinygo.org/x/drivers/net"
)
const CRLF = "\r\n"
// Device wraps UART connection to the ESP8266/ESP32.
type Device struct {
bus drivers.UART
@@ -37,10 +39,10 @@ type Device struct {
// data received from a TCP/UDP connection forwarded by the ESP8266/ESP32
socketdata []byte
}
// ActiveDevice is the currently configured Device in use. There can only be one.
var ActiveDevice *Device
// dump extra data to console?
Debug bool
}
// New returns a new espat driver. Pass in a fully configured UART bus.
func New(b drivers.UART) *Device {
@@ -48,9 +50,9 @@ func New(b drivers.UART) *Device {
}
// Configure sets up the device for communication.
func (d Device) Configure() {
ActiveDevice = &d
net.ActiveDevice = ActiveDevice
func (d *Device) Configure() {
// set the configured Device in use. There can only be one.
net.UseDriver(d)
}
// 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"
_, err := d.Response(100)
if err != nil {
return false
}
return true
return err == nil
}
// Write raw bytes to the UART.
@@ -80,21 +79,33 @@ const pause = 300
// Execute sends an AT command to the ESP8266/ESP32.
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
}
// Query sends an AT command to the ESP8266/ESP32 that returns the
// current value for some configuration parameter.
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
}
// Set sends an AT command with params to the ESP8266/ESP32 for a
// configuration value to be set.
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
}
@@ -103,6 +114,10 @@ func (d Device) Version() []byte {
d.Execute(Version)
r, err := d.Response(100)
if err != nil {
if d.Debug {
debugprintln(string(r))
}
return []byte("unknown")
}
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.
func (d *Device) Response(timeout int) ([]byte, error) {
// read data
var size int
var start, end int
pause := 100 // pause to wait for 100 ms
retries := timeout / pause
pause := 10 * time.Millisecond
starting := time.Now()
for {
size = d.bus.Buffered()
if size > 0 {
if size := d.bus.Buffered(); size > 0 {
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 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 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 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?
@@ -185,12 +203,11 @@ func (d *Device) Response(timeout int) ([]byte, error) {
}
// wait longer?
retries--
if retries == 0 {
return nil, errors.New("response timeout error:" + string(d.response[start:end]))
if time.Since(starting) > time.Duration(timeout)*time.Millisecond {
return nil, errors.New("response timeout error:" + string(d.response[: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 {
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+"\"")
resp, err := d.Response(1000)
if err != nil {
if d.Debug {
println(string(resp))
}
return "", err
}
if !strings.Contains(string(resp), ":") {
@@ -36,13 +39,17 @@ func (d *Device) GetDNS(domain string) (string, error) {
// Currently only supports single connection mode.
func (d *Device) ConnectTCPSocket(addr, port string) error {
protocol := "TCP"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120"
val := "\"" + protocol + "\"," + addr + "," + port + ",120"
err := d.Set(TCPConnect, val)
if err != nil {
return err
}
_, e := d.Response(3000)
r, e := d.Response(3000)
if e != nil {
if d.Debug {
println(string(r))
}
return e
}
return nil
@@ -51,13 +58,17 @@ func (d *Device) ConnectTCPSocket(addr, port string) error {
// ConnectUDPSocket creates a new UDP connection for the ESP8266/ESP32.
func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
protocol := "UDP"
val := "\"" + protocol + "\",\"" + addr + "\"," + sendport + "," + listenport + ",2"
val := "\"" + protocol + "\"," + addr + "," + sendport + "," + listenport + ",2"
err := d.Set(TCPConnect, val)
if err != nil {
return err
}
_, e := d.Response(3000)
r, e := d.Response(3000)
if e != nil {
if d.Debug {
println(string(r))
}
return e
}
return nil
@@ -67,11 +78,15 @@ func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
// Currently only supports single connection mode.
func (d *Device) ConnectSSLSocket(addr, port string) error {
protocol := "SSL"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120"
val := "\"" + protocol + "\"," + addr + "," + port + ",120"
d.Set(TCPConnect, val)
// 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 d.Debug {
println(string(r))
}
return err
}
return nil
@@ -83,8 +98,12 @@ func (d *Device) DisconnectSocket() error {
if err != nil {
return err
}
_, e := d.Response(pause)
r, e := d.Response(pause)
if e != nil {
if d.Debug {
println(string(r))
}
return e
}
return nil
@@ -95,7 +114,11 @@ func (d *Device) DisconnectSocket() error {
func (d *Device) SetMux(mode int) error {
val := strconv.Itoa(mode)
d.Set(TCPMultiple, val)
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err
}
@@ -110,7 +133,11 @@ func (d *Device) GetMux() ([]byte, error) {
func (d *Device) SetTCPTransferMode(mode int) error {
val := strconv.Itoa(mode)
d.Set(TransmissionMode, val)
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err
}
@@ -123,12 +150,19 @@ func (d *Device) GetTCPTransferMode() ([]byte, error) {
// StartSocketSend gets the ESP8266/ESP32 ready to receive TCP/UDP socket data.
func (d *Device) StartSocketSend(size int) error {
val := strconv.Itoa(size)
d.Set(TCPSend, val)
err := d.Set(TCPSend, val)
if err != nil {
return err
}
// when ">" is received, it indicates
// ready to receive data
r, err := d.Response(2000)
r, err := d.Response(500)
if err != nil {
if d.Debug {
println(string(r))
}
return err
}
if strings.Contains(string(r), ">") {
@@ -142,6 +176,10 @@ func (d *Device) StartSocketSend(size int) error {
func (d *Device) EndSocketSend() error {
d.Write([]byte("+++"))
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err
}
+53 -8
View File
@@ -25,7 +25,11 @@ func (d *Device) GetWifiMode() ([]byte, error) {
func (d *Device) SetWifiMode(mode int) error {
val := strconv.Itoa(mode)
d.Set(WifiMode, val)
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -43,8 +47,12 @@ func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
val := "\"" + ssid + "\",\"" + pwd + "\""
d.Set(ConnectAP, val)
_, err := d.Response(ws * 1000)
r, err := d.Response(ws * 1000)
if err != nil {
if d.Debug {
debugprintln(string(r))
}
return err
}
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.
func (d *Device) DisconnectFromAP() error {
d.Execute(Disconnect)
_, err := d.Response(1000)
r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -68,7 +80,11 @@ func (d *Device) GetClientIP() (string, error) {
func (d *Device) SetClientIP(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(ConnectAP, val)
_, err := d.Response(500)
r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -78,6 +94,10 @@ func (d *Device) SetClientIP(ipaddr string) error {
func (d *Device) GetAPConfig() (string, error) {
d.Query(SoftAPConfigCurrent)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -89,7 +109,11 @@ func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigCurrent, val)
_, err := d.Response(1000)
r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -97,6 +121,9 @@ func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
func (d *Device) GetAPClients() (string, error) {
d.Query(ListConnectedIP)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -104,6 +131,9 @@ func (d *Device) GetAPClients() (string, error) {
func (d *Device) GetAPIP() (string, error) {
d.Query(SetSoftAPIPCurrent)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -111,7 +141,10 @@ func (d *Device) GetAPIP() (string, error) {
func (d *Device) SetAPIP(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPCurrent, val)
_, err := d.Response(500)
r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -120,6 +153,9 @@ func (d *Device) SetAPIP(ipaddr string) error {
func (d *Device) GetAPConfigFlash() (string, error) {
d.Query(SoftAPConfigFlash)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -132,7 +168,10 @@ func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigFlash, val)
_, err := d.Response(1000)
r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -141,6 +180,9 @@ func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
func (d *Device) GetAPIPFlash() (string, error) {
d.Query(SetSoftAPIPFlash)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -149,6 +191,9 @@ func (d *Device) GetAPIPFlash() (string, error) {
func (d *Device) SetAPIPFlash(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPFlash, val)
_, err := d.Response(500)
r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}