forked from massivebox/ecodash
Refactoring
This commit is contained in:
parent
9bd3f35cc7
commit
345adcf479
|
@ -1,7 +1,7 @@
|
|||
# options for analysis running
|
||||
run:
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
timeout: 5m
|
||||
timeout: 10m
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
|
|
|
@ -5,7 +5,10 @@ COPY --from=0 /usr/bin/golangci-lint /usr/bin/golangci-lint
|
|||
RUN apk add --no-cache gcc libc-dev
|
||||
|
||||
WORKDIR /app
|
||||
COPY src /app/
|
||||
COPY src /app/src
|
||||
COPY go.mod /app/
|
||||
COPY go.sum /app/
|
||||
COPY .golangci.yml /app/
|
||||
|
||||
RUN golangci-lint run
|
||||
RUN go test ./src/...
|
||||
|
|
|
@ -31,18 +31,21 @@ func (config *Config) queryHistory(entityID string, startTime, endTime time.Time
|
|||
req, err := http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodGet,
|
||||
config.HomeAssistant.BaseURL+
|
||||
"/api/history/period/"+url.QueryEscape(startTime.Format(time.RFC3339))+
|
||||
"?filter_entity_id="+entityID+
|
||||
"&end_time="+url.QueryEscape(endTime.Format(time.RFC3339)),
|
||||
nil,
|
||||
fmt.Sprintf(
|
||||
"%s/api/history/period/%s?filter_entity_id=%s&end_time=%s",
|
||||
config.HomeAssistant.BaseURL,
|
||||
url.QueryEscape(startTime.Format(time.RFC3339)),
|
||||
entityID,
|
||||
url.QueryEscape(endTime.Format(time.RFC3339)),
|
||||
),
|
||||
http.NoBody,
|
||||
)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return HistoryResult{}, err
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", "Bearer "+config.HomeAssistant.ApiKey)
|
||||
req.Header.Add("Authorization", "Bearer "+config.HomeAssistant.APIKey)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
@ -239,7 +242,7 @@ func fillMissing(days []DayData, startTime, endTime time.Time) []DayData {
|
|||
previousDay time.Time
|
||||
defaultDay time.Time
|
||||
previousValue float32
|
||||
ret []DayData
|
||||
ret = make([]DayData, 0, len(days))
|
||||
currentTime = time.Now()
|
||||
)
|
||||
|
|
@ -27,7 +27,7 @@ type Config struct {
|
|||
type HomeAssistant struct {
|
||||
InstallationDate time.Time `json:"installation_date"`
|
||||
BaseURL string `json:"base_url"`
|
||||
ApiKey string `json:"api_key"`
|
||||
APIKey string `json:"api_key"`
|
||||
}
|
||||
type Sensors struct {
|
||||
PolledSmartEnergySummation string `json:"polled_smart_energy_summation"`
|
||||
|
@ -54,7 +54,7 @@ func formatURL(url string) (string, error) {
|
|||
}
|
||||
url = strings.TrimSuffix(url, "/")
|
||||
|
||||
test := regexp.MustCompile(`(?m)https?:\/\/[^/]*`).ReplaceAllString(url, "")
|
||||
test := regexp.MustCompile(`(?m)https?://[^/]*`).ReplaceAllString(url, "")
|
||||
if test != "" {
|
||||
return "", errBadHAFormat
|
||||
}
|
||||
|
@ -128,9 +128,9 @@ func (config *Config) isAuthorized(c *fiber.Ctx) bool {
|
|||
return c.Cookies("admin_username") == config.Administrator.Username && c.Cookies("admin_password_hash") == config.Administrator.PasswordHash
|
||||
}
|
||||
|
||||
func (config *Config) equals(new *Config) bool {
|
||||
return reflect.DeepEqual(new.HomeAssistant, config.HomeAssistant) &&
|
||||
reflect.DeepEqual(new.Sensors, config.Sensors) &&
|
||||
reflect.DeepEqual(new.Administrator, config.Administrator) &&
|
||||
reflect.DeepEqual(new.Dashboard, config.Dashboard)
|
||||
func (config *Config) Equals(c *Config) bool {
|
||||
return reflect.DeepEqual(c.HomeAssistant, config.HomeAssistant) &&
|
||||
reflect.DeepEqual(c.Sensors, config.Sensors) &&
|
||||
reflect.DeepEqual(c.Administrator, config.Administrator) &&
|
||||
reflect.DeepEqual(c.Dashboard, config.Dashboard)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
@ -62,18 +63,26 @@ func (config *Config) refreshCacheFromPast(pastTime time.Time) error {
|
|||
return err
|
||||
}
|
||||
|
||||
for key, day := range greenEnergyPercentage {
|
||||
var action2 string
|
||||
if greenEnergyPercentage[key].Value != 0 && historyPolledSmartEnergySummation[key].Value != 0 {
|
||||
action2 = "REPLACE"
|
||||
} else {
|
||||
action2 = "IGNORE"
|
||||
}
|
||||
|
||||
stmt, err := config.db.Prepare("INSERT OR " + action2 + " INTO cache(time, green_energy_percentage, energy_consumption) values(?,?,?)")
|
||||
stmtReplace, err := config.db.Prepare("INSERT OR REPLACE INTO cache(time, green_energy_percentage, energy_consumption) values(?,?,?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmtReplace.Close()
|
||||
|
||||
stmtIgnore, err := config.db.Prepare("INSERT OR IGNORE INTO cache(time, green_energy_percentage, energy_consumption) values(?,?,?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmtIgnore.Close()
|
||||
|
||||
for key, day := range greenEnergyPercentage {
|
||||
var stmt *sql.Stmt
|
||||
if greenEnergyPercentage[key].Value != 0 && historyPolledSmartEnergySummation[key].Value != 0 {
|
||||
stmt = stmtReplace
|
||||
} else {
|
||||
stmt = stmtIgnore
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(day.DayTime.Unix(), greenEnergyPercentage[key].Value, historyPolledSmartEnergySummation[key].Value)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -101,10 +110,13 @@ func (config *Config) readHistory() (History, error) {
|
|||
)
|
||||
err = rows.Scan(&date, &greenEnergyPercentage, &polledSmartEnergyConsumption)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return History{}, err
|
||||
}
|
||||
ret = append(ret, HistoryEntry{date, greenEnergyPercentage, polledSmartEnergyConsumption})
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return History{}, rows.Err()
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"math"
|
||||
"os"
|
||||
|
@ -48,7 +49,7 @@ func (config *Config) adminEndpoint(c *fiber.Ctx) error {
|
|||
if err != nil {
|
||||
return config.renderAdminPanel(c, Warning{
|
||||
Header: "An error occurred!",
|
||||
Body: err.Error(),
|
||||
Body: html.EscapeString(err.Error()),
|
||||
})
|
||||
}
|
||||
return config.renderAdminPanel(c, Warning{
|
||||
|
@ -81,6 +82,7 @@ func (config *Config) renderAdminPanel(c *fiber.Ctx, warning ...Warning) error {
|
|||
}
|
||||
|
||||
if len(warning) > 0 {
|
||||
// #nosec // TODO this is dangerous, even if we're escaping the only place where we're passing a non-literal
|
||||
warning[0].BodyHTML = template.HTML(warning[0].Body)
|
||||
return c.Render("admin", fiber.Map{
|
||||
"Defaults": config.getTemplateDefaults(),
|
||||
|
@ -116,7 +118,7 @@ func (config *Config) saveAdminForm(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
form := &Config{
|
||||
HomeAssistant: HomeAssistant{ /*BaseURL to be filled later*/ ApiKey: c.FormValue("api_key"), InstallationDate: dayStart(parsedTime)},
|
||||
HomeAssistant: HomeAssistant{ /*BaseURL to be filled later*/ APIKey: c.FormValue("api_key"), InstallationDate: dayStart(parsedTime)},
|
||||
Sensors: Sensors{PolledSmartEnergySummation: c.FormValue("polled_smart_energy_summation"), FossilPercentage: c.FormValue("fossil_percentage")},
|
||||
Administrator: Administrator{Username: c.FormValue("username") /*PasswordHash to be filled later*/},
|
||||
Dashboard: Dashboard{Theme: c.FormValue("theme"), Name: c.FormValue("name"), HeaderLinks: config.Dashboard.HeaderLinks, FooterLinks: config.Dashboard.FooterLinks},
|
||||
|
@ -134,7 +136,7 @@ func (config *Config) saveAdminForm(c *fiber.Ctx) error {
|
|||
}
|
||||
form.HomeAssistant.BaseURL = fmtURL
|
||||
|
||||
if form.equals(config) {
|
||||
if form.Equals(config) {
|
||||
return errNoChanges
|
||||
}
|
||||
|
||||
|
@ -149,7 +151,7 @@ func (config *Config) saveAdminForm(c *fiber.Ctx) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile("config.json", js, 0o666)
|
||||
return os.WriteFile("config.json", js, 0o600)
|
||||
}
|
||||
|
||||
func averageExcludingCurrentDay(data []float32) float32 {
|
||||
|
@ -207,10 +209,12 @@ func templateDivide(num1, num2 float32) template.HTML {
|
|||
|
||||
powerOfTen := int(math.Floor(math.Log10(division)))
|
||||
if powerOfTen >= -2 && powerOfTen <= 2 {
|
||||
// #nosec G203 // We're only printing floats
|
||||
return template.HTML(strconv.FormatFloat(math.Round(division*100)/100, 'f', -1, 64))
|
||||
}
|
||||
|
||||
preComma := division / math.Pow10(powerOfTen)
|
||||
// #nosec G203 // We're only printing floats
|
||||
return template.HTML(fmt.Sprintf("%s * 10<sup>%d</sup>", strconv.FormatFloat(math.Round(preComma*100)/100, 'f', -1, 64), powerOfTen))
|
||||
}
|
||||
|
||||
|
@ -218,5 +222,6 @@ func templateHTMLDateFormat(date time.Time) template.HTML {
|
|||
if date.IsZero() {
|
||||
return ""
|
||||
}
|
||||
// #nosec G203 // We're only printing a date
|
||||
return template.HTML(date.Format("2006-01-02"))
|
||||
}
|
Loading…
Reference in a new issue