Extend this program:

- add a database for devices
- read devices from database and present this data on a simple web/REST
interface

The code or model is from a blog entry from Alex Edward:
https://www.alexedwards.net/blog/organising-database-access
This commit is contained in:
Siegfried Siegert 2020-08-30 07:16:50 +02:00
parent cf4274c1e1
commit daa79b27ca
6 changed files with 137 additions and 3 deletions

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

7
config.toml Normal file
View File

@ -0,0 +1,7 @@
[BROKER]
Address="s1.mimbach49.de"
Port=8883
ClientId = "mqttListener"
Username = "testuser"
Password = "xyz123"
EnableTLS = true

11
go.mod Normal file
View File

@ -0,0 +1,11 @@
module mqttListener
go 1.14
require (
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/mattn/go-sqlite3 v1.14.2
github.com/mmcdole/gofeed v1.0.0
github.com/pelletier/go-toml v1.2.0
github.com/spf13/cobra v1.0.0
)

38
main.go
View File

@ -2,16 +2,23 @@ package main
import (
"mqttListener/Config"
"mqttListener/models"
"mqttListener/mqtt"
//"mqttListener/cmd"
"fmt"
"log"
//"fmt"
"os"
"os/signal"
"syscall"
"net/http"
)
type Env struct {
db models.Datastore
}
func main() {
c := make(chan os.Signal, 1)
@ -22,13 +29,38 @@ func main() {
// DEBUG Config
// fmt.Println("BrokerAddress = ", Config.BrokerAddress)
db, err := models.NewDB("simple.sqlite")
if err != nil {
log.Panic(err)
}
env := &Env{db}
mqtt.Setup()
mqtt.Connect()
go mqtt.Listen()
//cmd.Exec()
http.HandleFunc("/devices", env.devicesIndex)
go http.ListenAndServe(":3000", nil)
fmt.Println("awaiting signal")
<-c // wait for SIGTERM
fmt.Println("exiting")
mqtt.Disconnect()
}
func (env *Env) devicesIndex(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, http.StatusText(405), 405)
return
}
devices, err := env.db.AllDevices()
if err != nil {
http.Error(w, http.StatusText(500), 500)
return
}
for _, device := range devices {
fmt.Fprintf(w, "%s, %s, %s, £%.2f\n", device.ID, device.MAC, device.SN, device.LastMsg)
}
}

33
models/db.go Normal file
View File

@ -0,0 +1,33 @@
package models
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
type Datastore interface {
AllDevices() ([]*Device, error)
}
type DB struct {
*sql.DB
}
func NewDB(dataSourceName string) (*DB, error) {
db, err := sql.Open("sqlite3", dataSourceName)
if err != nil {
return nil, err
}
if err = db.Ping(); err != nil {
return nil, err
}
sqlStmt := "CREATE TABLE IF NOT EXISTS devices (id TEXT not null primary key, mac TEXT, sn TEXT, lastMsg TEXT);"
_, err = db.Exec(sqlStmt)
if err != nil {
return nil, err
}
return &DB{db}, nil
}

36
models/devices.go Normal file
View File

@ -0,0 +1,36 @@
package models
type Device struct {
ID string
MAC string
SN string
LastMsg string
}
func (db *DB) AllDevices() ([]*Device, error) {
rows, err := db.Query("SELECT * FROM devices")
if err != nil {
return nil, err
}
defer rows.Close()
devices := make([]*Device, 0)
for rows.Next() {
device := new(Device)
err := rows.Scan(&device.ID, &device.MAC, &device.SN, &device.LastMsg)
if err != nil {
return nil, err
}
devices = append(devices, device)
}
if err = rows.Err(); err != nil {
return nil, err
}
return devices, nil
}