From daa79b27ca4a2b5dcb8711fa095bbdba63da3aa1 Mon Sep 17 00:00:00 2001 From: Siegfried Siegert Date: Sun, 30 Aug 2020 07:16:50 +0200 Subject: [PATCH] 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 --- .gitignore | 15 +++++++++++++++ config.toml | 7 +++++++ go.mod | 11 +++++++++++ main.go | 38 +++++++++++++++++++++++++++++++++++--- models/db.go | 33 +++++++++++++++++++++++++++++++++ models/devices.go | 36 ++++++++++++++++++++++++++++++++++++ 6 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 config.toml create mode 100644 go.mod create mode 100644 models/db.go create mode 100644 models/devices.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66fd13c --- /dev/null +++ b/.gitignore @@ -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/ diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..7fe4fdf --- /dev/null +++ b/config.toml @@ -0,0 +1,7 @@ +[BROKER] +Address="s1.mimbach49.de" +Port=8883 +ClientId = "mqttListener" +Username = "testuser" +Password = "xyz123" +EnableTLS = true diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f08de5c --- /dev/null +++ b/go.mod @@ -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 +) diff --git a/main.go b/main.go index 12c530e..4966e50 100644 --- a/main.go +++ b/main.go @@ -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) + } +} diff --git a/models/db.go b/models/db.go new file mode 100644 index 0000000..b28ff76 --- /dev/null +++ b/models/db.go @@ -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 +} diff --git a/models/devices.go b/models/devices.go new file mode 100644 index 0000000..dcf4ecb --- /dev/null +++ b/models/devices.go @@ -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 +} + +