Skip to content

Commit

Permalink
Merge pull request #13 from AaronSaikovski/v2.0.5_refactor
Browse files Browse the repository at this point in the history
V2.0.5 refactor
  • Loading branch information
AaronSaikovski authored May 10, 2024
2 parents fcdf213 + a8b7823 commit 2df7c56
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 187 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# GoGoodwe - CHANGELOG

## v2.0.3 (2024-04-26

## v2.0.5 (2024-05-10)

- Optimised and refactored code to reduce CPU usage and memory pressure and increased speed.



## v2.0.3 (2024-04-26)

- Minor fixes
-
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div align="center">

## GoGoodwe V2.0.4
## GoGoodwe V2.0.5

A command line tool to query the GOODWE SEMS Inverter APIs - written in 100% Go.
A command line tool to query the GOODWE SEMS Solar Inverter APIs - written in 100% Go.

[![Build Status](https://github.com/AaronSaikovski/gogoodwe/workflows/build/badge.svg)](https://github.com/AaronSaikovski/gogoodwe/actions)
[![Licence](https://img.shields.io/github/license/AaronSaikovski/gogoodwe)](LICENSE)
Expand Down
40 changes: 18 additions & 22 deletions cmd/gogoodwe/apilogin/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,16 @@ import (
"github.com/AaronSaikovski/gogoodwe/cmd/gogoodwe/utils"
)

// Login - Login to the SEMS API passing in a LoginCredentials struct and returning a LoginResponse struct.
// APILogin logs in to the SEMS API using the provided credentials.
//
// It takes the login credentials as a parameter and returns the API login response and an error.
func (loginCredentials *ApiLoginCredentials) APILogin() (*ApiLoginResponse, error) {

// API Response struct
loginApiResponse := ApiLoginResponse{}

//check if the UserLogin struct is empty
// Check if the UserLogin struct is empty
if err := checkUserLoginInfo(loginCredentials); err != nil {
return nil, err
}

// User login struct to be converted to JSON
// Convert User login struct to JSON
loginData, err := utils.MarshalStructToJSON(loginCredentials)
if err != nil {
return nil, err
Expand All @@ -55,34 +53,32 @@ func (loginCredentials *ApiLoginCredentials) APILogin() (*ApiLoginResponse, erro
return nil, err
}

//Add headers pass in the pointer to set the headers on the request object
// Add headers
setHeaders(req)

//make the API Call
client := &http.Client{Timeout: time.Duration(HTTPTimeout) * time.Second}
// Make the API call
client := &http.Client{Timeout: HTTPTimeout * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, err
}

defer resp.Body.Close()

// Get the response body
respBody, respErr := utils.FetchResponseBody(resp.Body)
if respErr != nil {
return nil, respErr
respBody, err := utils.FetchResponseBody(resp.Body)
if err != nil {
return nil, err
}

//marshall response to loginresponse struct
dataErr := utils.UnmarshalDataToStruct(respBody, &loginApiResponse)
if dataErr != nil {
return nil, dataErr
// Unmarshal response to loginresponse struct
var loginApiResponse ApiLoginResponse
if err := utils.UnmarshalDataToStruct(respBody, &loginApiResponse); err != nil {
return nil, err
}

// check for successful login return value..return a login error
loginErr := checkUserLoginResponse(loginApiResponse.Msg)
if loginErr != nil {
return nil, loginErr
// Check for successful login
if err := checkUserLoginResponse(loginApiResponse.Msg); err != nil {
return nil, err
}

return &loginApiResponse, nil
Expand Down
25 changes: 18 additions & 7 deletions cmd/gogoodwe/apilogin/loginutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,39 @@ package apilogin

import (
"errors"
"fmt"
"net/http"
"strings"
)

// SetHeaders - Set the login headers for the SEMS API login
// setHeaders sets the headers for the SEMS API login.
//
// It takes a pointer to an http.Request as a parameter and adds the following headers:
// - "Content-Type": "application/json"
// - "Token": "{\"version\":\"v2.1.0\",\"client\":\"ios\",\"language\":\"en\"}"
func setHeaders(r *http.Request) {
r.Header.Add("Content-Type", "application/json")
r.Header.Add("Token", "{\"version\":\"v2.1.0\",\"client\":\"ios\",\"language\":\"en\"}")
}

// CheckUserLoginResponse - check for successful login return value..return a login error
// checkUserLoginResponse checks for successful login return value and returns a login error if unsuccessful.
//
// Parameter:
// - loginResponse: the response string to check.
// Return type: error
func checkUserLoginResponse(loginResponse string) error {
if strings.Compare(loginResponse, "Successful") != 0 {
return errors.New("**API Login Error: " + loginResponse)
if loginResponse != "Successful" {
return fmt.Errorf("**API Login Error: %s", loginResponse)
}
return nil
}

// CheckUserLoginInfo - Check user login struct is valid/not null
// checkUserLoginInfo checks if the provided user login credentials are valid or not.
//
// It takes a pointer to an ApiLoginCredentials struct as a parameter and returns an error if the credentials are empty or invalid.
// The function returns nil if the credentials are valid.
func checkUserLoginInfo(userLogin *ApiLoginCredentials) error {
if *userLogin == (ApiLoginCredentials{}) {
return errors.New("**Error: User Login details are empty or invalid..**")
return errors.New("**Error: User Login details are empty or invalid**")
}
return nil
}
27 changes: 16 additions & 11 deletions cmd/gogoodwe/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,40 @@ SOFTWARE.
*/
package app

// Main package - This is the main program entry point
import (
"github.com/AaronSaikovski/gogoodwe/cmd/gogoodwe/utils"
"github.com/alexflint/go-arg"
)

// Main package - This is the main program entry point

// Run is the main program runner.
//
// No parameters.
// Returns an error.
// It takes a version string as a parameter and returns an error.
// The version string is used to set the build information.
// The function parses the command line arguments using the utils.Args struct.
// It checks if the email address and powerstation ID are in the correct format.
// If not, it fails with an error message.
// Finally, it calls the fetchData function to get data from the API and returns any errors.
func Run(versionString string) error {
// Set version build info

//Get the args input data
var args utils.Args
//set the version build info
args.SetVersion(versionString)

// Parse args
p := arg.MustParse(&args)

//check for valid email address input
// Check for valid email address input
if !utils.CheckValidEmail(args.Account) {
p.Fail("Invalid Email address format - should be: 'user@somedomain.com'.")
p.Fail("invalid email address format: should be 'user@somedomain.com'")
}

//check for valid powerstation Id
// Check for valid powerstation ID
if !utils.CheckValidPowerstationID(args.PowerStationID) {
p.Fail("Invalid Powerstation ID format: - should be: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'.")
p.Fail("invalid Powerstation ID format: should be 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'")
}

// Get the data from the API, return any errors. Pass in args as string
// Get the data from the API, return any errors
return fetchData(args.Account, args.Password, args.PowerStationID, args.DailySummary)

}
34 changes: 14 additions & 20 deletions cmd/gogoodwe/app/fetchdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,36 @@ package app

// Main package - This is the main program entry point
import (
"fmt"

"github.com/AaronSaikovski/gogoodwe/cmd/gogoodwe/apilogin"
"github.com/AaronSaikovski/gogoodwe/cmd/gogoodwe/monitordata"
"github.com/AaronSaikovski/gogoodwe/cmd/gogoodwe/utils"
)

// fetchData fetches data based on user account credentials and power station ID, and can retrieve daily summary if specified.
//
// Parameters:
// - Account: the email account associated with the user.
// - Password: the password associated with the user's account.
// - PowerStationID: the ID of the power station.
// - DailySummary: a boolean indicating whether to retrieve a daily summary.
// fetchData fetches data using the provided account credentials and power station ID.
//
// Returns:
// - error: an error if there was a problem logging in or fetching data.
func fetchData(Account string, Password string, PowerStationID string, DailySummary bool) error {

// Account: the email account associated with the user.
// Password: the password associated with the user's account.
// PowerStationID: the ID of the power station.
// DailySummary: a boolean indicating whether to retrieve a daily summary.
// error: an error if there was a problem logging in or fetching data.
func fetchData(Account, Password, PowerStationID string, DailySummary bool) error {
// User account struct
loginCreds := &apilogin.ApiLoginCredentials{
Account: Account,
Password: Password,
PowerStationID: PowerStationID,
}

// Do the login..check for errors
// Do the login
loginApiResponse, err := loginCreds.APILogin()
if err != nil {
utils.HandleError(err)
return err
return fmt.Errorf("login failed: %w", err)
}

//fetch data and output
dataErr := monitordata.GetData(loginCreds, loginApiResponse, DailySummary)
if dataErr != nil {
utils.HandleError(dataErr)
return dataErr
// Fetch data and handle errors
if err := monitordata.GetData(loginCreds, loginApiResponse, DailySummary); err != nil {
return fmt.Errorf("data fetching failed: %w", err)
}

return nil
Expand Down
14 changes: 6 additions & 8 deletions cmd/gogoodwe/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,21 @@ package main

import (
_ "embed"
"os"
"log"

"github.com/AaronSaikovski/gogoodwe/cmd/gogoodwe/app"
"github.com/AaronSaikovski/gogoodwe/cmd/gogoodwe/utils"
)

//ref: https://levelup.gitconnected.com/a-better-way-than-ldflags-to-add-a-build-version-to-your-go-binaries-2258ce419d2d

//go:generate bash get_version.sh
//go:embed version.txt
var version string

// main is the entry point of the Go program.
//
// It calls the app.Run function with the version string as a parameter.
// If an error is returned, it logs the error message and exits the program.
func main() {

if err := app.Run(version); err != nil {
utils.HandleError(err)
os.Exit(1)
log.Fatalf("Error: %v", err)
}

}
Loading

0 comments on commit 2df7c56

Please sign in to comment.