Refactored protocol and radio interfaces
This commit is contained in:
@@ -9,9 +9,10 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.maze.io/go/ham/protocol"
|
||||
"git.maze.io/go/ham/protocol/meshcore/crypto"
|
||||
"git.maze.io/go/ham/radio"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -24,21 +25,6 @@ type Node struct {
|
||||
driver nodeDriver
|
||||
}
|
||||
|
||||
type NodeInfo struct {
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
FirmwareVersion string `json:"firmware_version"`
|
||||
Type NodeType `json:"node_type"`
|
||||
Name string `json:"name"`
|
||||
Power uint8 `json:"power"`
|
||||
MaxPower uint8 `json:"max_power"`
|
||||
PublicKey *crypto.PublicKey `json:"public_key"`
|
||||
Position *Position `json:"position"`
|
||||
Frequency float64 `json:"frequency"` // in MHz
|
||||
Bandwidth float64 `json:"bandwidth"` // in kHz
|
||||
SpreadingFactor uint8 `json:"sf"`
|
||||
CodingRate uint8 `json:"cr"`
|
||||
}
|
||||
|
||||
// NewCompanion connects to a companion device type (over serial, TCP or BLE).
|
||||
func NewCompanion(conn io.ReadWriteCloser) (*Node, error) {
|
||||
driver := newCompanionDriver(conn)
|
||||
@@ -64,19 +50,17 @@ func (dev *Node) RawPackets() <-chan *protocol.Packet {
|
||||
return dev.driver.RawPackets()
|
||||
}
|
||||
|
||||
func (dev *Node) Info() *NodeInfo {
|
||||
func (dev *Node) Info() *radio.Info {
|
||||
return dev.driver.Info()
|
||||
}
|
||||
|
||||
type nodeDriver interface {
|
||||
radio.Device
|
||||
protocol.PacketReceiver
|
||||
|
||||
Setup() error
|
||||
|
||||
Close() error
|
||||
|
||||
Packets() <-chan *Packet
|
||||
RawPackets() <-chan *protocol.Packet
|
||||
|
||||
Info() *NodeInfo
|
||||
}
|
||||
|
||||
type CompanionError struct {
|
||||
@@ -107,7 +91,35 @@ type companionDriver struct {
|
||||
mu sync.Mutex
|
||||
packets chan *Packet
|
||||
rawPackets chan *protocol.Packet
|
||||
info NodeInfo
|
||||
info companionInfo
|
||||
}
|
||||
|
||||
type companionInfo struct {
|
||||
// Fields returns by CMD_APP_START.
|
||||
Type NodeType
|
||||
Power byte // in dBm
|
||||
MaxPower byte // in dBm
|
||||
PublicKey [32]byte
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
HasMultiACKs bool
|
||||
AdvertLocationPolicy byte
|
||||
TelemetryFlags byte
|
||||
ManualAddContacts byte
|
||||
Frequency float64 // in MHz
|
||||
Bandwidth float64 // in kHz
|
||||
SpreadingFactor byte
|
||||
CodingRate byte
|
||||
Name string
|
||||
|
||||
// Fields returns by CMD_DEVICE_QUERY.
|
||||
FirmwareVersion string
|
||||
FirmwareVersionCode byte
|
||||
FirmwareBuildDate string
|
||||
Manufacturer string
|
||||
MaxContacts int
|
||||
MaxGroupChannels int
|
||||
BLEPIN [4]byte
|
||||
}
|
||||
|
||||
func newCompanionDriver(conn io.ReadWriteCloser) *companionDriver {
|
||||
@@ -145,8 +157,25 @@ func (drv *companionDriver) RawPackets() <-chan *protocol.Packet {
|
||||
return drv.rawPackets
|
||||
}
|
||||
|
||||
func (drv *companionDriver) Info() *NodeInfo {
|
||||
return &drv.info
|
||||
func (drv *companionDriver) Info() *radio.Info {
|
||||
var pos *radio.Position
|
||||
if drv.info.Latitude != 0 && drv.info.Longitude != 0 {
|
||||
pos = &radio.Position{
|
||||
Latitude: drv.info.Latitude,
|
||||
Longitude: drv.info.Longitude,
|
||||
}
|
||||
}
|
||||
return &radio.Info{
|
||||
Name: drv.info.Name,
|
||||
Manufacturer: drv.info.Manufacturer,
|
||||
Modulation: protocol.LoRa,
|
||||
Position: pos,
|
||||
Frequency: drv.info.Frequency,
|
||||
Bandwidth: drv.info.Bandwidth,
|
||||
Power: float64(drv.info.Power),
|
||||
LoRaSF: drv.info.SpreadingFactor,
|
||||
LoRaCR: drv.info.CodingRate,
|
||||
}
|
||||
}
|
||||
|
||||
func (drv *companionDriver) readFrame() ([]byte, error) {
|
||||
@@ -252,6 +281,7 @@ func (drv *companionDriver) handleRXData(b []byte) {
|
||||
return // not listening for packets, discard
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
packet := new(Packet)
|
||||
if err := packet.UnmarshalBytes(b[2:]); err == nil {
|
||||
packet.SNR = float64(b[0]) / 4
|
||||
@@ -264,6 +294,7 @@ func (drv *companionDriver) handleRXData(b []byte) {
|
||||
if drv.rawPackets != nil {
|
||||
select {
|
||||
case drv.rawPackets <- &protocol.Packet{
|
||||
Time: now,
|
||||
Protocol: "meshcore",
|
||||
SNR: packet.SNR,
|
||||
RSSI: packet.RSSI,
|
||||
@@ -295,18 +326,18 @@ func (drv *companionDriver) sendAppStart() (err error) {
|
||||
drv.info.Type = NodeType(b[0])
|
||||
drv.info.Power = b[1]
|
||||
drv.info.MaxPower = b[2]
|
||||
drv.info.PublicKey, _ = crypto.NewPublicKey(b[3 : 3+crypto.PublicKeySize])
|
||||
drv.info.Position = new(Position)
|
||||
drv.info.Position.Unmarshal(b[35:])
|
||||
//drv.info.HasMultiACKs = b[43] != 0
|
||||
//drv.info.AdvertLocationPolicy = b[44]
|
||||
//drv.info.TelemetryFlags = b[45]
|
||||
//drv.info.ManualAddContacts = b[46]
|
||||
copy(drv.info.PublicKey[:], b[3:])
|
||||
drv.info.Latitude, drv.info.Longitude = decodeLatLon(b[35:])
|
||||
drv.info.HasMultiACKs = b[43] != 0
|
||||
drv.info.AdvertLocationPolicy = b[44]
|
||||
drv.info.TelemetryFlags = b[45]
|
||||
drv.info.ManualAddContacts = b[46]
|
||||
drv.info.Frequency = decodeFrequency(b[47:])
|
||||
drv.info.Bandwidth = decodeFrequency(b[51:])
|
||||
drv.info.SpreadingFactor = b[55]
|
||||
drv.info.CodingRate = b[56]
|
||||
drv.info.Name = strings.TrimRight(string(b[57:]), "\x00")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -325,6 +356,10 @@ func (drv *companionDriver) sendDeviceInfo() (err error) {
|
||||
}
|
||||
b = b[1:]
|
||||
|
||||
drv.info.FirmwareVersionCode = b[0]
|
||||
drv.info.MaxContacts = int(b[1]) * 2
|
||||
drv.info.MaxGroupChannels = int(b[2])
|
||||
drv.info.FirmwareBuildDate = decodeCString(b[7:19])
|
||||
drv.info.Manufacturer = decodeCString(b[19:59])
|
||||
drv.info.FirmwareVersion = decodeCString(b[59:79])
|
||||
|
||||
@@ -339,3 +374,8 @@ func (drv *companionDriver) poll() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
_ protocol.PacketReceiver = (*Node)(nil)
|
||||
_ nodeDriver = (*companionDriver)(nil)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user