Add constants to frame decoder
This commit is contained in:
105
mk2driver/mk2.go
105
mk2driver/mk2.go
@@ -34,6 +34,38 @@ const (
|
|||||||
ramVarInverterPower1
|
ramVarInverterPower1
|
||||||
ramVarInverterPower2
|
ramVarInverterPower2
|
||||||
ramVarOutPower
|
ramVarOutPower
|
||||||
|
|
||||||
|
ramVarMaxOffset = 14
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
infoFrameHeader = 0x20
|
||||||
|
frameHeader = 0xff
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
acL1InfoFrame = 0x08
|
||||||
|
dcInfoFrame = 0x0C
|
||||||
|
setTargetFrame = 0x41
|
||||||
|
infoReqFrame = 0x46
|
||||||
|
ledFrame = 0x4C
|
||||||
|
vFrame = 0x56
|
||||||
|
winmonFrame = 0x57
|
||||||
|
)
|
||||||
|
|
||||||
|
// info frame types
|
||||||
|
const (
|
||||||
|
infoReqAddrDC = 0x00
|
||||||
|
infoReqAddrACL1 = 0x01
|
||||||
|
)
|
||||||
|
|
||||||
|
// winmon frame commands
|
||||||
|
const (
|
||||||
|
commandReadRAMVar = 0x30
|
||||||
|
commandGetRAMVarInfo = 0x36
|
||||||
|
|
||||||
|
commandReadRAMResponse = 0x85
|
||||||
|
commandGetRAMVarInfoResponse = 0x8E
|
||||||
)
|
)
|
||||||
|
|
||||||
type mk2Ser struct {
|
type mk2Ser struct {
|
||||||
@@ -53,7 +85,7 @@ func NewMk2Connection(dev io.ReadWriter) (Mk2, error) {
|
|||||||
mk2.info = &Mk2Info{}
|
mk2.info = &Mk2Info{}
|
||||||
mk2.scaleCount = 0
|
mk2.scaleCount = 0
|
||||||
mk2.frameLock = false
|
mk2.frameLock = false
|
||||||
mk2.scales = make([]scaling, 0, 14)
|
mk2.scales = make([]scaling, 0, ramVarMaxOffset)
|
||||||
mk2.setTarget()
|
mk2.setTarget()
|
||||||
mk2.run = make(chan struct{})
|
mk2.run = make(chan struct{})
|
||||||
mk2.infochan = make(chan *Mk2Info)
|
mk2.infochan = make(chan *Mk2Info)
|
||||||
@@ -64,9 +96,8 @@ func NewMk2Connection(dev io.ReadWriter) (Mk2, error) {
|
|||||||
|
|
||||||
// Locks to incoming frame.
|
// Locks to incoming frame.
|
||||||
func (m *mk2Ser) frameLocker() {
|
func (m *mk2Ser) frameLocker() {
|
||||||
|
|
||||||
frame := make([]byte, 256)
|
frame := make([]byte, 256)
|
||||||
var size byte
|
var frameLength byte
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-m.run:
|
case <-m.run:
|
||||||
@@ -75,34 +106,36 @@ func (m *mk2Ser) frameLocker() {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
if m.frameLock {
|
if m.frameLock {
|
||||||
size = m.readByte()
|
frameLength = m.readByte()
|
||||||
l, err := io.ReadFull(m.p, frame[0:int(size)+1])
|
frameLengthOffset := int(frameLength) + 1
|
||||||
|
l, err := io.ReadFull(m.p, frame[:frameLengthOffset])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.addError(fmt.Errorf("Read Error: %v", err))
|
m.addError(fmt.Errorf("Read Error: %v", err))
|
||||||
m.frameLock = false
|
m.frameLock = false
|
||||||
} else if l != int(size)+1 {
|
} else if l != frameLengthOffset {
|
||||||
m.addError(errors.New("Read Length Error"))
|
m.addError(errors.New("Read Length Error"))
|
||||||
m.frameLock = false
|
m.frameLock = false
|
||||||
} else {
|
} else {
|
||||||
m.handleFrame(size, frame[0:int(size+1)])
|
m.handleFrame(frameLength, frame[:frameLengthOffset])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmp := m.readByte()
|
tmp := m.readByte()
|
||||||
if tmp == 0xff || tmp == 0x20 {
|
frameLengthOffset := int(frameLength)
|
||||||
l, err := io.ReadFull(m.p, frame[0:int(size)])
|
if tmp == frameHeader || tmp == infoFrameHeader {
|
||||||
|
l, err := io.ReadFull(m.p, frame[:frameLengthOffset])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.addError(fmt.Errorf("Read Error: %v", err))
|
m.addError(fmt.Errorf("Read Error: %v", err))
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
} else if l != int(size) {
|
} else if l != frameLengthOffset {
|
||||||
m.addError(errors.New("Read Length Error"))
|
m.addError(errors.New("Read Length Error"))
|
||||||
} else {
|
} else {
|
||||||
if checkChecksum(size, tmp, frame[0:int(size)]) {
|
if checkChecksum(frameLength, tmp, frame[:frameLengthOffset]) {
|
||||||
m.frameLock = true
|
m.frameLock = true
|
||||||
log.Printf("Locked")
|
log.Printf("Locked")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size = tmp
|
frameLength = tmp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,27 +183,27 @@ func (m *mk2Ser) updateReport() {
|
|||||||
func (m *mk2Ser) handleFrame(l byte, frame []byte) {
|
func (m *mk2Ser) handleFrame(l byte, frame []byte) {
|
||||||
if checkChecksum(l, frame[0], frame[1:]) {
|
if checkChecksum(l, frame[0], frame[1:]) {
|
||||||
switch frame[0] {
|
switch frame[0] {
|
||||||
case 0xff:
|
case frameHeader:
|
||||||
switch frame[1] {
|
switch frame[1] {
|
||||||
case 0x56: // V
|
case vFrame:
|
||||||
m.versionDecode(frame[2:])
|
m.versionDecode(frame[2:])
|
||||||
case 0x57:
|
case winmonFrame:
|
||||||
switch frame[2] {
|
switch frame[2] {
|
||||||
case 0x8e:
|
case commandGetRAMVarInfoResponse:
|
||||||
m.scaleDecode(frame[2:])
|
m.scaleDecode(frame[2:])
|
||||||
case 0x85:
|
case commandReadRAMResponse:
|
||||||
m.stateDecode(frame[2:])
|
m.stateDecode(frame[2:])
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x4C: // L
|
case ledFrame:
|
||||||
m.ledDecode(frame[2:])
|
m.ledDecode(frame[2:])
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x20:
|
case infoFrameHeader:
|
||||||
switch frame[5] {
|
switch frame[5] {
|
||||||
case 0x0C:
|
case dcInfoFrame:
|
||||||
m.dcDecode(frame[1:])
|
m.dcDecode(frame[1:])
|
||||||
case 0x08:
|
case acL1InfoFrame:
|
||||||
m.acDecode(frame[1:])
|
m.acDecode(frame[1:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +216,7 @@ func (m *mk2Ser) handleFrame(l byte, frame []byte) {
|
|||||||
// Set the target VBus device.
|
// Set the target VBus device.
|
||||||
func (m *mk2Ser) setTarget() {
|
func (m *mk2Ser) setTarget() {
|
||||||
cmd := make([]byte, 3)
|
cmd := make([]byte, 3)
|
||||||
cmd[0] = 0x41 // A
|
cmd[0] = setTargetFrame
|
||||||
cmd[1] = 0x01
|
cmd[1] = 0x01
|
||||||
cmd[2] = 0x00
|
cmd[2] = 0x00
|
||||||
m.sendCommand(cmd)
|
m.sendCommand(cmd)
|
||||||
@@ -192,8 +225,8 @@ func (m *mk2Ser) setTarget() {
|
|||||||
// Request the scaling factor for entry 'in'.
|
// Request the scaling factor for entry 'in'.
|
||||||
func (m *mk2Ser) reqScaleFactor(in byte) {
|
func (m *mk2Ser) reqScaleFactor(in byte) {
|
||||||
cmd := make([]byte, 4)
|
cmd := make([]byte, 4)
|
||||||
cmd[0] = 0x57 // W
|
cmd[0] = winmonFrame
|
||||||
cmd[1] = 0x36
|
cmd[1] = commandGetRAMVarInfo
|
||||||
cmd[2] = in
|
cmd[2] = in
|
||||||
m.sendCommand(cmd)
|
m.sendCommand(cmd)
|
||||||
}
|
}
|
||||||
@@ -218,7 +251,7 @@ func (m *mk2Ser) scaleDecode(frame []byte) {
|
|||||||
}
|
}
|
||||||
m.scales = append(m.scales, tmp)
|
m.scales = append(m.scales, tmp)
|
||||||
m.scaleCount++
|
m.scaleCount++
|
||||||
if m.scaleCount < 14 {
|
if m.scaleCount < ramVarMaxOffset {
|
||||||
m.reqScaleFactor(byte(m.scaleCount))
|
m.reqScaleFactor(byte(m.scaleCount))
|
||||||
} else {
|
} else {
|
||||||
log.Print("Monitoring starting.")
|
log.Print("Monitoring starting.")
|
||||||
@@ -234,14 +267,14 @@ func (m *mk2Ser) versionDecode(frame []byte) {
|
|||||||
m.info.Version += uint32(frame[i]) << uint(i) * 8
|
m.info.Version += uint32(frame[i]) << uint(i) * 8
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.scaleCount < 14 {
|
if m.scaleCount < ramVarMaxOffset {
|
||||||
log.Print("Get scaling factors.")
|
logrus.Info("Get scaling factors.")
|
||||||
m.reqScaleFactor(byte(m.scaleCount))
|
m.reqScaleFactor(byte(m.scaleCount))
|
||||||
} else {
|
} else {
|
||||||
// Send DC status request
|
// Send DC status request
|
||||||
cmd := make([]byte, 2)
|
cmd := make([]byte, 2)
|
||||||
cmd[0] = 0x46 //F
|
cmd[0] = infoReqFrame
|
||||||
cmd[1] = 0
|
cmd[1] = infoReqAddrDC
|
||||||
m.sendCommand(cmd)
|
m.sendCommand(cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,8 +309,8 @@ func (m *mk2Ser) dcDecode(frame []byte) {
|
|||||||
|
|
||||||
// Send L1 status request
|
// Send L1 status request
|
||||||
cmd := make([]byte, 2)
|
cmd := make([]byte, 2)
|
||||||
cmd[0] = 0x46 //F
|
cmd[0] = infoReqFrame
|
||||||
cmd[1] = 1
|
cmd[1] = infoReqAddrACL1
|
||||||
m.sendCommand(cmd)
|
m.sendCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +329,7 @@ func (m *mk2Ser) acDecode(frame []byte) {
|
|||||||
|
|
||||||
// Send status request
|
// Send status request
|
||||||
cmd := make([]byte, 1)
|
cmd := make([]byte, 1)
|
||||||
cmd[0] = 0x4C //F
|
cmd[0] = ledFrame
|
||||||
m.sendCommand(cmd)
|
m.sendCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,9 +345,9 @@ func (m *mk2Ser) ledDecode(frame []byte) {
|
|||||||
m.info.LEDs = getLEDs(frame[0], frame[1])
|
m.info.LEDs = getLEDs(frame[0], frame[1])
|
||||||
// Send charge state request
|
// Send charge state request
|
||||||
cmd := make([]byte, 4)
|
cmd := make([]byte, 4)
|
||||||
cmd[0] = 0x57 //W
|
cmd[0] = winmonFrame
|
||||||
cmd[1] = 0x30
|
cmd[1] = commandReadRAMVar
|
||||||
cmd[2] = 13
|
cmd[2] = ramVarChargeState
|
||||||
m.sendCommand(cmd)
|
m.sendCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +374,7 @@ func (m *mk2Ser) sendCommand(data []byte) {
|
|||||||
l := len(data)
|
l := len(data)
|
||||||
dataOut := make([]byte, l+3)
|
dataOut := make([]byte, l+3)
|
||||||
dataOut[0] = byte(l + 1)
|
dataOut[0] = byte(l + 1)
|
||||||
dataOut[1] = 0xff
|
dataOut[1] = frameHeader
|
||||||
cr := -dataOut[0] - dataOut[1]
|
cr := -dataOut[0] - dataOut[1]
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
cr = cr - data[i]
|
cr = cr - data[i]
|
||||||
|
|||||||
Reference in New Issue
Block a user