diff --git a/API Server/internal/plugins/builtin/ankersolix/modbus.go b/API Server/internal/plugins/builtin/ankersolix/modbus.go index 43baf35..cd1b728 100644 --- a/API Server/internal/plugins/builtin/ankersolix/modbus.go +++ b/API Server/internal/plugins/builtin/ankersolix/modbus.go @@ -65,8 +65,8 @@ const ( regSolarBalancing = 20090 regCPVoltage = 20091 regCPSignal = 20092 - regRelay1Temp = 20093 // INT16, degC - regRelay2Temp = 20094 // INT16, degC + regRelay1Temp = 20093 // INT16, decidegC — see decodeLive on the gain + regRelay2Temp = 20094 // INT16, decidegC regBoostMode = 20095 regLEDBrightness = 20096 // % regChargingStatus = 20097 // same 0-8 enum as the cloud's operating_state @@ -171,8 +171,8 @@ type ModbusSnapshot struct { CPSignal *int `json:"cpSignal,omitempty"` CPSignalDesc string `json:"cpSignalDesc,omitempty"` - Relay1TempC *int `json:"relay1TempC,omitempty"` - Relay2TempC *int `json:"relay2TempC,omitempty"` + Relay1TempC *float64 `json:"relay1TempC,omitempty"` + Relay2TempC *float64 `json:"relay2TempC,omitempty"` OcppStatus *int `json:"ocppStatus,omitempty"` OcppStatusDesc string `json:"ocppStatusDesc,omitempty"` @@ -271,13 +271,19 @@ func decodeLive(snap *ModbusSnapshot, regs []uint16) { b := v != 0 return &b } - degrees := func(addr int) *int { + // The spec's gain column says 1 for the two relay temperatures, but a charger + // idling with nothing plugged in reads 331 and 319 there, which is a gain of + // 10 and not a pair of relays at 331 °C. The same table gives the maximum + // current setting in watts and the timeout in amps, so its unit and gain + // columns are not load-bearing; the LED brightness two registers earlier + // reads exactly 100 at gain 1, which is what fixes the alignment. + degrees := func(addr int) *float64 { v, ok := at(addr) if !ok { return nil } - n := int(int16(v)) // signed: the relays can read below zero - return &n + c := float64(int16(v)) / 10 // signed: the relays can read below zero + return &c } snap.VoltageL1 = scaled(regVoltageL1N, 10) diff --git a/API Server/internal/plugins/builtin/ankersolix/modbus_test.go b/API Server/internal/plugins/builtin/ankersolix/modbus_test.go index 06cae86..1b863c6 100644 --- a/API Server/internal/plugins/builtin/ankersolix/modbus_test.go +++ b/API Server/internal/plugins/builtin/ankersolix/modbus_test.go @@ -106,18 +106,19 @@ func TestDecodeLiveNamesStates(t *testing.T) { func TestDecodeLiveReadsNegativeTemperatures(t *testing.T) { b := newLiveBlock() - below := int16(-7) + below := int16(-72) b.set(regRelay1Temp, uint16(below)) - b.set(regRelay2Temp, 41) + // 331 is what an idle charger actually reports: 33.1 °C, not 331 °C. + b.set(regRelay2Temp, 331) var snap ModbusSnapshot decodeLive(&snap, b) - if snap.Relay1TempC == nil || *snap.Relay1TempC != -7 { - t.Errorf("Relay1TempC = %v, want -7", snap.Relay1TempC) + if snap.Relay1TempC == nil || *snap.Relay1TempC != -7.2 { + t.Errorf("Relay1TempC = %v, want -7.2", snap.Relay1TempC) } - if snap.Relay2TempC == nil || *snap.Relay2TempC != 41 { - t.Errorf("Relay2TempC = %v, want 41", snap.Relay2TempC) + if snap.Relay2TempC == nil || *snap.Relay2TempC != 33.1 { + t.Errorf("Relay2TempC = %v, want 33.1", snap.Relay2TempC) } }