evcc icon indicating copy to clipboard operation
evcc copied to clipboard

Custom charger: add typical meter measurements

Open andig opened this issue 1 year ago • 4 comments

Fix https://github.com/evcc-io/evcc/issues/14508

andig avatar Jun 24 '24 18:06 andig

Wow, der PR hat 27000 Zeilen generierten Code geändert. Langsam mache ich mir Sorgen!

UPDATE binary geht von 103MB auf 117MB auf dem Mac. Das ist leider ein No-Go!

@GrimmiMeloni dazu fällt dir auch nichts ein, oder?

andig avatar Jun 24 '24 18:06 andig

Zwei (hässliche) Optimierungsideen fallen mir ein:

  • falls es meter nicht gibt ist die ganze Kombinatorik der weiteren Strommesswerte irrelavant, sie könnten also entfallen.
  • ich frage mich, ob es irgendwie möglich wäre, einen Sum-Type (struct) aus spezifischem Charger und spezifischem Meter zu erzeugen, aber jedes nur für sich zu erzeugen

andig avatar Jun 24 '24 19:06 andig

@GrimmiMeloni I've prototyped the idea above. This does work:


func TestMeterDecoration(t *testing.T) {
	ctrl := gomock.NewController(t)

	type chargerStruct = struct {
		api.Charger
		api.PhaseSwitcher
	}

	charger := chargerStruct{
		api.NewMockCharger(ctrl),
		api.NewMockPhaseSwitcher(ctrl),
	}

	assert.Implements(t, (*api.Charger)(nil), charger)
	assert.Implements(t, (*api.PhaseSwitcher)(nil), charger)

	meter := api.NewMockMeter(ctrl)

	combined := struct {
		chargerStruct
		api.Meter
	}{
		charger,
		meter,
	}

	assert.Implements(t, (*api.Charger)(nil), combined)
	assert.Implements(t, (*api.PhaseSwitcher)(nil), combined)
	assert.Implements(t, (*api.Meter)(nil), combined)
}

while this doesn't:

func TestMeterDecoration(t *testing.T) {
	ctrl := gomock.NewController(t)

	charger := struct {
		api.Charger
		api.PhaseSwitcher
	}{
		api.NewMockCharger(ctrl),
		api.NewMockPhaseSwitcher(ctrl),
	}

	assert.Implements(t, (*api.Charger)(nil), charger)
	assert.Implements(t, (*api.PhaseSwitcher)(nil), charger)

	meter := api.NewMockMeter(ctrl)

	combined := struct {
		api.Charger
		api.Meter
	}{
		charger,
		meter,
	}

	assert.Implements(t, (*api.Charger)(nil), combined)
	assert.Implements(t, (*api.PhaseSwitcher)(nil), combined)
	assert.Implements(t, (*api.Meter)(nil), combined)
}

This makes me think that it might work to partition the combinations and build a combined type of specific charger and meter sub types.

andig avatar Jun 26 '24 07:06 andig

Refs https://groups.google.com/g/golang-nuts/c/Oo9Nwm4AZRI

andig avatar Jun 26 '24 08:06 andig

Testcase nochmal aktualisiert:

package main

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

type If1 interface {
	F1()
}

type If1Impl struct{}

func (i *If1Impl) F1() {
}

type If2 interface {
	F2()
}

type If2Impl struct{}

func (i *If2Impl) F2() {
}

type If3 interface {
	F3()
}

type If3Impl struct{}

func (i *If3Impl) F3() {
}

type If12 interface {
	If1
	If2
}

func TestEmbedding(t *testing.T) {
	type if12T struct {
		If1
		If2
	}

	if12 := if12T{
		new(If1Impl),
		new(If2Impl),
	}

	meter := new(If3Impl)

	check := func(i any, msg string) {
		assert.Implements(t, (*If1)(nil), i, msg)
		assert.Implements(t, (*If2)(nil), i, msg)
		assert.Implements(t, (*If3)(nil), i, msg)
	}

	structs := struct {
		*if12T
		If3
	}{
		&if12,
		meter,
	}
	check(structs, "structs")

	interfaces := struct {
		If12
		If3
	}{
		if12,
		meter,
	}
	check(interfaces, "interfaces")

	interfaces2 := struct {
		If1
		If3
	}{
		if12,
		meter,
	}
	check(interfaces2, "implicit interfaces")
}

ergibt:

--- FAIL: TestEmbedding (0.00s)
    /Users/andig/htdocs/interfaces/main_test.go:56: 
        	Error Trace:	/Users/andig/htdocs/interfaces/main_test.go:56
        	            				/Users/andig/htdocs/interfaces/main_test.go:85
        	Error:      	struct { main.If1; main.If3 } must implement main.If2
        	Test:       	TestEmbedding
        	Messages:   	implicit interfaces

andig avatar Jul 14 '24 12:07 andig