mirror of
https://github.com/MickMake/GoSungrow.git
synced 2025-03-23 16:11:43 +01:00
615 lines
14 KiB
Go
615 lines
14 KiB
Go
package iSolarCloud
|
|
|
|
import (
|
|
"GoSungrow/iSolarCloud/api"
|
|
"GoSungrow/iSolarCloud/api/GoStruct/output"
|
|
"GoSungrow/iSolarCloud/api/GoStruct/valueTypes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/MickMake/GoUnify/Only"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
|
|
// ****************************************************** //
|
|
|
|
func (sg *SunGrow) NewSunGrowData() SunGrowData {
|
|
var data SunGrowData
|
|
for range Only.Once {
|
|
data.New(sg)
|
|
|
|
data.SetOutputType(sg.OutputType)
|
|
data.SetSaveAsFile(sg.SaveAsFile)
|
|
}
|
|
return data
|
|
}
|
|
|
|
|
|
func SplitArg(arg string) []string {
|
|
var ret []string
|
|
for range Only.Once {
|
|
ret = []string{arg}
|
|
for _, s := range []string{ ",", "/", " "} {
|
|
if strings.Contains(arg, s) {
|
|
ret = strings.Split(arg, s)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
|
|
type EndPoints map[string]EndPoint
|
|
type EndPoint struct {
|
|
Func SunGrowDataFunction
|
|
HasArgs bool
|
|
}
|
|
|
|
|
|
type SunGrowData struct {
|
|
Args []string
|
|
endPoints []string
|
|
Request SunGrowDataRequest
|
|
|
|
Results SunGrowDataResults
|
|
|
|
sunGrow *SunGrow
|
|
outputType output.OutputType
|
|
saveAsFile bool
|
|
cacheTimeout time.Duration
|
|
|
|
Debug bool
|
|
Error error
|
|
}
|
|
|
|
func (sgd *SunGrowData) PrintDebug(format string, args ...interface{}) {
|
|
if sgd.Debug { _, _ = fmt.Fprintf(os.Stderr, format, args...) }
|
|
}
|
|
|
|
func (sgd *SunGrowData) New(ref *SunGrow) {
|
|
for range Only.Once {
|
|
sgd.sunGrow = ref
|
|
sgd.Results = make(SunGrowDataResults)
|
|
sgd.cacheTimeout = time.Minute * 5
|
|
}
|
|
}
|
|
|
|
func (sgd *SunGrowData) SetCacheTimeout(t time.Duration) {
|
|
sgd.cacheTimeout = t
|
|
}
|
|
|
|
func (sgd *SunGrowData) SetOutput(t string) {
|
|
sgd.outputType.Set(t)
|
|
}
|
|
|
|
func (sgd *SunGrowData) SetOutputType(t output.OutputType) {
|
|
sgd.outputType = t
|
|
}
|
|
|
|
func (sgd *SunGrowData) SetSaveAsFile(yes bool) {
|
|
sgd.saveAsFile = yes
|
|
}
|
|
|
|
func (sgd *SunGrowData) SetEndpoints(endpoints ...string) {
|
|
sgd.endPoints = endpoints
|
|
}
|
|
|
|
func (sgd *SunGrowData) SetArgs(args ...string) {
|
|
sgd.Args = args
|
|
}
|
|
|
|
func (sgd *SunGrowData) SetPsIds(psids ...string) {
|
|
for range Only.Once {
|
|
var pids valueTypes.PsIds
|
|
pids = sgd.sunGrow.SetPsIds(psids...)
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
|
|
sgd.Request.SetPSIDs(pids.Strings())
|
|
}
|
|
}
|
|
|
|
func (sgd *SunGrowData) CallEndpoint(endpoint api.EndPoint, request SunGrowDataRequest) SunGrowDataResponse {
|
|
var response SunGrowDataResponse
|
|
for range Only.Once {
|
|
if !request.Validate(endpoint) {
|
|
request.Help(endpoint)
|
|
sgd.Error = errors.New("missing argument")
|
|
break
|
|
}
|
|
|
|
var req []byte
|
|
req, sgd.Error = json.Marshal(request)
|
|
if sgd.Error != nil {
|
|
fmt.Printf("GetEndPoint - Error: %s\n", sgd.Error)
|
|
break
|
|
}
|
|
// fmt.Printf("Request: %s\n", req)
|
|
|
|
if string(req) != "" {
|
|
endpoint = endpoint.SetRequestByJson(output.Json(req))
|
|
sgd.Error = endpoint.GetError()
|
|
if sgd.Error != nil {
|
|
fmt.Println(endpoint.Help())
|
|
break
|
|
}
|
|
}
|
|
sgd.PrintDebug("Request: %s\n", endpoint.GetRequestJson())
|
|
|
|
// @TODO - Make this a config option.
|
|
endpoint = endpoint.SetCacheTimeout(sgd.cacheTimeout)
|
|
|
|
endpoint = endpoint.Call()
|
|
sgd.Error = endpoint.GetError()
|
|
if sgd.Error != nil {
|
|
if strings.Contains(sgd.Error.Error(), "er_token_login_invalid") {
|
|
sgd.sunGrow.Logout()
|
|
break
|
|
}
|
|
fmt.Println(endpoint.Help())
|
|
sgd.PrintDebug("Error response[%s]: %s\n", sgd.Error, endpoint.GetResponseJson())
|
|
break
|
|
}
|
|
sgd.PrintDebug("Response: %s\n", endpoint.GetResponseJson())
|
|
|
|
response.Data = endpoint.GetEndPointData()
|
|
args := request.GetArgs(response.Data.EndPoint)
|
|
name := endpoint.GetArea().String() + "." + endpoint.GetName().String()
|
|
var title string
|
|
var file string // + " - " + request.RequestAsFilePrefix(),
|
|
key := request.GetPrimaryArg()
|
|
if key != "" {
|
|
title = key
|
|
file = key
|
|
}
|
|
|
|
response.Options = OutputOptions {
|
|
Name: name,
|
|
OutputType: sgd.sunGrow.OutputType,
|
|
PrimaryKey: key,
|
|
FileSuffix: file,
|
|
SaveAsFile: sgd.sunGrow.SaveAsFile,
|
|
TitleSuffix: args,
|
|
GraphRequest: output.GraphRequest {
|
|
Title: title,
|
|
SubTitle: args,
|
|
TimeColumn: nil,
|
|
DataColumn: nil,
|
|
UnitsColumn: nil,
|
|
NameColumn: nil,
|
|
DataMin: nil,
|
|
DataMax: nil,
|
|
Width: nil,
|
|
Height: nil,
|
|
Error: nil,
|
|
},
|
|
}
|
|
sgd.PrintDebug("OutputOptions: %v\n", response.Options)
|
|
}
|
|
|
|
return response
|
|
}
|
|
|
|
func (sgd *SunGrowData) GetData() error {
|
|
for range Only.Once {
|
|
if len(sgd.endPoints) == 0 {
|
|
sgd.Error = errors.New("need an endpoint")
|
|
break
|
|
}
|
|
|
|
for _, endpoint := range sgd.endPoints {
|
|
sgd.Error = sgd.GetDataSingle(endpoint)
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowData) GetDataSingle(endpoint string) error {
|
|
for range Only.Once {
|
|
// Lookup endpoint interface from string.
|
|
ep := sgd.sunGrow.GetEndpoint(endpoint)
|
|
if sgd.sunGrow.IsError() {
|
|
sgd.Error = sgd.sunGrow.Error
|
|
break
|
|
}
|
|
sgd.Request.SetRequired(ep.GetRequestArgNames())
|
|
sgd.Request.SetArgs(sgd.Args...)
|
|
|
|
// PsId not required.
|
|
if sgd.Request.IsPsIdNotRequired() {
|
|
sgd.Error = sgd.getDataSinglePsIdNotRequired(ep)
|
|
break
|
|
}
|
|
|
|
// PsId required.
|
|
if sgd.Request.IsPsIdRequired() {
|
|
sgd.Error = sgd.getDataSinglePsIdRequired(ep)
|
|
break
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowData) getDataSinglePsIdNotRequired(ep api.EndPoint) error {
|
|
for range Only.Once {
|
|
var result SunGrowDataResult
|
|
result.EndPointArea = ep.GetArea()
|
|
result.EndPointName = ep.GetName()
|
|
result.EndPoint = ep
|
|
result.Request = sgd.Request
|
|
|
|
result.Response = sgd.CallEndpoint(ep, result.Request)
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
|
|
sgd.Results[result.EndPointName.String()] = result
|
|
sgd.Error = sgd.Process()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowData) getDataSinglePsIdRequired(ep api.EndPoint) error {
|
|
for range Only.Once {
|
|
if sgd.Request.aPsId == nil {
|
|
sgd.SetPsIds()
|
|
}
|
|
|
|
for _, psId := range sgd.Request.aPsId {
|
|
var result SunGrowDataResult
|
|
result.Request = sgd.Request
|
|
result.Request.SetPsId(psId.String())
|
|
|
|
result.EndPointArea = ep.GetArea()
|
|
result.EndPointName = ep.GetName()
|
|
result.EndPoint = ep
|
|
result.Response = sgd.CallEndpoint(ep, result.Request)
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
sgd.Results[result.EndPointName.String() + "/" + psId.String()] = result
|
|
}
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
|
|
sgd.Error = sgd.Process()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowData) Process() error {
|
|
for range Only.Once {
|
|
if len(sgd.Results) == 0 {
|
|
fmt.Println("No results found.")
|
|
break
|
|
}
|
|
|
|
for _, result := range sgd.Results {
|
|
result.Response.Data.ProcessMap()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowData) Output() error {
|
|
for range Only.Once {
|
|
if len(sgd.Results) == 0 {
|
|
fmt.Println("No results found.")
|
|
break
|
|
}
|
|
|
|
for _, result := range sgd.Results {
|
|
sgd.Error = result.Response.Output()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowData) OutputDataTables() error {
|
|
for range Only.Once {
|
|
if len(sgd.Results) == 0 {
|
|
fmt.Println("No results found.")
|
|
break
|
|
}
|
|
|
|
for _, result := range sgd.Results {
|
|
sgd.Error = result.Response.OutputDataTables()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
|
|
type SunGrowDataResults map[string]SunGrowDataResult
|
|
type SunGrowDataResult struct {
|
|
EndPointArea api.AreaName
|
|
EndPointName api.EndPointName
|
|
EndPoint api.EndPoint
|
|
Request SunGrowDataRequest
|
|
Response SunGrowDataResponse
|
|
|
|
Error error
|
|
}
|
|
|
|
func (sgd *SunGrowDataResult) Process() error {
|
|
sgd.Response.Data.ProcessMap()
|
|
sgd.Error = sgd.Response.Data.Error
|
|
return sgd.Error
|
|
}
|
|
|
|
// func (sgd *SunGrowDataResult) ProcessMapForMqtt() error {
|
|
// sgd.Response.Data.ProcessMapForMqtt()
|
|
// sgd.Error = sgd.Response.Data.Error
|
|
// return sgd.Error
|
|
// }
|
|
|
|
// func (sgd *SunGrowDataResult) CreateResultTable(full bool) output.Table {
|
|
// ret := sgd.Response.CreateResultTable(full)
|
|
// sgd.Error = sgd.Response.Data.Error
|
|
// return ret
|
|
// }
|
|
|
|
// func (sgd *SunGrowDataResult) CreateDataTables() api.Tables {
|
|
// tables := sgd.Response.CreateDataTables()
|
|
// sgd.Error = sgd.Response.Data.Error
|
|
// return tables
|
|
// }
|
|
|
|
func (sgd *SunGrowDataResult) Sort() []string {
|
|
return sgd.Response.Data.Sort()
|
|
}
|
|
|
|
func (sgd *SunGrowDataResult) Print() {
|
|
fmt.Println(sgd.Response.Data.String())
|
|
}
|
|
|
|
|
|
type OutputOptions struct {
|
|
Name string
|
|
TitleSuffix string
|
|
OutputType output.OutputType
|
|
PrimaryKey string
|
|
FileSuffix string
|
|
SaveAsFile bool
|
|
GraphRequest output.GraphRequest
|
|
|
|
// table.InitGraph(output.GraphRequest {
|
|
// Title: "",
|
|
// TimeColumn: output.SetString("Date/Time"),
|
|
// SearchColumn: output.SetString("Point Id"),
|
|
// NameColumn: output.SetString("Point Name"),
|
|
// ValueColumn: output.SetString("Value"),
|
|
// UnitsColumn: output.SetString("Units"),
|
|
// SearchString: output.SetString(""),
|
|
// MinLeftAxis: output.SetFloat(0),
|
|
// MaxLeftAxis: output.SetFloat(0),
|
|
// })
|
|
}
|
|
|
|
type SunGrowDataResponses map[string]SunGrowDataResponse
|
|
type SunGrowDataFunction func(request SunGrowDataRequest) SunGrowDataResponse
|
|
type SunGrowDataResponse struct {
|
|
Data api.DataMap
|
|
Options OutputOptions
|
|
Error error
|
|
}
|
|
|
|
// func (sgd *SunGrowDataResponse) CreateResultTable(full bool) output.Table {
|
|
// ret := sgd.Data.CreateResultTable(full)
|
|
// sgd.Error = sgd.Data.Error
|
|
// return ret
|
|
// }
|
|
|
|
// func (sgd *SunGrowDataResponse) CreateDataTables() api.Tables {
|
|
// tables := sgd.Data.CreateDataTables()
|
|
// sgd.Error = sgd.Data.Error
|
|
// return tables
|
|
// }
|
|
|
|
func (sgd *SunGrowDataResponse) Output() error {
|
|
for range Only.Once {
|
|
// Outputs that don't drop through.
|
|
if sgd.Options.OutputType.IsStruct() || sgd.Options.OutputType.IsList() || sgd.Options.OutputType.IsRaw() || sgd.Options.OutputType.IsJson() {
|
|
table := sgd.Data.CreateResultTable(true)
|
|
table.OutputType = sgd.Options.OutputType
|
|
table.SetSaveFile(sgd.Options.SaveAsFile)
|
|
table.AppendTitle(" - %s", sgd.Options.TitleSuffix)
|
|
table.AppendFilePrefix(sgd.Options.FileSuffix)
|
|
sgd.Error = table.Output()
|
|
break
|
|
}
|
|
|
|
// Outputs that can drop through to DataTables.
|
|
if sgd.Options.OutputType.IsTable() || sgd.Options.OutputType.IsXLSX() || sgd.Options.OutputType.IsCsv() || sgd.Options.OutputType.IsXML() {
|
|
table := sgd.Data.CreateResultTable(false)
|
|
table.OutputType = sgd.Options.OutputType
|
|
table.SetSaveFile(sgd.Options.SaveAsFile)
|
|
table.AppendTitle(" - %s", sgd.Options.TitleSuffix)
|
|
table.AppendFilePrefix(sgd.Options.FileSuffix)
|
|
sgd.Error = table.Output()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
// break
|
|
}
|
|
|
|
sgd.Error = sgd.OutputDataTables()
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowDataResponse) OutputDataTables() error {
|
|
for range Only.Once {
|
|
tables := sgd.Data.CreateDataTables()
|
|
if sgd.Data.Error != nil {
|
|
sgd.Error = sgd.Data.Error
|
|
break
|
|
}
|
|
if len(tables) == 0 {
|
|
break
|
|
}
|
|
|
|
// @iSolarCloud/api/struct_data.go:420
|
|
for _, data := range tables {
|
|
if sgd.Options.TitleSuffix == "" {
|
|
sgd.Options.TitleSuffix = data.Table.GetTitle()
|
|
}
|
|
data.Table.OutputType = sgd.Options.OutputType
|
|
data.Table.SetSaveFile(sgd.Options.SaveAsFile) // sgd.Options.SaveAsFile
|
|
|
|
if sgd.Options.OutputType.IsGraph() {
|
|
if !data.IsValid {
|
|
fmt.Printf("# %s.%s - has no graphable data.\n", data.Area, data.Name)
|
|
continue
|
|
}
|
|
|
|
data.Table.SetSaveFile(true)
|
|
|
|
if sgd.Options.GraphRequest.TimeColumn == nil {
|
|
for _, col := range data.Table.GetHeaders() {
|
|
val := data.Values.GetCell(0, col)
|
|
if val.IsTypeDateTime() {
|
|
sgd.Options.GraphRequest.TimeColumn = &col
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if sgd.Options.GraphRequest.TimeColumn == nil {
|
|
// No time column - abort.
|
|
break
|
|
}
|
|
|
|
if sgd.Options.GraphRequest.UnitsColumn != nil {
|
|
for _, col := range data.Table.GetHeaders() {
|
|
if *sgd.Options.GraphRequest.UnitsColumn != col {
|
|
continue
|
|
}
|
|
val := data.Values.GetCell(0, col)
|
|
unit := val.Unit()
|
|
if unit != "" {
|
|
continue
|
|
}
|
|
sgd.Options.GraphRequest.UnitsColumn = &col
|
|
sgd.Options.GraphRequest.DataUnit = &unit
|
|
break
|
|
}
|
|
}
|
|
|
|
if sgd.Options.GraphRequest.NameColumn == nil {
|
|
}
|
|
|
|
// if sgd.Options.GraphRequest.Width == nil {
|
|
// }
|
|
|
|
// if sgd.Options.GraphRequest.Height == nil {
|
|
// }
|
|
|
|
var values []string
|
|
if sgd.Options.GraphRequest.DataColumn == nil {
|
|
fmt.Println("Finding points to graph...")
|
|
fmt.Printf("Table Headers: %s\n", strings.Join(data.Table.GetHeaders(), ", "))
|
|
fmt.Printf("Table rows: %d\n", data.Rows)
|
|
// We don't have any DataColumn defined - find them.
|
|
for _, col := range data.Table.GetHeaders() {
|
|
val := data.Values.GetCell(0, col)
|
|
if !val.IsNumber() {
|
|
continue
|
|
}
|
|
values = append(values, col)
|
|
// if val.ValueKey() == "" {
|
|
// values = append(values, col)
|
|
// continue
|
|
// }
|
|
// if val.DeviceId() == "" {
|
|
// values = append(values, val.ValueKey())
|
|
// continue
|
|
// }
|
|
// values = append(values, val.DeviceId() + "." + val.ValueKey())
|
|
}
|
|
fmt.Printf("Found %d points.\n", len(values))
|
|
}
|
|
|
|
title := data.Table.GetTitle()
|
|
file := data.Table.GetFilePrefix()
|
|
|
|
sort.Strings(values)
|
|
for _, value := range values {
|
|
// @TODO - Lookup pointIds here.
|
|
sgd.Options.GraphRequest.DataColumn = &value
|
|
if sgd.Options.PrimaryKey != "" {
|
|
data.Table.SetTitle("%s - %s - %s", title, sgd.Options.PrimaryKey, value)
|
|
data.Table.SetFilePrefix("%s-%s-%s", file, sgd.Options.PrimaryKey, value)
|
|
} else {
|
|
data.Table.SetTitle("%s - %s", title, value)
|
|
data.Table.SetFilePrefix("%s-%s", file, value)
|
|
}
|
|
sgd.Options.GraphRequest.Title = data.Table.GetTitle()
|
|
|
|
sgd.Error = data.Table.SetGraph(sgd.Options.GraphRequest)
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
|
|
sgd.Error = data.Table.Output()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
break
|
|
}
|
|
|
|
data.Table.AppendTitle(" - %s", sgd.Options.TitleSuffix)
|
|
data.Table.AppendFilePrefix(sgd.Options.FileSuffix)
|
|
fmt.Println()
|
|
sgd.Error = data.Table.Output()
|
|
if sgd.Error != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return sgd.Error
|
|
}
|
|
|
|
func (sgd *SunGrowDataResponse) LookUpPointId() {
|
|
|
|
}
|
|
|
|
func (sgd *SunGrowDataResponse) Print() {
|
|
fmt.Println(sgd.Data.String())
|
|
}
|