238 lines
5.4 KiB
Go
238 lines
5.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/binary"
|
||
|
"encoding/json"
|
||
|
"flag"
|
||
|
"log"
|
||
|
"math"
|
||
|
"os"
|
||
|
"path"
|
||
|
"strconv"
|
||
|
"time"
|
||
|
|
||
|
"periph.io/x/conn/v3/i2c"
|
||
|
"periph.io/x/conn/v3/i2c/i2creg"
|
||
|
"periph.io/x/conn/v3/mmr"
|
||
|
"periph.io/x/host/v3"
|
||
|
|
||
|
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
|
||
|
)
|
||
|
|
||
|
type config struct {
|
||
|
DataStorage string `json:"data_storage"`
|
||
|
InfluxdbHost string `json:"influxdb_host"`
|
||
|
InfluxdbPort int `json:"influxdb_port"`
|
||
|
InfluxdbToken string `json:"influxdb_token"`
|
||
|
TriggerLevel float64 `json:"trigger_level"`
|
||
|
TriggerHysterese float64 `json:"trigger_hysterese"`
|
||
|
StepWidth float64 `json:"step_width"`
|
||
|
Zustandszahl float64 `json:"zustandszahl"`
|
||
|
BrennwertHS float64 `json:"brennwert_hs"`
|
||
|
}
|
||
|
|
||
|
type data struct {
|
||
|
Unit string `json:"unit"`
|
||
|
Value float64 `json:"value"`
|
||
|
}
|
||
|
|
||
|
type sample struct {
|
||
|
Volume data `json:"volume"`
|
||
|
Power data `json:"power"`
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
logger log.Logger = *log.Default()
|
||
|
config_path string
|
||
|
config_cache = config{
|
||
|
DataStorage: "",
|
||
|
InfluxdbHost: "",
|
||
|
InfluxdbPort: 0,
|
||
|
InfluxdbToken: "",
|
||
|
TriggerLevel: 0.0,
|
||
|
TriggerHysterese: 0.0,
|
||
|
StepWidth: 0.0,
|
||
|
Zustandszahl: 0.0,
|
||
|
BrennwertHS: 0.0,
|
||
|
}
|
||
|
)
|
||
|
|
||
|
func read_config() {
|
||
|
data, err := os.ReadFile(config_path)
|
||
|
if err != nil {
|
||
|
logger.Printf("Unable to read %s", config_path)
|
||
|
return
|
||
|
}
|
||
|
err = json.Unmarshal(data, &config_cache)
|
||
|
if err != nil {
|
||
|
logger.Print("Unable to evaluate config data")
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
// file, err := os.OpenFile("log.txt", os.O_WRONLY|os.O_CREATE, 0644)
|
||
|
// if err != nil {
|
||
|
// logger.Println(err)
|
||
|
// }
|
||
|
// defer file.Close()
|
||
|
// logger.SetOutput(file)
|
||
|
|
||
|
logger.SetPrefix("Gas: ")
|
||
|
logger.Println("Starting")
|
||
|
|
||
|
flag.StringVar(&config_path, "c", "./config/config.json", "Specify path to find the config file. Default is ./config/config.json")
|
||
|
flag.Parse()
|
||
|
read_config()
|
||
|
|
||
|
trigger_state := false
|
||
|
old_state := false
|
||
|
|
||
|
var gas sample
|
||
|
|
||
|
// Create data storage directory
|
||
|
dir := path.Dir(config_cache.DataStorage)
|
||
|
err := os.MkdirAll(dir, os.ModePerm)
|
||
|
if err != nil {
|
||
|
logger.Fatal(err)
|
||
|
}
|
||
|
|
||
|
// Try reading stored value
|
||
|
data, err := os.ReadFile(config_cache.DataStorage)
|
||
|
if err != nil {
|
||
|
log.Print(err)
|
||
|
gas.Volume.Unit = "m³"
|
||
|
gas.Volume.Value = 0.0
|
||
|
gas.Power.Unit = "kW/h"
|
||
|
gas.Power.Value = 0.0
|
||
|
} else {
|
||
|
err = json.Unmarshal(data, &gas)
|
||
|
if err != nil {
|
||
|
logger.Print(err)
|
||
|
}
|
||
|
}
|
||
|
last_value := gas.Volume.Value
|
||
|
|
||
|
// prepare influx connection
|
||
|
influxdb_url := "http://" + config_cache.InfluxdbHost + ":" + strconv.Itoa(config_cache.InfluxdbPort)
|
||
|
client := influxdb2.NewClient(influxdb_url, config_cache.InfluxdbToken)
|
||
|
// always close client at the end
|
||
|
defer client.Close()
|
||
|
|
||
|
// get non-blocking write client
|
||
|
writeAPI := client.WriteAPIBlocking("tkl", "home")
|
||
|
|
||
|
ctx := context.Background()
|
||
|
|
||
|
// Int I2C system
|
||
|
if _, err := host.Init(); err != nil {
|
||
|
logger.Fatal(err)
|
||
|
}
|
||
|
bus, err := i2creg.Open("")
|
||
|
if err != nil {
|
||
|
logger.Fatal(err)
|
||
|
}
|
||
|
defer bus.Close()
|
||
|
i2c_dev := i2c.Dev{
|
||
|
Bus: bus,
|
||
|
Addr: 0x0d,
|
||
|
}
|
||
|
mem_dev := mmr.Dev8{
|
||
|
Conn: &i2c_dev,
|
||
|
Order: binary.BigEndian,
|
||
|
}
|
||
|
err = mem_dev.WriteUint8(0x09, 0x1d)
|
||
|
if err != nil {
|
||
|
logger.Fatal("unable to write to reg 0x09")
|
||
|
}
|
||
|
|
||
|
for { // ever
|
||
|
var raw [6]uint8
|
||
|
var i uint8
|
||
|
for i = 0; i < 6; i++ {
|
||
|
res, err := mem_dev.ReadUint8(i)
|
||
|
if err != nil {
|
||
|
logger.Print("unable to read from reg 0")
|
||
|
continue
|
||
|
}
|
||
|
raw[i] = res
|
||
|
}
|
||
|
var mag_x int16
|
||
|
mag_x = int16(raw[0])
|
||
|
mag_x |= int16(raw[1]) << 8
|
||
|
fmag_x := float64(mag_x)
|
||
|
|
||
|
var mag_y int16
|
||
|
mag_y = int16(raw[2])
|
||
|
mag_y |= int16(raw[3]) << 8
|
||
|
fmag_y := float64(mag_y)
|
||
|
|
||
|
var mag_z int16
|
||
|
mag_z = int16(raw[4])
|
||
|
mag_z |= int16(raw[5]) << 8
|
||
|
fmag_z := float64(mag_z)
|
||
|
|
||
|
mag := math.Sqrt(fmag_x*fmag_x + fmag_y*fmag_y + fmag_z*fmag_z)
|
||
|
logger.Printf("mag: %f\n\n", mag)
|
||
|
|
||
|
old_state = trigger_state
|
||
|
if mag > config_cache.TriggerLevel+config_cache.TriggerHysterese {
|
||
|
trigger_state = true
|
||
|
} else if mag < config_cache.TriggerLevel-config_cache.TriggerHysterese {
|
||
|
trigger_state = false
|
||
|
}
|
||
|
|
||
|
if !old_state && trigger_state {
|
||
|
gas.Volume.Value += config_cache.StepWidth
|
||
|
}
|
||
|
logger.Printf("Volume: %f %s\n", gas.Volume.Value, gas.Volume.Unit)
|
||
|
gas.Power.Value = gas.Volume.Value * config_cache.BrennwertHS * config_cache.Zustandszahl
|
||
|
logger.Printf("Power: %f %s\n", gas.Power.Value, gas.Power.Unit)
|
||
|
|
||
|
if last_value != gas.Volume.Value {
|
||
|
last_value = gas.Volume.Value
|
||
|
|
||
|
file, err := os.OpenFile(config_cache.DataStorage, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||
|
if err != nil {
|
||
|
log.Print(err)
|
||
|
} else {
|
||
|
res, err := json.Marshal(gas)
|
||
|
if err != nil {
|
||
|
logger.Print(err)
|
||
|
} else {
|
||
|
file.Write(res)
|
||
|
}
|
||
|
file.Close()
|
||
|
}
|
||
|
|
||
|
point := influxdb2.NewPointWithMeasurement("gas")
|
||
|
point.AddTag("sensor", "gasmeter")
|
||
|
point.AddField("volume", gas.Volume.Value)
|
||
|
point.AddField("unit", gas.Volume.Unit)
|
||
|
|
||
|
point.SetTime(time.Now())
|
||
|
err = writeAPI.WritePoint(ctx, point)
|
||
|
if err != nil {
|
||
|
logger.Print(err.Error())
|
||
|
}
|
||
|
point = influxdb2.NewPointWithMeasurement("gas")
|
||
|
point.AddTag("sensor", "gasmeter")
|
||
|
point.AddField("power", gas.Power.Value)
|
||
|
point.AddField("unit", gas.Power.Unit)
|
||
|
|
||
|
point.SetTime(time.Now())
|
||
|
err = writeAPI.WritePoint(ctx, point)
|
||
|
if err != nil {
|
||
|
logger.Print(err.Error())
|
||
|
}
|
||
|
err = writeAPI.Flush(ctx)
|
||
|
if err != nil {
|
||
|
logger.Print(err.Error())
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
time.Sleep(time.Millisecond * 1000)
|
||
|
}
|
||
|
}
|