Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion charger/eebus-ohpcf.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type EEBusOHPCF struct {
mpcEntity spineapi.EntityRemoteInterface
dhwEntity spineapi.EntityRemoteInterface
enabled bool
dimmed bool
reboosting bool

connector *eebus.Connector
Expand Down Expand Up @@ -186,6 +187,14 @@ func (c *EEBusOHPCF) lastEnabled() bool {
return c.enabled
}

// controlEnable is the effective on/off intent: a §14a/LPC dim overrides enable.
func (c *EEBusOHPCF) controlEnable() bool {
c.mu.RLock()
defer c.mu.RUnlock()

return c.enabled && !c.dimmed
}

// ohpcfStatus maps the compressor process state to a charge status: running is
// consuming (C), any other connected state is standby (B). Disconnected (A) is handled in Status.
func ohpcfStatus(state ucapi.CompressorPowerConsumptionStateType) api.ChargeStatus {
Expand Down Expand Up @@ -360,6 +369,26 @@ func (c *EEBusOHPCF) MaxCurrent(int64) error {
return c.apply()
}

var _ api.Dimmer = (*EEBusOHPCF)(nil)

// Dimmed implements the api.Dimmer interface, reporting the active §14a/LPC dim state.
func (c *EEBusOHPCF) Dimmed() (bool, error) {
c.mu.RLock()
defer c.mu.RUnlock()

return c.dimmed, nil
}

// Dim implements the api.Dimmer interface. A §14a/LPC consumption limit pauses
// or aborts the optional consumption; releasing it resumes per the on/off intent.
func (c *EEBusOHPCF) Dim(dim bool) error {
c.mu.Lock()
c.dimmed = dim
c.mu.Unlock()

return c.apply()
}

// apply issues the command to align the optional consumption with the on/off
// intent. It is idempotent: ohpcfControlAction only acts on a state transition.
func (c *EEBusOHPCF) apply() error {
Expand All @@ -374,7 +403,7 @@ func (c *EEBusOHPCF) apply() error {
return nil
}

switch ohpcfControlAction(state, c.lastEnabled()) {
switch ohpcfControlAction(state, c.controlEnable()) {
case ohpcfSchedule:
return c.await(func(cb func(model.ResultDataType)) (*model.MsgCounterType, error) {
// 0 = start immediately (relative schedule, see SchedulePowerConsumptionProcess)
Expand Down
15 changes: 15 additions & 0 deletions charger/eebus-ohpcf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ func TestEEBusOHPCFNotConnected(t *testing.T) {

require.ErrorIs(t, c.Enable(true), errNotConnected)
require.ErrorIs(t, c.MaxCurrent(16), errNotConnected)
require.ErrorIs(t, c.Dim(true), errNotConnected)
}

// a §14a/LPC dim overrides the on/off intent: the compressor is only driven on
// when enabled and not dimmed.
func TestOHPCFDimGate(t *testing.T) {
c := &EEBusOHPCF{enabled: true}
assert.True(t, c.controlEnable())

c.dimmed = true
assert.False(t, c.controlEnable(), "dim overrides enable")

dimmed, err := c.Dimmed()
require.NoError(t, err)
assert.True(t, dimmed)
}

// status mapping: running is C, every other connected state (incl. completed
Expand Down
2 changes: 1 addition & 1 deletion templates/definition/charger/eebus-ohpcf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ products:
de: EEBUS Wärmepumpe (OHPCF)
en: EEBUS heat pump (OHPCF)
group: heating
capabilities: ["meter"]
capabilities: ["meter", "dim"]
params:
- preset: eebus
- name: reboost
Expand Down
Loading