mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-19 14:14:00 +00:00
espat: add support for esp8266/esp32 Wifi adaptor AT command set with net-compatible UDP support
Signed-off-by: Ron Evans <ron@hybridgroup.com>
This commit is contained in:
committed by
Ayke van Laethem
parent
ae53ea7d81
commit
0c2924cd77
@@ -0,0 +1,104 @@
|
|||||||
|
package espat
|
||||||
|
|
||||||
|
// Basic AT commands
|
||||||
|
const (
|
||||||
|
// Test that the device is working.
|
||||||
|
Test = ""
|
||||||
|
|
||||||
|
// Restart module
|
||||||
|
Restart = "+RST"
|
||||||
|
|
||||||
|
// Version show info about the current software version.
|
||||||
|
Version = "+GMR"
|
||||||
|
|
||||||
|
// Enter deep-sleep mode
|
||||||
|
Sleep = "+GSLP"
|
||||||
|
|
||||||
|
// Configure echo.
|
||||||
|
EchoConfig = "E"
|
||||||
|
|
||||||
|
// EchoConfigOn
|
||||||
|
EchoConfigOn = EchoConfig + "1"
|
||||||
|
|
||||||
|
// EchoConfigOff
|
||||||
|
EchoConfigOff = EchoConfig + "0"
|
||||||
|
|
||||||
|
// Configure UART
|
||||||
|
UARTConfig = "+UART"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WiFi commands.
|
||||||
|
const (
|
||||||
|
// WiFi mode (sta/AP/sta+AP)
|
||||||
|
WifiMode = "+CWMODE"
|
||||||
|
|
||||||
|
// Connect to an access point.
|
||||||
|
ConnectAP = "+CWJAP"
|
||||||
|
|
||||||
|
// List available AP's
|
||||||
|
ListAP = "+CWLAP"
|
||||||
|
|
||||||
|
// Disconnect from the current AP
|
||||||
|
Disconnect = "+CWQAP"
|
||||||
|
|
||||||
|
// Set softAP configuration. This also activates the ESP8266/ESP32 to act as an access point.
|
||||||
|
// The settings will not be saved in flash memory, so they will be forgotten on next reset.
|
||||||
|
SoftAPConfigCurrent = "+CWSAP_CUR"
|
||||||
|
|
||||||
|
// Set softAP configuration as saved in flash. This also activates the ESP8266/ESP32 to act as an
|
||||||
|
// access point. The settings will be saved in flash memory, so they will be used on next reset.
|
||||||
|
SoftAPConfigFlash = "+CWSAP_DEF"
|
||||||
|
|
||||||
|
// List station IP's connected to softAP
|
||||||
|
ListConnectedIP = "+CWLIF"
|
||||||
|
|
||||||
|
// Enable/disable DHCP
|
||||||
|
DHCPConfig = "+CWDHCP"
|
||||||
|
|
||||||
|
// Set MAC address of station
|
||||||
|
SetStationMACAddress = "+CIPSTAMAC"
|
||||||
|
|
||||||
|
// Set MAC address of softAP
|
||||||
|
SetAPMACAddress = "+CIPAPMAC"
|
||||||
|
|
||||||
|
// Set IP address of ESP8266/ESP32 station
|
||||||
|
SetStationIP = "+CIPSTA"
|
||||||
|
|
||||||
|
// Set IP address of ESP8266/ESP32 when acting as access point.
|
||||||
|
// The IP address will not be saved in flash memory, so it will be forgotten on next reset.
|
||||||
|
SetSoftAPIPCurrent = "+CIPAP_CUR"
|
||||||
|
|
||||||
|
// Set IP address of ESP8266/ESP32 when acting as access point.
|
||||||
|
// The IP address will be saved in flash memory, so they will be used on next reset.
|
||||||
|
SetSoftAPIPFlash = "+CIPAP_DEF"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TCP/IP commands
|
||||||
|
const (
|
||||||
|
// Get connection status
|
||||||
|
TCPStatus = "+CIPSTATUS"
|
||||||
|
|
||||||
|
// Establish TCP connection or register UDP port
|
||||||
|
TCPConnect = "+CIPSTART"
|
||||||
|
|
||||||
|
// Send Data
|
||||||
|
TCPSend = "+CIPSEND"
|
||||||
|
|
||||||
|
// Close TCP/UDP connection
|
||||||
|
TCPClose = "+CIPCLOSE"
|
||||||
|
|
||||||
|
// Get local IP address
|
||||||
|
GetLocalIP = "+CIFSR"
|
||||||
|
|
||||||
|
// Set multiple connections mode
|
||||||
|
TCPMultiple = "+CIPMUX"
|
||||||
|
|
||||||
|
// Configure as server
|
||||||
|
ServerConfig = "+CIPSERVER"
|
||||||
|
|
||||||
|
// Set transmission mode
|
||||||
|
TransmissionMode = "+CIPMODE"
|
||||||
|
|
||||||
|
// Set timeout when ESP8266/ESP32 runs as TCP server
|
||||||
|
SetServerTimeout = "+CIPSTO"
|
||||||
|
)
|
||||||
+252
@@ -0,0 +1,252 @@
|
|||||||
|
// Package espat implements TCP/UDP wireless communication over serial
|
||||||
|
// with a separate ESP8266 or ESP32 board using the Espressif AT command set
|
||||||
|
// across a UART interface.
|
||||||
|
//
|
||||||
|
// In order to use this driver, the ESP8266/ESP32 must be flashed with firmware
|
||||||
|
// supporting the AT command set. Many ESP8266/ESP32 chips already have this firmware
|
||||||
|
// installed by default. You will need to install this firmware if you have an
|
||||||
|
// ESP8266 that has been flashed with NodeMCU (Lua) or Arduino firmware.
|
||||||
|
//
|
||||||
|
// AT Command Core repository:
|
||||||
|
// https://github.com/espressif/esp32-at
|
||||||
|
//
|
||||||
|
// Datasheet:
|
||||||
|
// https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf
|
||||||
|
//
|
||||||
|
// AT command set:
|
||||||
|
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
|
||||||
|
//
|
||||||
|
package espat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Device wraps UART connection to the ESP8266/ESP32.
|
||||||
|
type Device struct {
|
||||||
|
bus machine.UART
|
||||||
|
|
||||||
|
// command responses that come back from the ESP8266/ESP32
|
||||||
|
response []byte
|
||||||
|
|
||||||
|
// data received from a TCP/UDP connection forwarded by the ESP8266/ESP32
|
||||||
|
socketdata []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new espat driver. Pass in a fully configured UART bus.
|
||||||
|
func New(b machine.UART) *Device {
|
||||||
|
return &Device{bus: b, response: make([]byte, 512), socketdata: make([]byte, 0, 1024)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure sets up the device for communication.
|
||||||
|
func (d Device) Configure() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connected checks if there is communication with the ESP8266/ESP32.
|
||||||
|
func (d *Device) Connected() bool {
|
||||||
|
d.Execute(Test)
|
||||||
|
|
||||||
|
// handle response here, should include "OK"
|
||||||
|
r := d.Response()
|
||||||
|
if strings.Contains(string(r), "OK") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write raw bytes to the UART.
|
||||||
|
func (d *Device) Write(b []byte) (n int, err error) {
|
||||||
|
return d.bus.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read raw bytes from the UART.
|
||||||
|
func (d *Device) Read(b []byte) (n int, err error) {
|
||||||
|
return d.bus.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// how long in milliseconds to pause after sending AT commands
|
||||||
|
const pause = 100
|
||||||
|
|
||||||
|
// Execute sends an AT command to the ESP8266/ESP32.
|
||||||
|
func (d Device) Execute(cmd string) error {
|
||||||
|
_, err := d.Write([]byte("AT" + cmd + "\r\n"))
|
||||||
|
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"))
|
||||||
|
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"))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns the ESP8266/ESP32 firmware version info.
|
||||||
|
func (d Device) Version() []byte {
|
||||||
|
d.Execute(Version)
|
||||||
|
return d.Response()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Echo sets the ESP8266/ESP32 echo setting.
|
||||||
|
func (d Device) Echo(set bool) {
|
||||||
|
if set {
|
||||||
|
d.Execute(EchoConfigOn)
|
||||||
|
} else {
|
||||||
|
d.Execute(EchoConfigOff)
|
||||||
|
}
|
||||||
|
// TODO: check for success
|
||||||
|
d.Response()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset restarts the ESP8266/ESP32 firmware. Due to how the baud rate changes,
|
||||||
|
// this messes up communication with the ESP8266/ESP32 module. So make sure you know
|
||||||
|
// what you are doing when you call this.
|
||||||
|
func (d Device) Reset() {
|
||||||
|
d.Execute(Restart)
|
||||||
|
d.Response()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadSocket returns the data that has already been read in from the responses.
|
||||||
|
func (d *Device) ReadSocket(b []byte) (n int, err error) {
|
||||||
|
// make sure no data in buffer
|
||||||
|
d.Response()
|
||||||
|
|
||||||
|
count := len(b)
|
||||||
|
if len(b) >= len(d.socketdata) {
|
||||||
|
// copy it all, then clear socket data
|
||||||
|
count = len(d.socketdata)
|
||||||
|
copy(b, d.socketdata[:count])
|
||||||
|
d.socketdata = d.socketdata[:0]
|
||||||
|
} else {
|
||||||
|
// copy all we can, then keep the remaining socket data around
|
||||||
|
copy(b, d.socketdata[:count])
|
||||||
|
copy(d.socketdata, d.socketdata[count:])
|
||||||
|
d.socketdata = d.socketdata[:len(d.socketdata)-count]
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response gets the next response bytes from the ESP8266/ESP32.
|
||||||
|
func (d *Device) Response() []byte {
|
||||||
|
var i, retries int
|
||||||
|
|
||||||
|
header := make([]byte, 2)
|
||||||
|
for {
|
||||||
|
for d.bus.Buffered() > 0 {
|
||||||
|
// get the first 2 bytes
|
||||||
|
header[0], _ = d.bus.ReadByte()
|
||||||
|
header[1], _ = d.bus.ReadByte()
|
||||||
|
|
||||||
|
if d.isLeadingCRLF(header) {
|
||||||
|
// skip it
|
||||||
|
header[0], _ = d.bus.ReadByte()
|
||||||
|
header[1], _ = d.bus.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.isIPD(header) {
|
||||||
|
// is socket data packet
|
||||||
|
d.parseIPD()
|
||||||
|
} else {
|
||||||
|
// no, so put into response
|
||||||
|
d.response[i] = header[0]
|
||||||
|
i++
|
||||||
|
d.response[i] = header[1]
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the rest of normal command response
|
||||||
|
for d.bus.Buffered() > 0 {
|
||||||
|
data, err := d.bus.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
d.response[i] = data
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retries++
|
||||||
|
if retries > 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// pause to make sure is no more data to be read
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
}
|
||||||
|
return d.response[:i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) isLeadingCRLF(b []byte) bool {
|
||||||
|
if len(b) < 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b[0] == 13 && b[1] == 10 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) isIPD(b []byte) bool {
|
||||||
|
if len(b) < 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b[0] == '+' && b[1] == 'I' {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) parseIPD() bool {
|
||||||
|
data, _ := d.bus.ReadByte()
|
||||||
|
if data != 'P' {
|
||||||
|
// error
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
data, _ = d.bus.ReadByte()
|
||||||
|
if data != 'D' {
|
||||||
|
// error
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
data, _ = d.bus.ReadByte()
|
||||||
|
if data != ',' {
|
||||||
|
// error
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the expected data length
|
||||||
|
// skip remaining header up to the ":"
|
||||||
|
buf := []byte{}
|
||||||
|
data, _ = d.bus.ReadByte()
|
||||||
|
for data != ':' {
|
||||||
|
// put into the buffer with int value here
|
||||||
|
buf = append(buf, data)
|
||||||
|
|
||||||
|
// read next value
|
||||||
|
data, _ = d.bus.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
val := string(buf)
|
||||||
|
count, err := strconv.Atoi(val)
|
||||||
|
if err != nil {
|
||||||
|
// not expected data here. what to do?
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// load up the socket data
|
||||||
|
// only read the expected amount of data
|
||||||
|
for m := 0; m < count; m++ {
|
||||||
|
data, _ = d.bus.ReadByte()
|
||||||
|
d.socketdata = append(d.socketdata, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
+143
@@ -0,0 +1,143 @@
|
|||||||
|
package espat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DialUDP makes a UDP network connection. raadr is the port that the messages will
|
||||||
|
// be sent to, and laddr is the port that will be listened to in order to
|
||||||
|
// receive incoming messages.
|
||||||
|
func (d Device) DialUDP(network string, laddr, raddr *UDPAddr) (*SerialConn, error) {
|
||||||
|
addr := raddr.IP.String()
|
||||||
|
sendport := strconv.Itoa(raddr.Port)
|
||||||
|
listenport := strconv.Itoa(laddr.Port)
|
||||||
|
|
||||||
|
// disconnect any old socket
|
||||||
|
d.DisconnectSocket()
|
||||||
|
|
||||||
|
// connect new socket
|
||||||
|
d.ConnectUDPSocket(addr, sendport, listenport)
|
||||||
|
|
||||||
|
return &SerialConn{Adaptor: &d, laddr: laddr, raddr: raddr}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenUDP listens for UDP connections on the port listed in laddr.
|
||||||
|
func (d Device) ListenUDP(network string, laddr *UDPAddr) (*SerialConn, error) {
|
||||||
|
addr := "0"
|
||||||
|
sendport := "0"
|
||||||
|
listenport := strconv.Itoa(laddr.Port)
|
||||||
|
|
||||||
|
// disconnect any old socket
|
||||||
|
d.DisconnectSocket()
|
||||||
|
|
||||||
|
// connect new socket
|
||||||
|
d.ConnectUDPSocket(addr, sendport, listenport)
|
||||||
|
|
||||||
|
return &SerialConn{Adaptor: &d, laddr: laddr}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SerialConn is a loosely net.Conn compatible intended to support
|
||||||
|
// TCP/UDP over serial.
|
||||||
|
type SerialConn struct {
|
||||||
|
Adaptor *Device
|
||||||
|
laddr *UDPAddr
|
||||||
|
raddr *UDPAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads data from the connection.
|
||||||
|
// TODO: implement the full method functionality:
|
||||||
|
// Read can be made to time out and return an Error with Timeout() == true
|
||||||
|
// after a fixed time limit; see SetDeadline and SetReadDeadline.
|
||||||
|
func (c *SerialConn) Read(b []byte) (n int, err error) {
|
||||||
|
// read only the data that has been received via "+IPD" socket
|
||||||
|
return c.Adaptor.ReadSocket(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes data to the connection.
|
||||||
|
// TODO: implement the full method functionality for timeouts.
|
||||||
|
// Write can be made to time out and return an Error with Timeout() == true
|
||||||
|
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
|
||||||
|
func (c *SerialConn) Write(b []byte) (n int, err error) {
|
||||||
|
// specify that is a data transfer to the
|
||||||
|
// currently open socket, not commands to the ESP8266/ESP32.
|
||||||
|
c.Adaptor.StartSocketSend(len(b))
|
||||||
|
return c.Adaptor.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the connection.
|
||||||
|
// Currently only supports a single Read or Write operations without blocking.
|
||||||
|
func (c *SerialConn) Close() error {
|
||||||
|
c.Adaptor.DisconnectSocket()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalAddr returns the local network address.
|
||||||
|
func (c *SerialConn) LocalAddr() UDPAddr {
|
||||||
|
return *c.laddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteAddr returns the remote network address.
|
||||||
|
func (c *SerialConn) RemoteAddr() UDPAddr {
|
||||||
|
return *c.laddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline sets the read and write deadlines associated
|
||||||
|
// with the connection. It is equivalent to calling both
|
||||||
|
// SetReadDeadline and SetWriteDeadline.
|
||||||
|
//
|
||||||
|
// A deadline is an absolute time after which I/O operations
|
||||||
|
// fail with a timeout (see type Error) instead of
|
||||||
|
// blocking. The deadline applies to all future and pending
|
||||||
|
// I/O, not just the immediately following call to Read or
|
||||||
|
// Write. After a deadline has been exceeded, the connection
|
||||||
|
// can be refreshed by setting a deadline in the future.
|
||||||
|
//
|
||||||
|
// An idle timeout can be implemented by repeatedly extending
|
||||||
|
// the deadline after successful Read or Write calls.
|
||||||
|
//
|
||||||
|
// A zero value for t means I/O operations will not time out.
|
||||||
|
func (c *SerialConn) SetDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline sets the deadline for future Read calls
|
||||||
|
// and any currently-blocked Read call.
|
||||||
|
// A zero value for t means Read will not time out.
|
||||||
|
func (c *SerialConn) SetReadDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline sets the deadline for future Write calls
|
||||||
|
// and any currently-blocked Write call.
|
||||||
|
// Even if write times out, it may return n > 0, indicating that
|
||||||
|
// some of the data was successfully written.
|
||||||
|
// A zero value for t means Write will not time out.
|
||||||
|
func (c *SerialConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following definitions are here to support a Golang standard package
|
||||||
|
// net-compatible interface for IP until TinyGo can compile the net package.
|
||||||
|
|
||||||
|
// IP is an IP address. Unlike the standard implementation, it is only
|
||||||
|
// a buffer of bytes that contains the string form of the IP address, not the
|
||||||
|
// full byte format used by the Go standard .
|
||||||
|
type IP []byte
|
||||||
|
|
||||||
|
// UDPAddr here to serve as compatible type. until TinyGo can compile the net package.
|
||||||
|
type UDPAddr struct {
|
||||||
|
IP IP
|
||||||
|
Port int
|
||||||
|
Zone string // IPv6 scoped addressing zone; added in Go 1.1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseIP parses s as an IP address, returning the result.
|
||||||
|
func ParseIP(s string) IP {
|
||||||
|
return IP([]byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string form of the IP address ip.
|
||||||
|
func (ip IP) String() string {
|
||||||
|
return string(ip)
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package espat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCPMuxSingle = 0
|
||||||
|
TCPMuxMultiple = 1
|
||||||
|
|
||||||
|
TCPTransferModeNormal = 0
|
||||||
|
TCPTransferModeUnvarnished = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConnectTCPSocket creates a new TCP socket connection for the ESP8266/ESP32.
|
||||||
|
// Currently only supports single connection mode.
|
||||||
|
func (d *Device) ConnectTCPSocket(addr, port string) error {
|
||||||
|
protocol := "TCP"
|
||||||
|
val := "\"" + protocol + "\",\"" + addr + "\"," + port
|
||||||
|
d.Set(TCPConnect, val)
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
d.Set(TCPConnect, val)
|
||||||
|
time.Sleep(pause * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisconnectSocket disconnects the ESP8266/ESP32 from the current TCP/UDP connection.
|
||||||
|
func (d *Device) DisconnectSocket() error {
|
||||||
|
d.Execute(TCPClose)
|
||||||
|
time.Sleep(pause * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMux sets the ESP8266/ESP32 current client TCP/UDP configuration for concurrent connections
|
||||||
|
// either single TCPMuxSingle or multiple TCPMuxMultiple (up to 4).
|
||||||
|
func (d *Device) SetMux(mode int) error {
|
||||||
|
val := strconv.Itoa(mode)
|
||||||
|
d.Set(TCPMultiple, val)
|
||||||
|
time.Sleep(pause * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMux returns the ESP8266/ESP32 current client TCP/UDP configuration for concurrent connections.
|
||||||
|
func (d *Device) GetMux() ([]byte, error) {
|
||||||
|
d.Query(TCPMultiple)
|
||||||
|
return d.Response(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTCPTransferMode sets the ESP8266/ESP32 current client TCP/UDP transfer mode.
|
||||||
|
// Either TCPTransferModeNormal or TCPTransferModeUnvarnished.
|
||||||
|
func (d *Device) SetTCPTransferMode(mode int) error {
|
||||||
|
val := strconv.Itoa(mode)
|
||||||
|
d.Set(TransmissionMode, val)
|
||||||
|
time.Sleep(pause * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTCPTransferMode returns the ESP8266/ESP32 current client TCP/UDP transfer mode.
|
||||||
|
func (d *Device) GetTCPTransferMode() []byte {
|
||||||
|
d.Query(TransmissionMode)
|
||||||
|
return d.Response()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// TODO: wait until ">" is received, which indicates
|
||||||
|
// ready to receive data
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndSocketSend tell the ESP8266/ESP32 the TCP/UDP socket data sending is complete,
|
||||||
|
// and to return to command mode. This is only used in "unvarnished" raw mode.
|
||||||
|
func (d *Device) EndSocketSend() error {
|
||||||
|
d.Write([]byte("+++"))
|
||||||
|
|
||||||
|
// TODO: wait until ">" is received, which indicates
|
||||||
|
// ready to receive data
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
package espat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WifiModeClient = 1
|
||||||
|
WifiModeAP = 2
|
||||||
|
WifiModeDual = 3
|
||||||
|
|
||||||
|
WifiAPSecurityOpen = 1
|
||||||
|
WifiAPSecurityWPA_PSK = 2
|
||||||
|
WifiAPSecurityWPA2_PSK = 3
|
||||||
|
WifiAPSecurityWPA_WPA2_PSK = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetWifiMode returns the ESP8266/ESP32 wifi mode.
|
||||||
|
func (d *Device) GetWifiMode() []byte {
|
||||||
|
d.Query(WifiMode)
|
||||||
|
return d.Response()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWifiMode sets the ESP8266/ESP32 wifi mode.
|
||||||
|
func (d *Device) SetWifiMode(mode int) error {
|
||||||
|
val := strconv.Itoa(mode)
|
||||||
|
d.Set(WifiMode, val)
|
||||||
|
time.Sleep(pause * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wifi Client
|
||||||
|
|
||||||
|
// GetConnectedAP returns the ESP8266/ESP32 is currently connected to as a client.
|
||||||
|
func (d *Device) GetConnectedAP() []byte {
|
||||||
|
d.Query(ConnectAP)
|
||||||
|
return d.Response()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectToAP connects the ESP8266/ESP32 to an access point.
|
||||||
|
// ws is the number of seconds to wait for connection.
|
||||||
|
func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
|
||||||
|
val := "\"" + ssid + "\",\"" + pwd + "\""
|
||||||
|
d.Set(ConnectAP, val)
|
||||||
|
// TODO: a better way to wait for connect and check for up to ws seconds.
|
||||||
|
time.Sleep(time.Duration(ws) * time.Second)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisconnectFromAP disconnects the ESP8266/ESP32 from the current access point.
|
||||||
|
func (d *Device) DisconnectFromAP() error {
|
||||||
|
d.Execute(Disconnect)
|
||||||
|
time.Sleep(1000 * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetClientIP returns the ESP8266/ESP32 current client IP addess when connected to an Access Point.
|
||||||
|
func (d *Device) GetClientIP() string {
|
||||||
|
d.Query(SetStationIP)
|
||||||
|
return string(d.Response())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetClientIP sets the ESP8266/ESP32 current client IP addess when connected to an Access Point.
|
||||||
|
func (d *Device) SetClientIP(ipaddr string) []byte {
|
||||||
|
val := "\"" + ipaddr + "\""
|
||||||
|
d.Set(ConnectAP, val)
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access Point
|
||||||
|
|
||||||
|
// GetAPConfig returns the ESP8266/ESP32 current configuration when acting as an Access Point.
|
||||||
|
func (d *Device) GetAPConfig() string {
|
||||||
|
d.Query(SoftAPConfigCurrent)
|
||||||
|
return string(d.Response())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAPConfig sets the ESP8266/ESP32 current configuration when acting as an Access Point.
|
||||||
|
// ch indicates which radiochannel to use. security should be one of the const values
|
||||||
|
// such as WifiAPSecurityOpen etc.
|
||||||
|
func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
|
||||||
|
chval := strconv.Itoa(ch)
|
||||||
|
ecnval := strconv.Itoa(security)
|
||||||
|
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
|
||||||
|
d.Set(SoftAPConfigCurrent, val)
|
||||||
|
time.Sleep(1000 * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPClients returns the ESP8266/ESP32 current clients when acting as an Access Point.
|
||||||
|
func (d *Device) GetAPClients() string {
|
||||||
|
d.Query(ListConnectedIP)
|
||||||
|
return string(d.Response())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPIP returns the ESP8266/ESP32 current IP addess when configured as an Access Point.
|
||||||
|
func (d *Device) GetAPIP() string {
|
||||||
|
d.Query(SetSoftAPIPCurrent)
|
||||||
|
return string(d.Response())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAPIP sets the ESP8266/ESP32 current IP addess when configured as an Access Point.
|
||||||
|
func (d *Device) SetAPIP(ipaddr string) error {
|
||||||
|
val := "\"" + ipaddr + "\""
|
||||||
|
d.Set(SetSoftAPIPCurrent, val)
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPConfigFlash returns the ESP8266/ESP32 current configuration acting as an Access Point
|
||||||
|
// from flash storage. These settings are those used after a reset.
|
||||||
|
func (d *Device) GetAPConfigFlash() string {
|
||||||
|
d.Query(SoftAPConfigFlash)
|
||||||
|
return string(d.Response())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAPConfigFlash sets the ESP8266/ESP32 current configuration acting as an Access Point,
|
||||||
|
// and saves them to flash storage. These settings will be used after a reset.
|
||||||
|
// ch indicates which radiochannel to use. security should be one of the const values
|
||||||
|
// such as WifiAPSecurityOpen etc.
|
||||||
|
func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
|
||||||
|
chval := strconv.Itoa(ch)
|
||||||
|
ecnval := strconv.Itoa(security)
|
||||||
|
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
|
||||||
|
d.Set(SoftAPConfigFlash, val)
|
||||||
|
time.Sleep(1000 * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPIPFlash returns the ESP8266/ESP32 IP address as saved to flash storage.
|
||||||
|
// This is the IP address that will be used after a reset.
|
||||||
|
func (d *Device) GetAPIPFlash() string {
|
||||||
|
d.Query(SetSoftAPIPFlash)
|
||||||
|
return string(d.Response())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAPIPFlash sets the ESP8266/ESP32 current IP addess when configured as an Access Point.
|
||||||
|
// The IP will be saved to flash storage, and will be used after a reset.
|
||||||
|
func (d *Device) SetAPIPFlash(ipaddr string) error {
|
||||||
|
val := "\"" + ipaddr + "\""
|
||||||
|
d.Set(SetSoftAPIPFlash, val)
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
d.Response()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
// This is a console to a ESP8266/ESP32 running on the device UART1.
|
||||||
|
// Allows you to type AT commands from your computer via the microcontroller.
|
||||||
|
//
|
||||||
|
// In other words:
|
||||||
|
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
|
||||||
|
//
|
||||||
|
// More information on the Espressif AT command set at:
|
||||||
|
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
|
||||||
|
//
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tinygo-org/drivers/espat"
|
||||||
|
)
|
||||||
|
|
||||||
|
// change actAsAP to true to act as an access point instead of connecting to one.
|
||||||
|
const actAsAP = false
|
||||||
|
|
||||||
|
// access point info
|
||||||
|
const ssid = "YOURSSID"
|
||||||
|
const pass = "YOURPASS"
|
||||||
|
|
||||||
|
// change these to connect to a different UART or pins for the ESP8266/ESP32
|
||||||
|
var (
|
||||||
|
uart = machine.UART1
|
||||||
|
tx uint8 = machine.D10
|
||||||
|
rx uint8 = machine.D11
|
||||||
|
|
||||||
|
console = machine.UART0
|
||||||
|
|
||||||
|
adaptor *espat.Device
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
|
||||||
|
|
||||||
|
// Init esp8266
|
||||||
|
adaptor = espat.New(uart)
|
||||||
|
adaptor.Configure()
|
||||||
|
|
||||||
|
// first check if connected
|
||||||
|
if adaptor.Connected() {
|
||||||
|
adaptor.Echo(false)
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
console.Write([]byte("ESP-AT console enabled.\r\n"))
|
||||||
|
console.Write([]byte("Firmware version:\r\n"))
|
||||||
|
console.Write(adaptor.Version())
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
|
||||||
|
if actAsAP {
|
||||||
|
provideAP()
|
||||||
|
} else {
|
||||||
|
connectToAP()
|
||||||
|
}
|
||||||
|
|
||||||
|
console.Write([]byte("Type an AT command then press enter:\r\n"))
|
||||||
|
prompt()
|
||||||
|
} else {
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
console.Write([]byte("Unable to connect to wifi adaptor.\r\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
input := make([]byte, 64)
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
if console.Buffered() > 0 {
|
||||||
|
data, _ := console.ReadByte()
|
||||||
|
|
||||||
|
switch data {
|
||||||
|
case 13:
|
||||||
|
// return key
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
|
||||||
|
// send command to ESP8266
|
||||||
|
input[i] = byte('\r')
|
||||||
|
input[i+1] = byte('\n')
|
||||||
|
adaptor.Write(input[:i+2])
|
||||||
|
|
||||||
|
// give the ESP8266 a chance to respond.
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
|
||||||
|
// display response
|
||||||
|
console.Write(adaptor.Response())
|
||||||
|
|
||||||
|
// prompt
|
||||||
|
prompt()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
// just echo the character
|
||||||
|
console.WriteByte(data)
|
||||||
|
input[i] = data
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prompt() {
|
||||||
|
console.Write([]byte("ESPAT>"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect to access point
|
||||||
|
func connectToAP() {
|
||||||
|
console.Write([]byte("Connecting to wifi network...\r\n"))
|
||||||
|
adaptor.SetWifiMode(espat.WifiModeClient)
|
||||||
|
adaptor.ConnectToAP(ssid, pass, 10)
|
||||||
|
console.Write([]byte("Connected.\r\n"))
|
||||||
|
console.Write([]byte(adaptor.GetClientIP()))
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// provide access point
|
||||||
|
func provideAP() {
|
||||||
|
console.Write([]byte("Starting wifi network as access point '"))
|
||||||
|
console.Write([]byte(ssid))
|
||||||
|
console.Write([]byte("'...\r\n"))
|
||||||
|
adaptor.SetWifiMode(espat.WifiModeAP)
|
||||||
|
adaptor.SetAPConfig(ssid, pass, 7, espat.WifiAPSecurityWPA2_PSK)
|
||||||
|
console.Write([]byte("Ready.\r\n"))
|
||||||
|
console.Write([]byte(adaptor.GetAPIP()))
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
// This is a sensor hub that uses a ESP8266/ESP32 running on the device UART1.
|
||||||
|
// It creates a UDP "server" you can use to get info to/from your computer via the microcontroller.
|
||||||
|
//
|
||||||
|
// In other words:
|
||||||
|
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
|
||||||
|
//
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tinygo-org/drivers/espat"
|
||||||
|
)
|
||||||
|
|
||||||
|
// change actAsAP to true to act as an access point instead of connecting to one.
|
||||||
|
const actAsAP = false
|
||||||
|
|
||||||
|
// access point info
|
||||||
|
const ssid = "YOURSSID"
|
||||||
|
const pass = "YOURPASS"
|
||||||
|
|
||||||
|
// change these to connect to a different UART or pins for the ESP8266/ESP32
|
||||||
|
var (
|
||||||
|
uart = machine.UART1
|
||||||
|
tx uint8 = machine.D10
|
||||||
|
rx uint8 = machine.D11
|
||||||
|
|
||||||
|
console = machine.UART0
|
||||||
|
|
||||||
|
adaptor *espat.Device
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
|
||||||
|
|
||||||
|
// Init esp8266
|
||||||
|
adaptor = espat.New(uart)
|
||||||
|
adaptor.Configure()
|
||||||
|
|
||||||
|
readyled := machine.GPIO{machine.LED}
|
||||||
|
readyled.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
|
||||||
|
readyled.High()
|
||||||
|
|
||||||
|
// first check if connected
|
||||||
|
if adaptor.Connected() {
|
||||||
|
console.Write([]byte("Connected to wifi adaptor.\r\n"))
|
||||||
|
adaptor.Echo(false)
|
||||||
|
|
||||||
|
if actAsAP {
|
||||||
|
provideAP()
|
||||||
|
} else {
|
||||||
|
connectToAP()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
console.Write([]byte("Unable to connect to wifi adaptor.\r\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// now make UDP connection
|
||||||
|
laddr := &espat.UDPAddr{Port: 2222}
|
||||||
|
console.Write([]byte("Loading UDP listener...\r\n"))
|
||||||
|
conn, _ := adaptor.ListenUDP("UDP", laddr)
|
||||||
|
|
||||||
|
console.Write([]byte("Waiting for data...\r\n"))
|
||||||
|
data := make([]byte, 50)
|
||||||
|
blink := true
|
||||||
|
for {
|
||||||
|
n, _ := conn.Read(data)
|
||||||
|
if n > 0 {
|
||||||
|
console.Write(data[:n])
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
conn.Write([]byte("hello back\r\n"))
|
||||||
|
}
|
||||||
|
blink = !blink
|
||||||
|
if blink {
|
||||||
|
readyled.High()
|
||||||
|
} else {
|
||||||
|
readyled.Low()
|
||||||
|
}
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right now this code is never reached. Need a way to trigger it...
|
||||||
|
console.Write([]byte("Disconnecting UDP...\r\n"))
|
||||||
|
conn.Close()
|
||||||
|
console.Write([]byte("Done.\r\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect to access point
|
||||||
|
func connectToAP() {
|
||||||
|
console.Write([]byte("Connecting to wifi network...\r\n"))
|
||||||
|
adaptor.SetWifiMode(espat.WifiModeClient)
|
||||||
|
adaptor.ConnectToAP(ssid, pass, 10)
|
||||||
|
console.Write([]byte("Connected.\r\n"))
|
||||||
|
console.Write([]byte(adaptor.GetClientIP()))
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// provide access point
|
||||||
|
func provideAP() {
|
||||||
|
console.Write([]byte("Starting wifi network as access point '"))
|
||||||
|
console.Write([]byte(ssid))
|
||||||
|
console.Write([]byte("'...\r\n"))
|
||||||
|
adaptor.SetWifiMode(espat.WifiModeAP)
|
||||||
|
adaptor.SetAPConfig(ssid, pass, 7, espat.WifiAPSecurityWPA2_PSK)
|
||||||
|
console.Write([]byte("Ready.\r\n"))
|
||||||
|
console.Write([]byte(adaptor.GetAPIP()))
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
|
||||||
|
// It creates a UDP connection you can use to get info to/from your computer via the microcontroller.
|
||||||
|
//
|
||||||
|
// In other words:
|
||||||
|
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
|
||||||
|
//
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tinygo-org/drivers/espat"
|
||||||
|
)
|
||||||
|
|
||||||
|
// access point info
|
||||||
|
const ssid = "YOURSSID"
|
||||||
|
const pass = "YOURPASS"
|
||||||
|
|
||||||
|
// IP address of the listener aka "hub". Replace with your own info.
|
||||||
|
const hubIP = "0.0.0.0"
|
||||||
|
|
||||||
|
// change these to connect to a different UART or pins for the ESP8266/ESP32
|
||||||
|
var (
|
||||||
|
uart = machine.UART1
|
||||||
|
tx uint8 = machine.D10
|
||||||
|
rx uint8 = machine.D11
|
||||||
|
|
||||||
|
console = machine.UART0
|
||||||
|
|
||||||
|
adaptor *espat.Device
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
|
||||||
|
|
||||||
|
// Init esp8266/esp32
|
||||||
|
adaptor = espat.New(uart)
|
||||||
|
adaptor.Configure()
|
||||||
|
|
||||||
|
// first check if connected
|
||||||
|
if adaptor.Connected() {
|
||||||
|
console.Write([]byte("Connected to wifi adaptor.\r\n"))
|
||||||
|
adaptor.Echo(false)
|
||||||
|
|
||||||
|
connectToAP()
|
||||||
|
} else {
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
console.Write([]byte("Unable to connect to wifi adaptor.\r\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// now make UDP connection
|
||||||
|
ip := espat.ParseIP(hubIP)
|
||||||
|
raddr := &espat.UDPAddr{IP: ip, Port: 2222}
|
||||||
|
laddr := &espat.UDPAddr{Port: 2222}
|
||||||
|
|
||||||
|
console.Write([]byte("Dialing UDP connection...\r\n"))
|
||||||
|
conn, _ := adaptor.DialUDP("udp", laddr, raddr)
|
||||||
|
|
||||||
|
for {
|
||||||
|
// send data
|
||||||
|
console.Write([]byte("Sending data...\r\n"))
|
||||||
|
conn.Write([]byte("hello\r\n"))
|
||||||
|
|
||||||
|
time.Sleep(1000 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right now this code is never reached. Need a way to trigger it...
|
||||||
|
console.Write([]byte("Disconnecting UDP...\r\n"))
|
||||||
|
conn.Close()
|
||||||
|
console.Write([]byte("Done.\r\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect to access point
|
||||||
|
func connectToAP() {
|
||||||
|
console.Write([]byte("Connecting to wifi network...\r\n"))
|
||||||
|
adaptor.SetWifiMode(espat.WifiModeClient)
|
||||||
|
adaptor.ConnectToAP(ssid, pass, 10)
|
||||||
|
console.Write([]byte("Connected.\r\n"))
|
||||||
|
console.Write([]byte(adaptor.GetClientIP()))
|
||||||
|
console.Write([]byte("\r\n"))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user