No longer use RAM value scale signedness for info frames.
The signedness calculated along with the RAM value scale and offset was incorrectly applied to the info frame value. This caused some values to be interpreted as unsigned instead of signed leading to negative values reporting as very large positive values.
This commit is contained in:
@@ -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
|
||||||
@@ -358,10 +358,10 @@ 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)
|
||||||
|
|
||||||
if frame[13] == 0xff {
|
if frame[13] == 0xff {
|
||||||
m.info.InFrequency = 0
|
m.info.InFrequency = 0
|
||||||
|
|||||||
@@ -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,9 +50,18 @@ 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 {
|
||||||
|
name string
|
||||||
|
knownReadBuffer []byte
|
||||||
|
knownWrites []byte
|
||||||
|
result Mk2Info
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic",
|
||||||
|
knownReadBuffer: []byte{
|
||||||
//Len Cmd
|
//Len Cmd
|
||||||
0x04, 0xff, 0x41, 0x01, 0x00, 0xbb, 0x07, 0xff, 0x56, 0x96, 0x3e, 0x11, 0x00, 0x00, 0xbf,
|
0x04, 0xff, 0x41, 0x01, 0x00, 0xbb,
|
||||||
|
0x07, 0xff, 0x56, 0x96, 0x3e, 0x11, 0x00, 0x00, 0xbf,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
0x08, 0xff, 0x57, 0x8e, 0x64, 0x80, 0x8f, 0x00, 0x00, 0xa1,
|
||||||
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
0x08, 0xff, 0x57, 0x8e, 0x9c, 0x7f, 0x8f, 0x00, 0x00, 0x6a,
|
||||||
@@ -72,9 +81,40 @@ func TestSync(t *testing.T) {
|
|||||||
0x0f, 0x20, 0x01, 0x01, 0xca, 0x09, 0x08, 0xaa, 0x58, 0xab, 0x00, 0xaa, 0x58, 0x9a, 0x00, 0xc3, 0xe8,
|
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,
|
0x06, 0xff, 0x4c, 0x03, 0x00, 0x00, 0x00, 0xac,
|
||||||
0x05, 0xff, 0x57, 0x85, 0xc8, 0x00, 0x58,
|
0x05, 0xff, 0x57, 0x85, 0xc8, 0x00, 0x58,
|
||||||
}
|
},
|
||||||
|
knownWrites: []byte{
|
||||||
expectedLEDs := map[Led]LEDstate{
|
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,
|
LedMain: LedOn,
|
||||||
LedAbsorption: LedOn,
|
LedAbsorption: LedOn,
|
||||||
LedBulk: LedOff,
|
LedBulk: LedOff,
|
||||||
@@ -83,29 +123,89 @@ func TestSync(t *testing.T) {
|
|||||||
LedOverload: LedOff,
|
LedOverload: LedOff,
|
||||||
LedLowBattery: LedOff,
|
LedLowBattery: LedOff,
|
||||||
LedTemperature: 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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
testIO := NewIOStub(knownReadBuffer)
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
testIO := NewIOStub(tt.knownReadBuffer)
|
||||||
mk2, err := NewMk2Connection(testIO)
|
mk2, err := NewMk2Connection(testIO)
|
||||||
assert.NoError(t, err, "Could not open MK2")
|
assert.NoError(t, err, "Could not open MK2")
|
||||||
|
|
||||||
event := <-mk2.C()
|
event := <-mk2.C()
|
||||||
mk2.Close()
|
mk2.Close()
|
||||||
|
|
||||||
|
if len(tt.knownWrites) > 0 {
|
||||||
assert.Equal(t, 0, bytes.Compare(writeBuffer.Bytes(), knownWrites), "Expected writes did not match received writes")
|
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.True(t, event.Valid, "data not valid")
|
||||||
assert.Equal(t, uint32(2736), event.Version, "Invalid version decoded")
|
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, 0, len(event.Errors), "Reported errors not empty")
|
||||||
assert.Equal(t, expectedLEDs, event.LEDs, "Reported LEDs incorrect")
|
assert.Equal(t, tt.result.LEDs, event.LEDs, "Reported LEDs incorrect")
|
||||||
|
|
||||||
assert.InEpsilon(t, 14.41, event.BatVoltage, testEpsilon, "BatVoltage conversion failed")
|
assert.InDelta(t, tt.result.BatVoltage, event.BatVoltage, testDelta, "BatVoltage conversion failed")
|
||||||
assert.InEpsilon(t, -0.4, event.BatCurrent, testEpsilon, "BatCurrent conversion failed")
|
assert.InDelta(t, tt.result.BatCurrent, event.BatCurrent, testDelta, "BatCurrent conversion failed")
|
||||||
assert.InEpsilon(t, 226.98, event.InVoltage, testEpsilon, "InVoltage conversion failed")
|
assert.InDelta(t, tt.result.InVoltage, event.InVoltage, testDelta, "InVoltage conversion failed")
|
||||||
assert.InEpsilon(t, 1.71, event.InCurrent, testEpsilon, "InCurrent conversion failed")
|
assert.InDelta(t, tt.result.InCurrent, event.InCurrent, testDelta, "InCurrent conversion failed")
|
||||||
assert.InEpsilon(t, 50.10256410256411, event.InFrequency, testEpsilon, "InFrequency conversion failed")
|
assert.InDelta(t, tt.result.InFrequency, event.InFrequency, testDelta, "InFrequency conversion failed")
|
||||||
assert.InEpsilon(t, 226.980, event.OutVoltage, testEpsilon, "OutVoltage conversion failed")
|
assert.InDelta(t, tt.result.OutVoltage, event.OutVoltage, testDelta, "OutVoltage conversion failed")
|
||||||
assert.InEpsilon(t, 1.54, event.OutCurrent, testEpsilon, "OutCurrent conversion failed")
|
assert.InDelta(t, tt.result.OutCurrent, event.OutCurrent, testDelta, "OutCurrent conversion failed")
|
||||||
assert.InEpsilon(t, 50.025510204081634, event.OutFrequency, testEpsilon, "OutFrequency conversion failed")
|
assert.InDelta(t, tt.result.OutFrequency, event.OutFrequency, testDelta, "OutFrequency conversion failed")
|
||||||
assert.InEpsilon(t, 1, event.ChargeState, testEpsilon, "ChargeState conversion failed")
|
assert.InDelta(t, tt.result.ChargeState, event.ChargeState, testDelta, "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,9 +241,10 @@ 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user