forked from massivebox/ecodash
Added arm builds, improve database
- The program will now be cross-compiled and released for arm as well as x86 - What we previously called "cache" is not actually a cache, as it holds content that can't be always retrieved. Now we're stopping calling it a cache. - Improved history merging - Fixed the README to include the database as a volume, and to fix some errors
This commit is contained in:
parent
52ba0ea4c1
commit
7a1214d492
|
@ -1,12 +1,6 @@
|
||||||
pipeline:
|
pipeline:
|
||||||
|
|
||||||
build:
|
docker:
|
||||||
image: golang
|
|
||||||
commands:
|
|
||||||
- go get ecodash
|
|
||||||
- go build
|
|
||||||
|
|
||||||
docker-publish:
|
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
settings:
|
settings:
|
||||||
registry: gitea.massivebox.net
|
registry: gitea.massivebox.net
|
||||||
|
@ -16,11 +10,19 @@ pipeline:
|
||||||
password:
|
password:
|
||||||
from_secret: auth_token
|
from_secret: auth_token
|
||||||
|
|
||||||
|
build:
|
||||||
|
image: golang
|
||||||
|
commands:
|
||||||
|
- go get ecodash
|
||||||
|
- go build -o ecodash-x86
|
||||||
|
- env GOOS=linux GOARCH=arm go build -o ecodash-arm
|
||||||
|
|
||||||
prepare-gitea-release:
|
prepare-gitea-release:
|
||||||
image: alpine
|
image: alpine
|
||||||
commands:
|
commands:
|
||||||
- apk update; apk add zip
|
- apk update; apk add zip
|
||||||
- zip -r ecodash.zip templates ecodash
|
- mv ecodash-x86 ecodash; zip -r ecodash-x86.zip templates ecodash
|
||||||
|
- mv ecodash-arm ecodash; zip -r ecodash-arm.zip templates ecodash
|
||||||
when:
|
when:
|
||||||
event: tag
|
event: tag
|
||||||
|
|
||||||
|
@ -28,7 +30,7 @@ pipeline:
|
||||||
image: plugins/gitea-release
|
image: plugins/gitea-release
|
||||||
settings:
|
settings:
|
||||||
base_url: https://gitea.massivebox.net
|
base_url: https://gitea.massivebox.net
|
||||||
files: ecodash.zip
|
files: ecodash-x86.zip ecodash-arm.zip
|
||||||
api_key:
|
api_key:
|
||||||
from_secret: auth_token
|
from_secret: auth_token
|
||||||
title: ${CI_COMMIT_TAG}
|
title: ${CI_COMMIT_TAG}
|
||||||
|
|
18
README.md
18
README.md
|
@ -1,4 +1,5 @@
|
||||||
# 🌿 EcoDash
|
# 🌿 EcoDash
|
||||||
|
|
||||||
[![status-badge](https://woodpecker.massivebox.net/api/badges/massivebox/ecodash/status.svg)](https://woodpecker.massivebox.net/massivebox/ecodash)
|
[![status-badge](https://woodpecker.massivebox.net/api/badges/massivebox/ecodash/status.svg)](https://woodpecker.massivebox.net/massivebox/ecodash)
|
||||||
|
|
||||||
EcoDash is a simple way to show your users how much your server consumes.
|
EcoDash is a simple way to show your users how much your server consumes.
|
||||||
|
@ -15,14 +16,17 @@ You can see it in action here: https://ecodash.massivebox.net
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
#### Using Docker run:
|
#### Using Docker run:
|
||||||
|
|
||||||
```
|
```
|
||||||
touch config.json
|
docker run -v /absolute_path_to/config.json:/app/config.json -v /absolute_path_to/database.db:/app/database.db --name ecodash -p 8080:80 gitea.massivebox.net/massivebox/ecodash
|
||||||
docker run -v ./config.json:/app/config.json --name ecodash -p 8080:80 gitea.massivebox.net/massivebox/ecodash
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This will open the container on port 8080. Replace "8080" in the command with whatever number you want to open that specific port.
|
This will open the container on port 8080. Replace "8080" in the command with whatever number you want to open that specific port.
|
||||||
|
|
||||||
#### Using Docker Compose:
|
#### Using Docker Compose:
|
||||||
|
|
||||||
Create a file `docker-compose.yml` with the following content:
|
Create a file `docker-compose.yml` with the following content:
|
||||||
|
|
||||||
```
|
```
|
||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
|
@ -33,17 +37,20 @@ services:
|
||||||
- '8080:80'
|
- '8080:80'
|
||||||
volumes:
|
volumes:
|
||||||
- ./config.json:/app/config.json
|
- ./config.json:/app/config.json
|
||||||
|
- ./database.db:/app/database.db
|
||||||
restart: always
|
restart: always
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the container with
|
||||||
|
|
||||||
```
|
```
|
||||||
Run the container with
|
|
||||||
```
|
|
||||||
touch config.json
|
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
This will open the container on port 8080. Replace "8080" in the file with whatever number you want to open that specific port.
|
This will open the container on port 8080. Replace "8080" in the file with whatever number you want to open that specific port.
|
||||||
|
|
||||||
#### Using the binary
|
#### Using the binary
|
||||||
|
|
||||||
Grab a binary from the Releases page and run it. You can use the `PORT` environment variable to override the default port (80).
|
Grab a binary from the Releases page and run it. You can use the `PORT` environment variable to override the default port (80).
|
||||||
|
|
||||||
## Set up
|
## Set up
|
||||||
|
@ -62,6 +69,7 @@ If you've just added your energy meter into HomeAssistant, note that it will tak
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
If something isn't working, you can find some help here:
|
If something isn't working, you can find some help here:
|
||||||
|
|
||||||
- [Matrix support room](https://matrix.to/#/#support:massivebox.net)
|
- [Matrix support room](https://matrix.to/#/#support:massivebox.net)
|
||||||
- [Issues page](./issues)
|
- [Issues page](./issues)
|
||||||
- [Contact me](https://massivebox.net/contact.html)
|
- [Contact me](https://massivebox.net/contact.html)
|
||||||
|
|
4
api.go
4
api.go
|
@ -126,7 +126,7 @@ func (config Config) historyBulkAverageAndConvertToGreen(entityID string, startT
|
||||||
}
|
}
|
||||||
value := float32(val)
|
value := float32(val)
|
||||||
var found bool
|
var found bool
|
||||||
dayNo := historyChange.LastUpdated.Local().Day()
|
dayNo := dayStart(historyChange.LastUpdated.Local()).Day()
|
||||||
for key, day := range days {
|
for key, day := range days {
|
||||||
if dayNo == day.DayNumber {
|
if dayNo == day.DayNumber {
|
||||||
found = true
|
found = true
|
||||||
|
@ -205,7 +205,7 @@ func (config Config) historyBulkDelta(entityID string, startTime, endTime time.T
|
||||||
}
|
}
|
||||||
value := float32(val)
|
value := float32(val)
|
||||||
var found bool
|
var found bool
|
||||||
dayNo := historyChange.LastUpdated.Local().Day()
|
dayNo := dayStart(historyChange.LastUpdated.Local()).Day()
|
||||||
for key, day := range days {
|
for key, day := range days {
|
||||||
if dayNo == day.DayNumber {
|
if dayNo == day.DayNumber {
|
||||||
found = true
|
found = true
|
||||||
|
|
|
@ -6,14 +6,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CacheEntry struct {
|
type HistoryEntry struct {
|
||||||
Date int64
|
Date int64
|
||||||
GreenEnergyPercentage float32
|
GreenEnergyPercentage float32
|
||||||
PolledSmartEnergySummation float32
|
PolledSmartEnergySummation float32
|
||||||
}
|
}
|
||||||
type CacheData []CacheEntry
|
type History []HistoryEntry
|
||||||
|
|
||||||
func (config Config) updateCache() {
|
func (config Config) updateHistory() {
|
||||||
|
|
||||||
greenEnergyPercentage, err := config.historyAverageAndConvertToGreen(config.Sensors.FossilPercentage, time.Now())
|
greenEnergyPercentage, err := config.historyAverageAndConvertToGreen(config.Sensors.FossilPercentage, time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -24,9 +24,9 @@ func (config Config) updateCache() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
config.db.Exec("INSERT INTO cache(time,green_energy_percentage,energy_consumption) VALUES (?,?,?);", dayStart(time.Now()).Unix(), greenEnergyPercentage.Value, historyPolledSmartEnergySummation.Value)
|
config.db.Exec("INSERT OR REPLACE INTO cache(time,green_energy_percentage,energy_consumption) VALUES (?,?,?);", dayStart(time.Now()).Unix(), greenEnergyPercentage.Value, historyPolledSmartEnergySummation.Value)
|
||||||
|
|
||||||
cached, err := config.readCache()
|
cached, err := config.readHistory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -60,32 +60,40 @@ func (config Config) refreshCacheFromPast(pastTime time.Time) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = config.db.Exec("DELETE FROM cache")
|
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(?,?,?)")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = stmt.Exec(day.DayTime.Unix(), greenEnergyPercentage[key].Value, historyPolledSmartEnergySummation[key].Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, day := range greenEnergyPercentage {
|
|
||||||
_, err := config.db.Exec("INSERT INTO cache(time,green_energy_percentage,energy_consumption) VALUES (?,?,?);", day.DayTime.Unix(), greenEnergyPercentage[key].Value, historyPolledSmartEnergySummation[key].Value)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config Config) readCache() (CacheData, error) {
|
func (config Config) readHistory() (History, error) {
|
||||||
|
|
||||||
start := dayStart(time.Now()).AddDate(0, 0, -8)
|
start := dayStart(time.Now()).AddDate(0, 0, -8)
|
||||||
|
|
||||||
rows, err := config.db.Query("SELECT time, green_energy_percentage, energy_consumption FROM cache WHERE time > ?", start.Unix())
|
rows, err := config.db.Query("SELECT time, green_energy_percentage, energy_consumption FROM cache WHERE time > ?", start.Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CacheData{}, err
|
return History{}, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
var ret CacheData
|
var ret History
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var (
|
var (
|
||||||
|
@ -94,7 +102,7 @@ func (config Config) readCache() (CacheData, error) {
|
||||||
polledSmartEnergyConsumption float32
|
polledSmartEnergyConsumption float32
|
||||||
)
|
)
|
||||||
err = rows.Scan(&date, &greenEnergyPercentage, &polledSmartEnergyConsumption)
|
err = rows.Scan(&date, &greenEnergyPercentage, &polledSmartEnergyConsumption)
|
||||||
ret = append(ret, CacheEntry{date, greenEnergyPercentage, polledSmartEnergyConsumption})
|
ret = append(ret, HistoryEntry{date, greenEnergyPercentage, polledSmartEnergyConsumption})
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
2
http.go
2
http.go
|
@ -177,7 +177,7 @@ func (config Config) renderIndex(c *fiber.Ctx) error {
|
||||||
}, "base")
|
}, "base")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := config.readCache()
|
data, err := config.readHistory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
4
main.go
4
main.go
|
@ -18,12 +18,12 @@ func main() {
|
||||||
|
|
||||||
if !isFirstRun {
|
if !isFirstRun {
|
||||||
cr := cron.New()
|
cr := cron.New()
|
||||||
_, err = cr.AddFunc("@hourly", config.updateCache)
|
_, err = cr.AddFunc("@hourly", config.updateHistory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
cr.Start()
|
cr.Start()
|
||||||
config.updateCache()
|
config.updateHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
engine := html.New("./templates/"+config.Dashboard.Theme, ".html")
|
engine := html.New("./templates/"+config.Dashboard.Theme, ".html")
|
||||||
|
|
Loading…
Reference in a new issue