Skip to content

Commit

Permalink
Refactor message unpacking in SCM and IDM.
Browse files Browse the repository at this point in the history
  • Loading branch information
bemasher committed Jun 14, 2015
1 parent f3d51f2 commit 07607af
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 70 deletions.
118 changes: 64 additions & 54 deletions idm/idm.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,41 @@ func NewParser(symbolLength int, fastMag bool) (p Parser) {
return
}

func (p Parser) Parse(indices []int) (msgs []parse.Message) {
seen := make(map[string]bool)

for _, pkt := range p.Decoder.Slice(indices) {
s := string(pkt)
if seen[s] {
continue
}
seen[s] = true

data := parse.NewDataFromBytes(pkt)

// If the packet is too short, bail.
if l := len(data.Bytes); l != 92 {
continue
}

// If the checksum fails, bail.
if residue := p.Checksum(data.Bytes[4:92]); residue != p.Residue {
continue
}

idm := NewIDM(data)

// If the meter id is 0, bail.
if idm.ERTSerialNumber == 0 {
continue
}

msgs = append(msgs, idm)
}

return
}

// Standard Consumption Message
type IDM struct {
Preamble uint32 // Training and Frame sync.
Expand All @@ -92,6 +127,35 @@ type IDM struct {
PacketCRC uint16
}

func NewIDM(data parse.Data) (idm IDM) {
idm.Preamble = binary.BigEndian.Uint32(data.Bytes[0:4])
idm.PacketTypeID = data.Bytes[4]
idm.PacketLength = data.Bytes[5]
idm.HammingCode = data.Bytes[6]
idm.ApplicationVersion = data.Bytes[7]
idm.ERTType = data.Bytes[8] & 0x0F
idm.ERTSerialNumber = binary.BigEndian.Uint32(data.Bytes[9:13])
idm.ConsumptionIntervalCount = data.Bytes[13]
idm.ModuleProgrammingState = data.Bytes[14]
idm.TamperCounters = data.Bytes[15:21]
idm.AsynchronousCounters = binary.BigEndian.Uint16(data.Bytes[21:23])
idm.PowerOutageFlags = data.Bytes[23:29]
idm.LastConsumptionCount = binary.BigEndian.Uint32(data.Bytes[29:33])

offset := 264
for idx := range idm.DifferentialConsumptionIntervals {
interval, _ := strconv.ParseUint(data.Bits[offset:offset+9], 2, 9)
idm.DifferentialConsumptionIntervals[idx] = uint16(interval)
offset += 9
}

idm.TransmitTimeOffset = binary.BigEndian.Uint16(data.Bytes[86:88])
idm.SerialNumberCRC = binary.BigEndian.Uint16(data.Bytes[88:90])
idm.PacketCRC = binary.BigEndian.Uint16(data.Bytes[90:92])

return
}

type Interval [47]uint16

// func (interval Interval) MarshalText() (text []byte, err error) {
Expand Down Expand Up @@ -162,57 +226,3 @@ func (idm IDM) Record() (r []string) {

return
}

func (p Parser) Parse(indices []int) (msgs []parse.Message) {
seen := make(map[string]bool)

for _, pkt := range p.Decoder.Slice(indices) {
s := string(pkt)
if seen[s] {
continue
}
seen[s] = true

data := parse.NewDataFromBytes(pkt)

// If the checksum fails, bail.
if residue := p.Checksum(data.Bytes[4:92]); residue != p.Residue {
continue
}

var idm IDM
idm.Preamble = binary.BigEndian.Uint32(data.Bytes[0:4])
idm.PacketTypeID = data.Bytes[4]
idm.PacketLength = data.Bytes[5]
idm.HammingCode = data.Bytes[6]
idm.ApplicationVersion = data.Bytes[7]
idm.ERTType = data.Bytes[8] & 0x0F
idm.ERTSerialNumber = binary.BigEndian.Uint32(data.Bytes[9:13])
idm.ConsumptionIntervalCount = data.Bytes[13]
idm.ModuleProgrammingState = data.Bytes[14]
idm.TamperCounters = data.Bytes[15:21]
idm.AsynchronousCounters = binary.BigEndian.Uint16(data.Bytes[21:23])
idm.PowerOutageFlags = data.Bytes[23:29]
idm.LastConsumptionCount = binary.BigEndian.Uint32(data.Bytes[29:33])

offset := 264
for idx := range idm.DifferentialConsumptionIntervals {
interval, _ := strconv.ParseUint(data.Bits[offset:offset+9], 2, 9)
idm.DifferentialConsumptionIntervals[idx] = uint16(interval)
offset += 9
}

idm.TransmitTimeOffset = binary.BigEndian.Uint16(data.Bytes[86:88])
idm.SerialNumberCRC = binary.BigEndian.Uint16(data.Bytes[88:90])
idm.PacketCRC = binary.BigEndian.Uint16(data.Bytes[90:92])

// If the meter id is 0, bail.
if idm.ERTSerialNumber == 0 {
continue
}

msgs = append(msgs, idm)
}

return
}
36 changes: 20 additions & 16 deletions scm/scm.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (p Parser) Parse(indices []int) (msgs []parse.Message) {
data := parse.NewDataFromBytes(pkt)

// If the packet is too short, bail.
if l := len(data.Bytes); l < 12 {
if l := len(data.Bytes); l != 12 {
continue
}

Expand All @@ -92,21 +92,7 @@ func (p Parser) Parse(indices []int) (msgs []parse.Message) {
continue
}

ertid, _ := strconv.ParseUint(data.Bits[21:23]+data.Bits[56:80], 2, 26)
erttype, _ := strconv.ParseUint(data.Bits[26:30], 2, 4)
tamperphy, _ := strconv.ParseUint(data.Bits[24:26], 2, 2)
tamperenc, _ := strconv.ParseUint(data.Bits[30:32], 2, 2)
consumption, _ := strconv.ParseUint(data.Bits[32:56], 2, 24)
checksum, _ := strconv.ParseUint(data.Bits[80:96], 2, 16)

var scm SCM

scm.ID = uint32(ertid)
scm.Type = uint8(erttype)
scm.TamperPhy = uint8(tamperphy)
scm.TamperEnc = uint8(tamperenc)
scm.Consumption = uint32(consumption)
scm.Checksum = uint16(checksum)
scm := NewSCM(data)

// If the meter id is 0, bail.
if scm.ID == 0 {
Expand All @@ -129,6 +115,24 @@ type SCM struct {
Checksum uint16 `xml:",attr"`
}

func NewSCM(data parse.Data) (scm SCM) {
ertid, _ := strconv.ParseUint(data.Bits[21:23]+data.Bits[56:80], 2, 26)
erttype, _ := strconv.ParseUint(data.Bits[26:30], 2, 4)
tamperphy, _ := strconv.ParseUint(data.Bits[24:26], 2, 2)
tamperenc, _ := strconv.ParseUint(data.Bits[30:32], 2, 2)
consumption, _ := strconv.ParseUint(data.Bits[32:56], 2, 24)
checksum, _ := strconv.ParseUint(data.Bits[80:96], 2, 16)

scm.ID = uint32(ertid)
scm.Type = uint8(erttype)
scm.TamperPhy = uint8(tamperphy)
scm.TamperEnc = uint8(tamperenc)
scm.Consumption = uint32(consumption)
scm.Checksum = uint16(checksum)

return
}

func (scm SCM) MsgType() string {
return "SCM"
}
Expand Down

0 comments on commit 07607af

Please sign in to comment.