Skip to content

Commit

Permalink
Fix various issues in NRGKick implementation (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig committed May 19, 2020
1 parent bc4fcea commit 044eb87
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 49 deletions.
46 changes: 25 additions & 21 deletions charger/nrgble/nrg_linux.go
Expand Up @@ -4,26 +4,27 @@ import (
"errors"
"fmt"
"strings"
"time"

"github.com/muka/go-bluetooth/api"
"github.com/muka/go-bluetooth/bluez/profile/adapter"
"github.com/muka/go-bluetooth/bluez/profile/agent"
"github.com/muka/go-bluetooth/bluez/profile/device"
)

func FindDevice(a *adapter.Adapter1, hwaddr string) (*device.Device1, error) {
dev, err := Discover(a, hwaddr)
func FindDevice(a *adapter.Adapter1, hwaddr string, timeout time.Duration) (*device.Device1, error) {
dev, err := Discover(a, hwaddr, timeout)
if err != nil {
return nil, err
}
if dev == nil {
return nil, errors.New("Device not found, is it advertising?")
return nil, errors.New("device not found, is it advertising?")
}

return dev, nil
}

func Discover(a *adapter.Adapter1, hwaddr string) (*device.Device1, error) {
func Discover(a *adapter.Adapter1, hwaddr string, timeout time.Duration) (*device.Device1, error) {
err := a.FlushDevices()
if err != nil {
return nil, err
Expand All @@ -34,28 +35,31 @@ func Discover(a *adapter.Adapter1, hwaddr string) (*device.Device1, error) {
return nil, err
}

defer cancel()
timer := time.NewTimer(timeout)

for ev := range discovery {
dev, err1 := device.NewDevice1(ev.Path)
if err != nil {
return nil, err1
}

if dev == nil || dev.Properties == nil {
continue
}
for {
select {
case ev := <-discovery:
dev, err := device.NewDevice1(ev.Path)
if err != nil {
return nil, err
}
if dev == nil || dev.Properties == nil {
continue
}

p := dev.Properties
p := dev.Properties
if p.Address != hwaddr {
continue
}

if p.Address != hwaddr {
continue
cancel()
return dev, nil
case <-timer.C:
cancel()
return nil, errors.New("discovery timeout exceeded")
}

return dev, nil
}

return nil, nil
}

func Connect(dev *device.Device1, ag *agent.SimpleAgent, adapterID string) error {
Expand Down
51 changes: 28 additions & 23 deletions charger/nrgble_linux.go
Expand Up @@ -18,16 +18,20 @@ import (
"github.com/muka/go-bluetooth/hw"
)

const nrgTimeout = 30 * time.Second

// NRGKickBLE charger implementation
type NRGKickBLE struct {
log *util.Logger
timer *time.Timer
adapter *adapter.Adapter1
agent *agent.SimpleAgent
dev *device.Device1
device string
macaddress string
pin int
log *util.Logger
timer *time.Timer
adapter *adapter.Adapter1
agent *agent.SimpleAgent
dev *device.Device1
device string
macaddress string
pin int
pauseCharging bool
current int
}

// NewNRGKickBLEFromConfig creates a NRGKickBLE charger from generic config
Expand Down Expand Up @@ -107,9 +111,9 @@ func NewNRGKickBLE(device, macaddress string, pin int) *NRGKickBLE {
}

func (nrg *NRGKickBLE) connect() (*device.Device1, error) {
dev, err := nrgble.FindDevice(nrg.adapter, nrg.macaddress)
dev, err := nrgble.FindDevice(nrg.adapter, nrg.macaddress, nrgTimeout)
if err != nil {
return nil, fmt.Errorf("findDevice: %s", err)
return nil, fmt.Errorf("find device: %s", err)
}

err = nrgble.Connect(dev, nrg.agent, nrg.device)
Expand Down Expand Up @@ -196,15 +200,16 @@ func (nrg *NRGKickBLE) write(service string, val interface{}) error {
return nil
}

func (nrg *NRGKickBLE) defaultSettings(info nrgble.Info) nrgble.Settings {
func (nrg *NRGKickBLE) mergeSettings(info nrgble.Info) nrgble.Settings {
return nrgble.Settings{
PIN: nrg.pin,
ChargingEnergyLimit: 19997, // magic const for "disable"
KWhPer100: info.KWhPer100,
AmountPerKWh: info.AmountPerKWh,
Efficiency: info.Efficiency,
PauseCharging: info.PauseCharging,
BLETransmissionPower: info.BLETransmissionPower,
PauseCharging: nrg.pauseCharging, // apply last value
Current: nrg.current, // apply last value
}
}

Expand All @@ -215,7 +220,7 @@ func (nrg *NRGKickBLE) Status() (api.ChargeStatus, error) {
return api.StatusF, err
}

nrg.log.TRACE.Printf("power: %+v", res)
nrg.log.TRACE.Printf("read power: %+v", res)

switch res.CPSignal {
case 3:
Expand All @@ -237,7 +242,7 @@ func (nrg *NRGKickBLE) Enabled() (bool, error) {
return false, err
}

nrg.log.TRACE.Printf("info: %+v", res)
nrg.log.TRACE.Printf("read info: %+v", res)

return !res.PauseCharging, nil
}
Expand All @@ -249,10 +254,10 @@ func (nrg *NRGKickBLE) Enable(enable bool) error {
return err
}

nrg.log.TRACE.Printf("info: %+v", res)
nrg.pauseCharging = !enable // use cached value to work around API roundtrip delay
settings := nrg.mergeSettings(res)

settings := nrg.defaultSettings(res)
settings.PauseCharging = !enable
nrg.log.TRACE.Printf("write settings: %+v", settings)

return nrg.write(nrgble.SettingsService, &settings)
}
Expand All @@ -264,10 +269,10 @@ func (nrg *NRGKickBLE) MaxCurrent(current int64) error {
return err
}

nrg.log.TRACE.Printf("info: %+v", res)
nrg.current = int(current) // use cached value to work around API roundtrip delay
settings := nrg.mergeSettings(res)

settings := nrg.defaultSettings(res)
settings.Current = int(current)
nrg.log.TRACE.Printf("write settings: %+v", settings)

return nrg.write(nrgble.SettingsService, &settings)
}
Expand All @@ -279,7 +284,7 @@ func (nrg *NRGKickBLE) CurrentPower() (float64, error) {
return 0, err
}

nrg.log.TRACE.Printf("power: %+v", res)
nrg.log.TRACE.Printf("read power: %+v", res)

return float64(res.TotalPower) * 10, nil
}
Expand All @@ -291,7 +296,7 @@ func (nrg *NRGKickBLE) TotalEnergy() (float64, error) {
return 0, err
}

nrg.log.TRACE.Printf("energy: %+v", res)
nrg.log.TRACE.Printf("read energy: %+v", res)

return float64(res.TotalEnergy) / 1000, nil
}
Expand All @@ -303,7 +308,7 @@ func (nrg *NRGKickBLE) Currents() (float64, float64, float64, error) {
return 0, 0, 0, err
}

nrg.log.TRACE.Printf("voltage/current: %+v", res)
nrg.log.TRACE.Printf("read voltage/current: %+v", res)

return float64(res.CurrentL1) / 100,
float64(res.CurrentL2) / 100,
Expand Down
10 changes: 5 additions & 5 deletions charger/nrgconnect.go
Expand Up @@ -131,7 +131,7 @@ func (nrg *NRGKickConnect) Status() (api.ChargeStatus, error) {
// Enabled implements the Charger.Enabled interface
func (nrg *NRGKickConnect) Enabled() (bool, error) {
var settings NRGSettings
err := nrg.getJSON(nrg.apiURL(apiSettings), settings)
err := nrg.getJSON(nrg.apiURL(apiSettings), &settings)

return *settings.Values.ChargingStatus.Charging, err
}
Expand All @@ -157,23 +157,23 @@ func (nrg *NRGKickConnect) MaxCurrent(current int64) error {
// CurrentPower implements the Meter interface
func (nrg *NRGKickConnect) CurrentPower() (float64, error) {
var measurements NRGMeasurements
err := nrg.getJSON(nrg.apiURL(apiMeasurements), measurements)
err := nrg.getJSON(nrg.apiURL(apiMeasurements), &measurements)

return 1000 * measurements.ChargingPower, err
}

// TotalEnergy implements the MeterEnergy interface
func (nrg *NRGKickConnect) TotalEnergy() (float64, error) {
var measurements NRGMeasurements
err := nrg.getJSON(nrg.apiURL(apiMeasurements), measurements)
err := nrg.getJSON(nrg.apiURL(apiMeasurements), &measurements)

return measurements.ChargingEnergyOverAll, err
}

// Currents implements the MeterCurrent interface
func (nrg *NRGKickConnect) Currents() (float64, float64, float64, error) {
var measurements NRGMeasurements
err := nrg.getJSON(nrg.apiURL(apiMeasurements), measurements)
err := nrg.getJSON(nrg.apiURL(apiMeasurements), &measurements)

if len(measurements.ChargingCurrentPhase) != 3 {
return 0, 0, 0, fmt.Errorf("unexpected response: %v", measurements)
Expand All @@ -189,6 +189,6 @@ func (nrg *NRGKickConnect) Currents() (float64, float64, float64, error) {
// NOTE: apparently shows energy of a stopped charging session, hence substituted by TotalEnergy
// func (nrg *NRGKickConnect) ChargedEnergy() (float64, error) {
// var measurements NRGMeasurements
// err := nrg.getJSON(nrg.apiURL(apiMeasurements), measurements)
// err := nrg.getJSON(nrg.apiURL(apiMeasurements), &measurements)
// return measurements.ChargingEnergy, err
// }

0 comments on commit 044eb87

Please sign in to comment.