Skip to content

Commit

Permalink
Add battery charge
Browse files Browse the repository at this point in the history
  • Loading branch information
andig committed Apr 25, 2024
1 parent 02bef4c commit ce83e05
Showing 1 changed file with 45 additions and 24 deletions.
69 changes: 45 additions & 24 deletions meter/e3dc.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,38 +223,59 @@ func (m *E3dc) batterySoc() (float64, error) {
func (m *E3dc) setBatteryMode(mode api.BatteryMode) error {
switch mode {
case api.BatteryNormal:
_, err := m.conn.Send(rscp.Message{
Tag: rscp.BAT_REQ_DATA,
DataType: rscp.Container,
Value: []rscp.Message{
{
Tag: rscp.EMS_POWER_LIMITS_USED,
DataType: rscp.Bool,
Value: 0,
},
},
_, err := m.conn.SendMultiple([]rscp.Message{
e3dcDischargeBatteryLimit(false, 0),
e3dcBatteryCharge(0),
})
return err

case api.BatteryHold:
_, err := m.conn.Send(rscp.Message{
Tag: rscp.EMS_REQ_SET_POWER_SETTINGS,
DataType: rscp.Container,
Value: []rscp.Message{
{
Tag: rscp.EMS_POWER_LIMITS_USED,
DataType: rscp.Bool,
Value: 1,
}, {
Tag: rscp.EMS_MAX_DISCHARGE_POWER,
DataType: rscp.Int32,
Value: 0,
},
},
_, err := m.conn.SendMultiple([]rscp.Message{

This comment has been minimized.

Copy link
@spali

spali Apr 25, 2024

würde Response immer anschauen... kann ein rscp Error von E3DC enthalten (die go-rscp gibt den 1:1 weiter).

rscp.Message{
  Tag:      rscp.IRGEND_EIN_TAG,
  DataType: rscp.Error,
  Value:    rscp.ERR_....
}

siehe: https://github.com/spali/go-rscp/blob/master/rscp/rscperror.go

Rudimentär könntest du immer den Datentyp checken auf rscp.Error und wenn ja Tag und Value als Error loggen.

Update: Value ist für den Fall von DataType rsc.Error immer uint32 entspechend den rscperror.go Konstanten.
Update 2: Kann leider nicht sagen ob ein Error in einem Container vorkommen kann oder nicht... hab es bis jetzt zumindestens nur immer als einzelnen Wert gesehen. Kann aber natürlich bei SendMultiple nur ein Element betreffen. Sprich im Antwort array müsstest du jedes Element mindestens den DataType auf rscp.Error absuchen.

This comment has been minimized.

Copy link
@andig

andig Apr 25, 2024

Author Member

Hast du dafür schon eine Libraryfubktion die aus Message einen oder mehrere errors macht? Sonst bau ich eine.

This comment has been minimized.

Copy link
@spali

spali Apr 25, 2024

Bin nicht sicher ob ich dich richtig verstanden habe... Du meinst aus rscp.Message "Errors" go Errors machen?

err von SendMultiple enthält nur errors von go-rscp selber. Mögliche errors: https://github.com/spali/go-rscp/blob/master/rscp/errors.go

_ enthält responses... jede Response könnte auch ein rscp Error enthalten (von E3DC gesendet).
Das Beispiel oben kann als Antwort auf ein Request kommen... sprich du musst aktuell _ von SendMultiple loopen und nach DataType: rscp.Error suchen. Ob du diese in go errors umwandeln willst oder ist dir überlassen... zumindestens das Struct dumpen im LogLevel error würde ich.
Im normalbetrieb sollten sich diese Errors in Grenzen halten.. die meisten kommen durch ungültige Requests. Ich würde mir nicht die mühe machen ein schönen error draus zu machen solange du eh nicht viel damit anfangen kannst. Denke loggen sollte reichen. Falls ein Szenario einttritt wo bei einem Nutzer ein Error kommt wo es beim andern nicht tut... müsste man das nochmals genauer anschauen ob man irgendwie auf den Error reagieren kann....

This comment has been minimized.

Copy link
@andig

andig Apr 25, 2024

Author Member

Wirf nochmal einen Blick drauf. Jetzt gibts eine kleine Funktion die über n Messages nach rscp.Error scannt und diesen in einen Go Error verwandelt. Ein bisschen nervig ist dabei, dass NewMessage und Send mit *Message arbeiten, SendMultiple aber mit Message. Das wirkt etwas willkürlich. Konsistenz wäre Klasse, aber natürlich auch breaking :)

This comment has been minimized.

Copy link
@spali

spali Apr 25, 2024

Könnte funzen 😉
bzgl. Pointer ... soweit mir ist, ein Slice ist bereits ein Pointer zu einem unterliegendem Array. Da lässt sich jetzt drüber streiten ob man davon nur der "Optik" wegen nochmals hinter einem Pointer versteckt.
Aber verstehe dein anliegen. Falls es dir ums *NewMessage geht.... lass das doch weg und nutz direkt ein struct-Literal rscp.Message... dann kannst du mehrere in einem Slice definieren ohne * (siehe cmd/example ).

This comment has been minimized.

Copy link
@andig

andig Apr 25, 2024

Author Member

Das stimmt natürlich- aber es bleibt ein Array of Struct statt []*Message. Man sieht ja im Code das man je nach single/multi Result immer umdenken muss. Ist aber auch nicht kriegsentscheidend und nun ist ja ja schonmal da ;)

e3dcDischargeBatteryLimit(true, 0),
e3dcBatteryCharge(0),
})
return err

case api.BatteryCharge:
_, err := m.conn.SendMultiple([]rscp.Message{
e3dcDischargeBatteryLimit(true, 0),
e3dcBatteryCharge(10000), // 10kWh
})
return err

default:
return api.ErrNotAvailable
}
}

func e3dcDischargeBatteryLimit(active bool, limit int) rscp.Message {
container := []rscp.Message{
{
Tag: rscp.EMS_POWER_LIMITS_USED,
DataType: rscp.Bool,
Value: cast.ToInt(active),

This comment has been minimized.

Copy link
@spali

spali Apr 25, 2024

sollte auch wirklich Bool sein... ;) Sonst knallts beim übersetzen in Bytes.

},
}

if active {
container = append(container, rscp.Message{
Tag: rscp.EMS_MAX_DISCHARGE_POWER,
DataType: rscp.Uint32,
Value: limit,
})
}

return rscp.Message{
Tag: rscp.EMS_REQ_SET_POWER_SETTINGS,
DataType: rscp.Container,
Value: container,
}
}

func e3dcBatteryCharge(amount int) rscp.Message {
return rscp.Message{
Tag: rscp.EMS_REQ_START_MANUAL_CHARGE,
DataType: rscp.Uint32,
Value: amount, // 10kWh
}
}

0 comments on commit ce83e05

Please sign in to comment.