Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
574e832152 | ||
|
|
2a84799832 | ||
|
|
8adf3c8261 | ||
|
|
b3245aba9b | ||
|
|
dac2149fbd | ||
|
|
e501f6d125 |
2
.github/workflows/docker-build.yml
vendored
2
.github/workflows/docker-build.yml
vendored
@@ -57,7 +57,7 @@ jobs:
|
|||||||
- name: Build and push to GitHub Container Registry
|
- name: Build and push to GitHub Container Registry
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const (
|
|||||||
acL1InfoFrame = 0x08
|
acL1InfoFrame = 0x08
|
||||||
dcInfoFrame = 0x0C
|
dcInfoFrame = 0x0C
|
||||||
setTargetFrame = 0x41
|
setTargetFrame = 0x41
|
||||||
infoReqFrame = 0x46
|
infoReqFrame = 0x46 //F
|
||||||
ledFrame = 0x4C
|
ledFrame = 0x4C
|
||||||
vFrame = 0x56
|
vFrame = 0x56
|
||||||
winmonFrame = 0x57
|
winmonFrame = 0x57
|
||||||
@@ -346,7 +346,7 @@ func (m *mk2Ser) dcDecode(frame []byte) {
|
|||||||
chargeC := m.applyScale(getUnsigned(frame[10:13]), ramVarIBat)
|
chargeC := m.applyScale(getUnsigned(frame[10:13]), ramVarIBat)
|
||||||
m.info.BatCurrent = usedC - chargeC
|
m.info.BatCurrent = usedC - chargeC
|
||||||
|
|
||||||
m.info.OutFrequency = 10 / (m.applyScale(float64(frame[13]), ramVarInverterPeriod))
|
m.info.OutFrequency = m.calcFreq(frame[13], ramVarInverterPeriod)
|
||||||
logrus.Debugf("dcDecode %#v", m.info)
|
logrus.Debugf("dcDecode %#v", m.info)
|
||||||
|
|
||||||
// Send L1 status request
|
// Send L1 status request
|
||||||
@@ -358,16 +358,12 @@ func (m *mk2Ser) dcDecode(frame []byte) {
|
|||||||
|
|
||||||
// Decodes AC frame.
|
// Decodes AC frame.
|
||||||
func (m *mk2Ser) acDecode(frame []byte) {
|
func (m *mk2Ser) acDecode(frame []byte) {
|
||||||
m.info.InVoltage = m.applyScaleAndSign(frame[5:7], ramVarVMains)
|
m.info.InVoltage = m.applyScale(getSigned(frame[5:7]), ramVarVMains)
|
||||||
m.info.InCurrent = m.applyScaleAndSign(frame[7:9], ramVarIMains)
|
m.info.InCurrent = m.applyScale(getSigned(frame[7:9]), ramVarIMains)
|
||||||
m.info.OutVoltage = m.applyScaleAndSign(frame[9:11], ramVarVInverter)
|
m.info.OutVoltage = m.applyScale(getSigned(frame[9:11]), ramVarVInverter)
|
||||||
m.info.OutCurrent = m.applyScaleAndSign(frame[11:13], ramVarIInverter)
|
m.info.OutCurrent = m.applyScale(getSigned(frame[11:13]), ramVarIInverter)
|
||||||
|
m.info.InFrequency = m.calcFreq(frame[13], ramVarMainPeriod)
|
||||||
|
|
||||||
if frame[13] == 0xff {
|
|
||||||
m.info.InFrequency = 0
|
|
||||||
} else {
|
|
||||||
m.info.InFrequency = 10 / (m.applyScale(float64(frame[13]), ramVarMainPeriod))
|
|
||||||
}
|
|
||||||
logrus.Debugf("acDecode %#v", m.info)
|
logrus.Debugf("acDecode %#v", m.info)
|
||||||
|
|
||||||
// Send status request
|
// Send status request
|
||||||
@@ -376,6 +372,13 @@ func (m *mk2Ser) acDecode(frame []byte) {
|
|||||||
m.sendCommand(cmd)
|
m.sendCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mk2Ser) calcFreq(data byte, scaleIndex int) float64 {
|
||||||
|
if data == 0xff || data == 0x00 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 10 / (m.applyScale(float64(data), scaleIndex))
|
||||||
|
}
|
||||||
|
|
||||||
// Decode charge state of battery.
|
// Decode charge state of battery.
|
||||||
func (m *mk2Ser) stateDecode(frame []byte) {
|
func (m *mk2Ser) stateDecode(frame []byte) {
|
||||||
m.info.ChargeState = m.applyScaleAndSign(frame[1:3], ramVarChargeState)
|
m.info.ChargeState = m.applyScaleAndSign(frame[1:3], ramVarChargeState)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ var knownWrites = []byte{
|
|||||||
var writeBuffer = bytes.NewBuffer(nil)
|
var writeBuffer = bytes.NewBuffer(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testEpsilon = 0.00000001
|
testDelta = 0.00000001
|
||||||
)
|
)
|
||||||
|
|
||||||
type testIo struct {
|
type testIo struct {
|
||||||
@@ -50,62 +50,162 @@ func NewIOStub(readBuffer []byte) io.ReadWriter {
|
|||||||
|
|
||||||
// Test a know sequence as reference as extracted from Mk2
|
// Test a know sequence as reference as extracted from Mk2
|
||||||
func TestSync(t *testing.T) {
|
func TestSync(t *testing.T) {
|
||||||
knownReadBuffer := []byte{
|
tests := []struct {
|
||||||
//Len Cmd
|
name string
|
||||||
0x04, 0xff, 0x41, 0x01, 0x00, 0xbb, 0x07, 0xff, 0x56, 0x96, 0x3e, 0x11, 0x00, 0x00, 0xbf,
|
knownReadBuffer []byte
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
knownWrites []byte
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
result Mk2Info
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
}{
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
{
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
name: "basic",
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
knownReadBuffer: []byte{
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
//Len Cmd
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x57, 0x78, 0x8f, 0x00, 0x01, 0xb5,
|
0x04, 0xff, 0x41, 0x01, 0x00, 0xbb,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x2f, 0x7c, 0x8f, 0x00, 0x00, 0xda,
|
0x07, 0xff, 0x56, 0x96, 0x3e, 0x11, 0x00, 0x00, 0xbf,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x04, 0x00, 0x8f, 0x00, 0x80, 0x01,
|
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x01, 0x00, 0x8f, 0x00, 0x80, 0x04,
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x02, 0x00, 0x8f, 0x00, 0x80, 0x03,
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x38, 0x7f, 0x8f, 0x00, 0x00, 0xce,
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
||||||
0x07, 0xff, 0x56, 0x96, 0x3e, 0x11, 0x00, 0x00, 0xbf,
|
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
||||||
0x0f, 0x20, 0xf3, 0x00, 0xc8, 0x02, 0x0c, 0xa1, 0x05, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x88, 0xb2,
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
||||||
0x0f, 0x20, 0x01, 0x01, 0xca, 0x09, 0x08, 0xaa, 0x58, 0xab, 0x00, 0xaa, 0x58, 0x9a, 0x00, 0xc3, 0xe8,
|
0x08, 0xff, 0x57, 0x8e, 0x57, 0x78, 0x8f, 0x00, 0x01, 0xb5,
|
||||||
0x06, 0xff, 0x4c, 0x03, 0x00, 0x00, 0x00, 0xac,
|
0x08, 0xff, 0x57, 0x8e, 0x2f, 0x7c, 0x8f, 0x00, 0x00, 0xda,
|
||||||
0x05, 0xff, 0x57, 0x85, 0xc8, 0x00, 0x58,
|
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x04, 0x00, 0x8f, 0x00, 0x80, 0x01,
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x01, 0x00, 0x8f, 0x00, 0x80, 0x04,
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x02, 0x00, 0x8f, 0x00, 0x80, 0x03,
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x38, 0x7f, 0x8f, 0x00, 0x00, 0xce,
|
||||||
|
0x07, 0xff, 0x56, 0x96, 0x3e, 0x11, 0x00, 0x00, 0xbf,
|
||||||
|
0x0f, 0x20, 0xf3, 0x00, 0xc8, 0x02, 0x0c, 0xa1, 0x05, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x88, 0xb2,
|
||||||
|
0x0f, 0x20, 0x01, 0x01, 0xca, 0x09, 0x08, 0xaa, 0x58, 0xab, 0x00, 0xaa, 0x58, 0x9a, 0x00, 0xc3, 0xe8,
|
||||||
|
0x06, 0xff, 0x4c, 0x03, 0x00, 0x00, 0x00, 0xac,
|
||||||
|
0x05, 0xff, 0x57, 0x85, 0xc8, 0x00, 0x58,
|
||||||
|
},
|
||||||
|
knownWrites: []byte{
|
||||||
|
0x04, 0xff, 0x41, 0x01, 0x00, 0xbb,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x00, 0x00, 0x6f,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x01, 0x00, 0x6e,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x02, 0x00, 0x6d,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x03, 0x00, 0x6c,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x04, 0x00, 0x6b,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x05, 0x00, 0x6a,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x06, 0x00, 0x69,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x07, 0x00, 0x68,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x08, 0x00, 0x67,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x09, 0x00, 0x66,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x0a, 0x00, 0x65,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x0b, 0x00, 0x64,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x0c, 0x00, 0x63,
|
||||||
|
0x05, 0xff, 0x57, 0x36, 0x0d, 0x00, 0x62,
|
||||||
|
0x03, 0xff, 0x46, 0x00, 0xb8,
|
||||||
|
0x03, 0xff, 0x46, 0x01, 0xb7,
|
||||||
|
0x02, 0xff, 0x4c, 0xb3,
|
||||||
|
0x05, 0xff, 0x57, 0x30, 0x0d, 0x00, 0x68,
|
||||||
|
},
|
||||||
|
result: Mk2Info{
|
||||||
|
Version: uint32(2736),
|
||||||
|
BatVoltage: 14.41,
|
||||||
|
BatCurrent: -0.4,
|
||||||
|
InVoltage: 226.98,
|
||||||
|
InCurrent: 1.71,
|
||||||
|
InFrequency: 50.10256410256411,
|
||||||
|
OutVoltage: 226.980,
|
||||||
|
OutCurrent: 1.54,
|
||||||
|
OutFrequency: 50.025510204081634,
|
||||||
|
ChargeState: 1,
|
||||||
|
LEDs: map[Led]LEDstate{
|
||||||
|
LedMain: LedOn,
|
||||||
|
LedAbsorption: LedOn,
|
||||||
|
LedBulk: LedOff,
|
||||||
|
LedFloat: LedOff,
|
||||||
|
LedInverter: LedOff,
|
||||||
|
LedOverload: LedOff,
|
||||||
|
LedLowBattery: LedOff,
|
||||||
|
LedTemperature: LedOff,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiplus24/3000",
|
||||||
|
knownReadBuffer: []byte{
|
||||||
|
//Len Cmd
|
||||||
|
0x04, 0xff, 0x41, 0x01, 0x00, 0xbb,
|
||||||
|
0x07, 0xff, 0x56, 0x98, 0x3e, 0x11, 0x00, 0x00, 0xbd, // version
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x0, 0x0, 0x6a, // scale 0
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x0, 0x0, 0x6a, // scale 1
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x0, 0x0, 0x6a, // scale 2
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x0, 0x0, 0x6a, // scale 3
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x0, 0x0, 0x6a, // scale 4
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x0, 0x0, 0xa1, // scale 5
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x0, 0x0, 0x6a, // scale 6
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x57, 0x78, 0x8f, 0x0, 0x1, 0xb5, // scale 7
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x2f, 0x7c, 0x8f, 0x0, 0x0, 0xda, // scale 8
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x0, 0x0, 0xa1, //scale 9
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x4, 0x0, 0x8f, 0x0, 0x80, 0x1, // scale 10
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x1, 0x0, 0x8f, 0x0, 0x80, 0x4, // scale 11
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x6, 0x0, 0x8f, 0x0, 0x80, 0xff, // scale 12
|
||||||
|
0x08, 0xff, 0x57, 0x8e, 0x38, 0x7f, 0x8f, 0x0, 0x0, 0xce, // scale 13
|
||||||
|
0x07, 0xff, 0x56, 0x98, 0x3e, 0x11, 0x0, 0x0, 0xbd, // version
|
||||||
|
0x0f, 0x20, 0xb6, 0x89, 0x6d, 0xb7, 0xc, 0x4e, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x82, // dc info
|
||||||
|
0x0f, 0x20, 0x1, 0x1, 0x6d, 0xb7, 0x8, 0x77, 0x5b, 0x21, 0x0, 0x77, 0x5b, 0xfe, 0xff, 0xc3, 0x1e, // ac info
|
||||||
|
0x08, 0xff, 0x4c, 0x9, 0x0, 0x0, 0x0, 0x3, 0x0, 0xa1,
|
||||||
|
0x05, 0xff, 0x57, 0x85, 0xc8, 0x0, 0x58,
|
||||||
|
},
|
||||||
|
knownWrites: []byte{},
|
||||||
|
result: Mk2Info{
|
||||||
|
Version: 0xac0,
|
||||||
|
BatVoltage: 26.38,
|
||||||
|
BatCurrent: 0,
|
||||||
|
InVoltage: 234.15,
|
||||||
|
InCurrent: 0.33,
|
||||||
|
InFrequency: 50.1025641025641,
|
||||||
|
OutVoltage: 234.15,
|
||||||
|
OutCurrent: -0.02,
|
||||||
|
OutFrequency: 50.025510204081634,
|
||||||
|
ChargeState: 1,
|
||||||
|
LEDs: map[Led]LEDstate{
|
||||||
|
LedMain: LedOn,
|
||||||
|
LedAbsorption: LedOff,
|
||||||
|
LedBulk: LedOff,
|
||||||
|
LedFloat: LedOn,
|
||||||
|
LedInverter: LedOff,
|
||||||
|
LedOverload: LedOff,
|
||||||
|
LedLowBattery: LedOff,
|
||||||
|
LedTemperature: LedOff,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedLEDs := map[Led]LEDstate{
|
for _, tt := range tests {
|
||||||
LedMain: LedOn,
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
LedAbsorption: LedOn,
|
testIO := NewIOStub(tt.knownReadBuffer)
|
||||||
LedBulk: LedOff,
|
mk2, err := NewMk2Connection(testIO)
|
||||||
LedFloat: LedOff,
|
assert.NoError(t, err, "Could not open MK2")
|
||||||
LedInverter: LedOff,
|
|
||||||
LedOverload: LedOff,
|
event := <-mk2.C()
|
||||||
LedLowBattery: LedOff,
|
mk2.Close()
|
||||||
LedTemperature: LedOff,
|
|
||||||
|
if len(tt.knownWrites) > 0 {
|
||||||
|
assert.Equal(t, 0, bytes.Compare(writeBuffer.Bytes(), knownWrites), "Expected writes did not match received writes")
|
||||||
|
}
|
||||||
|
assert.True(t, event.Valid, "data not valid")
|
||||||
|
assert.Equal(t, tt.result.Version, event.Version, "Invalid version decoded")
|
||||||
|
assert.Equal(t, 0, len(event.Errors), "Reported errors not empty")
|
||||||
|
assert.Equal(t, tt.result.LEDs, event.LEDs, "Reported LEDs incorrect")
|
||||||
|
|
||||||
|
assert.InDelta(t, tt.result.BatVoltage, event.BatVoltage, testDelta, "BatVoltage conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.BatCurrent, event.BatCurrent, testDelta, "BatCurrent conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.InVoltage, event.InVoltage, testDelta, "InVoltage conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.InCurrent, event.InCurrent, testDelta, "InCurrent conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.InFrequency, event.InFrequency, testDelta, "InFrequency conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.OutVoltage, event.OutVoltage, testDelta, "OutVoltage conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.OutCurrent, event.OutCurrent, testDelta, "OutCurrent conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.OutFrequency, event.OutFrequency, testDelta, "OutFrequency conversion failed")
|
||||||
|
assert.InDelta(t, tt.result.ChargeState, event.ChargeState, testDelta, "ChargeState conversion failed")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
testIO := NewIOStub(knownReadBuffer)
|
|
||||||
mk2, err := NewMk2Connection(testIO)
|
|
||||||
assert.NoError(t, err, "Could not open MK2")
|
|
||||||
|
|
||||||
event := <-mk2.C()
|
|
||||||
mk2.Close()
|
|
||||||
|
|
||||||
assert.Equal(t, 0, bytes.Compare(writeBuffer.Bytes(), knownWrites), "Expected writes did not match received writes")
|
|
||||||
assert.True(t, event.Valid, "data not valid")
|
|
||||||
assert.Equal(t, uint32(2736), event.Version, "Invalid version decoded")
|
|
||||||
assert.Equal(t, 0, len(event.Errors), "Reported errors not empty")
|
|
||||||
assert.Equal(t, expectedLEDs, event.LEDs, "Reported LEDs incorrect")
|
|
||||||
|
|
||||||
assert.InEpsilon(t, 14.41, event.BatVoltage, testEpsilon, "BatVoltage conversion failed")
|
|
||||||
assert.InEpsilon(t, -0.4, event.BatCurrent, testEpsilon, "BatCurrent conversion failed")
|
|
||||||
assert.InEpsilon(t, 226.98, event.InVoltage, testEpsilon, "InVoltage conversion failed")
|
|
||||||
assert.InEpsilon(t, 1.71, event.InCurrent, testEpsilon, "InCurrent conversion failed")
|
|
||||||
assert.InEpsilon(t, 50.10256410256411, event.InFrequency, testEpsilon, "InFrequency conversion failed")
|
|
||||||
assert.InEpsilon(t, 226.980, event.OutVoltage, testEpsilon, "OutVoltage conversion failed")
|
|
||||||
assert.InEpsilon(t, 1.54, event.OutCurrent, testEpsilon, "OutCurrent conversion failed")
|
|
||||||
assert.InEpsilon(t, 50.025510204081634, event.OutFrequency, testEpsilon, "OutFrequency conversion failed")
|
|
||||||
assert.InEpsilon(t, 1, event.ChargeState, testEpsilon, "ChargeState conversion failed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_mk2Ser_scaleDecode(t *testing.T) {
|
func Test_mk2Ser_scaleDecode(t *testing.T) {
|
||||||
@@ -116,16 +216,16 @@ func Test_mk2Ser_scaleDecode(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Valid scale",
|
name: "Valid scale",
|
||||||
frame: []byte{0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a},
|
frame: []byte{0x8e, 0x9c, 0x7f, 0x8f, 0x01, 0x00, 0x6a},
|
||||||
expectedScaling: scaling{
|
expectedScaling: scaling{
|
||||||
scale: 0.00013679890560875513,
|
scale: 0.01,
|
||||||
offset: 143,
|
offset: 1,
|
||||||
supported: true,
|
supported: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Unsupported frame",
|
name: "Unsupported frame",
|
||||||
frame: []byte{0x57, 0x00},
|
frame: []byte{0x00},
|
||||||
expectedScaling: scaling{
|
expectedScaling: scaling{
|
||||||
supported: false,
|
supported: false,
|
||||||
},
|
},
|
||||||
@@ -141,10 +241,71 @@ func Test_mk2Ser_scaleDecode(t *testing.T) {
|
|||||||
assert.Equal(t, 1, len(m.scales))
|
assert.Equal(t, 1, len(m.scales))
|
||||||
assert.Equal(t, 1, m.scaleCount)
|
assert.Equal(t, 1, m.scaleCount)
|
||||||
assert.Equal(t, tt.expectedScaling.supported, m.scales[0].supported)
|
assert.Equal(t, tt.expectedScaling.supported, m.scales[0].supported)
|
||||||
|
assert.Equal(t, tt.expectedScaling.signed, m.scales[0].signed)
|
||||||
if tt.expectedScaling.supported {
|
if tt.expectedScaling.supported {
|
||||||
assert.InEpsilon(t, tt.expectedScaling.offset, m.scales[0].offset, testEpsilon)
|
assert.InDelta(t, tt.expectedScaling.offset, m.scales[0].offset, testDelta)
|
||||||
assert.InEpsilon(t, tt.expectedScaling.scale, m.scales[0].scale, testEpsilon)
|
assert.InDelta(t, tt.expectedScaling.scale, m.scales[0].scale, testDelta)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_mk2Ser_calcFreq(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
scales []scaling
|
||||||
|
data byte
|
||||||
|
scaleIndex int
|
||||||
|
want float64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Calculate working low",
|
||||||
|
scales: []scaling{
|
||||||
|
{supported: false},
|
||||||
|
},
|
||||||
|
data: 0x01,
|
||||||
|
scaleIndex: 0,
|
||||||
|
want: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Calculate working high",
|
||||||
|
scales: []scaling{
|
||||||
|
{
|
||||||
|
supported: true,
|
||||||
|
offset: 0,
|
||||||
|
scale: 0.01,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: 0xFE,
|
||||||
|
scaleIndex: 0,
|
||||||
|
want: 3.937007874015748,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Calculate clip high",
|
||||||
|
scales: []scaling{
|
||||||
|
{supported: false},
|
||||||
|
},
|
||||||
|
data: 0xff,
|
||||||
|
scaleIndex: 0,
|
||||||
|
want: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Calculate clip low",
|
||||||
|
scales: []scaling{
|
||||||
|
{supported: false},
|
||||||
|
},
|
||||||
|
data: 0x00,
|
||||||
|
scaleIndex: 0,
|
||||||
|
want: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := &mk2Ser{
|
||||||
|
scales: tt.scales,
|
||||||
|
}
|
||||||
|
got := m.calcFreq(tt.data, tt.scaleIndex)
|
||||||
|
assert.InDelta(t, tt.want, got, testDelta)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user