Skip to content

Commit

Permalink
Add session log (evcc-io#4162)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Oct 5, 2022
1 parent 3a3277e commit 85d0117
Show file tree
Hide file tree
Showing 17 changed files with 521 additions and 64 deletions.
2 changes: 0 additions & 2 deletions .goreleaser-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ builds:
- -tags=release
ldflags:
- -X github.com/evcc-io/evcc/server.Version={{ .Tag }} -X github.com/evcc-io/evcc/server.Commit={{ .ShortCommit }} -s -w
env:
- CGO_ENABLED=0
goos:
- linux
goarch:
Expand Down
2 changes: 0 additions & 2 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ builds:
- -tags=release
ldflags:
- -X github.com/evcc-io/evcc/server.Version={{ .Version }} -s -w
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
Expand Down
6 changes: 6 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"fmt"
"io"
"net/http"
"reflect"
"strings"
Expand Down Expand Up @@ -227,3 +228,8 @@ type FeatureDescriber interface {
Features() []Feature
Has(Feature) bool
}

// CsvWriter converts to csv
type CsvWriter interface {
WriteCsv(io.Writer)
}
60 changes: 38 additions & 22 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ import (
"golang.org/x/exp/maps"
)

var conf = config{
Interval: 10 * time.Second,
Log: "info",
Network: networkConfig{
Schema: "http",
Host: "evcc.local",
Port: 7070,
},
Mqtt: mqttConfig{
Topic: "evcc",
},
Database: dbConfig{
Type: "sqlite",
Dsn: "~/.evcc/evcc.db",
},
}

type config struct {
URI interface{} // TODO deprecated
Network networkConfig
Expand All @@ -37,6 +54,7 @@ type config struct {
Levels map[string]string
Interval time.Duration
Mqtt mqttConfig
Database dbConfig
Javascript map[string]interface{}
Influx server.InfluxConfig
EEBus map[string]interface{}
Expand All @@ -50,33 +68,14 @@ type config struct {
LoadPoints []map[string]interface{}
}

type networkConfig struct {
Schema string
Host string
Port int
}

func (c networkConfig) HostPort() string {
if c.Schema == "http" && c.Port == 80 || c.Schema == "https" && c.Port == 443 {
return c.Host
}
return net.JoinHostPort(c.Host, strconv.Itoa(c.Port))
}

func (c networkConfig) URI() string {
return fmt.Sprintf("%s://%s", c.Schema, c.HostPort())
}

type mqttConfig struct {
mqtt.Config `mapstructure:",squash"`
Topic string
}

func (conf *mqttConfig) RootTopic() string {
if conf.Topic != "" {
return conf.Topic
}
return "evcc"
type dbConfig struct {
Type string
Dsn string
}

type qualifiedConfig struct {
Expand All @@ -100,6 +99,23 @@ type tariffConfig struct {
FeedIn typedConfig
}

type networkConfig struct {
Schema string
Host string
Port int
}

func (c networkConfig) HostPort() string {
if c.Schema == "http" && c.Port == 80 || c.Schema == "https" && c.Port == 443 {
return c.Host
}
return net.JoinHostPort(c.Host, strconv.Itoa(c.Port))
}

func (c networkConfig) URI() string {
return fmt.Sprintf("%s://%s", c.Schema, c.HostPort())
}

// ConfigProvider provides configuration items
type ConfigProvider struct {
meters map[string]api.Meter
Expand Down
21 changes: 8 additions & 13 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,6 @@ var (
ignoreMqtt = []string{"auth", "releaseNotes"} // excessive size may crash certain brokers
)

var conf = config{
Interval: 10 * time.Second,
Log: "info",
Network: networkConfig{
Schema: "http",
Host: "evcc.local",
Port: 7070,
},
}

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "evcc",
Expand Down Expand Up @@ -219,6 +209,11 @@ func runRoot(cmd *cobra.Command, args []string) {
err = configureEnvironment(cmd, conf)
}

// setup session log
if err == nil && conf.Database.Dsn != "" {
err = configureDatabase(conf.Database)
}

// setup site and loadpoints
var site *core.Site
if err == nil {
Expand All @@ -228,12 +223,12 @@ func runRoot(cmd *cobra.Command, args []string) {

// setup database
if err == nil && conf.Influx.URL != "" {
configureDatabase(conf.Influx, site.LoadPoints(), tee.Attach())
configureInflux(conf.Influx, site.LoadPoints(), tee.Attach())
}

// setup mqtt publisher
if err == nil && conf.Mqtt.Broker != "" {
publisher := server.NewMQTT(conf.Mqtt.RootTopic())
publisher := server.NewMQTT(strings.Trim(conf.Mqtt.Topic, "/"))
go publisher.Run(site, pipe.NewDropper(ignoreMqtt...).Pipe(tee.Attach()))
}

Expand Down Expand Up @@ -326,7 +321,7 @@ func runRoot(cmd *cobra.Command, args []string) {
wg.Add(2)

// wait for main loop and shutdown functions to finish
go func() { <-shutdown.Done(conf.Interval); wg.Done() }()
go func() { <-shutdown.Done(); wg.Done() }()
go func() { <-siteC; wg.Done() }()
go func() { wg.Wait(); close(exitC) }()

Expand Down
17 changes: 9 additions & 8 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/evcc-io/evcc/provider/mqtt"
"github.com/evcc-io/evcc/push"
"github.com/evcc-io/evcc/server"
"github.com/evcc-io/evcc/server/db"
"github.com/evcc-io/evcc/tariff"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/machine"
Expand Down Expand Up @@ -95,8 +96,13 @@ func configureEnvironment(cmd *cobra.Command, conf config) (err error) {
return
}

// setup influx database
func configureDatabase(conf server.InfluxConfig, loadPoints []loadpoint.API, in <-chan util.Param) {
// configureDatabase configures session database
func configureDatabase(conf dbConfig) error {
return db.NewInstance(conf.Type, conf.Dsn)
}

// configureInflux configures influx database
func configureInflux(conf server.InfluxConfig, loadPoints []loadpoint.API, in <-chan util.Param) {
influx := server.NewInfluxClient(
conf.URL,
conf.Token,
Expand All @@ -110,11 +116,6 @@ func configureDatabase(conf server.InfluxConfig, loadPoints []loadpoint.API, in
dedupe := pipe.NewDeduplicator(30*time.Minute, "vehicleCapacity", "vehicleSoC", "vehicleRange", "vehicleOdometer", "chargedEnergy", "chargeRemainingEnergy")
in = dedupe.Pipe(in)

// reduce number of values written to influx
// TODO this breaks writing vehicleRange as its re-writting in short interval
// limiter := pipe.NewLimiter(5 * time.Second)
// in = limiter.Pipe(in)

go influx.Run(loadPoints, in)
}

Expand All @@ -124,7 +125,7 @@ func configureMQTT(conf mqttConfig) error {

var err error
mqtt.Instance, err = mqtt.RegisteredClient(log, conf.Broker, conf.User, conf.Password, conf.ClientID, 1, conf.Insecure, func(options *paho.ClientOptions) {
topic := fmt.Sprintf("%s/status", conf.RootTopic())
topic := fmt.Sprintf("%s/status", strings.Trim(conf.Topic, "/"))
options.SetWill(topic, "offline", 1, true)
})
if err != nil {
Expand Down
20 changes: 5 additions & 15 deletions cmd/shutdown/shutdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package shutdown

import (
"sync"
"time"
)

var (
Expand All @@ -11,12 +10,14 @@ var (
exitC = make(chan struct{})
)

// Register registers a function for executing on application shutdown
func Register(cb func()) {
mu.Lock()
handlers = append(handlers, cb)
mu.Unlock()
}

// Run executes the registered shutdown functions when the stop channel closes
func Run(stopC <-chan struct{}) {
<-stopC
wg := new(sync.WaitGroup)
Expand All @@ -36,18 +37,7 @@ func Run(stopC <-chan struct{}) {
close(exitC)
}

func Done(timeout ...time.Duration) <-chan struct{} {
to := time.Second
if len(timeout) == 1 {
to = timeout[0]
}

select {
case <-exitC:
return exitC
case <-time.After(to):
exitC := make(chan struct{})
close(exitC)
return exitC
}
// Done returns a readable channel that closes when all registered functions have completed
func Done() <-chan struct{} {
return exitC
}
52 changes: 52 additions & 0 deletions core/db/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package db

import (
"time"

serverdb "github.com/evcc-io/evcc/server/db"
"github.com/evcc-io/evcc/util"
"gorm.io/gorm"
)

// DB is a SQL database storage service
type DB struct {
log *util.Logger
db *gorm.DB
name string
}

type Database interface {
Txn(startEnergy float64) *Transaction
Persist(txn interface{})
}

// New creates a database storage driver
func New(name string) (*DB, error) {
db := &DB{
log: util.NewLogger("db"),
db: serverdb.Instance,
name: name,
}

return db, nil
}

// Txn creates a charging transaction
func (s *DB) Txn(meter float64) *Transaction {
t := Transaction{
Loadpoint: s.name,
Created: time.Now(),
MeterStart: meter,
}

return &t
}

// Persist creates or updates a transaction in the database
func (s *DB) Persist(txn interface{}) {
s.log.TRACE.Printf("store: %+v", txn)

if err := s.db.Save(txn).Error; err != nil {
s.log.ERROR.Printf("store: %v", err)
}
}
Loading

0 comments on commit 85d0117

Please sign in to comment.