Skip to content

Commit

Permalink
Add charger, meter and vehicle commands (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Apr 15, 2020
1 parent 9513e91 commit dde26c7
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 38 deletions.
66 changes: 66 additions & 0 deletions cmd/charger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package cmd

import (
"fmt"

"github.com/andig/evcc/provider"
"github.com/andig/evcc/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// chargerCmd represents the charger command
var chargerCmd = &cobra.Command{
Use: "charger [name]",
Short: "Query configured chargers",
Run: runCharger,
}

func init() {
cobra.OnInitialize(initConfig)
rootCmd.AddCommand(chargerCmd)
configureCommand(chargerCmd)
}

func runCharger(cmd *cobra.Command, args []string) {
level, _ := cmd.PersistentFlags().GetString("log")
configureLogging(level)
log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit)

// load config
conf := loadConfigFile(cfgFile)

// setup mqtt
if viper.Get("mqtt") != nil {
provider.MQTT = provider.NewMqttClient(conf.Mqtt.Broker, conf.Mqtt.User, conf.Mqtt.Password, clientID(), 1)
}

chargers := configureChargers(conf)

for name, v := range chargers {
if len(args) == 1 {
if target := args[0]; name != target {
if _, ok := chargers[target]; !ok {
log.FATAL.Fatalf("charger not found: %s", target)
}
continue
}
} else if len(chargers) != 1 {
fmt.Println(name)
}

if status, err := v.Status(); err != nil {
fmt.Printf("Status: %v\n", err)
} else {
fmt.Printf("Status: %s\n", status)
}

if enabled, err := v.Enabled(); err != nil {
fmt.Printf("Enabled: %v\n", err)
} else {
fmt.Printf("Enabled: %s\n", truefalse[enabled])
}

dumpAPIs(v)
}
}
43 changes: 43 additions & 0 deletions cmd/dump.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cmd

import (
"fmt"

"github.com/andig/evcc/api"
)

var truefalse = map[bool]string{false: "false", true: "true"}

func dumpAPIs(v interface{}) {
if v, ok := v.(api.Meter); ok {
if power, err := v.CurrentPower(); err != nil {
fmt.Printf("Power: %v\n", err)
} else {
fmt.Printf("Power: %.0fW\n", power)
}
}

if v, ok := v.(api.MeterEnergy); ok {
if energy, err := v.TotalEnergy(); err != nil {
fmt.Printf("Energy: %v\n", err)
} else {
fmt.Printf("Energy: %.0fkWh\n", energy)
}
}

if v, ok := v.(api.ChargeRater); ok {
if energy, err := v.ChargedEnergy(); err != nil {
fmt.Printf("Charged: %v\n", err)
} else {
fmt.Printf("Charged: %.0fkWh\n", energy)
}
}

if v, ok := v.(api.ChargeTimer); ok {
if duration, err := v.ChargingTime(); err != nil {
fmt.Printf("Duration: %v\n", err)
} else {
fmt.Printf("Duration: %v\n", duration)
}
}
}
54 changes: 54 additions & 0 deletions cmd/meter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package cmd

import (
"fmt"

"github.com/andig/evcc/provider"
"github.com/andig/evcc/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// meterCmd represents the meter command
var meterCmd = &cobra.Command{
Use: "meter [name]",
Short: "Query configured meters",
Run: runMeter,
}

func init() {
cobra.OnInitialize(initConfig)
rootCmd.AddCommand(meterCmd)
configureCommand(meterCmd)
}

func runMeter(cmd *cobra.Command, args []string) {
level, _ := cmd.PersistentFlags().GetString("log")
configureLogging(level)
log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit)

// load config
conf := loadConfigFile(cfgFile)

// setup mqtt
if viper.Get("mqtt") != nil {
provider.MQTT = provider.NewMqttClient(conf.Mqtt.Broker, conf.Mqtt.User, conf.Mqtt.Password, clientID(), 1)
}

meters := configureMeters(conf)

for name, v := range meters {
if len(args) == 1 {
if target := args[0]; name != target {
if _, ok := meters[target]; !ok {
log.FATAL.Fatalf("meter not found: %s", target)
}
continue
}
} else if len(meters) != 1 {
fmt.Println(name)
}

dumpAPIs(v)
}
}
66 changes: 33 additions & 33 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/andig/evcc/api"
"github.com/andig/evcc/core"
"github.com/andig/evcc/provider"
"github.com/andig/evcc/server"

"github.com/spf13/cobra"
Expand All @@ -26,46 +27,49 @@ var rootCmd = &cobra.Command{
Run: run,
}

func bind(flag string) {
if err := viper.BindPFlag(flag, rootCmd.PersistentFlags().Lookup(flag)); err != nil {
func bind(cmd *cobra.Command, flag string) {
if err := viper.BindPFlag(flag, cmd.PersistentFlags().Lookup(flag)); err != nil {
panic(err)
}
}

func configureCommand(cmd *cobra.Command) {
cmd.PersistentFlags().StringP(
"log", "l",
"error",
"Log level (fatal, error, warn, info, debug, trace)",
)
bind(cmd, "log")

cmd.PersistentFlags().StringVarP(&cfgFile,
"config", "c",
"",
"Config file (default \"~/evcc.yaml\" or \"/etc/evcc.yaml\")",
)
cmd.PersistentFlags().BoolP(
"help", "h",
false,
"Help for "+cmd.Name(),
)
}

func init() {
cobra.OnInitialize(initConfig)
configureCommand(rootCmd)

rootCmd.PersistentFlags().StringP(
"uri", "u",
"0.0.0.0:7070",
"Listen address",
)
bind("uri")

rootCmd.PersistentFlags().StringP(
"log", "l",
"info",
"Log level (fatal, error, warn, info, debug, trace)",
)
bind("log")
bind(rootCmd, "uri")

rootCmd.PersistentFlags().DurationP(
"interval", "i",
10*time.Second,
"Update interval",
)
bind("interval")

rootCmd.PersistentFlags().StringVarP(&cfgFile,
"config", "c",
"",
"Config file (default \"~/evcc.yaml\" or \"/etc/evcc.yaml\")",
)
rootCmd.PersistentFlags().BoolP(
"help", "h",
false,
"Help for "+rootCmd.Name(),
)
bind(rootCmd, "interval")
}

// initConfig reads in config file and ENV variables if set
Expand Down Expand Up @@ -158,17 +162,8 @@ func run(cmd *cobra.Command, args []string) {
configureLogging(level)
log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit)

var conf config
if cfgFile != "" {
log.INFO.Println("using config file", cfgFile)
if err := viper.UnmarshalExact(&conf); err != nil {
log.FATAL.Fatalf("config: failed parsing config file %s: %v", cfgFile, err)
}
} else {
log.FATAL.Fatal("missing evcc config")
}

// re-configure after reading config file
// load config and re-configure logging after reading config file
conf := loadConfigFile(cfgFile)
configureLogging(conf.Log)

go checkVersion()
Expand All @@ -179,6 +174,11 @@ func run(cmd *cobra.Command, args []string) {
// setup messaging
notificationChan := configureMessengers(conf.Messaging)

// setup mqtt
if viper.Get("mqtt") != nil {
provider.MQTT = provider.NewMqttClient(conf.Mqtt.Broker, conf.Mqtt.User, conf.Mqtt.Password, clientID(), 1)
}

// setup loadpoints
loadPoints := loadConfig(conf, notificationChan)

Expand Down
17 changes: 12 additions & 5 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/andig/evcc/api"
"github.com/andig/evcc/charger"
"github.com/andig/evcc/core"
"github.com/andig/evcc/provider"
"github.com/andig/evcc/push"
"github.com/andig/evcc/vehicle"
"github.com/spf13/viper"
Expand Down Expand Up @@ -95,10 +94,6 @@ func configureLoadPoint(lp *core.LoadPoint, lpc loadPointConfig, subv *viper.Vip
}

func loadConfig(conf config, eventsChan chan push.Event) (loadPoints []*core.LoadPoint) {
if viper.Get("mqtt") != nil {
provider.MQTT = provider.NewMqttClient(conf.Mqtt.Broker, conf.Mqtt.User, conf.Mqtt.Password, clientID(), 1)
}

meters := configureMeters(conf)
chargers := configureChargers(conf)
vehicles := configureVehicles(conf)
Expand Down Expand Up @@ -148,3 +143,15 @@ func loadConfig(conf config, eventsChan chan push.Event) (loadPoints []*core.Loa

return
}

func loadConfigFile(cfgFile string) (conf config) {
if cfgFile != "" {
log.INFO.Println("using config file", cfgFile)
if err := viper.UnmarshalExact(&conf); err != nil {
log.FATAL.Fatalf("config: failed parsing config file %s: %v", cfgFile, err)
}
} else {
log.FATAL.Fatal("missing evcc config")
}
return
}
60 changes: 60 additions & 0 deletions cmd/vehicle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cmd

import (
"fmt"

"github.com/andig/evcc/provider"
"github.com/andig/evcc/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// vehicleCmd represents the vehicle command
var vehicleCmd = &cobra.Command{
Use: "vehicle [name]",
Short: "Query configured vehicles",
Run: runVehicle,
}

func init() {
cobra.OnInitialize(initConfig)
rootCmd.AddCommand(vehicleCmd)
configureCommand(vehicleCmd)
}

func runVehicle(cmd *cobra.Command, args []string) {
level, _ := cmd.PersistentFlags().GetString("log")
configureLogging(level)
log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit)

// load config
conf := loadConfigFile(cfgFile)

// setup mqtt
if viper.Get("mqtt") != nil {
provider.MQTT = provider.NewMqttClient(conf.Mqtt.Broker, conf.Mqtt.User, conf.Mqtt.Password, clientID(), 1)
}

vehicles := configureVehicles(conf)

for name, v := range vehicles {
if len(args) == 1 {
if target := args[0]; name != target {
if _, ok := vehicles[target]; !ok {
log.FATAL.Fatalf("charger not found: %s", target)
}
continue
}
} else if len(vehicles) != 1 {
fmt.Println(name)
}

if soc, err := v.ChargeState(); err != nil {
fmt.Printf("State: %v\n", err)
} else {
fmt.Printf("State: %.0f%%\n", soc)
}

dumpAPIs(v)
}
}

0 comments on commit dde26c7

Please sign in to comment.