mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-20 14:39:00 +00:00
espat: add DialTLS and Dial methods, update MQTT example to allow both MQTT and MQTTS connections
Signed-off-by: Ron Evans <ron@hybridgroup.com>
This commit is contained in:
+177
-8
@@ -1,6 +1,7 @@
|
|||||||
package espat
|
package espat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -54,6 +55,56 @@ func (d *Device) DialTCP(network string, laddr, raddr *TCPAddr) (*TCPSerialConn,
|
|||||||
return &TCPSerialConn{SerialConn: SerialConn{Adaptor: d}, laddr: laddr, raddr: raddr}, nil
|
return &TCPSerialConn{SerialConn: SerialConn{Adaptor: d}, laddr: laddr, raddr: raddr}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dial connects to the address on the named network.
|
||||||
|
// It tries to provide a mostly compatible interface
|
||||||
|
// to net.Dial().
|
||||||
|
func (d *Device) Dial(network, address string) (Conn, error) {
|
||||||
|
switch network {
|
||||||
|
case "tcp":
|
||||||
|
raddr, err := d.ResolveTCPAddr(network, address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, e := d.DialTCP(network, &TCPAddr{}, raddr)
|
||||||
|
return c.opConn(), e
|
||||||
|
case "udp":
|
||||||
|
raddr, err := d.ResolveUDPAddr(network, address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, e := d.DialUDP(network, &UDPAddr{}, raddr)
|
||||||
|
return c.opConn(), e
|
||||||
|
default:
|
||||||
|
return nil, errors.New("invalid network for dial")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialTLS makes a TLS network connection. It tries to provide a mostly compatible interface
|
||||||
|
// to tls.Dial().
|
||||||
|
// DialTLS connects to the given network address.
|
||||||
|
func (d *Device) DialTLS(network, address string, config *TLSConfig) (*TCPSerialConn, error) {
|
||||||
|
raddr, err := d.ResolveTCPAddr(network, address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := raddr.IP.String()
|
||||||
|
sendport := strconv.Itoa(raddr.Port)
|
||||||
|
|
||||||
|
// disconnect any old socket
|
||||||
|
d.DisconnectSocket()
|
||||||
|
|
||||||
|
// connect new socket
|
||||||
|
err = d.ConnectSSLSocket(addr, sendport)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &TCPSerialConn{SerialConn: SerialConn{Adaptor: d}, raddr: raddr}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SerialConn is a loosely net.Conn compatible implementation
|
// SerialConn is a loosely net.Conn compatible implementation
|
||||||
type SerialConn struct {
|
type SerialConn struct {
|
||||||
Adaptor *Device
|
Adaptor *Device
|
||||||
@@ -103,23 +154,37 @@ func (c *SerialConn) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LocalAddr returns the local network address.
|
// LocalAddr returns the local network address.
|
||||||
func (c *UDPSerialConn) LocalAddr() UDPAddr {
|
func (c *UDPSerialConn) LocalAddr() Addr {
|
||||||
return *c.laddr
|
return c.laddr.opAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteAddr returns the remote network address.
|
// RemoteAddr returns the remote network address.
|
||||||
func (c *UDPSerialConn) RemoteAddr() UDPAddr {
|
func (c *UDPSerialConn) RemoteAddr() Addr {
|
||||||
return *c.laddr
|
return c.laddr.opAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPSerialConn) opConn() Conn {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalAddr returns the local network address.
|
// LocalAddr returns the local network address.
|
||||||
func (c *TCPSerialConn) LocalAddr() TCPAddr {
|
func (c *TCPSerialConn) LocalAddr() Addr {
|
||||||
return *c.laddr
|
return c.laddr.opAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteAddr returns the remote network address.
|
// RemoteAddr returns the remote network address.
|
||||||
func (c *TCPSerialConn) RemoteAddr() TCPAddr {
|
func (c *TCPSerialConn) RemoteAddr() Addr {
|
||||||
return *c.laddr
|
return c.laddr.opAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TCPSerialConn) opConn() Conn {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeadline sets the read and write deadlines associated
|
// SetDeadline sets the read and write deadlines associated
|
||||||
@@ -217,6 +282,26 @@ type UDPAddr struct {
|
|||||||
Zone string // IPv6 scoped addressing zone; added in Go 1.1
|
Zone string // IPv6 scoped addressing zone; added in Go 1.1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Network returns the address's network name, "udp".
|
||||||
|
func (a *UDPAddr) Network() string { return "udp" }
|
||||||
|
|
||||||
|
func (a *UDPAddr) String() string {
|
||||||
|
if a == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
if a.Port != 0 {
|
||||||
|
return a.IP.String() + ":" + strconv.Itoa(a.Port)
|
||||||
|
}
|
||||||
|
return a.IP.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *UDPAddr) opAddr() Addr {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
// TCPAddr here to serve as compatible type. until TinyGo can compile the net package.
|
// TCPAddr here to serve as compatible type. until TinyGo can compile the net package.
|
||||||
type TCPAddr struct {
|
type TCPAddr struct {
|
||||||
IP IP
|
IP IP
|
||||||
@@ -224,6 +309,26 @@ type TCPAddr struct {
|
|||||||
Zone string // IPv6 scoped addressing zone
|
Zone string // IPv6 scoped addressing zone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Network returns the address's network name, "tcp".
|
||||||
|
func (a *TCPAddr) Network() string { return "tcp" }
|
||||||
|
|
||||||
|
func (a *TCPAddr) String() string {
|
||||||
|
if a == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
if a.Port != 0 {
|
||||||
|
return a.IP.String() + ":" + strconv.Itoa(a.Port)
|
||||||
|
}
|
||||||
|
return a.IP.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *TCPAddr) opAddr() Addr {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
// ParseIP parses s as an IP address, returning the result.
|
// ParseIP parses s as an IP address, returning the result.
|
||||||
func ParseIP(s string) IP {
|
func ParseIP(s string) IP {
|
||||||
return IP([]byte(s))
|
return IP([]byte(s))
|
||||||
@@ -233,3 +338,67 @@ func ParseIP(s string) IP {
|
|||||||
func (ip IP) String() string {
|
func (ip IP) String() string {
|
||||||
return string(ip)
|
return string(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TLSConfig is a placeholder for future compatibility with
|
||||||
|
// tls.Config.
|
||||||
|
type TLSConfig struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conn is a generic stream-oriented network connection.
|
||||||
|
// This interface is from the Go standard library.
|
||||||
|
type Conn interface {
|
||||||
|
// Read reads data from the connection.
|
||||||
|
// Read can be made to time out and return an Error with Timeout() == true
|
||||||
|
// after a fixed time limit; see SetDeadline and SetReadDeadline.
|
||||||
|
Read(b []byte) (n int, err error)
|
||||||
|
|
||||||
|
// Write writes data to the connection.
|
||||||
|
// Write can be made to time out and return an Error with Timeout() == true
|
||||||
|
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
|
||||||
|
Write(b []byte) (n int, err error)
|
||||||
|
|
||||||
|
// Close closes the connection.
|
||||||
|
// Any blocked Read or Write operations will be unblocked and return errors.
|
||||||
|
Close() error
|
||||||
|
|
||||||
|
// LocalAddr returns the local network address.
|
||||||
|
LocalAddr() Addr
|
||||||
|
|
||||||
|
// RemoteAddr returns the remote network address.
|
||||||
|
RemoteAddr() Addr
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
SetDeadline(t time.Time) error
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
SetReadDeadline(t time.Time) error
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
SetWriteDeadline(t time.Time) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr represents a network end point address.
|
||||||
|
type Addr interface {
|
||||||
|
Network() string // name of the network (for example, "tcp", "udp")
|
||||||
|
String() string // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,6 +54,20 @@ func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
|
|||||||
return errors.New("ConnectUDPSocket error:" + string(r))
|
return errors.New("ConnectUDPSocket error:" + string(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConnectSSLSocket creates a new SSL socket connection for the ESP8266/ESP32.
|
||||||
|
// Currently only supports single connection mode.
|
||||||
|
func (d *Device) ConnectSSLSocket(addr, port string) error {
|
||||||
|
protocol := "SSL"
|
||||||
|
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120"
|
||||||
|
d.Set(TCPConnect, val)
|
||||||
|
time.Sleep(5000 * time.Millisecond)
|
||||||
|
r := d.Response()
|
||||||
|
if strings.Contains(string(r), "CONNECT") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("ConnectSSLSocket error:" + string(r))
|
||||||
|
}
|
||||||
|
|
||||||
// DisconnectSocket disconnects the ESP8266/ESP32 from the current TCP/UDP connection.
|
// DisconnectSocket disconnects the ESP8266/ESP32 from the current TCP/UDP connection.
|
||||||
func (d *Device) DisconnectSocket() error {
|
func (d *Device) DisconnectSocket() error {
|
||||||
d.Execute(TCPClose)
|
d.Execute(TCPClose)
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ import (
|
|||||||
// access point info
|
// access point info
|
||||||
const ssid = "YOURSSID"
|
const ssid = "YOURSSID"
|
||||||
const pass = "YOURPASS"
|
const pass = "YOURPASS"
|
||||||
|
const useSSL = true
|
||||||
|
|
||||||
// IP address of the MQTT broker to use. Replace with your own info.
|
// IP address of the MQTT broker to use. Replace with your own info.
|
||||||
const server = "test.mosquitto.org:1883"
|
//const server = "test.mosquitto.org:1883"
|
||||||
|
const server = "test.mosquitto.org:8883"
|
||||||
|
|
||||||
// change these to connect to a different UART or pins for the ESP8266/ESP32
|
// change these to connect to a different UART or pins for the ESP8266/ESP32
|
||||||
var (
|
var (
|
||||||
@@ -36,7 +38,7 @@ var (
|
|||||||
console = machine.UART0
|
console = machine.UART0
|
||||||
|
|
||||||
adaptor *espat.Device
|
adaptor *espat.Device
|
||||||
conn *espat.TCPSerialConn
|
conn espat.Conn
|
||||||
err error
|
err error
|
||||||
mid uint16
|
mid uint16
|
||||||
topic = "tinygo"
|
topic = "tinygo"
|
||||||
@@ -64,20 +66,23 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// now make TCP connection
|
// make connection
|
||||||
raddr, _ := adaptor.ResolveTCPAddr("tcp", server)
|
if useSSL {
|
||||||
if raddr != nil {
|
println("Dialing SSL connection...")
|
||||||
println("The IP address from DNS lookup is:")
|
conn, err = adaptor.DialTLS("tcp", server, nil)
|
||||||
println(string(raddr.IP))
|
if err != nil {
|
||||||
println(raddr.Port)
|
println("SSL connect error")
|
||||||
}
|
println(err)
|
||||||
laddr := &espat.TCPAddr{Port: 1883}
|
return
|
||||||
|
}
|
||||||
println("Dialing TCP connection...")
|
} else {
|
||||||
conn, err = adaptor.DialTCP("tcp", laddr, raddr)
|
println("Dialing TCP connection...")
|
||||||
if err != nil {
|
conn, err = adaptor.Dial("tcp", server)
|
||||||
println("tcp connect error")
|
if err != nil {
|
||||||
println(err.Error())
|
println("TCP connect error")
|
||||||
|
println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = connectToMQTTServer()
|
err = connectToMQTTServer()
|
||||||
|
|||||||
Reference in New Issue
Block a user