Browse Source

修改布局

master
lihua 5 years ago
parent
commit
0155b2747b
  1. 334
      LoRaDTUMock.go
  2. 82
      model.go
  3. 107
      model/down.go
  4. 261
      utils.go

334
LoRaDTUMock.go

@ -1,12 +1,8 @@
package main
import (
"LoRaDTUMock/model"
"LoRaDTUMock/packets"
"bytes"
"crypto/aes"
"crypto/tls"
"crypto/x509"
"encoding/hex"
"encoding/json"
"fmt"
@ -17,45 +13,17 @@ import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
"github.com/lxn/win"
"github.com/pkg/errors"
"io/ioutil"
"math/rand"
"os"
"syscall"
"time"
)
type ConnectConfig struct {
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
CACert string `json:"ca_cert"`
TLSCert string `json:"tls_cert"`
TLSKey string `json:"tls_key"`
}
type DTUConfig struct {
OTAA bool `json:"otaa"`
GatewayId string `json:"gatewayId"`
DevEui string `json:"devEui"`
DevAddr string `json:"devAddr"`
AppKey string `json:"appKey"`
AppSKey string `json:"appSKey"`
NwkSKey string `json:"nwkSKey"`
FPort uint8 `json:"fPort"`
FCnt uint32 `json:"fCnt"`
Freq float64 `json:"freq"`
msg []byte
devNonce lorawan.DevNonce
}
type DTUMainWindow struct {
*walk.MainWindow
mqttClient paho.Client
upModel *model.DTUUpModel
downModel *model.DTUDownModel
upTv,downTv *walk.TableView
model *DTUModel
tv *walk.TableView
host,username,password *walk.LineEdit
port *walk.NumberEdit
connect, disconnect,caConf,send *walk.PushButton
@ -66,15 +34,9 @@ type DTUMainWindow struct {
connConfFileName string
dtuConfFileName string
}
func BytesToString(b []byte) string {
_,err := syscall.UTF16FromString(string(b))
if err == nil {
return string(b)
}
return ""
}
func main() {
mw := &DTUMainWindow{upModel: model.NewDTUUpModel(),downModel:model.NewDTUDownModel()}
mw := &DTUMainWindow{model: NewDTUModel()}
maxWidth := int(win.GetSystemMetrics(win.SM_CXSCREEN)) - 200
maxHeight := int(win.GetSystemMetrics(win.SM_CYSCREEN)) - 100
err := MainWindow{
@ -107,13 +69,15 @@ func main() {
Layout: HBox{},
Children: []Widget{
TableView{
AssignTo: &mw.upTv,
AssignTo: &mw.tv,
CheckBoxes: true,
ColumnsOrderable: true,
MultiSelection: true,
Columns: []TableViewColumn{
{Title: "序号"},
{Title: "数据方向"},
{Title: "终端EUI"},
{Title: "终端地址"},
{Title: "消息类型"},
{Title: "网关ID"},
{Title: "信号强度"},
@ -125,28 +89,8 @@ func main() {
{Title: "ASCII数据"},
{Title: "时间"},
},
Model: mw.upModel,
OnItemActivated: mw.upTvItemActivated,
},
TableView{
AssignTo: &mw.downTv,
CheckBoxes: true,
ColumnsOrderable: true,
MultiSelection: true,
Columns: []TableViewColumn{
{Title: "序号"},
{Title: "终端EUI"},
{Title: "消息类型"},
{Title: "终端地址"},
{Title: "网关ID"},
{Title: "计数"},
{Title: "端口"},
{Title: "HEX数据"},
{Title: "ASCII数据"},
{Title: "时间"},
},
Model: mw.downModel,
OnItemActivated: mw.downTvItemActivated,
Model: mw.model,
OnItemActivated: mw.tvItemActivated,
},
},
},
@ -175,36 +119,6 @@ func main() {
mw.Run()
}
func newTLSConfig(cafile, certFile, certKeyFile string) (*tls.Config, error) {
if cafile == "" && certFile == "" && certKeyFile == "" {
return nil, nil
}
tlsConfig := &tls.Config{}
// Import trusted certificates from CAfile.pem.
if cafile != "" {
cacert, err := ioutil.ReadFile(cafile)
if err != nil {
return nil, err
}
certpool := x509.NewCertPool()
certpool.AppendCertsFromPEM(cacert)
tlsConfig.RootCAs = certpool // RootCAs = certs used to verify server cert.
}
// Import certificate and the key
if certFile != "" && certKeyFile != "" {
kp, err := tls.LoadX509KeyPair(certFile, certKeyFile)
if err != nil {
return nil, err
}
tlsConfig.Certificates = []tls.Certificate{kp}
}
return tlsConfig, nil
}
func (mw *DTUMainWindow) Connect() {
go func() {
@ -485,177 +399,21 @@ func (mw *DTUMainWindow) ConnectConfig() {
dlg.Run()
}
func (mw *DTUMainWindow) BuildUpData() (*packets.PushDataPacket,*lorawan.PHYPayload) {
now := time.Now().Round(time.Second)
compactTS := packets.CompactTime(now)
tmms := int64(time.Second / time.Millisecond)
var phy lorawan.PHYPayload
phy.MHDR.MType = lorawan.ConfirmedDataUp
phy.MHDR.Major = lorawan.LoRaWANR1
var mac lorawan.MACPayload
_ = mac.FHDR.DevAddr.UnmarshalText([]byte(mw.dtuConf.DevAddr))
_ = mac.FHDR.FCtrl.UnmarshalBinary([]byte{128})
mac.FHDR.FCnt = mw.dtuConf.FCnt
mac.FPort = &mw.dtuConf.FPort
var dataPayload lorawan.DataPayload
_ = dataPayload.UnmarshalBinary(true, mw.dtuConf.msg)
mac.FRMPayload = []lorawan.Payload{&dataPayload}
phy.MACPayload = &mac
var aseKey lorawan.AES128Key
_ = aseKey.UnmarshalText([]byte(mw.dtuConf.NwkSKey))
_ = phy.EncryptFRMPayload(aseKey)
sf :=[...]string{"SF12","SF11","SF10","SF9","SF8","SF7"}
var dr uint8 = 5
var ch uint8 = 2
_ = phy.SetUplinkDataMIC(lorawan.LoRaWAN1_0, 0, dr, ch, aseKey, aseKey)
data,_ := phy.MarshalBinary()
var gatewayMac lorawan.EUI64
_ = gatewayMac.UnmarshalText([]byte(mw.dtuConf.GatewayId))
return &packets.PushDataPacket{
ProtocolVersion: packets.ProtocolVersion2,
RandomToken: uint16(rand.Uint32()),
GatewayMAC: gatewayMac,
Payload: packets.PushDataPayload{
RXPK: []packets.RXPK{
{
Time: &compactTS,
Tmst: 708016819,
Tmms: &tmms,
Freq: mw.dtuConf.Freq,
Chan: ch,
RFCh: 1,
Stat: 1,
Modu: "LORA",
DatR: packets.DatR{LoRa: sf[dr]+"BW125"},
CodR: "4/5",
RSSI: -51,
LSNR: 7,
Size: uint16(len(data)),
Data: data,
},
},
},
},&phy
func (mw *DTUMainWindow) BuildUpData() (*packets.PushDataPacket,*lorawan.PHYPayload,error) {
var fCtrl lorawan.FCtrl
_ = fCtrl.UnmarshalBinary([]byte{128})
return BuildUpData(mw.dtuConf.GatewayId,mw.dtuConf.DevAddr,mw.dtuConf.NwkSKey,
mw.dtuConf.FCnt,mw.dtuConf.FPort,5,2,mw.dtuConf.Freq,7,
lorawan.UnconfirmedDataUp,fCtrl,-51,mw.dtuConf.msg)
}
func (mw *DTUMainWindow) BuildJoin() (*packets.PushDataPacket,*lorawan.PHYPayload) {
now := time.Now().Round(time.Second)
compactTS := packets.CompactTime(now)
tmms := int64(time.Second / time.Millisecond)
var phy lorawan.PHYPayload
phy.MHDR.MType = lorawan.JoinRequest
phy.MHDR.Major = lorawan.LoRaWANR1
var DevEUI lorawan.EUI64
_ = DevEUI.UnmarshalText([]byte(mw.dtuConf.DevEui))
func (mw *DTUMainWindow) BuildJoin() (*packets.PushDataPacket,*lorawan.PHYPayload,error) {
mw.dtuConf.devNonce = lorawan.DevNonce(rand.Uint32())
phy.MACPayload = &lorawan.JoinRequestPayload{
DevEUI: DevEUI,
JoinEUI: lorawan.EUI64{8, 7, 6, 5, 4, 3, 2, 1},
DevNonce: mw.dtuConf.devNonce,
}
var aseKey lorawan.AES128Key
_ = aseKey.UnmarshalText([]byte(mw.dtuConf.AppKey))
sf :=[...]string{"SF12","SF11","SF10","SF9","SF8","SF7"}
var dr uint8 = 5
var ch uint8 = 2
_ = phy.SetUplinkJoinMIC(aseKey)
data,_ := phy.MarshalBinary()
var gatewayMac lorawan.EUI64
_ = gatewayMac.UnmarshalText([]byte(mw.dtuConf.GatewayId))
return &packets.PushDataPacket{
ProtocolVersion: packets.ProtocolVersion2,
RandomToken: uint16(rand.Uint32()),
GatewayMAC: gatewayMac,
Payload: packets.PushDataPayload{
RXPK: []packets.RXPK{
{
Time: &compactTS,
Tmst: 708016819,
Tmms: &tmms,
Freq: mw.dtuConf.Freq,
Chan: ch,
RFCh: 1,
Stat: 1,
Modu: "LORA",
DatR: packets.DatR{LoRa: sf[dr]+"BW125"},
CodR: "4/5",
RSSI: -51,
LSNR: 7,
Size: uint16(len(data)),
Data: data,
},
},
},
},&phy
}
// getNwkSKey returns the network session key.
func getNwkSKey(appkey lorawan.AES128Key, netID lorawan.NetID, joinNonce lorawan.JoinNonce, devNonce lorawan.DevNonce) (lorawan.AES128Key, error) {
return getSKey(0x01, appkey, netID, joinNonce, devNonce)
}
// getAppSKey returns the application session key.
func getAppSKey(appkey lorawan.AES128Key, netID lorawan.NetID, joinNonce lorawan.JoinNonce, devNonce lorawan.DevNonce) (lorawan.AES128Key, error) {
return getSKey(0x02, appkey, netID, joinNonce, devNonce)
appEui := "0807060504030201"
return BuildJoin(mw.dtuConf.GatewayId,appEui,mw.dtuConf.DevEui,mw.dtuConf.AppKey,
5,2,mw.dtuConf.Freq,7,-51, mw.dtuConf.devNonce)
}
func getSKey(typ byte, nwkKey lorawan.AES128Key, netID lorawan.NetID,joinNonce lorawan.JoinNonce, devNonce lorawan.DevNonce) (lorawan.AES128Key, error) {
var key lorawan.AES128Key
b := make([]byte, 16)
b[0] = typ
netIDB, err := netID.MarshalBinary()
if err != nil {
return key, errors.Wrap(err, "marshal binary error")
}
joinNonceB, err := joinNonce.MarshalBinary()
if err != nil {
return key, errors.Wrap(err, "marshal binary error")
}
devNonceB, err := devNonce.MarshalBinary()
if err != nil {
return key, errors.Wrap(err, "marshal binary error")
}
copy(b[1:4], joinNonceB)
copy(b[4:7], netIDB)
copy(b[7:9], devNonceB)
block, err := aes.NewCipher(nwkKey[:])
if err != nil {
return key, err
}
if block.BlockSize() != len(b) {
return key, fmt.Errorf("block-size of %d bytes is expected", len(b))
}
block.Encrypt(key[:], b)
return key, nil
}
func MarshalFRMPayload(p *lorawan.MACPayload) ([]byte, error) {
var out []byte
var b []byte
var err error
for _, fp := range p.FRMPayload {
if mac, ok := fp.(*lorawan.MACCommand); ok {
if p.FPort == nil || (p.FPort != nil && *p.FPort != 0) {
return []byte{}, errors.New("lorawan: a MAC command is only allowed when FPort=0")
}
b, err = mac.MarshalBinary()
} else {
b, err = fp.MarshalBinary()
}
if err != nil {
return nil, err
}
out = append(out, b...)
}
return out, nil
}
func (mw *DTUMainWindow) HandleData(client paho.Client, message paho.Message){
var downlinkFrame gw.DownlinkFrame
@ -677,11 +435,12 @@ func (mw *DTUMainWindow) HandleData(client paho.Client, message paho.Message){
var origData bytes.Buffer
jsonData,_ := phy.MarshalJSON()
_ = json.Indent(&origData, jsonData, "", " ")
dd := &model.DTUDown{
Index: mw.downModel.Len() + 1,
dd := &DTU{
Index: mw.model.Len() + 1,
Direction:"downlink",
DevEUI: mw.dtuConf.DevEui,
MType: phy.MHDR.MType.String(),
DevAddr: mw.dtuConf.DevAddr,
MType: phy.MHDR.MType.String(),
GatewayID: hex.EncodeToString(downlinkFrame.TxInfo.GatewayId),
Time:time.Now().Format("2006-01-02 15:04:05"),
OrigData:origData.String(),
@ -698,9 +457,9 @@ func (mw *DTUMainWindow) HandleData(client paho.Client, message paho.Message){
dd.HexData = hex.EncodeToString(p)
}
}
mw.downModel.Items = append(mw.downModel.Items, dd)
mw.downModel.PublishRowsReset()
_ = mw.downTv.SetSelectedIndexes([]int{})
mw.model.Items = append(mw.model.Items, dd)
mw.model.PublishRowsReset()
_ = mw.tv.SetSelectedIndexes([]int{})
}
}
}
@ -759,12 +518,13 @@ func (mw *DTUMainWindow) PushData(gatewayEUI string,event string, msg proto.Mess
func (mw *DTUMainWindow) Send(){
if mw.dtuConf.OTAA && mw.dtuConf.DevAddr == ""{
packet,phy := mw.BuildJoin()
packet,phy,_ := mw.BuildJoin()
var origData bytes.Buffer
jsonData,_ := phy.MarshalJSON()
_ = json.Indent(&origData, jsonData, "", " ")
du := &model.DTUUp{
Index:mw.upModel.Len() + 1,
du := &DTU{
Index:mw.model.Len() + 1,
Direction:"uplink",
DevEUI:mw.dtuConf.DevEui,
MType:phy.MHDR.MType.String(),
GatewayID:mw.dtuConf.GatewayId,
@ -774,9 +534,9 @@ func (mw *DTUMainWindow) Send(){
Time:time.Now().Format("2006-01-02 15:04:05"),
OrigData:origData.String(),
}
mw.upModel.Items = append(mw.upModel.Items, du)
mw.upModel.PublishRowsReset()
_ = mw.upTv.SetSelectedIndexes([]int{})
mw.model.Items = append(mw.model.Items, du)
mw.model.PublishRowsReset()
_ = mw.tv.SetSelectedIndexes([]int{})
frames,_:= packet.GetUplinkFrames(true,false)
for j := range frames {
mw.PushData(mw.dtuConf.GatewayId,"up",&frames[j])
@ -792,13 +552,15 @@ func (mw *DTUMainWindow) Send(){
return
}
}
packet,phy := mw.BuildUpData()
packet,phy,_ := mw.BuildUpData()
var origData bytes.Buffer
jsonData,_ := phy.MarshalJSON()
_ = json.Indent(&origData, jsonData, "", " ")
du := &model.DTUUp{
Index:mw.upModel.Len() + 1,
du := &DTU{
Index:mw.model.Len() + 1,
Direction:"uplink",
DevEUI:mw.dtuConf.DevEui,
DevAddr:mw.dtuConf.DevAddr,
MType:phy.MHDR.MType.String(),
GatewayID:mw.dtuConf.GatewayId,
Rssi:packet.Payload.RXPK[0].RSSI,
@ -811,9 +573,9 @@ func (mw *DTUMainWindow) Send(){
Time:time.Now().Format("2006-01-02 15:04:05"),
OrigData:origData.String(),
}
mw.upModel.Items = append(mw.upModel.Items, du)
mw.upModel.PublishRowsReset()
_ = mw.upTv.SetSelectedIndexes([]int{})
mw.model.Items = append(mw.model.Items, du)
mw.model.PublishRowsReset()
_ = mw.tv.SetSelectedIndexes([]int{})
frames,_:= packet.GetUplinkFrames(true,false)
for j := range frames {
mw.PushData(mw.dtuConf.GatewayId,"up",&frames[j])
@ -825,18 +587,10 @@ func (mw *DTUMainWindow) Send(){
_ = ioutil.WriteFile(mw.dtuConfFileName,confData.Bytes(),0644)
}
func (mw *DTUMainWindow) upTvItemActivated() {
msg := ""
for _, i := range mw.upTv.SelectedIndexes() {
msg += mw.upModel.Items[i].OrigData + "\n"
}
walk.MsgBox(mw, "原始数据", msg, walk.MsgBoxOK)
}
func (mw *DTUMainWindow) downTvItemActivated() {
func (mw *DTUMainWindow) tvItemActivated() {
msg := ""
for _, i := range mw.downTv.SelectedIndexes() {
msg += mw.downModel.Items[i].OrigData + "\n"
for _, i := range mw.tv.SelectedIndexes() {
msg += mw.model.Items[i].OrigData + "\n"
}
walk.MsgBox(mw, "原始数据", msg, walk.MsgBoxOK)
}

82
model/up.go → model.go

@ -1,13 +1,41 @@
package model
package main
import (
"github.com/brocaar/lorawan"
"github.com/lxn/walk"
"sort"
)
type DTUUp struct {
type ConnectConfig struct {
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
CACert string `json:"ca_cert"`
TLSCert string `json:"tls_cert"`
TLSKey string `json:"tls_key"`
}
type DTUConfig struct {
OTAA bool `json:"otaa"`
GatewayId string `json:"gatewayId"`
DevEui string `json:"devEui"`
DevAddr string `json:"devAddr"`
AppKey string `json:"appKey"`
AppSKey string `json:"appSKey"`
NwkSKey string `json:"nwkSKey"`
FPort uint8 `json:"fPort"`
FCnt uint32 `json:"fCnt"`
Freq float64 `json:"freq"`
msg []byte
devNonce lorawan.DevNonce
}
type DTU struct {
Index int
Direction string
DevEUI string
DevAddr string
MType string
GatewayID string
Rssi int16
@ -22,70 +50,74 @@ type DTUUp struct {
OrigData string
}
type DTUUpModel struct {
type DTUModel struct {
walk.TableModelBase
walk.SorterBase
SortColumn int
SortOrder walk.SortOrder
Items []*DTUUp
Items []*DTU
}
func (m *DTUUpModel) RowCount() int {
func (m *DTUModel) RowCount() int {
return len(m.Items)
}
func (m *DTUUpModel) Value(row, col int) interface{} {
func (m *DTUModel) Value(row, col int) interface{} {
item := m.Items[row]
switch col {
case 0:
return item.Index
case 1:
return item.DevEUI
return item.Direction
case 2:
return item.MType
return item.DevEUI
case 3:
return item.GatewayID
return item.DevAddr
case 4:
return item.Rssi
return item.MType
case 5:
return item.LoRaSNR
return item.GatewayID
case 6:
return item.Frequency
return item.Rssi
case 7:
return item.FCnt
return item.LoRaSNR
case 8:
return item.FPort
return item.Frequency
case 9:
return item.HexData
return item.FCnt
case 10:
return item.AsciiData
return item.FPort
case 11:
return item.HexData
case 12:
return item.AsciiData
case 13:
return item.Time
}
panic("unexpected col")
}
func (m *DTUUpModel) Checked(row int) bool {
func (m *DTUModel) Checked(row int) bool {
return m.Items[row].checked
}
func (m *DTUUpModel) SetChecked(row int, checked bool) error {
func (m *DTUModel) SetChecked(row int, checked bool) error {
m.Items[row].checked = checked
return nil
}
func (m *DTUUpModel) Sort(col int, order walk.SortOrder) error {
func (m *DTUModel) Sort(col int, order walk.SortOrder) error {
m.SortColumn, m.SortOrder = col, order
sort.Stable(m)
return m.SorterBase.Sort(col, order)
}
func (m *DTUUpModel) Len() int {
func (m *DTUModel) Len() int {
return len(m.Items)
}
func (m *DTUUpModel) Less(i, j int) bool {
func (m *DTUModel) Less(i, j int) bool {
a, b := m.Items[i], m.Items[j]
c := func(ls bool) bool {
if m.SortOrder == walk.SortAscending {
@ -110,10 +142,10 @@ func (m *DTUUpModel) Less(i, j int) bool {
}
}
func (m *DTUUpModel) Swap(i, j int) {
func (m *DTUModel) Swap(i, j int) {
m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
}
func NewDTUUpModel() *DTUUpModel {
return new(DTUUpModel)
}
func NewDTUModel() *DTUModel {
return new(DTUModel)
}

107
model/down.go

@ -1,107 +0,0 @@
package model
import (
"github.com/lxn/walk"
"sort"
)
type DTUDown struct {
Index int
DevEUI string
MType string
DevAddr string
GatewayID string
FCnt uint32
FPort uint8
HexData string
AsciiData string
Time string
checked bool
OrigData string
}
type DTUDownModel struct {
walk.TableModelBase
walk.SorterBase
SortColumn int
SortOrder walk.SortOrder
Items []*DTUDown
}
func (m *DTUDownModel) RowCount() int {
return len(m.Items)
}
func (m *DTUDownModel) Value(row, col int) interface{} {
item := m.Items[row]
switch col {
case 0:
return item.Index
case 1:
return item.DevEUI
case 2:
return item.MType
case 3:
return item.DevAddr
case 4:
return item.GatewayID
case 5:
return item.FCnt
case 6:
return item.FPort
case 7:
return item.HexData
case 8:
return item.AsciiData
case 9:
return item.Time
}
panic("unexpected col")
}
func (m *DTUDownModel) Checked(row int) bool {
return m.Items[row].checked
}
func (m *DTUDownModel) SetChecked(row int, checked bool) error {
m.Items[row].checked = checked
return nil
}
func (m *DTUDownModel) Sort(col int, order walk.SortOrder) error {
m.SortColumn, m.SortOrder = col, order
sort.Stable(m)
return m.SorterBase.Sort(col, order)
}
func (m *DTUDownModel) Len() int {
return len(m.Items)
}
func (m *DTUDownModel) Less(i, j int) bool {
a, b := m.Items[i], m.Items[j]
c := func(ls bool) bool {
if m.SortOrder == walk.SortAscending {
return ls
}
return !ls
}
switch m.SortColumn {
case 0:
return c(a.Index < b.Index)
case 2:
return c(a.DevEUI < b.DevEUI)
default:
return false
}
}
func (m *DTUDownModel) Swap(i, j int) {
m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
}
func NewDTUDownModel() *DTUDownModel {
return new(DTUDownModel)
}

261
utils.go

@ -0,0 +1,261 @@
package main
import (
"LoRaDTUMock/packets"
"crypto/aes"
"crypto/tls"
"crypto/x509"
"fmt"
"github.com/brocaar/lorawan"
"github.com/pkg/errors"
"io/ioutil"
"math/rand"
"syscall"
"time"
)
func BytesToString(b []byte) string {
_,err := syscall.UTF16FromString(string(b))
if err == nil {
return string(b)
}
return ""
}
func newTLSConfig(cafile, certFile, certKeyFile string) (*tls.Config, error) {
if cafile == "" && certFile == "" && certKeyFile == "" {
return nil, nil
}
tlsConfig := &tls.Config{}
// Import trusted certificates from CAfile.pem.
if cafile != "" {
cacert, err := ioutil.ReadFile(cafile)
if err != nil {
return nil, err
}
certpool := x509.NewCertPool()
certpool.AppendCertsFromPEM(cacert)
tlsConfig.RootCAs = certpool // RootCAs = certs used to verify server cert.
}
// Import certificate and the key
if certFile != "" && certKeyFile != "" {
kp, err := tls.LoadX509KeyPair(certFile, certKeyFile)
if err != nil {
return nil, err
}
tlsConfig.Certificates = []tls.Certificate{kp}
}
return tlsConfig, nil
}
func BuildUpData(gatewayId,devAddr,nwkSKey string,
fCnt uint32,fPort,dr,ch uint8,freq,lsnr float64,
mType lorawan.MType,fCtrl lorawan.FCtrl,rssi int16,
userData []byte) (*packets.PushDataPacket,*lorawan.PHYPayload,error) {
var gatewayMac lorawan.EUI64
if err := gatewayMac.UnmarshalText([]byte(gatewayId)); err != nil {
return nil,nil,err
}
now := time.Now().Round(time.Second)
compactTS := packets.CompactTime(now)
tmms := int64(time.Second / time.Millisecond)
var phy lorawan.PHYPayload
phy.MHDR.MType = mType
phy.MHDR.Major = lorawan.LoRaWANR1
var mac lorawan.MACPayload
if err := mac.FHDR.DevAddr.UnmarshalText([]byte(devAddr)); err != nil {
return nil,nil,err
}
mac.FHDR.FCtrl = fCtrl
mac.FHDR.FCnt = fCnt
mac.FPort = &fPort
var dataPayload lorawan.DataPayload
if err := dataPayload.UnmarshalBinary(true, userData); err != nil {
return nil,nil,err
}
mac.FRMPayload = []lorawan.Payload{&dataPayload}
phy.MACPayload = &mac
var aseKey lorawan.AES128Key
if err := aseKey.UnmarshalText([]byte(nwkSKey));err != nil {
return nil,nil,err
}
if err := phy.EncryptFRMPayload(aseKey);err != nil {
return nil,nil,err
}
sf :=[...]string{"SF12","SF11","SF10","SF9","SF8","SF7"}
if err := phy.SetUplinkDataMIC(lorawan.LoRaWAN1_0, 0, dr, ch, aseKey, aseKey);err != nil {
return nil,nil,err
}
data,err := phy.MarshalBinary();
if err != nil {
return nil,nil,err
}
return &packets.PushDataPacket{
ProtocolVersion: packets.ProtocolVersion2,
RandomToken: uint16(rand.Uint32()),
GatewayMAC: gatewayMac,
Payload: packets.PushDataPayload{
RXPK: []packets.RXPK{
{
Time: &compactTS,
Tmst: 708016819,
Tmms: &tmms,
Freq: freq,
Chan: ch,
RFCh: 1,
Stat: 1,
Modu: "LORA",
DatR: packets.DatR{LoRa: sf[dr]+"BW125"},
CodR: "4/5",
RSSI: rssi,
LSNR: lsnr,
Size: uint16(len(data)),
Data: data,
},
},
},
},&phy,nil
}
func BuildJoin(gatewayId,appEui,devEui,appKey string,dr,ch uint8,
freq,lsnr float64,rssi int16,devNonce lorawan.DevNonce) (*packets.PushDataPacket,*lorawan.PHYPayload,error) {
if dr > 5 || dr < 0 {
return nil,nil,errors.New("dr exceed limit")
}
var gatewayMac lorawan.EUI64
if err := gatewayMac.UnmarshalText([]byte(gatewayId));err != nil{
return nil,nil,err
}
now := time.Now().Round(time.Second)
compactTS := packets.CompactTime(now)
tmms := int64(time.Second / time.Millisecond)
var phy lorawan.PHYPayload
phy.MHDR.MType = lorawan.JoinRequest
phy.MHDR.Major = lorawan.LoRaWANR1
var DevEUI lorawan.EUI64
if err := DevEUI.UnmarshalText([]byte(devEui));err != nil{
return nil,nil,err
}
var joinEUI lorawan.EUI64
if err := joinEUI.UnmarshalText([]byte(appEui));err != nil{
return nil,nil,err
}
phy.MACPayload = &lorawan.JoinRequestPayload{
DevEUI: DevEUI,
JoinEUI: joinEUI,
DevNonce: devNonce,
}
var aseKey lorawan.AES128Key
if err := aseKey.UnmarshalText([]byte(appKey));err != nil{
return nil,nil,err
}
sf :=[...]string{"SF12","SF11","SF10","SF9","SF8","SF7"}
if err := phy.SetUplinkJoinMIC(aseKey);err != nil{
return nil,nil,err
}
data,err := phy.MarshalBinary()
if err != nil {
return nil,nil,err
}
return &packets.PushDataPacket{
ProtocolVersion: packets.ProtocolVersion2,
RandomToken: uint16(rand.Uint32()),
GatewayMAC: gatewayMac,
Payload: packets.PushDataPayload{
RXPK: []packets.RXPK{
{
Time: &compactTS,
Tmst: 708016819,
Tmms: &tmms,
Freq: freq,
Chan: ch,
RFCh: 1,
Stat: 1,
Modu: "LORA",
DatR: packets.DatR{LoRa: sf[dr]+"BW125"},
CodR: "4/5",
RSSI: rssi,
LSNR: lsnr,
Size: uint16(len(data)),
Data: data,
},
},
},
},&phy,nil
}
// getNwkSKey returns the network session key.
func getNwkSKey(appkey lorawan.AES128Key, netID lorawan.NetID, joinNonce lorawan.JoinNonce, devNonce lorawan.DevNonce) (lorawan.AES128Key, error) {
return getSKey(0x01, appkey, netID, joinNonce, devNonce)
}
// getAppSKey returns the application session key.
func getAppSKey(appkey lorawan.AES128Key, netID lorawan.NetID, joinNonce lorawan.JoinNonce, devNonce lorawan.DevNonce) (lorawan.AES128Key, error) {
return getSKey(0x02, appkey, netID, joinNonce, devNonce)
}
func getSKey(typ byte, nwkKey lorawan.AES128Key, netID lorawan.NetID,joinNonce lorawan.JoinNonce, devNonce lorawan.DevNonce) (lorawan.AES128Key, error) {
var key lorawan.AES128Key
b := make([]byte, 16)
b[0] = typ
netIDB, err := netID.MarshalBinary()
if err != nil {
return key, errors.Wrap(err, "marshal binary error")
}
joinNonceB, err := joinNonce.MarshalBinary()
if err != nil {
return key, errors.Wrap(err, "marshal binary error")
}
devNonceB, err := devNonce.MarshalBinary()
if err != nil {
return key, errors.Wrap(err, "marshal binary error")
}
copy(b[1:4], joinNonceB)
copy(b[4:7], netIDB)
copy(b[7:9], devNonceB)
block, err := aes.NewCipher(nwkKey[:])
if err != nil {
return key, err
}
if block.BlockSize() != len(b) {
return key, fmt.Errorf("block-size of %d bytes is expected", len(b))
}
block.Encrypt(key[:], b)
return key, nil
}
func MarshalFRMPayload(p *lorawan.MACPayload) ([]byte, error) {
var out []byte
var b []byte
var err error
for _, fp := range p.FRMPayload {
if mac, ok := fp.(*lorawan.MACCommand); ok {
if p.FPort == nil || (p.FPort != nil && *p.FPort != 0) {
return []byte{}, errors.New("lorawan: a MAC command is only allowed when FPort=0")
}
b, err = mac.MarshalBinary()
} else {
b, err = fp.MarshalBinary()
}
if err != nil {
return nil, err
}
out = append(out, b...)
}
return out, nil
}
Loading…
Cancel
Save