mirror of
https://github.com/MickMake/GoSungrow.git
synced 2025-04-09 20:29:14 +02:00
v1.4.0 Implement HASSIO MQTT
This commit is contained in:
parent
b36a272818
commit
0dac734545
73
.idea/workspace.xml
generated
73
.idea/workspace.xml
generated
@ -5,22 +5,27 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="76adadc9-ae71-42a6-82a1-66dbc8ecb14c" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/mmMqtt/config.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/mmMqtt/funcs.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/mmMqtt/lights.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/mmMqtt/sensors.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/mmMqtt/struct.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/mmMqtt/switch.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220224-8042-InternalAirTemperature.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220224-8042-InternalAirTemperature.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryChargingPower.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryChargingPower.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryDischargingPower.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryDischargingPower.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryHealth(SOH).png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryHealth(SOH).png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryLevel(SOC).png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryLevel(SOC).png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryTemperature.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-BatteryTemperature.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-InternalAirTemperature.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-InternalAirTemperature.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-LoadPower.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-LoadPower.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-PurchasedPower.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-PurchasedPower.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-TotalDCPower.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-TotalDCPower.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-TotalExportActivePower.png" beforeDir="false" afterPath="$PROJECT_DIR$/docs/AppService_queryMutiPointDataList-20220228-8042-TotalExportActivePower.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/cmd/cmd_data_sub.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/cmd_data_sub.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/cmd/cmd_mqtt.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/cmd_mqtt.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/examples.txt" beforeDir="false" afterPath="$PROJECT_DIR$/examples.txt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/api/datetime.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/api/datetime.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/api/output/struct_graph.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/api/output/struct_graph.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/go.sum" beforeDir="false" afterPath="$PROJECT_DIR$/go.sum" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/AppService/queryDeviceList/data.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/AppService/queryDeviceList/data.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/api/output/file.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/api/output/file.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/api/output/struct_table.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/api/output/struct_table.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/api/output/struct_table2.go" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/api/web.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/api/web.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/funcs.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/funcs.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/struct_output.go" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/iSolarCloud/struct_template.go" beforeDir="false" afterPath="$PROJECT_DIR$/iSolarCloud/highlevel.go" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@ -86,7 +91,7 @@
|
||||
<configuration name="GoSungrow" type="GoApplicationRunConfiguration" factoryName="Go Application">
|
||||
<module name="GoSungrow" />
|
||||
<working_directory value="$PROJECT_DIR$" />
|
||||
<parameters value="data graph template 8042 20220224 '{"search_string":"p13019"}'" />
|
||||
<parameters value="mqtt" />
|
||||
<kind value="PACKAGE" />
|
||||
<package value="$PROJECT_DIR$" />
|
||||
<directory value="$PROJECT_DIR$" />
|
||||
@ -154,17 +159,17 @@
|
||||
<option name="timeStamp" value="115" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/struct_template.go</url>
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/highlevel.go</url>
|
||||
<line>119</line>
|
||||
<option name="timeStamp" value="190" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/struct_template.go</url>
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/highlevel.go</url>
|
||||
<line>124</line>
|
||||
<option name="timeStamp" value="191" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/struct_template.go</url>
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/highlevel.go</url>
|
||||
<line>134</line>
|
||||
<option name="timeStamp" value="192" />
|
||||
</line-breakpoint>
|
||||
@ -175,27 +180,12 @@
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>282</line>
|
||||
<option name="timeStamp" value="203" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>266</line>
|
||||
<option name="timeStamp" value="205" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>278</line>
|
||||
<option name="timeStamp" value="206" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>323</line>
|
||||
<line>133</line>
|
||||
<option name="timeStamp" value="210" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>311</line>
|
||||
<line>121</line>
|
||||
<option name="timeStamp" value="211" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
@ -208,21 +198,6 @@
|
||||
<line>302</line>
|
||||
<option name="timeStamp" value="256" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>345</line>
|
||||
<option name="timeStamp" value="261" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>363</line>
|
||||
<option name="timeStamp" value="265" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/funcs.go</url>
|
||||
<line>356</line>
|
||||
<option name="timeStamp" value="266" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/iSolarCloud/api/output/struct_graph.go</url>
|
||||
<line>257</line>
|
||||
|
25
README.md
25
README.md
@ -1,5 +1,6 @@
|
||||
# GoSungrow - iSolarCloud API written in GoLang.
|
||||
|
||||
|
||||
## What is it?
|
||||
|
||||
This GoLang package has a complete, (almost complete), implementation of the iSolarCloud API.
|
||||
@ -13,14 +14,16 @@ Note:
|
||||
|
||||

|
||||
|
||||
I'm currently using it in my [HomeAssistant](https://www.home-assistant.io/) instance.
|
||||
|
||||

|
||||
|
||||
|
||||
## What state is it in?
|
||||
|
||||
This is currently under development.
|
||||
This is currently usable for my needs, (seeing all data in [HomeAssistant](https://www.home-assistant.io/)), but there's quite a few API endpoints that need to be implemented for completeness.
|
||||
|
||||
So far I have mapped out all the API calls, but now figuring out JSON POST data formats.
|
||||
|
||||
It's tricky as their "API" changes regularly.
|
||||
So far I have mapped out all the API calls. It's tricky as their "API" changes regularly.
|
||||
|
||||
I've currently mapped out these API EndPoints. Only about 6%, but most of the API endpoints are a repeat and a lot of the data is repeated.
|
||||
So, in reality 50% of the critical endpoints are implemented.
|
||||
@ -39,19 +42,21 @@ So, in reality 50% of the critical endpoints are implemented.
|
||||
+-------------------+-------------------+--------------------+------------+
|
||||
```
|
||||
|
||||
|
||||
## What does it do?
|
||||
|
||||
This GoLang package does several things:
|
||||
1. Provides ready access to all API calls via a simple get/put framework.
|
||||
2. Update a GitHub repo with SunGrow PV data, (provide full revision history for any changes made to the SunGrow PV).
|
||||
3. Update a Google sheet with SunGrow PV data.
|
||||
2. MQTT client to push to [HomeAssistant](https://www.home-assistant.io/).
|
||||
3. Graphing any points data, (over daily, monthly and yearly).
|
||||
4. Update a GitHub repo with SunGrow PV data, (provide full revision history for any changes made to the SunGrow PV).
|
||||
5. Update a Google sheet with SunGrow PV data.
|
||||
|
||||
|
||||
## What is the roadmap?
|
||||
|
||||
I've planned a number of features, but my main goal is to be able to interface with my HASS instance.
|
||||
1. MQTT client to push to things like [HomeAssistant](https://www.home-assistant.io/).
|
||||
2. IFTTT support.
|
||||
3. Graphing a logging support.
|
||||
I've implemented most of the features I've wanted to, except for...
|
||||
1. IFTTT support.
|
||||
|
||||
|
||||
## Use case example:
|
||||
|
@ -63,7 +63,7 @@ func AttachCmdDataStats(cmd *cobra.Command) *cobra.Command {
|
||||
PreRunE: Cmd.SunGrowArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
_ = SwitchOutput(cmd)
|
||||
return Cmd.SunGrow.GetCurrentStats()
|
||||
return Cmd.SunGrow.PrintCurrentStats()
|
||||
},
|
||||
Args: cobra.ExactArgs(0),
|
||||
}
|
||||
|
203
cmd/cmd_mqtt.go
203
cmd/cmd_mqtt.go
@ -2,8 +2,12 @@ package cmd
|
||||
|
||||
import (
|
||||
"GoSungrow/Only"
|
||||
"GoSungrow/mmMqtt"
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
@ -17,7 +21,7 @@ func AttachCmdMqtt(cmd *cobra.Command) *cobra.Command {
|
||||
DisableFlagParsing: false,
|
||||
DisableFlagsInUseLine: false,
|
||||
PreRunE: Cmd.ProcessArgs,
|
||||
Run: cmdMqttFunc,
|
||||
RunE: cmdMqttFunc,
|
||||
Args: cobra.RangeArgs(0, 1),
|
||||
}
|
||||
cmd.AddCommand(cmdMqtt)
|
||||
@ -43,20 +47,195 @@ func AttachCmdMqtt(cmd *cobra.Command) *cobra.Command {
|
||||
}
|
||||
|
||||
|
||||
func cmdMqttFunc(cmd *cobra.Command, args []string) {
|
||||
func cmdMqttFunc(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
|
||||
for range Only.Once {
|
||||
switch {
|
||||
case len(args) == 0:
|
||||
Cmd.Error = cmd.Help()
|
||||
|
||||
case args[0] == "all":
|
||||
// Cmd.Error = Cmd.GoogleUpdate()
|
||||
|
||||
default:
|
||||
fmt.Println("Unknown sub-command.")
|
||||
_ = cmd.Help()
|
||||
foo := mmMqtt.New(mmMqtt.Mqtt{
|
||||
ClientId: "SunGrow",
|
||||
Username: "mickmake",
|
||||
Password: "rvsrzdd0",
|
||||
Host: "10.0.5.21",
|
||||
Port: "11883",
|
||||
})
|
||||
err = foo.GetError()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
err = foo.Connect()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
// }
|
||||
|
||||
err = Cmd.SunGrowArgs(cmd, args)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
var psId int64
|
||||
psId, err = Cmd.SunGrow.GetPsId()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep := Cmd.SunGrow.QueryDevice(psId)
|
||||
if ep.IsError() {
|
||||
err = ep.GetError()
|
||||
break
|
||||
}
|
||||
|
||||
data := ep.GetData()
|
||||
for i, r := range data.Entries {
|
||||
point_id := strings.ReplaceAll(r.PointId, ".", "-")
|
||||
id := "sungrow_" + point_id
|
||||
fmt.Println(id)
|
||||
|
||||
err = foo.SensorPublishConfig(id, r.PointName, r.Unit, i)
|
||||
// time.Sleep(time.Second)
|
||||
err = foo.SensorPublishState(id, r.Value)
|
||||
}
|
||||
|
||||
// sensor1 := mmMqtt.Sensor {
|
||||
// Device: mmMqtt.Device {
|
||||
// Connections: [][]string{{"sungrow_address", "1"}},
|
||||
// Identifiers: []string{"sungrow_battery_Level", "sungrow_address_1"},
|
||||
// Manufacturer: "MickMake",
|
||||
// Model: "SunGrow inverter",
|
||||
// Name: "SunGrow battery level",
|
||||
// SwVersion: "GoSunGrow https://github.com/MickMake/GoSungrow",
|
||||
// ViaDevice: "GoSunGrow",
|
||||
// },
|
||||
// Name: "SunGrow battery level",
|
||||
// StateTopic: "homeassistant/sensor/SunGrow/sungrow_battery_Level/state",
|
||||
// UniqueID: "sungrow_battery_Level",
|
||||
// UnitOfMeasurement: "%",
|
||||
// }
|
||||
|
||||
// err = foo.SensorPublishConfig("sungrow_battery_Level", "SunGrow battery level", "%", "1")
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
// err = foo.SensorPublishState("sungrow_battery_Level", randoPercent())
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
|
||||
// sensor2 := mmMqtt.Sensor {
|
||||
// Device: mmMqtt.Device {
|
||||
// Connections: [][]string{{"sungrow_address", "2"}},
|
||||
// Identifiers: []string{"sungrow_pv_energy", "sungrow_address_2"},
|
||||
// Manufacturer: "MickMake",
|
||||
// Model: "SunGrow inverter",
|
||||
// Name: "SunGrow PV Energy",
|
||||
// SwVersion: "GoSunGrow https://github.com/MickMake/GoSungrow",
|
||||
// ViaDevice: "GoSunGrow",
|
||||
// },
|
||||
// Name: "SunGrow PV Energy",
|
||||
// StateTopic: "homeassistant/sensor/SunGrow/sungrow_pv_energy/state",
|
||||
// UniqueID: "sungrow_pv_energy",
|
||||
// UnitOfMeasurement: "kWh",
|
||||
// }
|
||||
|
||||
// err = foo.SensorPublishConfig("sungrow_pv_energy", "SunGrow PV Energy", "kWh", "2")
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
// err = foo.SensorPublishState("sungrow_pv_energy", randoKWh())
|
||||
|
||||
|
||||
updateCounter := 0
|
||||
timer := time.NewTicker(10 * time.Second)
|
||||
for t := range timer.C {
|
||||
if updateCounter < 6 {
|
||||
updateCounter++
|
||||
fmt.Printf("Wait: %d - %s\n", updateCounter, t.String())
|
||||
continue
|
||||
}
|
||||
|
||||
updateCounter = 0
|
||||
fmt.Printf("Update: %s\n", t.String())
|
||||
ep = Cmd.SunGrow.QueryDevice(psId)
|
||||
if ep.IsError() {
|
||||
err = ep.GetError()
|
||||
break
|
||||
}
|
||||
|
||||
data = ep.GetData()
|
||||
for _, r := range data.Entries {
|
||||
point_id := strings.ReplaceAll(r.PointId, ".", "-")
|
||||
id := "sungrow_" + point_id
|
||||
fmt.Println(id)
|
||||
err = foo.SensorPublishState(id, r.Value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// switch {
|
||||
// case len(args) == 0:
|
||||
// Cmd.Error = cmd.Help()
|
||||
//
|
||||
// case args[0] == "all":
|
||||
// // Cmd.Error = Cmd.GoogleUpdate()
|
||||
//
|
||||
// default:
|
||||
// fmt.Println("Unknown sub-command.")
|
||||
// _ = cmd.Help()
|
||||
// }
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func cmdMqttSyncFunc(cmd *cobra.Command, args []string) {
|
||||
|
BIN
docs/SunGrowOnHASSIO.png
Normal file
BIN
docs/SunGrowOnHASSIO.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 339 KiB |
2
go.mod
2
go.mod
@ -4,6 +4,7 @@ go 1.17
|
||||
|
||||
require (
|
||||
github.com/acarl005/textcol v0.0.0
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||
github.com/go-co-op/gocron v1.12.0
|
||||
github.com/go-git/go-billy/v5 v5.3.1
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
@ -36,6 +37,7 @@ require (
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
|
5
go.sum
5
go.sum
@ -114,6 +114,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@ -236,6 +238,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
|
||||
@ -516,6 +520,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
|
@ -220,8 +220,8 @@ func (e *EndPoint) GetDataTable() output.Table {
|
||||
_ = table.SetHeader(
|
||||
"Date",
|
||||
"Point Id",
|
||||
"PointGroupName",
|
||||
"PointName",
|
||||
"Point Group Name",
|
||||
"Point Name",
|
||||
"Value",
|
||||
"Unit",
|
||||
)
|
||||
@ -254,3 +254,52 @@ func (e *EndPoint) GetDataTable() output.Table {
|
||||
}
|
||||
return table
|
||||
}
|
||||
|
||||
|
||||
type Data struct {
|
||||
// Headers DataHeaders
|
||||
Entries []DataEntry
|
||||
}
|
||||
// type DataHeaders struct {
|
||||
// Date string
|
||||
// PointId string
|
||||
// PointGroupName string
|
||||
// PointName string
|
||||
// Value string
|
||||
// Unit string
|
||||
// }
|
||||
type DataEntry struct {
|
||||
Date api.DateTime `json:"date"`
|
||||
PointId string `json:"point_id"`
|
||||
PointGroupName string `json:"point_group_name"`
|
||||
PointName string `json:"point_name"`
|
||||
Value string `json:"value"`
|
||||
Unit string `json:"unit"`
|
||||
}
|
||||
func (e *EndPoint) GetData() Data {
|
||||
var ret Data
|
||||
for range Only.Once {
|
||||
// ret.Headers = DataHeaders {
|
||||
// Date: "Date",
|
||||
// PointId: "Point Id",
|
||||
// PointGroupName: "Point Group Name",
|
||||
// PointName: "Point Name",
|
||||
// Value: "Value",
|
||||
// Unit: "Unit",
|
||||
// }
|
||||
|
||||
for _, d := range e.Response.ResultData.PageList {
|
||||
for _, p := range d.PointData {
|
||||
ret.Entries = append(ret.Entries, DataEntry {
|
||||
Date: api.NewDateTime(p.TimeStamp),
|
||||
PointId: fmt.Sprintf("%s.%d", d.PsKey, p.PointID),
|
||||
PointGroupName: p.PointGroupName,
|
||||
PointName: p.PointName,
|
||||
Value: p.Value,
|
||||
Unit: p.Unit,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
@ -134,3 +134,32 @@ func PlainFileWrite(fn string, data []byte, perm os.FileMode) error {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// FileRemove Removes a file path.
|
||||
func FileRemove(fn string) error {
|
||||
var err error
|
||||
for range Only.Once {
|
||||
if fn == "" {
|
||||
err = errors.New("empty file")
|
||||
break
|
||||
}
|
||||
|
||||
var f os.FileInfo
|
||||
f, err = os.Stat(fn)
|
||||
if os.IsNotExist(err) {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if f.IsDir() {
|
||||
err = errors.New("file is a directory")
|
||||
break
|
||||
}
|
||||
|
||||
err = os.Remove(fn)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"GoSungrow/Only"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go.pennock.tech/tabular"
|
||||
datatable "go.pennock.tech/tabular/auto"
|
||||
"os"
|
||||
)
|
||||
@ -39,6 +40,28 @@ func (t *Table) String() string {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (t *Table) GetHeaders() []tabular.Cell {
|
||||
return t.table.Headers()
|
||||
}
|
||||
|
||||
func (t *Table) AllRows() []*tabular.Row {
|
||||
return t.table.AllRows()
|
||||
}
|
||||
|
||||
type DataSet []DataRow
|
||||
type DataRow map[string]string
|
||||
func (t *Table) GetData() {
|
||||
headers := t.GetHeaders()
|
||||
for _, r := range t.AllRows() {
|
||||
for i, c := range r.Cells() {
|
||||
fmt.Printf("Header: %s\tValue: %v\n", headers[i], c)
|
||||
// err = foo.SensorPublishConfig()
|
||||
}
|
||||
// r.Cells()
|
||||
// err = foo.SensorPublishConfig()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Table) Print() {
|
||||
for range Only.Once {
|
||||
t.Error = t.table.RenderTo(os.Stdout)
|
||||
|
@ -1,74 +0,0 @@
|
||||
package output
|
||||
|
||||
|
||||
// type Table struct {
|
||||
// Data [][]interface{}
|
||||
// Header []string
|
||||
// Error error
|
||||
// }
|
||||
//
|
||||
//
|
||||
// func NewTable() Table {
|
||||
// return Table{}
|
||||
// }
|
||||
//
|
||||
// func (c Table) String() string {
|
||||
// var ret string
|
||||
// ret += c.HeaderString()
|
||||
// ret += c.DataString()
|
||||
// return ret
|
||||
// }
|
||||
//
|
||||
// func (c Table) Print() {
|
||||
// fmt.Println(c)
|
||||
// }
|
||||
//
|
||||
// func (c Table) HeaderString() string {
|
||||
// var ret string
|
||||
// for _, h := range c.Header {
|
||||
// ret += fmt.Sprintf("\"%s\",", h)
|
||||
// }
|
||||
// ret += fmt.Sprintln()
|
||||
// return ret
|
||||
// }
|
||||
//
|
||||
// func (c Table) DataString() string {
|
||||
// var ret string
|
||||
// for _, r := range c.Data {
|
||||
// for _, r := range r {
|
||||
// ret += fmt.Sprintf("\"%s\",", r)
|
||||
// }
|
||||
// ret += fmt.Sprintln()
|
||||
// }
|
||||
// return ret
|
||||
// }
|
||||
//
|
||||
// func (c Table) AddRow(row []string) Table {
|
||||
// foo := Cell{
|
||||
// string: "",
|
||||
// float64: 0,
|
||||
// }
|
||||
// c.Data = append(c.Data, foo)
|
||||
// for i := range row {
|
||||
//
|
||||
// }
|
||||
// return c
|
||||
// }
|
||||
//
|
||||
// func (c Table) SetHeader(header []string) Table {
|
||||
// c.Header = header
|
||||
// return c
|
||||
// }
|
||||
//
|
||||
// func (c *Table) WriteFile(fn string, perm os.FileMode) error {
|
||||
// for range Only.Once {
|
||||
// fmt.Printf("Writing file '%s'\n", fn)
|
||||
// c.Error = os.WriteFile(fn, []byte(c.String()), perm)
|
||||
// if c.Error != nil {
|
||||
// c.Error = errors.New(fmt.Sprintf("Unable to write to file %s - %v", fn, c.Error))
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return c.Error
|
||||
// }
|
@ -64,54 +64,6 @@ func (w *Web) Get(endpoint EndPoint) EndPoint {
|
||||
}
|
||||
}
|
||||
|
||||
// {
|
||||
// request := endpoint.RequestRef()
|
||||
// w.Error = apiReflect.VerifyOptionsRequired(request)
|
||||
// if w.Error != nil {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// w.Error = endpoint.IsRequestValid()
|
||||
// if w.Error != nil {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// u := endpoint.GetUrl()
|
||||
// w.Error = u.IsValid()
|
||||
// if w.Error != nil {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// postUrl := w.Url.AppendPath(u.String()).String()
|
||||
// j, _ := json.Marshal(request)
|
||||
//
|
||||
// w.httpResponse, w.Error = http.Post(postUrl, "application/json", bytes.NewBuffer(j))
|
||||
// if w.Error != nil {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// if w.httpResponse.StatusCode == 401 {
|
||||
// w.Error = errors.New(w.httpResponse.Status)
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// //goland:noinspection GoUnhandledErrorResult,GoDeferInLoop
|
||||
// defer w.httpResponse.Body.Close()
|
||||
// if w.Error != nil {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// if w.httpResponse.StatusCode != 200 {
|
||||
// w.Error = errors.New(fmt.Sprintf("API httpResponse is %s", w.httpResponse.Status))
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// w.Body, w.Error = ioutil.ReadAll(w.httpResponse.Body)
|
||||
// if w.Error != nil {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
|
||||
if len(w.Body) == 0 {
|
||||
w.Error = errors.New("empty httpResponse")
|
||||
break
|
||||
@ -120,16 +72,10 @@ func (w *Web) Get(endpoint EndPoint) EndPoint {
|
||||
endpoint = endpoint.SetResponse(w.Body)
|
||||
w.Error = endpoint.IsResponseValid()
|
||||
if w.Error != nil {
|
||||
_ = w.CacheRemove(endpoint)
|
||||
// fmt.Printf("ERROR: Body is:\n%s\n", w.Body)
|
||||
break
|
||||
}
|
||||
|
||||
// if newFile {
|
||||
// w.Error = w.CacheWrite(endpoint, w.Body)
|
||||
// if w.Error != nil {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
if w.Error != nil {
|
||||
@ -260,6 +206,12 @@ func (w *Web) CacheRead(endpoint EndPoint) ([]byte, error) {
|
||||
return output.PlainFileRead(fn)
|
||||
}
|
||||
|
||||
// CacheRemove Removes a cache file.
|
||||
func (w *Web) CacheRemove(endpoint EndPoint) error {
|
||||
fn := filepath.Join(w.cacheDir, endpoint.CacheFilename())
|
||||
return output.FileRemove(fn)
|
||||
}
|
||||
|
||||
// CacheWrite Saves cache data to a file path.
|
||||
func (w *Web) CacheWrite(endpoint EndPoint, data []byte) error {
|
||||
fn := filepath.Join(w.cacheDir, endpoint.CacheFilename())
|
||||
|
@ -2,16 +2,12 @@ package iSolarCloud
|
||||
|
||||
import (
|
||||
"GoSungrow/Only"
|
||||
"GoSungrow/iSolarCloud/AppService/getPowerDevicePointNames"
|
||||
"GoSungrow/iSolarCloud/AppService/getPsList"
|
||||
"GoSungrow/iSolarCloud/AppService/getTemplateList"
|
||||
"GoSungrow/iSolarCloud/AppService/queryDeviceList"
|
||||
"GoSungrow/iSolarCloud/AppService/queryMutiPointDataList"
|
||||
"GoSungrow/iSolarCloud/api"
|
||||
"GoSungrow/iSolarCloud/api/output"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -105,197 +101,6 @@ func (sg *SunGrow) GetByStruct(endpoint string, request interface{}, cache time.
|
||||
return ret
|
||||
}
|
||||
|
||||
// func (sg *SunGrow) GetHighLevel(name string, args ...string) error {
|
||||
// for range Only.Once {
|
||||
// name = strings.ToLower(name)
|
||||
// // if name == "stats" {
|
||||
// // sg.Error = sg.GetCurrentStats()
|
||||
// // break
|
||||
// // }
|
||||
// //
|
||||
// // if name == "template" {
|
||||
// // args = fillArray(3, args)
|
||||
// // if args[0] == "" {
|
||||
// // sg.Error = errors.New("need a date")
|
||||
// // break
|
||||
// // }
|
||||
// // sg.Error = sg.GetTemplateData(args[0], args[1], args[2])
|
||||
// // break
|
||||
// // }
|
||||
// //
|
||||
// // if name == "template-points" {
|
||||
// // args = fillArray(1, args)
|
||||
// // sg.Error = sg.GetTemplatePoints(args[0])
|
||||
// // break
|
||||
// // }
|
||||
//
|
||||
// // if name == "points" {
|
||||
// // args = fillArray(2, args)
|
||||
// // if args[0] == "" {
|
||||
// // sg.Error = errors.New("need a date")
|
||||
// // break
|
||||
// // }
|
||||
// // points := api.CreatePoints(args)
|
||||
// // sg.Error = sg.GetPointData(args[0], points)
|
||||
// // break
|
||||
// // }
|
||||
//
|
||||
// sg.Error = errors.New("unknown high-level command")
|
||||
// }
|
||||
// return sg.Error
|
||||
// }
|
||||
//
|
||||
// func (sg *SunGrow) ListHighLevel() {
|
||||
// fmt.Println("stats - Get current inverter stats, (last 5 minutes).")
|
||||
// fmt.Println("\tdata get stats")
|
||||
// fmt.Println("")
|
||||
//
|
||||
// fmt.Println("template [date] [template_id] - Get data from template.")
|
||||
// fmt.Println("\tdata get template - Get data using default template 8042 for today.")
|
||||
// fmt.Println("\tdata get template 2022 8040 - Get year data for template 8040 for the year 2022.")
|
||||
// fmt.Println("\tdata get template 202202 8040 - Get month data for template 8040 for the month 202202.")
|
||||
// fmt.Println("\tdata get template 20220202 8040 - Get day data for template 8040 for the day 20220202.")
|
||||
// fmt.Println("\tdata get template 2022 - Get year data for default template 8042 for the year 2022.")
|
||||
// fmt.Println("")
|
||||
//
|
||||
// fmt.Println("points <date> <device_id.point_id> ... - Get data from points list.")
|
||||
// fmt.Println("")
|
||||
// }
|
||||
|
||||
func (sg *SunGrow) AllCritical() error {
|
||||
var ep api.EndPoint
|
||||
for range Only.Once {
|
||||
ep = sg.GetByJson("AppService.powerDevicePointList", "")
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsList", "")
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
_getPsList := getPsList.AssertResultData(ep)
|
||||
psId := _getPsList.GetPsId()
|
||||
|
||||
ep = sg.GetByJson("AppService.queryDeviceList", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.queryDeviceListForApp", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("WebAppService.showPSView", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
// ep = sg.GetByJson("AppService.findPsType", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
// if ep.IsError() {
|
||||
// break
|
||||
// }
|
||||
|
||||
ep = sg.GetByJson("AppService.getPowerStatistics", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsDetail", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsDetailWithPsType", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsHealthState", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsListStaticData", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsWeatherList", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
// ep = sg.GetByJson("AppService.queryAllPsIdAndName", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
// if ep.IsError() {
|
||||
// break
|
||||
// }
|
||||
|
||||
// ep = sg.GetByJson("AppService.queryDeviceListByUserId", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
// if ep.IsError() {
|
||||
// break
|
||||
// }
|
||||
|
||||
ep = sg.GetByJson("AppService.queryDeviceListForApp", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sg.Error = ep.GetError()
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetCurrentStats() error {
|
||||
var ep api.EndPoint
|
||||
for range Only.Once {
|
||||
ep = sg.GetByStruct("AppService.getPsList", nil, DefaultCacheTimeout)
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
_getPsList := getPsList.Assert(ep)
|
||||
psId := _getPsList.GetPsId()
|
||||
table := _getPsList.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(_getPsList, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// ep = sg.GetByJson("AppService.queryDeviceList", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
ep = sg.GetByStruct(
|
||||
"AppService.queryDeviceList",
|
||||
queryDeviceList.RequestData{PsId: strconv.FormatInt(psId, 10)},
|
||||
DefaultCacheTimeout,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep2 := queryDeviceList.Assert(ep)
|
||||
table = ep2.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep2, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetPointData(date string, pointNames api.TemplatePoints) error {
|
||||
for range Only.Once {
|
||||
if len(pointNames) == 0 {
|
||||
@ -307,7 +112,12 @@ func (sg *SunGrow) GetPointData(date string, pointNames api.TemplatePoints) erro
|
||||
date = api.NewDateTime("").String()
|
||||
}
|
||||
when := api.NewDateTime(date)
|
||||
psId := sg.GetPsId()
|
||||
|
||||
var psId int64
|
||||
psId, sg.Error = sg.GetPsId()
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.queryMutiPointDataList",
|
||||
@ -341,62 +151,6 @@ func (sg *SunGrow) GetPointData(date string, pointNames api.TemplatePoints) erro
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetPointNames() error {
|
||||
for range Only.Once {
|
||||
for _, dt := range getPowerDevicePointNames.DeviceTypes {
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.getPowerDevicePointNames",
|
||||
getPowerDevicePointNames.RequestData{DeviceType: dt},
|
||||
DefaultCacheTimeout,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep2 := getPowerDevicePointNames.Assert(ep)
|
||||
table := ep2.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep2, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetTemplates() error {
|
||||
for range Only.Once {
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.getTemplateList",
|
||||
getTemplateList.RequestData{},
|
||||
DefaultCacheTimeout,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep2 := getTemplateList.Assert(ep)
|
||||
table := ep2.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep2, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) Output(endpoint api.EndPoint, table output.Table, graphFilter string) error {
|
||||
for range Only.Once {
|
||||
switch {
|
||||
@ -431,7 +185,7 @@ func (sg *SunGrow) Output(endpoint api.EndPoint, table output.Table, graphFilter
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetPsId() int64 {
|
||||
func (sg *SunGrow) GetPsId() (int64, error) {
|
||||
var ret int64
|
||||
|
||||
for range Only.Once {
|
||||
@ -446,7 +200,7 @@ func (sg *SunGrow) GetPsId() int64 {
|
||||
ret = _getPsList.GetPsId()
|
||||
}
|
||||
|
||||
return ret
|
||||
return ret, sg.Error
|
||||
}
|
||||
|
||||
func fillArray(count int, args []string) []string {
|
||||
|
366
iSolarCloud/highlevel.go
Normal file
366
iSolarCloud/highlevel.go
Normal file
@ -0,0 +1,366 @@
|
||||
package iSolarCloud
|
||||
|
||||
import (
|
||||
"GoSungrow/Only"
|
||||
"GoSungrow/iSolarCloud/AppService/getPowerDevicePointNames"
|
||||
"GoSungrow/iSolarCloud/AppService/getPsList"
|
||||
"GoSungrow/iSolarCloud/AppService/getTemplateList"
|
||||
"GoSungrow/iSolarCloud/AppService/queryDeviceList"
|
||||
"GoSungrow/iSolarCloud/AppService/queryMutiPointDataList"
|
||||
"GoSungrow/iSolarCloud/WebAppService/queryUserCurveTemplateData"
|
||||
"GoSungrow/iSolarCloud/api"
|
||||
"GoSungrow/iSolarCloud/api/output"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
func (sg *SunGrow) GetPointNamesFromTemplate(template string) api.TemplatePoints {
|
||||
var ret api.TemplatePoints
|
||||
|
||||
for range Only.Once {
|
||||
if template == "" {
|
||||
sg.Error = errors.New("no template defined")
|
||||
break
|
||||
}
|
||||
|
||||
ep := sg.GetByStruct(
|
||||
"WebAppService.queryUserCurveTemplateData",
|
||||
queryUserCurveTemplateData.RequestData{TemplateID: template},
|
||||
time.Hour,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
data := queryUserCurveTemplateData.AssertResultData(ep)
|
||||
for dn, dr := range data.PointsData.Devices {
|
||||
for _, pr := range dr.Points {
|
||||
ret = append(ret, api.TemplatePoint {
|
||||
PsKey: dn,
|
||||
PointId: "p" + pr.PointID,
|
||||
Description: pr.PointName,
|
||||
Unit: pr.Unit,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetTemplateData(template string, date string, filter string) error {
|
||||
for range Only.Once {
|
||||
if template == "" {
|
||||
template = "8042"
|
||||
}
|
||||
|
||||
if date == "" {
|
||||
date = api.NewDateTime("").String()
|
||||
}
|
||||
when := api.NewDateTime(date)
|
||||
|
||||
var psId int64
|
||||
psId, sg.Error = sg.GetPsId()
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
pointNames := sg.GetPointNamesFromTemplate(template)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.queryMutiPointDataList",
|
||||
queryMutiPointDataList.RequestData {
|
||||
PsID: psId,
|
||||
PsKey: pointNames.PrintKeys(),
|
||||
Points: pointNames.PrintPoints(),
|
||||
MinuteInterval: "5",
|
||||
StartTimeStamp: when.GetDayStartTimestamp(),
|
||||
EndTimeStamp: when.GetDayEndTimestamp(),
|
||||
},
|
||||
DefaultCacheTimeout,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
// data := queryMutiPointDataList.AssertResultData(ep)
|
||||
data := queryMutiPointDataList.Assert(ep)
|
||||
table := data.GetDataTable(pointNames)
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
fn := data.SetFilenamePrefix("%s-%s", when.String(), template)
|
||||
sg.Error = table.SetFilePrefix(fn)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep, table, filter)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetTemplatePoints(template string) error {
|
||||
for range Only.Once {
|
||||
if template == "" {
|
||||
template = "8042"
|
||||
}
|
||||
|
||||
table := output.NewTable()
|
||||
sg.Error = table.SetHeader(
|
||||
"Point Id",
|
||||
"Description",
|
||||
"Unit",
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ss := sg.GetPointNamesFromTemplate(template)
|
||||
for _, s := range ss {
|
||||
sg.Error = table.AddRow(
|
||||
s.PointId,
|
||||
s.Description,
|
||||
s.Unit,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
table.Print()
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) AllCritical() error {
|
||||
var ep api.EndPoint
|
||||
for range Only.Once {
|
||||
ep = sg.GetByJson("AppService.powerDevicePointList", "")
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsList", "")
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
_getPsList := getPsList.AssertResultData(ep)
|
||||
psId := _getPsList.GetPsId()
|
||||
|
||||
ep = sg.GetByJson("AppService.queryDeviceList", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.queryDeviceListForApp", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("WebAppService.showPSView", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
// ep = sg.GetByJson("AppService.findPsType", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
// if ep.IsError() {
|
||||
// break
|
||||
// }
|
||||
|
||||
ep = sg.GetByJson("AppService.getPowerStatistics", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsDetail", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsDetailWithPsType", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsHealthState", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsListStaticData", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
ep = sg.GetByJson("AppService.getPsWeatherList", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
// ep = sg.GetByJson("AppService.queryAllPsIdAndName", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
// if ep.IsError() {
|
||||
// break
|
||||
// }
|
||||
|
||||
// ep = sg.GetByJson("AppService.queryDeviceListByUserId", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
// if ep.IsError() {
|
||||
// break
|
||||
// }
|
||||
|
||||
ep = sg.GetByJson("AppService.queryDeviceListForApp", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sg.Error = ep.GetError()
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) PrintCurrentStats() error {
|
||||
var ep api.EndPoint
|
||||
for range Only.Once {
|
||||
ep = sg.GetByStruct("AppService.getPsList", nil, DefaultCacheTimeout)
|
||||
if ep.IsError() {
|
||||
break
|
||||
}
|
||||
_getPsList := getPsList.Assert(ep)
|
||||
psId := _getPsList.GetPsId()
|
||||
table := _getPsList.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(_getPsList, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// ep = sg.GetByJson("AppService.queryDeviceList", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
ep = sg.GetByStruct(
|
||||
"AppService.queryDeviceList",
|
||||
queryDeviceList.RequestData{PsId: strconv.FormatInt(psId, 10)},
|
||||
time.Second * 60,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep2 := queryDeviceList.Assert(ep)
|
||||
table = ep2.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep2, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) QueryDevice(psId int64) queryDeviceList.EndPoint {
|
||||
var ret queryDeviceList.EndPoint
|
||||
for range Only.Once {
|
||||
if psId == 0 {
|
||||
psId, sg.Error = sg.GetPsId()
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// ep = sg.GetByJson("AppService.queryDeviceList", fmt.Sprintf(`{"ps_id":"%d"}`, psId))
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.queryDeviceList",
|
||||
queryDeviceList.RequestData{PsId: strconv.FormatInt(psId, 10)},
|
||||
time.Second * 60,
|
||||
)
|
||||
// if sg.Error != nil {
|
||||
// break
|
||||
// }
|
||||
|
||||
ret = queryDeviceList.Assert(ep)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetPointNames() error {
|
||||
for range Only.Once {
|
||||
for _, dt := range getPowerDevicePointNames.DeviceTypes {
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.getPowerDevicePointNames",
|
||||
getPowerDevicePointNames.RequestData{DeviceType: dt},
|
||||
DefaultCacheTimeout,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep2 := getPowerDevicePointNames.Assert(ep)
|
||||
table := ep2.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep2, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetTemplates() error {
|
||||
for range Only.Once {
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.getTemplateList",
|
||||
getTemplateList.RequestData{},
|
||||
DefaultCacheTimeout,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep2 := getTemplateList.Assert(ep)
|
||||
table := ep2.GetDataTable()
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep2, table, "")
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package iSolarCloud
|
||||
|
||||
// const (
|
||||
// TypeNone = iota
|
||||
// TypeJson = iota
|
||||
// TypeFile = iota
|
||||
// TypeRaw = iota
|
||||
// TypeHuman = iota
|
||||
// TypeGraph = iota
|
||||
//
|
||||
// StringTypeNone = ""
|
||||
// StringTypeJson = "json"
|
||||
// StringTypeFile = "file"
|
||||
// StringTypeRaw = "raw"
|
||||
// StringTypeHuman = "human"
|
||||
// StringTypeGraph = "graph"
|
||||
// )
|
||||
//
|
||||
// type OutputType int
|
||||
//
|
||||
//
|
||||
// func (out *OutputType) SetNone() {
|
||||
// *out = TypeNone
|
||||
// }
|
||||
// func (out *OutputType) SetJson() {
|
||||
// *out = TypeJson
|
||||
// }
|
||||
// func (out *OutputType) SetFile() {
|
||||
// *out = TypeFile
|
||||
// }
|
||||
// func (out *OutputType) SetRaw() {
|
||||
// *out = TypeRaw
|
||||
// }
|
||||
// func (out *OutputType) SetHuman() {
|
||||
// *out = TypeHuman
|
||||
// }
|
||||
// func (out *OutputType) SetGraph() {
|
||||
// *out = TypeGraph
|
||||
// }
|
||||
//
|
||||
// func (out *OutputType) IsNone() bool {
|
||||
// if *out == TypeNone {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsJson() bool {
|
||||
// if *out == TypeJson {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsFile() bool {
|
||||
// if *out == TypeFile {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsRaw() bool {
|
||||
// if *out == TypeRaw {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsHuman() bool {
|
||||
// if *out == TypeHuman {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsGraph() bool {
|
||||
// if *out == TypeGraph {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// func (out *OutputType) IsStrNone(t string) bool {
|
||||
// if t == StringTypeNone {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsStrJson(t string) bool {
|
||||
// if t == StringTypeJson {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsStrFile(t string) bool {
|
||||
// if t == StringTypeFile {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsStrRaw(t string) bool {
|
||||
// if t == StringTypeRaw {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsStrHuman(t string) bool {
|
||||
// if t == StringTypeHuman {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// func (out *OutputType) IsStrGraph(t string) bool {
|
||||
// if t == StringTypeGraph {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
@ -1,143 +0,0 @@
|
||||
package iSolarCloud
|
||||
|
||||
import (
|
||||
"GoSungrow/Only"
|
||||
"GoSungrow/iSolarCloud/AppService/queryMutiPointDataList"
|
||||
"GoSungrow/iSolarCloud/WebAppService/queryUserCurveTemplateData"
|
||||
"GoSungrow/iSolarCloud/api"
|
||||
"GoSungrow/iSolarCloud/api/output"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
func (sg *SunGrow) GetPointNamesFromTemplate(template string) api.TemplatePoints {
|
||||
var ret api.TemplatePoints
|
||||
|
||||
for range Only.Once {
|
||||
if template == "" {
|
||||
sg.Error = errors.New("no template defined")
|
||||
break
|
||||
}
|
||||
|
||||
ep := sg.GetByStruct(
|
||||
"WebAppService.queryUserCurveTemplateData",
|
||||
queryUserCurveTemplateData.RequestData{TemplateID: template},
|
||||
time.Hour,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
data := queryUserCurveTemplateData.AssertResultData(ep)
|
||||
for dn, dr := range data.PointsData.Devices {
|
||||
for _, pr := range dr.Points {
|
||||
ret = append(ret, api.TemplatePoint {
|
||||
PsKey: dn,
|
||||
PointId: "p" + pr.PointID,
|
||||
Description: pr.PointName,
|
||||
Unit: pr.Unit,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetTemplateData(template string, date string, filter string) error {
|
||||
for range Only.Once {
|
||||
if template == "" {
|
||||
template = "8042"
|
||||
}
|
||||
|
||||
if date == "" {
|
||||
date = api.NewDateTime("").String()
|
||||
}
|
||||
when := api.NewDateTime(date)
|
||||
|
||||
psId := sg.GetPsId()
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
pointNames := sg.GetPointNamesFromTemplate(template)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ep := sg.GetByStruct(
|
||||
"AppService.queryMutiPointDataList",
|
||||
queryMutiPointDataList.RequestData {
|
||||
PsID: psId,
|
||||
PsKey: pointNames.PrintKeys(),
|
||||
Points: pointNames.PrintPoints(),
|
||||
MinuteInterval: "5",
|
||||
StartTimeStamp: when.GetDayStartTimestamp(),
|
||||
EndTimeStamp: when.GetDayEndTimestamp(),
|
||||
},
|
||||
DefaultCacheTimeout,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
// data := queryMutiPointDataList.AssertResultData(ep)
|
||||
data := queryMutiPointDataList.Assert(ep)
|
||||
table := data.GetDataTable(pointNames)
|
||||
if table.Error != nil {
|
||||
sg.Error = table.Error
|
||||
break
|
||||
}
|
||||
|
||||
fn := data.SetFilenamePrefix("%s-%s", when.String(), template)
|
||||
sg.Error = table.SetFilePrefix(fn)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
sg.Error = sg.Output(ep, table, filter)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
||||
|
||||
func (sg *SunGrow) GetTemplatePoints(template string) error {
|
||||
for range Only.Once {
|
||||
if template == "" {
|
||||
template = "8042"
|
||||
}
|
||||
|
||||
table := output.NewTable()
|
||||
sg.Error = table.SetHeader(
|
||||
"Point Id",
|
||||
"Description",
|
||||
"Unit",
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ss := sg.GetPointNamesFromTemplate(template)
|
||||
for _, s := range ss {
|
||||
sg.Error = table.AddRow(
|
||||
s.PointId,
|
||||
s.Description,
|
||||
s.Unit,
|
||||
)
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if sg.Error != nil {
|
||||
break
|
||||
}
|
||||
|
||||
table.Print()
|
||||
}
|
||||
|
||||
return sg.Error
|
||||
}
|
53
mmMqtt/config.go
Normal file
53
mmMqtt/config.go
Normal file
@ -0,0 +1,53 @@
|
||||
package mmMqtt
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
|
||||
// {
|
||||
// "device": {
|
||||
// "identifiers": [
|
||||
// "sungrow"
|
||||
// ],
|
||||
// "manufacturer": "MickMake",
|
||||
// "model": "GoLang",
|
||||
// "name": "sungrow",
|
||||
// "sw_version": "sungrow https://github.com/MickMake/GoSungrow"
|
||||
// },
|
||||
// "name": "sungrow",
|
||||
// "stat_t": "~/state",
|
||||
// "unique_id": "sungrow",
|
||||
// "~": "homeassistant/binary_sensor/SunGrow"
|
||||
// }
|
||||
|
||||
type Config struct {
|
||||
Entry string `json:"~,omitempty" required:"false"`
|
||||
Name string `json:"name,omitempty" required:"false"`
|
||||
UniqueId string `json:"unique_id,omitempty" required:"false"`
|
||||
StateTopic string `json:"state_topic,omitempty" required:"true"`
|
||||
DeviceConfig DeviceConfig `json:"device,omitempty" required:"false"`
|
||||
}
|
||||
type DeviceConfig struct {
|
||||
Identifiers []string `json:"identifiers,omitempty" required:"false"`
|
||||
SwVersion string `json:"sw_version,omitempty" required:"false"`
|
||||
Name string `json:"name,omitempty" required:"false"`
|
||||
Manufacturer string `json:"manufacturer,omitempty" required:"false"`
|
||||
Model string `json:"model,omitempty" required:"false"`
|
||||
}
|
||||
|
||||
func (c *Config) Json() string {
|
||||
j, _ := json.Marshal(*c)
|
||||
return string(j)
|
||||
}
|
||||
|
||||
|
||||
type Device struct {
|
||||
ConfigurationUrl string `json:"configuration_url,omitempty" required:"false"`
|
||||
Connections [][]string `json:"connections,omitempty" required:"false"`
|
||||
Identifiers []string `json:"identifiers,omitempty" required:"false"`
|
||||
Manufacturer string `json:"manufacturer,omitempty" required:"false"`
|
||||
Model string `json:"model,omitempty" required:"false"`
|
||||
Name string `json:"name,omitempty" required:"false"`
|
||||
SuggestedArea string `json:"suggested_area,omitempty" required:"false"`
|
||||
SwVersion string `json:"sw_version,omitempty" required:"false"`
|
||||
ViaDevice string `json:"via_device,omitempty" required:"false"`
|
||||
}
|
692
mmMqtt/funcs.go
Normal file
692
mmMqtt/funcs.go
Normal file
@ -0,0 +1,692 @@
|
||||
package mmMqtt
|
||||
|
||||
|
||||
// const DiscoveryPrefix = "homeassistant"
|
||||
//
|
||||
// var (
|
||||
// retain bool = true
|
||||
// qos byte = 0
|
||||
// )
|
||||
//
|
||||
// func getDevice() (d Device) {
|
||||
//
|
||||
// // id, err := machineid.ProtectedID(NodeID)
|
||||
// // if err != nil {
|
||||
// // log.Fatal(err)
|
||||
// // }
|
||||
//
|
||||
// d.Identifiers = []string{"id"}
|
||||
// d.Manufacturer = "MickMake"
|
||||
// d.Model = "NodeID"
|
||||
// d.Name = "InstanceName"
|
||||
// d.SwVersion = "SWVersion"
|
||||
//
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// ///////////////////
|
||||
//
|
||||
// type store struct {
|
||||
// BinarySensor map[string]string
|
||||
// Light struct {
|
||||
// BrightnessState map[string]string
|
||||
// ColorTempState map[string]string
|
||||
// EffectState map[string]string
|
||||
// HsState map[string]string
|
||||
// RgbState map[string]string
|
||||
// State map[string]string
|
||||
// WhiteValueState map[string]string
|
||||
// XyState map[string]string
|
||||
// }
|
||||
// Sensor map[string]string
|
||||
// Switch map[string]string
|
||||
// }
|
||||
//
|
||||
// func initStore() store {
|
||||
// var s store
|
||||
// s.BinarySensor = make(map[string]string)
|
||||
// s.Light.BrightnessState = make(map[string]string)
|
||||
// s.Light.ColorTempState = make(map[string]string)
|
||||
// s.Light.EffectState = make(map[string]string)
|
||||
// s.Light.HsState = make(map[string]string)
|
||||
// s.Light.RgbState = make(map[string]string)
|
||||
// s.Light.State = make(map[string]string)
|
||||
// s.Light.WhiteValueState = make(map[string]string)
|
||||
// s.Light.XyState = make(map[string]string)
|
||||
// s.Sensor = make(map[string]string)
|
||||
// s.Switch = make(map[string]string)
|
||||
// return s
|
||||
// }
|
||||
//
|
||||
// var topicStore = make(map[string]*func(mqtt.Message, mqtt.Client))
|
||||
// var stateStore = initStore()
|
||||
//
|
||||
// ///////////////////
|
||||
//
|
||||
// // GetTopicPrefix gets the prefix for all state/command topics
|
||||
// // This is for a light
|
||||
// func (device Light) GetTopicPrefix() string {
|
||||
// return NodeID + "/light/" + device.UniqueID + "/"
|
||||
// }
|
||||
//
|
||||
// // GetTopicPrefix gets the prefix for all state/command topics
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) GetTopicPrefix() string {
|
||||
// return NodeID + "/sensor/" + device.UniqueID + "/"
|
||||
// }
|
||||
//
|
||||
// // GetTopicPrefix gets the prefix for all state/command topics
|
||||
// // This is for a switch
|
||||
// func (device Switch) GetTopicPrefix() string {
|
||||
// return NodeID + "/switch/" + device.UniqueID + "/"
|
||||
// }
|
||||
//
|
||||
// // GetTopicPrefix gets the prefix for all state/command topics
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) GetTopicPrefix() string {
|
||||
// return NodeID + "/binary_sensor/" + device.UniqueID + "/"
|
||||
// }
|
||||
//
|
||||
// // GetDiscoveryTopic gets the topic for a device's discovery topic.
|
||||
// // This is for a light
|
||||
// func (device Light) GetDiscoveryTopic() string {
|
||||
// return DiscoveryPrefix + "/light/" + NodeID + "/" + device.UniqueID + "/" + "config"
|
||||
// }
|
||||
//
|
||||
// // GetDiscoveryTopic gets the topic for a device's discovery topic.
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) GetDiscoveryTopic() string {
|
||||
// return DiscoveryPrefix + "/sensor/" + NodeID + "/" + device.UniqueID + "/" + "config"
|
||||
// }
|
||||
//
|
||||
// // GetDiscoveryTopic gets the topic for a device's discovery topic.
|
||||
// // This is for a switch
|
||||
// func (device Switch) GetDiscoveryTopic() string {
|
||||
// return DiscoveryPrefix + "/switch/" + NodeID + "/" + device.UniqueID + "/" + "config"
|
||||
// }
|
||||
//
|
||||
// // GetDiscoveryTopic gets the topic for a device's discovery topic.
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) GetDiscoveryTopic() string {
|
||||
// return DiscoveryPrefix + "/binary_sensor/" + NodeID + "/" + device.UniqueID + "/" + "config"
|
||||
// }
|
||||
//
|
||||
// // GetCommandTopic gets the command topic for a device
|
||||
// // This is for a light
|
||||
// func (device Light) GetCommandTopic() string {
|
||||
// return device.GetTopicPrefix() + "command"
|
||||
// }
|
||||
//
|
||||
// // GetCommandTopic gets the command topic for a device
|
||||
// // This is for a switch
|
||||
// func (device Switch) GetCommandTopic() string {
|
||||
// return device.GetTopicPrefix() + "command"
|
||||
// }
|
||||
//
|
||||
// // GetStateTopic gets the state topic for a device
|
||||
// // This is for a light
|
||||
// func (device Light) GetStateTopic() string {
|
||||
// return device.GetTopicPrefix() + "state"
|
||||
// }
|
||||
//
|
||||
// // GetStateTopic gets the state topic for a device
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) GetStateTopic() string {
|
||||
// return device.GetTopicPrefix() + "state"
|
||||
// }
|
||||
//
|
||||
// // GetStateTopic gets the state topic for a device
|
||||
// // This is for a switch
|
||||
// func (device Switch) GetStateTopic() string {
|
||||
// return device.GetTopicPrefix() + "state"
|
||||
// }
|
||||
//
|
||||
// // GetStateTopic gets the state topic for a device
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) GetStateTopic() string {
|
||||
// return device.GetTopicPrefix() + "state"
|
||||
// }
|
||||
//
|
||||
// // GetAvailabilityTopic gets the availability topic for a device
|
||||
// // This is for a light
|
||||
// func (device Light) GetAvailabilityTopic() string {
|
||||
// return device.GetTopicPrefix() + "availability"
|
||||
// }
|
||||
//
|
||||
// // GetAvailabilityTopic gets the availability topic for a device
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) GetAvailabilityTopic() string {
|
||||
// return device.GetTopicPrefix() + "availability"
|
||||
// }
|
||||
//
|
||||
// // GetAvailabilityTopic gets the availability topic for a device
|
||||
// // This is for a switch
|
||||
// func (device Switch) GetAvailabilityTopic() string {
|
||||
// return device.GetTopicPrefix() + "availability"
|
||||
// }
|
||||
//
|
||||
// // GetAvailabilityTopic gets the availability topic for a device
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) GetAvailabilityTopic() string {
|
||||
// return device.GetTopicPrefix() + "availability"
|
||||
// }
|
||||
//
|
||||
// // Initialize sets topics as needed on a Light
|
||||
// func (device *Light) Initialize() {
|
||||
// device.Retain = false
|
||||
// device.Device = getDevice()
|
||||
//
|
||||
// device.AvailabilityTopic = device.GetAvailabilityTopic()
|
||||
//
|
||||
// // Brightness
|
||||
// if device.BrightnessCommandFunc != nil {
|
||||
// device.BrightnessCommandTopic = device.GetTopicPrefix() + "brightness/set"
|
||||
// topicStore[device.BrightnessCommandTopic] = &device.BrightnessCommandFunc
|
||||
// }
|
||||
// if device.BrightnessStateFunc != nil {
|
||||
// device.BrightnessStateTopic = device.GetTopicPrefix() + "brightness/get"
|
||||
// }
|
||||
//
|
||||
// // ColorTemp
|
||||
// if device.ColorTempCommandFunc != nil {
|
||||
// device.ColorTempCommandTopic = device.GetTopicPrefix() + "color-temp/set"
|
||||
// topicStore[device.ColorTempCommandTopic] = &device.ColorTempCommandFunc
|
||||
// }
|
||||
// if device.ColorTempStateFunc != nil {
|
||||
// device.ColorTempStateTopic = device.GetTopicPrefix() + "color-temp/get"
|
||||
// }
|
||||
//
|
||||
// // Command/State
|
||||
// if device.CommandFunc != nil {
|
||||
// device.CommandTopic = device.GetCommandTopic()
|
||||
// topicStore[device.CommandTopic] = &device.CommandFunc
|
||||
// }
|
||||
// if device.StateFunc != nil {
|
||||
// device.StateTopic = device.GetStateTopic()
|
||||
// }
|
||||
//
|
||||
// // Effect
|
||||
// if device.EffectCommandFunc != nil {
|
||||
// device.EffectCommandTopic = device.GetTopicPrefix() + "effect/set"
|
||||
// topicStore[device.EffectCommandTopic] = &device.EffectCommandFunc
|
||||
// }
|
||||
// if device.EffectStateFunc != nil {
|
||||
// device.EffectStateTopic = device.GetTopicPrefix() + "effect/get"
|
||||
// }
|
||||
//
|
||||
// // Hs
|
||||
// if device.HsCommandFunc != nil {
|
||||
// device.HsCommandTopic = device.GetTopicPrefix() + "hs/set"
|
||||
// topicStore[device.HsCommandTopic] = &device.HsCommandFunc
|
||||
// }
|
||||
// if device.HsStateFunc != nil {
|
||||
// device.HsStateTopic = device.GetTopicPrefix() + "hs/get"
|
||||
// }
|
||||
//
|
||||
// // Rgb
|
||||
// if device.RgbCommandFunc != nil {
|
||||
// device.RgbCommandTopic = device.GetTopicPrefix() + "rgb/set"
|
||||
// topicStore[device.RgbCommandTopic] = &device.RgbCommandFunc
|
||||
// }
|
||||
// if device.RgbStateFunc != nil {
|
||||
// device.RgbStateTopic = device.GetTopicPrefix() + "rgb/get"
|
||||
// }
|
||||
//
|
||||
// // WhiteValue
|
||||
// if device.WhiteValueCommandFunc != nil {
|
||||
// device.WhiteValueCommandTopic = device.GetTopicPrefix() + "white-value/set"
|
||||
// topicStore[device.WhiteValueCommandTopic] = &device.WhiteValueCommandFunc
|
||||
// }
|
||||
// if device.WhiteValueStateFunc != nil {
|
||||
// device.WhiteValueStateTopic = device.GetTopicPrefix() + "white-value/get"
|
||||
// }
|
||||
//
|
||||
// // Xy
|
||||
// if device.XyCommandFunc != nil {
|
||||
// device.XyCommandTopic = device.GetTopicPrefix() + "xy/set"
|
||||
// topicStore[device.XyCommandTopic] = &device.XyCommandFunc
|
||||
// }
|
||||
// if device.XyStateFunc != nil {
|
||||
// device.XyStateTopic = device.GetTopicPrefix() + "xy/get"
|
||||
// }
|
||||
//
|
||||
// device.messageHandler = func(client mqtt.Client, msg mqtt.Message) {
|
||||
//
|
||||
// topicFound := false
|
||||
//
|
||||
// for topic, f := range topicStore {
|
||||
// if msg.Topic() == topic {
|
||||
// topicFound = true
|
||||
// (*f)(msg, client)
|
||||
// device.UpdateState(client)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if !topicFound {
|
||||
// log.Println("Unknown Message on topic " + msg.Topic())
|
||||
// log.Println(msg.Payload())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Initialize sets topics as needed on a Switch
|
||||
// func (device *Switch) Initialize() {
|
||||
// device.CommandTopic = device.GetCommandTopic()
|
||||
// if device.StateFunc != nil {
|
||||
// device.StateTopic = device.GetStateTopic()
|
||||
// }
|
||||
// device.AvailabilityTopic = device.GetAvailabilityTopic()
|
||||
// device.Device = getDevice()
|
||||
// device.Retain = false
|
||||
//
|
||||
// topicStore[device.CommandTopic] = &device.CommandFunc
|
||||
//
|
||||
// device.messageHandler = func(client mqtt.Client, msg mqtt.Message) {
|
||||
//
|
||||
// topicFound := false
|
||||
//
|
||||
// for topic, f := range topicStore {
|
||||
// if msg.Topic() == topic {
|
||||
// topicFound = true
|
||||
// (*f)(msg, client)
|
||||
// device.UpdateState(client)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if !topicFound {
|
||||
// log.Println("Unknown Message on topic " + msg.Topic())
|
||||
// log.Println(msg.Payload())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // Initialize sets topics as needed on a Sensor
|
||||
// func (device *Sensor) Initialize() {
|
||||
// device.StateTopic = device.GetStateTopic()
|
||||
// device.AvailabilityTopic = device.GetAvailabilityTopic()
|
||||
// device.Device = getDevice()
|
||||
// }
|
||||
//
|
||||
// // Initialize sets topics as needed on a Binary Sensor
|
||||
// func (device *BinarySensor) Initialize() {
|
||||
// device.StateTopic = device.GetStateTopic()
|
||||
// device.AvailabilityTopic = device.GetAvailabilityTopic()
|
||||
// device.Device = getDevice()
|
||||
// }
|
||||
//
|
||||
// // UpdateState publishes any new state for a device
|
||||
// // This is for a light
|
||||
// func (device Light) UpdateState(client mqtt.Client) {
|
||||
// if device.BrightnessStateTopic != "" {
|
||||
// state := device.BrightnessStateFunc()
|
||||
// if state != stateStore.Light.BrightnessState[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.BrightnessStateTopic, qos, retain, state)
|
||||
// stateStore.Light.BrightnessState[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// if device.ColorTempStateTopic != "" {
|
||||
// state := device.ColorTempStateFunc()
|
||||
// if state != stateStore.Light.ColorTempState[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.ColorTempStateTopic, qos, retain, state)
|
||||
// stateStore.Light.ColorTempState[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// if device.EffectStateTopic != "" {
|
||||
// state := device.EffectStateFunc()
|
||||
// if state != stateStore.Light.EffectState[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.EffectStateTopic, qos, retain, state)
|
||||
// stateStore.Light.EffectState[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// if device.HsStateTopic != "" {
|
||||
// state := device.HsStateFunc()
|
||||
// if state != stateStore.Light.HsState[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.HsStateTopic, qos, retain, state)
|
||||
// stateStore.Light.HsState[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// if device.RgbStateTopic != "" {
|
||||
// state := device.RgbStateFunc()
|
||||
// if state != stateStore.Light.RgbState[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.RgbStateTopic, qos, retain, state)
|
||||
// stateStore.Light.RgbState[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// if device.StateTopic != "" {
|
||||
// state := device.StateFunc()
|
||||
// if state != stateStore.Light.State[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.StateTopic, qos, retain, state)
|
||||
// stateStore.Light.State[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// if device.WhiteValueStateTopic != "" {
|
||||
// state := device.WhiteValueStateFunc()
|
||||
// if state != stateStore.Light.WhiteValueState[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.WhiteValueStateTopic, qos, retain, state)
|
||||
// stateStore.Light.WhiteValueState[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// if device.XyStateTopic != "" {
|
||||
// state := device.XyStateFunc()
|
||||
// if state != stateStore.Light.XyState[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.XyStateTopic, qos, retain, state)
|
||||
// stateStore.Light.XyState[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // UpdateState publishes any new state for a device
|
||||
// // This is for a switch
|
||||
// func (device Switch) UpdateState(client mqtt.Client) {
|
||||
// if device.StateFunc != nil {
|
||||
// state := device.StateFunc()
|
||||
// if state != stateStore.Switch[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.StateTopic, qos, retain, state)
|
||||
// stateStore.Switch[device.UniqueID] = state
|
||||
// token.Wait()
|
||||
// }
|
||||
// } else {
|
||||
// log.Println("No statefunc for " + device.UniqueID + strconv.FormatFloat(float64(device.UpdateInterval), 'g', 1, 64))
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // UpdateState publishes any new state for a device
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) UpdateState(client mqtt.Client) {
|
||||
// if device.StateFunc != nil {
|
||||
// state := device.StateFunc()
|
||||
// if state != stateStore.Sensor[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.StateTopic, qos, retain, state)
|
||||
// token.Wait()
|
||||
// stateStore.Sensor[device.UniqueID] = state
|
||||
// }
|
||||
// } else {
|
||||
// log.Fatalln("No statefunc, this makes no sensor for a sensor!")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // UpdateState publishes any new state for a device
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) UpdateState(client mqtt.Client) {
|
||||
// if device.StateFunc != nil {
|
||||
// state := device.StateFunc()
|
||||
// if state != stateStore.BinarySensor[device.UniqueID] || device.ForceUpdateMQTT {
|
||||
// token := client.Publish(device.StateTopic, qos, retain, state)
|
||||
// token.Wait()
|
||||
// stateStore.BinarySensor[device.UniqueID] = state
|
||||
// }
|
||||
// } else {
|
||||
// log.Fatalln("No statefunc, this makes no sensor for a binary sensor!")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Subscribe announces and starts listening to MQTT topics appropriate for a device
|
||||
// // This is for a light
|
||||
// func (device Light) Subscribe(client mqtt.Client) {
|
||||
//
|
||||
// message, err := json.Marshal(device)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// if device.BrightnessCommandTopic != "" {
|
||||
// if token := client.Subscribe(device.BrightnessCommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// if device.ColorTempCommandTopic != "" {
|
||||
// if token := client.Subscribe(device.ColorTempCommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// if device.EffectCommandTopic != "" {
|
||||
// if token := client.Subscribe(device.EffectCommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// if device.HsCommandTopic != "" {
|
||||
// if token := client.Subscribe(device.HsCommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// if device.RgbCommandTopic != "" {
|
||||
// if token := client.Subscribe(device.RgbCommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// if device.CommandTopic != "" {
|
||||
// if token := client.Subscribe(device.CommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// if device.WhiteValueCommandTopic != "" {
|
||||
// if token := client.Subscribe(device.WhiteValueCommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// if device.XyCommandTopic != "" {
|
||||
// if token := client.Subscribe(device.XyCommandTopic, 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// token := client.Publish(device.GetDiscoveryTopic(), 0, true, message)
|
||||
// token.Wait()
|
||||
//
|
||||
// // HA needs time to process
|
||||
// time.Sleep(500 * time.Millisecond)
|
||||
//
|
||||
// device.AnnounceAvailable(client)
|
||||
//
|
||||
// device.UpdateState(client)
|
||||
//
|
||||
// if token := client.Subscribe(device.GetCommandTopic(), 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // Subscribe announces and starts listening to MQTT topics appropriate for a device
|
||||
// // This is for a switch
|
||||
// func (device Switch) Subscribe(client mqtt.Client) {
|
||||
//
|
||||
// message, err := json.Marshal(device)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// token := client.Publish(device.GetDiscoveryTopic(), 0, true, message)
|
||||
// token.Wait()
|
||||
//
|
||||
// // HA needs time to process
|
||||
// time.Sleep(500 * time.Millisecond)
|
||||
//
|
||||
// device.AnnounceAvailable(client)
|
||||
//
|
||||
// if device.StateFunc != nil {
|
||||
// device.UpdateState(client)
|
||||
// }
|
||||
//
|
||||
// if token := client.Subscribe(device.GetCommandTopic(), 0, device.messageHandler); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // Subscribe announces and MQTT topics appropriate for a device
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) Subscribe(client mqtt.Client) {
|
||||
//
|
||||
// message, err := json.Marshal(device)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// token := client.Publish(device.GetDiscoveryTopic(), 0, true, message)
|
||||
// token.Wait()
|
||||
//
|
||||
// // HA needs time to process
|
||||
// time.Sleep(500 * time.Millisecond)
|
||||
//
|
||||
// device.UpdateState(client)
|
||||
// device.AnnounceAvailable(client)
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // Subscribe announces and MQTT topics appropriate for a device
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) Subscribe(client mqtt.Client) {
|
||||
//
|
||||
// message, err := json.Marshal(device)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// token := client.Publish(device.GetDiscoveryTopic(), 0, true, message)
|
||||
// token.Wait()
|
||||
//
|
||||
// // HA needs time to process
|
||||
// time.Sleep(500 * time.Millisecond)
|
||||
//
|
||||
// device.UpdateState(client)
|
||||
// device.AnnounceAvailable(client)
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UnSubscribe from MQTT topics appropriate for a device, and publishes unavailability
|
||||
// // This is for a light
|
||||
// func (device Light) UnSubscribe(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "offline")
|
||||
// token.Wait()
|
||||
//
|
||||
// if device.BrightnessCommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.BrightnessCommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if device.ColorTempCommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.ColorTempCommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if device.EffectCommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.EffectCommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if device.HsCommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.HsCommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if device.RgbCommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.RgbCommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if device.CommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.CommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if device.WhiteValueCommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.WhiteValueCommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if device.XyCommandTopic != "" {
|
||||
// if token := client.Unsubscribe(device.XyCommandTopic); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UnSubscribe from MQTT topics appropriate for a device, and publishes unavailability
|
||||
// // This is for a switch
|
||||
// func (device Switch) UnSubscribe(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "offline")
|
||||
// token.Wait()
|
||||
//
|
||||
// if token := client.Unsubscribe(device.GetCommandTopic()); token.Wait() && token.Error() != nil {
|
||||
// log.Println(token.Error())
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // UnSubscribe publishes unavailability for a device
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) UnSubscribe(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "offline")
|
||||
// token.Wait()
|
||||
// }
|
||||
//
|
||||
// // UnSubscribe publishes unavailability for a device
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) UnSubscribe(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "offline")
|
||||
// token.Wait()
|
||||
// }
|
||||
//
|
||||
// // AnnounceAvailable publishes availability for a device
|
||||
// // This is for a light
|
||||
// func (device Light) AnnounceAvailable(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "online")
|
||||
// token.Wait()
|
||||
// }
|
||||
//
|
||||
// // AnnounceAvailable publishes availability for a device
|
||||
// // This is for a switch
|
||||
// func (device Switch) AnnounceAvailable(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "online")
|
||||
// token.Wait()
|
||||
// }
|
||||
//
|
||||
// // AnnounceAvailable publishes availability for a device
|
||||
// // This is for a sensor
|
||||
// func (device Sensor) AnnounceAvailable(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "online")
|
||||
// token.Wait()
|
||||
// }
|
||||
//
|
||||
// // AnnounceAvailable publishes availability for a device
|
||||
// // This is for a binary sensor
|
||||
// func (device BinarySensor) AnnounceAvailable(client mqtt.Client) {
|
||||
// token := client.Publish(device.GetAvailabilityTopic(), qos, retain, "online")
|
||||
// token.Wait()
|
||||
// }
|
135
mmMqtt/lights.go
Normal file
135
mmMqtt/lights.go
Normal file
@ -0,0 +1,135 @@
|
||||
package mmMqtt
|
||||
|
||||
|
||||
type Light struct {
|
||||
AvailabilityTopic string `json:"availability_topic,omitempty"`
|
||||
BrightnessCommandTopic string `json:"brightness_command_topic,omitempty"`
|
||||
BrightnessScale int `json:"brightness_scale,omitempty"`
|
||||
BrightnessStateTopic string `json:"brightness_state_topic,omitempty"`
|
||||
BrightnessValueTemplate string `json:"brightness_value_template,omitempty"`
|
||||
ColorTempCommandTemplate string `json:"color_temp_command_template,omitempty"`
|
||||
ColorTempCommandTopic string `json:"color_temp_command_topic,omitempty"`
|
||||
ColorTempStateTopic string `json:"color_temp_state_topic,omitempty"`
|
||||
ColorTempValueTemplate string `json:"color_temp_value_template,omitempty"`
|
||||
CommandTopic string `json:"command_topic"`
|
||||
Device Device `json:"device,omitempty"`
|
||||
EffectCommandTopic string `json:"effect_command_topic,omitempty"`
|
||||
EffectList []string `json:"effect_list,omitempty"`
|
||||
EffectStateTopic string `json:"effect_state_topic,omitempty"`
|
||||
EffectValueTemplate string `json:"effect_value_template,omitempty"`
|
||||
HsCommandTopic string `json:"hs_command_topic,omitempty"`
|
||||
HsStateTopic string `json:"hs_state_topic,omitempty"`
|
||||
HsValueTemplate string `json:"hs_value_template,omitempty"`
|
||||
JSONAttributesTemplate string `json:"json_attributes_template,omitempty"`
|
||||
JSONAttributesTopic string `json:"json_attributes_topic,omitempty"`
|
||||
MaxMireds int `json:"max_mireds,omitempty"`
|
||||
MinMireds int `json:"min_mireds,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
OnCommandType string `json:"on_command_type,omitempty"`
|
||||
Optimistic bool `json:"opt,omitempty"`
|
||||
PayloadAvailable string `json:"payload_available,omitempty"`
|
||||
PayloadNotAvailable string `json:"payload_not_available,omitempty"`
|
||||
PayloadOff string `json:"pl_off,omitempty"`
|
||||
PayloadOn string `json:"pl_on,omitempty"`
|
||||
QOS int `json:"qos,omitempty"`
|
||||
Retain bool `json:"ret,omitempty"`
|
||||
RgbCommandTemplate string `json:"rgb_command_template,omitempty"`
|
||||
RgbCommandTopic string `json:"rgb_command_topic,omitempty"`
|
||||
RgbStateTopic string `json:"rgb_state_topic,omitempty"`
|
||||
RgbValueTemplate string `json:"rgb_value_template,omitempty"`
|
||||
Schema string `json:"schema,omitempty"`
|
||||
StateTopic string `json:"state_topic,omitempty"`
|
||||
StateValueTemplate string `json:"state_value_template,omitempty"`
|
||||
UniqueID string `json:"unique_id,omitempty"`
|
||||
WhiteValueCommandTopic string `json:"white_value_command_topic,omitempty"`
|
||||
WhiteValueScale int `json:"white_value_scale,omitempty"`
|
||||
WhiteValueStateTopic string `json:"white_value_state_topic,omitempty"`
|
||||
WhiteValueTemplate string `json:"white_value_template,omitempty"`
|
||||
XyCommandTopic string `json:"xy_command_topic,omitempty"`
|
||||
XyStateTopic string `json:"xy_state_topic,omitempty"`
|
||||
XyValueTemplate string `json:"xy_value_template,omitempty"`
|
||||
ValueTemplate string `json:"value_template,omitempty"`
|
||||
|
||||
// BrightnessStateFunc func() string `json:"-"`
|
||||
// ColorTempStateFunc func() string `json:"-"`
|
||||
// EffectStateFunc func() string `json:"-"`
|
||||
// HsStateFunc func() string `json:"-"`
|
||||
// RgbStateFunc func() string `json:"-"`
|
||||
// StateFunc func() string `json:"-"`
|
||||
// WhiteValueStateFunc func() string `json:"-"`
|
||||
// XyStateFunc func() string `json:"-"`
|
||||
//
|
||||
// BrightnessCommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// ColorTempCommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// CommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// EffectCommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// HsCommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// RgbCommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// WhiteValueCommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// XyCommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
//
|
||||
// UpdateInterval float64 `json:"-"`
|
||||
// ForceUpdateMQTT bool `json:"-"`
|
||||
//
|
||||
// messageHandler mqtt.MessageHandler
|
||||
}
|
||||
|
||||
|
||||
// {
|
||||
// "brightness": true,
|
||||
// "cmd_t": "homeassistant/light/cbus_20/set",
|
||||
// "device": {
|
||||
// "connections": [
|
||||
// [
|
||||
// "cbus_group_address",
|
||||
// "20"
|
||||
// ]
|
||||
// ],
|
||||
// "identifiers": [
|
||||
// "cbus_light_20"
|
||||
// ],
|
||||
// "manufacturer": "Clipsal",
|
||||
// "model": "C-Bus Lighting Application",
|
||||
// "name": "C-Bus Light 020",
|
||||
// "sw_version": "cmqttd https://github.com/micolous/cbus",
|
||||
// "via_device": "cmqttd"
|
||||
// },
|
||||
// "name": "C-Bus Light 020",
|
||||
// "schema": "json",
|
||||
// "stat_t": "homeassistant/light/cbus_20/state",
|
||||
// "unique_id": "cbus_light_20"
|
||||
// }
|
||||
//
|
||||
// type LightConfig struct {
|
||||
// Name string `json:"name"`
|
||||
// UniqueId string `json:"unique_id"`
|
||||
// CmdT string `json:"cmd_t"`
|
||||
// StatT string `json:"stat_t"`
|
||||
// Schema string `json:"schema"`
|
||||
// Brightness bool `json:"brightness"`
|
||||
// LightDevice LightDevice `json:"device"`
|
||||
// }
|
||||
// type LightDevice struct {
|
||||
// Identifiers []string `json:"identifiers"`
|
||||
// Connections [][]string `json:"connections"`
|
||||
// SwVersion string `json:"sw_version"`
|
||||
// Name string `json:"name"`
|
||||
// Manufacturer string `json:"manufacturer"`
|
||||
// Model string `json:"model"`
|
||||
// ViaDevice string `json:"via_device"`
|
||||
// }
|
||||
|
||||
|
||||
// {
|
||||
// "brightness": 255,
|
||||
// "cbus_source_addr": 7,
|
||||
// "state": "ON",
|
||||
// "transition": 0
|
||||
// }
|
||||
|
||||
// type LightState struct {
|
||||
// State string `json:"state"`
|
||||
// Brightness int `json:"brightness"`
|
||||
// Transition int `json:"transition"`
|
||||
// CbusSourceAddr int `json:"cbus_source_addr"`
|
||||
// }
|
109
mmMqtt/sensors.go
Normal file
109
mmMqtt/sensors.go
Normal file
@ -0,0 +1,109 @@
|
||||
package mmMqtt
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
|
||||
// {
|
||||
// "device": {
|
||||
// "connections": [
|
||||
// [
|
||||
// "cbus_group_address",
|
||||
// "0"
|
||||
// ]
|
||||
// ],
|
||||
// "identifiers": [
|
||||
// "cbus_bin_sensor_0"
|
||||
// ],
|
||||
// "manufacturer": "Clipsal",
|
||||
// "model": "C-Bus Lighting Application",
|
||||
// "name": "C-Bus Light 000",
|
||||
// "sw_version": "cmqttd https://github.com/micolous/cbus",
|
||||
// "via_device": "cmqttd"
|
||||
// },
|
||||
// "name": "C-Bus Light 000 (as binary sensor)",
|
||||
// "stat_t": "homeassistant/binary_sensor/cbus_0/state",
|
||||
// "unique_id": "cbus_bin_sensor_0"
|
||||
// }
|
||||
|
||||
type BinarySensor struct {
|
||||
Availability *Availability `json:"availability,omitempty" required:"false"`
|
||||
AvailabilityMode string `json:"availability_mode,omitempty" required:"false"`
|
||||
AvailabilityTemplate string `json:"availability_template,omitempty" required:"false"`
|
||||
AvailabilityTopic string `json:"availability_topic,omitempty" required:"false"`
|
||||
Device Device `json:"device,omitempty" required:"false"`
|
||||
DeviceClass string `json:"device_class,omitempty" required:"false"`
|
||||
EnabledByDefault bool `json:"enabled_by_default,omitempty" required:"false"`
|
||||
Encoding string `json:"encoding,omitempty" required:"false"`
|
||||
EntityCategory string `json:"entity_category,omitempty" required:"false"`
|
||||
ExpireAfter int `json:"expire_after,omitempty" required:"false"`
|
||||
ForceUpdate bool `json:"force_update,omitempty" required:"false"`
|
||||
Icon string `json:"icon,omitempty" required:"false"`
|
||||
JsonAttributesTemplate string `json:"json_attributes_template,omitempty" required:"false"`
|
||||
JsonAttributesTopic string `json:"json_attributes_topic,omitempty" required:"false"`
|
||||
LastResetValueTemplate string `json:"last_reset_value_template,omitempty" required:"false"`
|
||||
Name string `json:"name,omitempty" required:"false"`
|
||||
ObjectId string `json:"object_id,omitempty" required:"false"`
|
||||
PayloadAvailable string `json:"payload_available,omitempty" required:"false"`
|
||||
PayloadNotAvailable string `json:"payload_not_available,omitempty" required:"false"`
|
||||
Qos int `json:"qos,omitempty" required:"false"`
|
||||
StateClass string `json:"state_class,omitempty" required:"false"`
|
||||
StateTopic string `json:"state_topic" required:"true"`
|
||||
UniqueId string `json:"unique_id,omitempty" required:"false"`
|
||||
UnitOfMeasurement string `json:"unit_of_measurement,omitempty" required:"false"`
|
||||
ValueTemplate string `json:"value_template,omitempty" required:"false"`
|
||||
|
||||
OffDelay int `json:"off_delay,omitempty" required:"false"`
|
||||
PayloadOff string `json:"pl_off,omitempty" required:"false"`
|
||||
PayloadOn string `json:"pl_on,omitempty" required:"false"`
|
||||
}
|
||||
type Availability struct {
|
||||
PayloadAvailable string `json:"payload_available,omitempty" required:"false"`
|
||||
PayloadNotAvailable string `json:"payload_not_available,omitempty" required:"false"`
|
||||
Topic string `json:"topic,omitempty" required:"true"`
|
||||
ValueTemplate string `json:"value_template,omitempty" required:"false"`
|
||||
}
|
||||
type SensorState string
|
||||
|
||||
func (c *BinarySensor) Json() string {
|
||||
j, _ := json.Marshal(*c)
|
||||
return string(j)
|
||||
}
|
||||
|
||||
|
||||
type Sensor struct {
|
||||
Availability *Availability `json:"availability,omitempty" required:"false"`
|
||||
AvailabilityMode string `json:"availability_mode,omitempty" required:"false"`
|
||||
AvailabilityTemplate string `json:"availability_template,omitempty" required:"false"`
|
||||
AvailabilityTopic string `json:"availability_topic,omitempty" required:"false"`
|
||||
Device Device `json:"device,omitempty" required:"false"`
|
||||
DeviceClass string `json:"device_class,omitempty" required:"false"`
|
||||
EnabledByDefault bool `json:"enabled_by_default,omitempty" required:"false"`
|
||||
Encoding string `json:"encoding,omitempty" required:"false"`
|
||||
EntityCategory string `json:"entity_category,omitempty" required:"false"`
|
||||
ExpireAfter int `json:"expire_after,omitempty" required:"false"`
|
||||
ForceUpdate bool `json:"force_update,omitempty" required:"false"`
|
||||
Icon string `json:"icon,omitempty" required:"false"`
|
||||
JsonAttributesTemplate string `json:"json_attributes_template,omitempty" required:"false"`
|
||||
JsonAttributesTopic string `json:"json_attributes_topic,omitempty" required:"false"`
|
||||
LastResetValueTemplate string `json:"last_reset_value_template,omitempty" required:"false"`
|
||||
Name string `json:"name,omitempty" required:"false"`
|
||||
ObjectId string `json:"object_id,omitempty" required:"false"`
|
||||
PayloadAvailable string `json:"payload_available,omitempty" required:"false"`
|
||||
PayloadNotAvailable string `json:"payload_not_available,omitempty" required:"false"`
|
||||
Qos int `json:"qos,omitempty" required:"false"`
|
||||
StateClass string `json:"state_class,omitempty" required:"false"`
|
||||
StateTopic string `json:"state_topic" required:"true"`
|
||||
UniqueId string `json:"unique_id,omitempty" required:"false"`
|
||||
UnitOfMeasurement string `json:"unit_of_measurement,omitempty" required:"false"`
|
||||
ValueTemplate string `json:"value_template,omitempty" required:"false"`
|
||||
|
||||
// StateFunc func() string `json:"-"`
|
||||
//
|
||||
// UpdateInterval float64 `json:"-"`
|
||||
// ForceUpdateMQTT bool `json:"-"`
|
||||
}
|
||||
|
||||
func (c *Sensor) Json() string {
|
||||
j, _ := json.Marshal(*c)
|
||||
return string(j)
|
||||
}
|
374
mmMqtt/struct.go
Normal file
374
mmMqtt/struct.go
Normal file
@ -0,0 +1,374 @@
|
||||
package mmMqtt
|
||||
|
||||
import (
|
||||
"GoSungrow/Only"
|
||||
"errors"
|
||||
"fmt"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
type Mqtt struct {
|
||||
ClientId string `json:"client_id"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
|
||||
url *url.URL
|
||||
client mqtt.Client
|
||||
pubClient mqtt.Client
|
||||
clientOptions *mqtt.ClientOptions
|
||||
err error
|
||||
}
|
||||
|
||||
func New(req Mqtt) *Mqtt {
|
||||
var ret Mqtt
|
||||
|
||||
for range Only.Once {
|
||||
ret.err = ret.setUrl(req)
|
||||
if ret.err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return &ret
|
||||
}
|
||||
|
||||
func (m *Mqtt) GetError() error {
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) IsError() bool {
|
||||
if m.err != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Mqtt) setUrl(req Mqtt) error {
|
||||
|
||||
for range Only.Once {
|
||||
// if req.Username == "" {
|
||||
// m.err = errors.New("username empty")
|
||||
// break
|
||||
// }
|
||||
m.Username = req.Username
|
||||
|
||||
// if req.Password == "" {
|
||||
// m.err = errors.New("password empty")
|
||||
// break
|
||||
// }
|
||||
m.Password = req.Password
|
||||
|
||||
if req.Host == "" {
|
||||
m.err = errors.New("host empty")
|
||||
break
|
||||
}
|
||||
m.Host = req.Host
|
||||
|
||||
if req.Port == "" {
|
||||
req.Port = "1883"
|
||||
}
|
||||
m.Port = req.Port
|
||||
|
||||
u := fmt.Sprintf("tcp://%s:%s@%s:%s",
|
||||
m.Username,
|
||||
m.Password,
|
||||
m.Host,
|
||||
m.Port,
|
||||
)
|
||||
m.url, m.err = url.Parse(u)
|
||||
}
|
||||
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) SetAuth(username string, password string) error {
|
||||
|
||||
for range Only.Once {
|
||||
if username == "" {
|
||||
m.err = errors.New("username empty")
|
||||
break
|
||||
}
|
||||
m.Username = username
|
||||
|
||||
if password == "" {
|
||||
m.err = errors.New("password empty")
|
||||
break
|
||||
}
|
||||
m.Password = password
|
||||
}
|
||||
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) Connect() error {
|
||||
for range Only.Once {
|
||||
m.err = m.createClientOptions()
|
||||
if m.err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
m.client = mqtt.NewClient(m.clientOptions)
|
||||
token := m.client.Connect()
|
||||
for !token.WaitTimeout(3 * time.Second) {
|
||||
}
|
||||
if m.err = token.Error(); m.err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
device := Config {
|
||||
Entry: ServiceBaseTopic,
|
||||
Name: ServiceBaseName,
|
||||
UniqueId: ServiceBaseUniqueId,
|
||||
StateTopic: "~/state",
|
||||
DeviceConfig: DeviceConfig {
|
||||
Identifiers: []string{"GoSunGrow", "SunGrow"},
|
||||
SwVersion: "GoSunGrow https://github.com/MickMake/GoSungrow",
|
||||
Name: ServiceBaseName,
|
||||
Manufacturer: "MickMake",
|
||||
Model: "SunGrow",
|
||||
},
|
||||
}
|
||||
|
||||
m.err = m.Publish(ServiceBaseTopic + "/config", 0, true, device.Json())
|
||||
if m.err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
m.err = m.Publish(ServiceBaseTopic + "/state", 0, true, "ON")
|
||||
if m.err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return m.err
|
||||
}
|
||||
|
||||
const ServiceBaseName = "GoSunGrow"
|
||||
const ServiceBaseUniqueId = ServiceBaseName + "_Service"
|
||||
const ServiceBaseTopic = "homeassistant/sensor/" + ServiceBaseName
|
||||
const SensorBaseTopic = "homeassistant/sensor/" + ServiceBaseName
|
||||
|
||||
func (m *Mqtt) createClientOptions() error {
|
||||
for range Only.Once {
|
||||
m.clientOptions = mqtt.NewClientOptions()
|
||||
m.clientOptions.AddBroker(fmt.Sprintf("tcp://%s", m.url.Host))
|
||||
m.clientOptions.SetUsername(m.url.User.Username())
|
||||
password, _ := m.url.User.Password()
|
||||
m.clientOptions.SetPassword(password)
|
||||
m.clientOptions.SetClientID(m.ClientId)
|
||||
|
||||
m.clientOptions.WillTopic = ServiceBaseTopic + "/state"
|
||||
m.clientOptions.WillPayload = []byte("OFF")
|
||||
m.clientOptions.WillQos = 0
|
||||
m.clientOptions.WillRetained = true
|
||||
m.clientOptions.WillEnabled = true
|
||||
}
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) Subscribe(topic string) error {
|
||||
for range Only.Once {
|
||||
m.client.Subscribe(topic, 0, func(client mqtt.Client, msg mqtt.Message) {
|
||||
fmt.Printf("* [%s] %s\n", msg.Topic(), string(msg.Payload()))
|
||||
})
|
||||
}
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) Publish(topic string, qos byte, retained bool, payload interface{}) error {
|
||||
for range Only.Once {
|
||||
m.client.Publish(topic, qos, retained, payload)
|
||||
}
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) SensorPublish(subtopic string, payload interface{}) error {
|
||||
for range Only.Once {
|
||||
m.client.Publish(SensorBaseTopic + "/" + subtopic, 0, true, payload)
|
||||
}
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) SensorPublishConfig(id string, name string, units string, address int) error {
|
||||
for range Only.Once {
|
||||
a := strconv.Itoa(address)
|
||||
class := ""
|
||||
switch units {
|
||||
case "MW":
|
||||
fallthrough
|
||||
case "kW":
|
||||
fallthrough
|
||||
case "W":
|
||||
class = "power"
|
||||
|
||||
case "MWh":
|
||||
fallthrough
|
||||
case "kWh":
|
||||
fallthrough
|
||||
case "Wh":
|
||||
class = "energy"
|
||||
|
||||
case "kvar":
|
||||
class = "reactive_power"
|
||||
|
||||
case "Hz":
|
||||
class = "frequency"
|
||||
|
||||
case "V":
|
||||
class = "voltage"
|
||||
|
||||
case "A":
|
||||
class = "current"
|
||||
|
||||
case "℃":
|
||||
class = "temperature"
|
||||
|
||||
case "%":
|
||||
class = "battery"
|
||||
}
|
||||
|
||||
payload := Sensor {
|
||||
Device: Device {
|
||||
Connections: [][]string{{"sungrow_address", a}},
|
||||
Identifiers: []string{id, "sungrow_address_" + a},
|
||||
Manufacturer: "MickMake",
|
||||
Model: "SunGrow inverter",
|
||||
Name: name,
|
||||
SwVersion: "GoSunGrow https://github.com/MickMake/GoSungrow",
|
||||
ViaDevice: "gosungrow",
|
||||
},
|
||||
Name: "SunGrow " + name,
|
||||
StateClass: "measurement",
|
||||
StateTopic: SensorBaseTopic + "/" + id + "/state",
|
||||
UniqueId: id,
|
||||
UnitOfMeasurement: units,
|
||||
DeviceClass: class,
|
||||
Qos: 0,
|
||||
ForceUpdate: true,
|
||||
ExpireAfter: 0,
|
||||
Encoding: "utf-8",
|
||||
EnabledByDefault: true,
|
||||
}
|
||||
|
||||
topic := SensorBaseTopic + "/" + id + "/config"
|
||||
m.client.Publish(topic, 0, true, payload.Json())
|
||||
}
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *Mqtt) SensorPublishState(sensor string, payload interface{}) error {
|
||||
for range Only.Once {
|
||||
m.client.Publish(SensorBaseTopic + "/" + sensor + "/state", 0, true, payload)
|
||||
}
|
||||
return m.err
|
||||
}
|
||||
|
||||
|
||||
// func (m *Mqtt) SetKeyFile(path string) error {
|
||||
//
|
||||
// for range Only.Once {
|
||||
// if path == "" {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// m.err = checkKeyFile(path)
|
||||
// if m.err != nil {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// m.KeyFile = path
|
||||
// }
|
||||
//
|
||||
// return m.err
|
||||
// }
|
||||
//
|
||||
// func (m *Mqtt) SetToken(t string) error {
|
||||
//
|
||||
// for range Only.Once {
|
||||
// if t == "" {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// m.Token = t
|
||||
// }
|
||||
//
|
||||
// return m.err
|
||||
// }
|
||||
//
|
||||
// func (m *Mqtt) SetRepo(repo string) error {
|
||||
//
|
||||
// for range Only.Once {
|
||||
// if repo == "" {
|
||||
// m.err = errors.New("repo empty")
|
||||
// break
|
||||
// }
|
||||
// m.RepoUrl = repo
|
||||
// }
|
||||
//
|
||||
// return m.err
|
||||
// }
|
||||
//
|
||||
// func (m *Mqtt) SetDir(dir string) error {
|
||||
//
|
||||
// for range Only.Once {
|
||||
// if dir == "" {
|
||||
// m.err = errors.New("dir empty")
|
||||
// break
|
||||
// }
|
||||
// m.RepoDir = dir
|
||||
// }
|
||||
//
|
||||
// return m.err
|
||||
// }
|
||||
//
|
||||
// func (m *Mqtt) SetDiffCmd(cmd string) error {
|
||||
//
|
||||
// for range Only.Once {
|
||||
// if cmd == "" {
|
||||
// cmd = "tkdiff"
|
||||
// }
|
||||
// m.DiffCmd = cmd
|
||||
// }
|
||||
//
|
||||
// return m.err
|
||||
// }
|
||||
//
|
||||
// func (m *Mqtt) IsOk() bool {
|
||||
// var ok bool
|
||||
//
|
||||
// for range Only.Once {
|
||||
// //if m.ApiUsername == "" {
|
||||
// // m.Error = errors.New("username empty")
|
||||
// // break
|
||||
// //}
|
||||
// //
|
||||
// //if m.ApiPassword == "" {
|
||||
// // m.Error = errors.New("password empty")
|
||||
// // break
|
||||
// //}
|
||||
//
|
||||
// if m.RepoUrl == "" {
|
||||
// m.err = errors.New("repo empty")
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// if m.RepoDir == "" {
|
||||
// m.err = errors.New("repo dir empty")
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// ok = true
|
||||
// }
|
||||
//
|
||||
// return ok
|
||||
// }
|
||||
// func (m *Mqtt) IsNotOk() bool {
|
||||
// return !m.IsOk()
|
||||
// }
|
32
mmMqtt/switch.go
Normal file
32
mmMqtt/switch.go
Normal file
@ -0,0 +1,32 @@
|
||||
package mmMqtt
|
||||
|
||||
|
||||
type Switch struct {
|
||||
AvailabilityTopic string `json:"avty_t,omitempty"`
|
||||
CommandTopic string `json:"cmd_t"`
|
||||
Device Device `json:"dev,omitempty"`
|
||||
Icon string `json:"ic,omitempty"`
|
||||
JSONAttributesTemplate string `json:"json_attr_tpl,omitempty"`
|
||||
JSONAttributesTopic string `json:"json_attr_t,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Optimistic bool `json:"opt,omitempty"`
|
||||
PayloadAvailable string `json:"pl_avail,omitempty"`
|
||||
PayloadNotAvailable string `json:"pl_not_avail,omitempty"`
|
||||
PayloadOff string `json:"pl_off,omitempty"`
|
||||
PayloadOn string `json:"pl_on,omitempty"`
|
||||
QOS int `json:"qos,omitempty"`
|
||||
Retain bool `json:"ret,omitempty"`
|
||||
StateOff string `json:"stat_off,omitempty"`
|
||||
StateOn string `json:"stat_on,omitempty"`
|
||||
StateTopic string `json:"stat_t,omitempty"`
|
||||
UniqueID string `json:"uniq_id,omitempty"`
|
||||
ValueTemplate string `json:"val_tpl,omitempty"`
|
||||
|
||||
// CommandFunc func(mqtt.Message, mqtt.Client) `json:"-"`
|
||||
// StateFunc func() string `json:"-"`
|
||||
//
|
||||
// UpdateInterval float64 `json:"-"`
|
||||
// ForceUpdateMQTT bool `json:"-"`
|
||||
//
|
||||
// messageHandler mqtt.MessageHandler
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user