GoSungrow/cmd/cmd_mqtt.go
2022-03-10 19:56:37 +11:00

306 lines
7.4 KiB
Go

package cmd
import (
"GoSungrow/Only"
"GoSungrow/mmMqtt"
"errors"
"fmt"
"github.com/go-co-op/gocron"
"github.com/spf13/cobra"
"strings"
"time"
)
func AttachCmdMqtt(cmd *cobra.Command) *cobra.Command {
// ******************************************************************************** //
var cmdMqtt = &cobra.Command{
Use: "mqtt",
Aliases: []string{""},
Short: fmt.Sprintf("Connect to a HASSIO broker."),
Long: fmt.Sprintf("Connect to a HASSIO broker."),
DisableFlagParsing: false,
DisableFlagsInUseLine: false,
PreRunE: Cmd.MqttArgs,
RunE: cmdMqttFunc,
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(cmdMqtt)
cmdMqtt.Example = PrintExamples(cmdMqtt, "run", "sync")
// ******************************************************************************** //
var cmdMqttRun = &cobra.Command{
Use: "run",
Aliases: []string{""},
Short: fmt.Sprintf("One-off sync to a HASSIO broker."),
Long: fmt.Sprintf("One-off sync to a HASSIO broker."),
DisableFlagParsing: false,
DisableFlagsInUseLine: false,
PreRunE: Cmd.MqttArgs,
RunE: cmdMqttRunFunc,
Args: cobra.RangeArgs(0, 1),
}
cmdMqtt.AddCommand(cmdMqttRun)
cmdMqttRun.Example = PrintExamples(cmdMqttRun, "")
// ******************************************************************************** //
var cmdMqttSync = &cobra.Command{
Use: "sync",
Aliases: []string{""},
Short: fmt.Sprintf("Sync to a HASSIO MQTT broker."),
Long: fmt.Sprintf("Sync to a HASSIO MQTT broker."),
DisableFlagParsing: false,
DisableFlagsInUseLine: false,
PreRunE: Cmd.MqttArgs,
RunE: cmdMqttSyncFunc,
Args: cobra.RangeArgs(0, 1),
}
cmdMqtt.AddCommand(cmdMqttSync)
cmdMqttSync.Example = PrintExamples(cmdMqttSync, "", "all")
return cmdMqtt
}
func (ca *CommandArgs) MqttArgs(cmd *cobra.Command, args []string) error {
for range Only.Once {
ca.Error = ca.ProcessArgs(cmd, args)
if ca.Error != nil {
break
}
LogPrintDate("Connecting to MQTT HASSIO Service...\n")
Cmd.Mqtt = mmMqtt.New(mmMqtt.Mqtt {
ClientId: "GoSunGrow",
Username: Cmd.MqttUsername,
Password: Cmd.MqttPassword,
Host: Cmd.MqttHost,
Port: Cmd.MqttPort,
})
Cmd.Error = Cmd.Mqtt.GetError()
if Cmd.Error != nil {
break
}
Cmd.Error = Cmd.Mqtt.Connect()
if Cmd.Error != nil {
break
}
LogPrintDate("Connecting to SunGrow...\n")
Cmd.Error = Cmd.SunGrowArgs(cmd, args)
if Cmd.Error != nil {
break
}
if Cmd.Mqtt.PsId == 0 {
Cmd.Mqtt.PsId, Cmd.Error = Cmd.SunGrow.GetPsId()
if Cmd.Error != nil {
break
}
LogPrintDate("Found SunGrow device %d\n", Cmd.Mqtt.PsId)
}
}
return Cmd.Error
}
func cmdMqttFunc(cmd *cobra.Command, _ []string) error {
return cmd.Help()
}
func cmdMqttRunFunc(_ *cobra.Command, _ []string) error {
for range Only.Once {
// switch1 := mmMqtt.BinarySensor {
// Device: mmMqtt.Device {
// Connections: [][]string{{"sungrow_address", "0"}},
// Identifiers: []string{"sungrow_bin_sensor_0"},
// Manufacturer: "MickMake",
// Model: "SunGrow inverter",
// Name: "SunGrow inverter online",
// SwVersion: "GoSunGrow https://github.com/MickMake/GoSungrow",
// ViaDevice: "GoSunGrow",
// },
// Name: "SunGrow inverter online",
// StateTopic: "homeassistant/binary_sensor/GoSunGrow_0/state",
// UniqueId: "sungrow_bin_sensor_0",
// }
// err = foo.Publish("homeassistant/binary_sensor/GoSunGrow_0/config", 0, true, switch1.Json())
// if err != nil {
// break
// }
// err = foo.Publish("homeassistant/binary_sensor/GoSunGrow_0/state", 0, true, "OFF")
// if err != nil {
// break
// }
Cmd.Error = MqttCron()
if Cmd.Error != nil {
break
}
LogPrintDate("Starting ticker...\n")
updateCounter := 0
timer := time.NewTicker(60 * time.Second)
for t := range timer.C {
if updateCounter < 5 {
updateCounter++
LogPrintDate("Sleeping: %d\n", updateCounter)
continue
}
updateCounter = 0
LogPrintDate("Update: %s\n", t.String())
Cmd.Error = MqttCron()
if Cmd.Error != nil {
break
}
// ep = Cmd.SunGrow.QueryDevice(psId)
// if ep.IsError() {
// Cmd.Error = ep.GetError()
// break
// }
//
// data = ep.GetData()
// for _, r := range data.Entries {
// // fmt.Printf("%s ", r.PointId)
// Cmd.Error = foo.SensorPublishState(r.PointId, r.Value)
// if err != nil {
// break
// }
// }
// // fmt.Println()
}
}
return Cmd.Error
}
func cmdMqttSyncFunc(_ *cobra.Command, args []string) error {
for range Only.Once {
// */1 * * * * /dir/command args args
cronString := "*/5 * * * *"
if len(args) > 0 {
cronString = strings.Join(args[0:5], " ")
cronString = strings.ReplaceAll(cronString, ".", "*")
}
Cron.Scheduler = gocron.NewScheduler(time.UTC)
Cron.Scheduler = Cron.Scheduler.Cron(cronString)
Cron.Scheduler = Cron.Scheduler.SingletonMode()
Cmd.Error = MqttCron()
if Cmd.Error != nil {
break
}
Cron.Job, Cmd.Error = Cron.Scheduler.Do(MqttCron)
if Cmd.Error != nil {
break
}
LogPrintDate("Created job schedule using '%s'\n", cronString)
Cron.Scheduler.StartBlocking()
if Cmd.Error != nil {
break
}
}
return Cmd.Error
}
func MqttCron() error {
for range Only.Once {
if Cmd.Mqtt == nil {
Cmd.Error = errors.New("mqtt not available")
break
}
if Cmd.SunGrow == nil {
Cmd.Error = errors.New("sungrow not available")
break
}
if Cmd.Mqtt.IsFirstRun() {
Cmd.Mqtt.UnsetFirstRun()
} else {
time.Sleep(time.Second * 40) // Takes up to 40 seconds for data to come in.
}
// Also getPowerStatistics, getHouseholdStoragePsReport, getPsList, getUpTimePoint,
ep := Cmd.SunGrow.QueryDevice(Cmd.Mqtt.PsId)
if ep.IsError() {
Cmd.Error = ep.GetError()
break
}
data := ep.GetData()
if Cmd.Mqtt.IsNewDay() {
LogPrintDate("New day: Configuring %d entries in HASSIO.\n", len(data.Entries))
for _, r := range data.Entries {
fmt.Printf(".")
// Cmd.Error = Cmd.Mqtt.SensorPublishConfig(r.PointId, r.PointName, r.Unit, i)
Cmd.Error = Cmd.Mqtt.SensorPublishConfig(r)
if Cmd.Error != nil {
break
}
}
fmt.Println()
}
LogPrintDate("Updating %d entries to HASSIO.\n", len(data.Entries))
for _, r := range data.Entries {
fmt.Printf(".")
// Cmd.Error = Cmd.Mqtt.SensorPublishState(r.PointId, r.Value)
Cmd.Error = Cmd.Mqtt.SensorPublishValue(r)
if Cmd.Error != nil {
break
}
}
fmt.Println()
Cmd.Mqtt.LastRefresh = time.Now()
if Cmd.Error != nil {
break
}
}
if Cmd.Error != nil {
LogPrintDate("Error: %s\n", Cmd.Error)
}
return Cmd.Error
}
// func toggle(v string) string {
// switch v {
// case "OFF":
// v = "ON"
// case "ON":
// v = "OFF"
// }
// return v
// }
//
// func randoPercent() string {
// t := time.Now()
// min := 0
// max := t.Second()
// i := (rand.Intn(max - min) + min) * t.Minute() // / float64(max)
// return fmt.Sprintf("%.2f", (float64(i) / 3600) * 100)
// }
//
// func randoKWh() string {
// t := time.Now()
// min := 0
// max := t.Minute()
// i := (rand.Intn(max - min) + min) * t.Second() // / float64(max)
// return fmt.Sprintf("%.2f", (float64(i) / 3600) * 11000)
// }