v1.4.0 Implement HASSIO MQTT

This commit is contained in:
MickMake 2022-03-02 14:32:56 +11:00
parent b36a272818
commit 0dac734545
22 changed files with 2117 additions and 713 deletions

73
.idea/workspace.xml generated
View File

@ -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 '{&quot;search_string&quot;:&quot;p13019&quot;}'" />
<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>

View File

@ -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:
![alt text](https://github.com/MickMake/GoSungrow/blob/master/docs/iSolarCloud.png?raw=true)
I'm currently using it in my [HomeAssistant](https://www.home-assistant.io/) instance.
![alt text](https://github.com/MickMake/GoSungrow/blob/master/docs/SunGrowOnHASSIO.png?raw=true)
## 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:

View File

@ -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),
}

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

2
go.mod
View File

@ -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
View File

@ -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=

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
// }

View File

@ -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())

View File

@ -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
View 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
}

View File

@ -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
// }

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
}