Skip to content

Commit

Permalink
Refactor parsing into packages for reuse.
Browse files Browse the repository at this point in the history
  • Loading branch information
bemasher committed Sep 16, 2014
1 parent 0092dd1 commit 5f508e5
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 89 deletions.
11 changes: 6 additions & 5 deletions idm.go → idm/idm.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package main
package idm

import (
"encoding/binary"
Expand All @@ -25,9 +25,10 @@ import (

"github.com/bemasher/rtlamr/crc"
"github.com/bemasher/rtlamr/decode"
"github.com/bemasher/rtlamr/parse"
)

func NewIDMPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
func NewPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
cfg.DataRate = 32768

cfg.SymbolLength = symbolLength
Expand All @@ -50,11 +51,11 @@ func NewIDMPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
return
}

type IDMParser struct {
type Parser struct {
crc.CRC
}

func NewIDMParser() (p IDMParser) {
func NewParser() (p Parser) {
p.CRC = crc.NewCRC("CCITT", 0xFFFF, 0x1021, 0x1D0F)
return
}
Expand Down Expand Up @@ -151,7 +152,7 @@ func (idm IDM) Record() (r []string) {
return
}

func (p IDMParser) Parse(data Data) (msg Message, err error) {
func (p Parser) Parse(data parse.Data) (msg parse.Message, err error) {
var idm IDM

if residue := p.Checksum(data.Bytes[4:]); residue != p.Residue {
Expand Down
72 changes: 72 additions & 0 deletions parse/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package parse

import (
"fmt"
"strconv"
"time"

"github.com/bemasher/rtlamr/csv"
)

const (
TimeFormat = "2006-01-02T15:04:05.000"
)

type Data struct {
Bits string
Bytes []byte
}

func NewDataFromBytes(data []byte) (d Data) {
d.Bytes = data
for _, b := range data {
d.Bits += fmt.Sprintf("%08b", b)
}

return
}

func NewDataFromBits(data string) (d Data) {
d.Bits = data
for idx := 0; idx < len(data); idx += 8 {
b, _ := strconv.ParseUint(d.Bits[idx:idx+8], 2, 8)
d.Bytes[idx>>3] = uint8(b)
}
return
}

type Parser interface {
Parse(Data) (Message, error)
}

type Message interface {
MsgType() string
MeterID() uint32
MeterType() uint8
csv.Recorder
}

type LogMessage struct {
Time time.Time
Offset int64
Length int
Message
}

func (msg LogMessage) String() string {
return fmt.Sprintf("{Time:%s Offset:%d Length:%d %s:%s}",
msg.Time.Format(TimeFormat), msg.Offset, msg.Length, msg.MsgType(), msg.Message,
)
}

func (msg LogMessage) StringNoOffset() string {
return fmt.Sprintf("{Time:%s %s:%s}", msg.Time.Format(TimeFormat), msg.MsgType(), msg.Message)
}

func (msg LogMessage) Record() (r []string) {
r = append(r, msg.Time.Format(time.RFC3339Nano))
r = append(r, strconv.FormatInt(msg.Offset, 10))
r = append(r, strconv.FormatInt(int64(msg.Length), 10))
r = append(r, msg.Message.Record()...)
return r
}
98 changes: 19 additions & 79 deletions recv.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,36 @@ import (
"os"
"os/signal"
"runtime/pprof"
"strconv"
"strings"
"time"

"github.com/bemasher/rtlamr/csv"
"github.com/bemasher/rtlamr/decode"
"github.com/bemasher/rtlamr/idm"
"github.com/bemasher/rtlamr/parse"
"github.com/bemasher/rtlamr/scm"
"github.com/bemasher/rtltcp"
)

const (
CenterFreq = 920299072
TimeFormat = "2006-01-02T15:04:05.000"
)

var rcvr Receiver

type Receiver struct {
rtltcp.SDR
d decode.Decoder
p Parser
p parse.Parser
}

func (rcvr *Receiver) NewReceiver() {
switch strings.ToLower(*msgType) {
case "scm":
rcvr.d = decode.NewDecoder(NewSCMPacketConfig(*symbolLength), *fastMag)
rcvr.p = NewSCMParser()
rcvr.d = decode.NewDecoder(scm.NewPacketConfig(*symbolLength), *fastMag)
rcvr.p = scm.NewParser()
case "idm":
rcvr.d = decode.NewDecoder(NewIDMPacketConfig(*symbolLength), *fastMag)
rcvr.p = NewIDMParser()
rcvr.d = decode.NewDecoder(idm.NewPacketConfig(*symbolLength), *fastMag)
rcvr.p = idm.NewParser()
default:
log.Fatalf("Invalid message type: %q\n", *msgType)
}
Expand Down Expand Up @@ -135,7 +135,7 @@ func (rcvr *Receiver) Run() {

pktFound := false
for _, pkt := range rcvr.d.Decode(block) {
scm, err := rcvr.p.Parse(NewDataFromBytes(pkt))
scm, err := rcvr.p.Parse(parse.NewDataFromBytes(pkt))
if err != nil {
// log.Println(err)
continue
Expand All @@ -149,11 +149,19 @@ func (rcvr *Receiver) Run() {
continue
}

msg := NewLogMessage(scm)
var msg parse.LogMessage
msg.Time = time.Now()
msg.Offset, _ = sampleFile.Seek(0, os.SEEK_CUR)
msg.Length = rcvr.d.Cfg.BufferLength << 1
msg.Message = scm

if encoder == nil {
// A nil encoder is just plain-text output.
fmt.Fprintln(logFile, msg)
if *sampleFilename == os.DevNull {
fmt.Fprintln(logFile, msg.StringNoOffset())
} else {
fmt.Fprintln(logFile, msg)
}
} else {
err = encoder.Encode(msg)
if err != nil {
Expand Down Expand Up @@ -188,74 +196,6 @@ func (rcvr *Receiver) Run() {
}
}

type Data struct {
Bits string
Bytes []byte
}

func NewDataFromBytes(data []byte) (d Data) {
d.Bytes = data
for _, b := range data {
d.Bits += fmt.Sprintf("%08b", b)
}

return
}

func NewDataFromBits(data string) (d Data) {
d.Bits = data
for idx := 0; idx < len(data); idx += 8 {
b, _ := strconv.ParseUint(d.Bits[idx:idx+8], 2, 8)
d.Bytes[idx>>3] = uint8(b)
}
return
}

type Parser interface {
Parse(Data) (Message, error)
}

type Message interface {
MsgType() string
MeterID() uint32
MeterType() uint8
csv.Recorder
}

type LogMessage struct {
Time time.Time
Offset int64
Length int
Message
}

func NewLogMessage(msg Message) (logMsg LogMessage) {
logMsg.Time = time.Now()
logMsg.Offset, _ = sampleFile.Seek(0, os.SEEK_CUR)
logMsg.Length = rcvr.d.Cfg.BufferLength << 1
logMsg.Message = msg

return
}

func (msg LogMessage) String() string {
if *sampleFilename == os.DevNull {
return fmt.Sprintf("{Time:%s %s:%s}", msg.Time.Format(TimeFormat), msg.MsgType(), msg.Message)
}

return fmt.Sprintf("{Time:%s Offset:%d Length:%d %s:%s}",
msg.Time.Format(TimeFormat), msg.Offset, msg.Length, msg.MsgType(), msg.Message,
)
}

func (msg LogMessage) Record() (r []string) {
r = append(r, msg.Time.Format(time.RFC3339Nano))
r = append(r, strconv.FormatInt(msg.Offset, 10))
r = append(r, strconv.FormatInt(int64(msg.Length), 10))
r = append(r, msg.Message.Record()...)
return r
}

func init() {
log.SetFlags(log.Lshortfile | log.Lmicroseconds)
}
Expand Down
11 changes: 6 additions & 5 deletions scm.go → scm/scm.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package main
package scm

import (
"errors"
Expand All @@ -23,9 +23,10 @@ import (

"github.com/bemasher/rtlamr/crc"
"github.com/bemasher/rtlamr/decode"
"github.com/bemasher/rtlamr/parse"
)

func NewSCMPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
func NewPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
cfg.DataRate = 32768

cfg.SymbolLength = symbolLength
Expand All @@ -49,16 +50,16 @@ func NewSCMPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
return
}

type SCMParser struct {
type Parser struct {
crc.CRC
}

func NewSCMParser() (p SCMParser) {
func NewParser() (p Parser) {
p.CRC = crc.NewCRC("BCH", 0, 0x6F63, 0)
return
}

func (p SCMParser) Parse(data Data) (msg Message, err error) {
func (p Parser) Parse(data parse.Data) (msg parse.Message, err error) {
var scm SCM

if p.Checksum(data.Bytes[2:]) != 0 {
Expand Down

0 comments on commit 5f508e5

Please sign in to comment.