Initial import.

This commit is contained in:
2022-02-26 22:57:13 -08:00
commit a3966fc28b
16 changed files with 730 additions and 0 deletions

62
topic/pht/pht.go Normal file
View File

@@ -0,0 +1,62 @@
package pht
import (
"context"
"encoding/json"
"git.wntrmute.dev/kyle/sensenet/topic"
"github.com/Masterminds/squirrel"
)
var psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
func createTable(ctx context.Context, db topic.Database) error {
stmt := `CREATE TABLE pht IF NOT EXISTS (
id uuid primary key default gen_random_uuid(),
source text,
timestamp int,
temp real,
press real,
humid real
);`
_, err := db.Exec(ctx, stmt)
return err
}
type reading struct {
Timestamp int64 `json:"timestamp"`
Temperature float64 `json:"temperature"`
Pressure float64 `json:"pressure"`
Humidity float64 `json:"relative_humidity"`
}
func store(ctx context.Context, db topic.Database, packet *topic.Packet) error {
r := &reading{}
err := json.Unmarshal(packet.Payload, r)
if err != nil {
return err
}
stmt := psql.Insert("pht").Columns(
"source",
"timestamp",
"temp",
"press",
"humid",
).Values(packet.Publisher, r.Timestamp, r.Pressure, r.Humidity)
query, args, err := stmt.ToSql()
if err != nil {
return err
}
_, err = db.Exec(ctx, query, args...)
return err
}
var PHT = &topic.Topic{
CreateTable: createTable,
Store: store,
}
func init() {
topic.Register("pht", PHT)
}

70
topic/topic.go Normal file
View File

@@ -0,0 +1,70 @@
package topic
import (
"context"
"fmt"
"log"
"sync"
"github.com/jackc/pgconn"
)
type Database interface {
Exec(ctx context.Context, query string, args ...interface{}) (pgconn.CommandTag, error)
}
type Topic struct {
CreateTable func(ctx context.Context, db Database) error
Store func(ctx context.Context, db Database, packet *Packet) error
}
var registry = struct {
topics map[string]*Topic
lock *sync.Mutex
}{
topics: map[string]*Topic{},
lock: new(sync.Mutex),
}
func Register(topic string, handler *Topic) {
registry.lock.Lock()
defer registry.lock.Unlock()
if _, ok := registry.topics[topic]; ok {
panic(fmt.Sprintf("attempt to register pht '%s' that has already been registered", topic))
}
registry.topics[topic] = handler
}
type Packet struct {
Topic string
Publisher string
Received int64 // unix timestamp
Payload []byte
}
// Setup ensures all the required tables are created.
func Setup(ctx context.Context, db Database) error {
registry.lock.Lock()
defer registry.lock.Unlock()
for key, topic := range registry.topics {
log.Println("running CreateTable for", key)
err := topic.CreateTable(ctx, db)
if err != nil {
return err
}
}
return nil
}
func Publish(ctx context.Context, db Database, packet *Packet) error {
topic, ok := registry.topics[packet.Topic]
if !ok {
return fmt.Errorf("topic: no handler for topic '%s' [%x]", packet.Topic, packet.Payload)
}
return topic.Store(ctx, db, packet)
}