mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-18 21:53:56 +00:00
rtl8720dn: add examples/rtl8720dn/mqtt*
This commit is contained in:
@@ -201,6 +201,8 @@ endif
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webserver/
|
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webserver/
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/mqttsub/
|
||||||
|
@md5sum ./build/test.hex
|
||||||
|
|
||||||
DRIVERS = $(wildcard */)
|
DRIVERS = $(wildcard */)
|
||||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
// This is a sensor station that uses a RTL8720DN running on the device UART2.
|
||||||
|
// It creates an MQTT connection that publishes a message every second
|
||||||
|
// to an MQTT broker.
|
||||||
|
//
|
||||||
|
// In other words:
|
||||||
|
// Your computer <--> USB-CDC <--> MCU <--> UART2 <--> RTL8720DN <--> Internet <--> MQTT broker.
|
||||||
|
//
|
||||||
|
// You must install the Paho MQTT package to build this program:
|
||||||
|
//
|
||||||
|
// go get -u github.com/eclipse/paho.mqtt.golang
|
||||||
|
//
|
||||||
|
// You can check that mqttpub is running successfully with the following command.
|
||||||
|
//
|
||||||
|
// mosquitto_sub -h test.mosquitto.org -t tinygo
|
||||||
|
//
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/net"
|
||||||
|
"tinygo.org/x/drivers/net/mqtt"
|
||||||
|
"tinygo.org/x/drivers/rtl8720dn"
|
||||||
|
)
|
||||||
|
|
||||||
|
// You can override the setting with the init() in another source code.
|
||||||
|
// func init() {
|
||||||
|
// ssid = "your-ssid"
|
||||||
|
// password = "your-password"
|
||||||
|
// debug = true
|
||||||
|
// server = "tinygo.org"
|
||||||
|
// }
|
||||||
|
|
||||||
|
var (
|
||||||
|
ssid string
|
||||||
|
password string
|
||||||
|
server string = "tcp://test.mosquitto.org:1883"
|
||||||
|
debug = false
|
||||||
|
)
|
||||||
|
|
||||||
|
var buf [0x400]byte
|
||||||
|
|
||||||
|
var lastRequestTime time.Time
|
||||||
|
var conn net.Conn
|
||||||
|
var adaptor *rtl8720dn.RTL8720DN
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := run()
|
||||||
|
for err != nil {
|
||||||
|
fmt.Printf("error: %s\r\n", err.Error())
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
topic = "tinygo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func run() error {
|
||||||
|
rtl, err := setupRTL8720DN()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
net.UseDriver(rtl)
|
||||||
|
|
||||||
|
err = rtl.ConnectToAP(ssid, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ip, subnet, gateway, err := rtl.GetIP()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("IP Address : %s\r\n", ip)
|
||||||
|
fmt.Printf("Mask : %s\r\n", subnet)
|
||||||
|
fmt.Printf("Gateway : %s\r\n", gateway)
|
||||||
|
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
opts := mqtt.NewClientOptions()
|
||||||
|
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
|
||||||
|
|
||||||
|
println("Connectng to MQTT...")
|
||||||
|
cl := mqtt.NewClient(opts)
|
||||||
|
if token := cl.Connect(); token.Wait() && token.Error() != nil {
|
||||||
|
failMessage(token.Error().Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
println("Publishing MQTT message...")
|
||||||
|
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
|
||||||
|
token := cl.Publish(topic, 0, false, data)
|
||||||
|
token.Wait()
|
||||||
|
if err := token.Error(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right now this code is never reached. Need a way to trigger it...
|
||||||
|
println("Disconnecting MQTT...")
|
||||||
|
cl.Disconnect(100)
|
||||||
|
|
||||||
|
println("Done.")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an int >= min, < max
|
||||||
|
func randomInt(min, max int) int {
|
||||||
|
return min + rand.Intn(max-min)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a random string of A-Z chars with len = l
|
||||||
|
func randomString(len int) string {
|
||||||
|
bytes := make([]byte, len)
|
||||||
|
for i := 0; i < len; i++ {
|
||||||
|
bytes[i] = byte(randomInt(65, 90))
|
||||||
|
}
|
||||||
|
return string(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func failMessage(msg string) {
|
||||||
|
for {
|
||||||
|
println(msg)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// +build wioterminal
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/sam"
|
||||||
|
"machine"
|
||||||
|
"runtime/interrupt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/rtl8720dn"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
uart UARTx
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleInterrupt(interrupt.Interrupt) {
|
||||||
|
// should reset IRQ
|
||||||
|
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
|
||||||
|
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
|
||||||
|
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
machine.RTL8720D_CHIP_PU.Low()
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
machine.RTL8720D_CHIP_PU.High()
|
||||||
|
time.Sleep(1000 * time.Millisecond)
|
||||||
|
if debug {
|
||||||
|
waitSerial()
|
||||||
|
}
|
||||||
|
|
||||||
|
uart = UARTx{
|
||||||
|
UART: &machine.UART{
|
||||||
|
Buffer: machine.NewRingBuffer(),
|
||||||
|
Bus: sam.SERCOM0_USART_INT,
|
||||||
|
SERCOM: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
|
||||||
|
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
|
||||||
|
|
||||||
|
rtl := rtl8720dn.New(uart)
|
||||||
|
rtl.Debug(debug)
|
||||||
|
|
||||||
|
_, err := rtl.Rpc_tcpip_adapter_init()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for user to open serial console
|
||||||
|
func waitSerial() {
|
||||||
|
for !machine.Serial.DTR() {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UARTx struct {
|
||||||
|
*machine.UART
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UARTx) Read(p []byte) (n int, err error) {
|
||||||
|
if u.Buffered() == 0 {
|
||||||
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return u.UART.Read(p)
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
// This is a sensor station that uses a RTL8720DN running on the device UART2.
|
||||||
|
// It creates an MQTT connection that publishes a message every second
|
||||||
|
// to an MQTT broker.
|
||||||
|
//
|
||||||
|
// In other words:
|
||||||
|
// Your computer <--> USB-CDC <--> MCU <--> UART2 <--> RTL8720DN <--> Internet <--> MQTT broker.
|
||||||
|
//
|
||||||
|
// You must also install the Paho MQTT package to build this program:
|
||||||
|
//
|
||||||
|
// go get -u github.com/eclipse/paho.mqtt.golang
|
||||||
|
//
|
||||||
|
// You can check that mqttpub/mqttsub is running successfully with the following command.
|
||||||
|
//
|
||||||
|
// mosquitto_sub -h test.mosquitto.org -t tinygo/tx
|
||||||
|
// mosquitto_pub -h test.mosquitto.org -t tinygo/rx -m "hello world"
|
||||||
|
//
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/net"
|
||||||
|
"tinygo.org/x/drivers/net/mqtt"
|
||||||
|
"tinygo.org/x/drivers/rtl8720dn"
|
||||||
|
)
|
||||||
|
|
||||||
|
// You can override the setting with the init() in another source code.
|
||||||
|
// func init() {
|
||||||
|
// ssid = "your-ssid"
|
||||||
|
// password = "your-password"
|
||||||
|
// debug = true
|
||||||
|
// server = "tinygo.org"
|
||||||
|
// }
|
||||||
|
|
||||||
|
var (
|
||||||
|
ssid string
|
||||||
|
password string
|
||||||
|
server string = "tcp://test.mosquitto.org:1883"
|
||||||
|
debug = false
|
||||||
|
)
|
||||||
|
|
||||||
|
var buf [0x400]byte
|
||||||
|
|
||||||
|
var lastRequestTime time.Time
|
||||||
|
var conn net.Conn
|
||||||
|
var adaptor *rtl8720dn.RTL8720DN
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := run()
|
||||||
|
for err != nil {
|
||||||
|
fmt.Printf("error: %s\r\n", err.Error())
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// change these to connect to a different UART or pins for the ESP8266/ESP32
|
||||||
|
var (
|
||||||
|
cl mqtt.Client
|
||||||
|
topicTx = "tinygo/tx"
|
||||||
|
topicRx = "tinygo/rx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func subHandler(client mqtt.Client, msg mqtt.Message) {
|
||||||
|
fmt.Printf("[%s] ", msg.Topic())
|
||||||
|
fmt.Printf("%s\r\n", msg.Payload())
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() error {
|
||||||
|
rtl, err := setupRTL8720DN()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
net.UseDriver(rtl)
|
||||||
|
|
||||||
|
err = rtl.ConnectToAP(ssid, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ip, subnet, gateway, err := rtl.GetIP()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("IP Address : %s\r\n", ip)
|
||||||
|
fmt.Printf("Mask : %s\r\n", subnet)
|
||||||
|
fmt.Printf("Gateway : %s\r\n", gateway)
|
||||||
|
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
opts := mqtt.NewClientOptions()
|
||||||
|
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
|
||||||
|
|
||||||
|
println("Connecting to MQTT broker at", server)
|
||||||
|
cl = mqtt.NewClient(opts)
|
||||||
|
if token := cl.Connect(); token.Wait() && token.Error() != nil {
|
||||||
|
failMessage(token.Error().Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// subscribe
|
||||||
|
token := cl.Subscribe(topicRx, 0, subHandler)
|
||||||
|
token.Wait()
|
||||||
|
if token.Error() != nil {
|
||||||
|
failMessage(token.Error().Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go publishing()
|
||||||
|
|
||||||
|
select {}
|
||||||
|
|
||||||
|
// Right now this code is never reached. Need a way to trigger it...
|
||||||
|
println("Disconnecting MQTT...")
|
||||||
|
cl.Disconnect(100)
|
||||||
|
|
||||||
|
println("Done.")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishing() {
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
println("Publishing MQTT message...")
|
||||||
|
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
|
||||||
|
token := cl.Publish(topicTx, 0, false, data)
|
||||||
|
token.Wait()
|
||||||
|
if token.Error() != nil {
|
||||||
|
println(token.Error().Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(20 * 100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an int >= min, < max
|
||||||
|
func randomInt(min, max int) int {
|
||||||
|
return min + rand.Intn(max-min)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a random string of A-Z chars with len = l
|
||||||
|
func randomString(len int) string {
|
||||||
|
bytes := make([]byte, len)
|
||||||
|
for i := 0; i < len; i++ {
|
||||||
|
bytes[i] = byte(randomInt(65, 90))
|
||||||
|
}
|
||||||
|
return string(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func failMessage(msg string) {
|
||||||
|
for {
|
||||||
|
println(msg)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// +build wioterminal
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/sam"
|
||||||
|
"machine"
|
||||||
|
"runtime/interrupt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/rtl8720dn"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
uart UARTx
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleInterrupt(interrupt.Interrupt) {
|
||||||
|
// should reset IRQ
|
||||||
|
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
|
||||||
|
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
|
||||||
|
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
machine.RTL8720D_CHIP_PU.Low()
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
machine.RTL8720D_CHIP_PU.High()
|
||||||
|
time.Sleep(1000 * time.Millisecond)
|
||||||
|
if debug {
|
||||||
|
waitSerial()
|
||||||
|
}
|
||||||
|
|
||||||
|
uart = UARTx{
|
||||||
|
UART: &machine.UART{
|
||||||
|
Buffer: machine.NewRingBuffer(),
|
||||||
|
Bus: sam.SERCOM0_USART_INT,
|
||||||
|
SERCOM: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
|
||||||
|
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
|
||||||
|
|
||||||
|
rtl := rtl8720dn.New(uart)
|
||||||
|
rtl.Debug(debug)
|
||||||
|
|
||||||
|
_, err := rtl.Rpc_tcpip_adapter_init()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for user to open serial console
|
||||||
|
func waitSerial() {
|
||||||
|
for !machine.Serial.DTR() {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UARTx struct {
|
||||||
|
*machine.UART
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UARTx) Read(p []byte) (n int, err error) {
|
||||||
|
if u.Buffered() == 0 {
|
||||||
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return u.UART.Read(p)
|
||||||
|
}
|
||||||
@@ -266,8 +266,15 @@ func (r *RTL8720DN) IsSocketDataAvailable() bool {
|
|||||||
if r.debug {
|
if r.debug {
|
||||||
fmt.Printf("IsSocketDataAvailable()\r\n")
|
fmt.Printf("IsSocketDataAvailable()\r\n")
|
||||||
}
|
}
|
||||||
fmt.Printf("not implemented yet\r\n")
|
ret, err := r.Rpc_lwip_available(r.socket)
|
||||||
return true
|
if err != nil {
|
||||||
|
fmt.Printf("error: %s\r\n", err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ret == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RTL8720DN) Response(timeout int) ([]byte, error) {
|
func (r *RTL8720DN) Response(timeout int) ([]byte, error) {
|
||||||
|
|||||||
+1746
-291
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ package rtl8720dn
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -66,7 +65,7 @@ func dumpHex(b []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RTL8720DN) readThread() {
|
func (r *RTL8720DN) read() {
|
||||||
for {
|
for {
|
||||||
n, _ := io.ReadFull(r.port, readBuf[:4])
|
n, _ := io.ReadFull(r.port, readBuf[:4])
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
@@ -93,13 +92,10 @@ func (r *RTL8720DN) readThread() {
|
|||||||
|
|
||||||
crcNew := computeCRC16(payload[:n])
|
crcNew := computeCRC16(payload[:n])
|
||||||
if g, e := crcNew, crc; g != e {
|
if g, e := crcNew, crc; g != e {
|
||||||
fmt.Printf("err CRC16: got %04X want %04X\n", g, e)
|
fmt.Printf("err CRC16: got %04X want %04X\r\n", g, e)
|
||||||
}
|
}
|
||||||
if payload[0] == 0x02 || payload[0] == 0x00 {
|
if payload[0] == 0x02 || payload[0] == 0x00 {
|
||||||
r.received <- true
|
return
|
||||||
|
|
||||||
// switch goroutine
|
|
||||||
time.Sleep(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-10
@@ -3,10 +3,10 @@ package rtl8720dn
|
|||||||
import "io"
|
import "io"
|
||||||
|
|
||||||
type RTL8720DN struct {
|
type RTL8720DN struct {
|
||||||
port io.ReadWriter
|
port io.ReadWriter
|
||||||
seq uint64
|
seq uint64
|
||||||
received chan bool
|
sema chan bool
|
||||||
debug bool
|
debug bool
|
||||||
|
|
||||||
connectionType ConnectionType
|
connectionType ConnectionType
|
||||||
socket int32
|
socket int32
|
||||||
@@ -26,14 +26,12 @@ const (
|
|||||||
|
|
||||||
func New(r io.ReadWriter) *RTL8720DN {
|
func New(r io.ReadWriter) *RTL8720DN {
|
||||||
ret := &RTL8720DN{
|
ret := &RTL8720DN{
|
||||||
port: r,
|
port: r,
|
||||||
seq: 1,
|
seq: 1,
|
||||||
received: make(chan bool, 1),
|
sema: make(chan bool, 1),
|
||||||
debug: false,
|
debug: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
go ret.readThread()
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user