lihua
5 years ago
20 changed files with 2494 additions and 1 deletions
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"otaa": false, |
||||
|
"gatewayId": "0102030405060708", |
||||
|
"devEui": "6ef1881ba5541419", |
||||
|
"devAddr": "0c18699", |
||||
|
"appKey": "", |
||||
|
"appSKey": "33998df974421457437d986eff739ffa", |
||||
|
"nwkSKey": "33998df974421457437d986eff739ffa", |
||||
|
"fPort": 2, |
||||
|
"fCnt": 0, |
||||
|
"freq": 470.3 |
||||
|
} |
@ -0,0 +1,838 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"LoRaDTUMock/model" |
||||
|
"LoRaDTUMock/packets" |
||||
|
"bytes" |
||||
|
"crypto/aes" |
||||
|
"crypto/tls" |
||||
|
"crypto/x509" |
||||
|
"encoding/hex" |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"github.com/brocaar/loraserver/api/gw" |
||||
|
"github.com/brocaar/lorawan" |
||||
|
paho "github.com/eclipse/paho.mqtt.golang" |
||||
|
"github.com/golang/protobuf/proto" |
||||
|
"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 |
||||
|
host,username,password *walk.LineEdit |
||||
|
port *walk.NumberEdit |
||||
|
connect, disconnect,caConf,send *walk.PushButton |
||||
|
msg *walk.TextEdit |
||||
|
ssl *walk.CheckBox |
||||
|
connConf ConnectConfig |
||||
|
dtuConf DTUConfig |
||||
|
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()} |
||||
|
maxWidth := int(win.GetSystemMetrics(win.SM_CXSCREEN)) - 200 |
||||
|
maxHeight := int(win.GetSystemMetrics(win.SM_CYSCREEN)) - 100 |
||||
|
err := MainWindow{ |
||||
|
AssignTo: &mw.MainWindow, |
||||
|
Title: "LoRaDTUMock", |
||||
|
//Icon: "test.ico",
|
||||
|
Size: Size{maxWidth,maxHeight }, |
||||
|
Layout: VBox{}, |
||||
|
Children: []Widget{ |
||||
|
Composite{ |
||||
|
Layout: HBox{MarginsZero: true}, |
||||
|
Children: []Widget{ |
||||
|
Label{Text:"主机/IP:"}, |
||||
|
LineEdit{AssignTo:&mw.host}, |
||||
|
Label{Text:"端口:"}, |
||||
|
NumberEdit{AssignTo:&mw.port,MinSize:Size{Width:50}}, |
||||
|
Label{Text:"用户名:"}, |
||||
|
LineEdit{AssignTo:&mw.username}, |
||||
|
Label{Text:"密码:"}, |
||||
|
LineEdit{AssignTo:&mw.password,PasswordMode:true}, |
||||
|
PushButton{Text:"连接", AssignTo: &mw.connect,OnClicked:mw.Connect}, |
||||
|
PushButton{Text:"断开连接", AssignTo:&mw.disconnect, Enabled:false, OnClicked: mw.Disconnect}, |
||||
|
CheckBox{Text:"开启SSL/TLS",AssignTo:&mw.ssl,OnClicked:mw.SSL}, |
||||
|
PushButton{Text:"证书配置",Enabled:false,AssignTo:&mw.caConf,OnClicked: mw.ConnectConfig}, |
||||
|
PushButton{Text:"终端配置",OnClicked: mw.DTUConfig}, |
||||
|
PushButton{Text:"发送",AssignTo:&mw.send,OnClicked: mw.Send}, |
||||
|
}, |
||||
|
}, |
||||
|
Composite{ |
||||
|
Layout: HBox{}, |
||||
|
Children: []Widget{ |
||||
|
TableView{ |
||||
|
AssignTo: &mw.upTv, |
||||
|
CheckBoxes: true, |
||||
|
ColumnsOrderable: true, |
||||
|
MultiSelection: true, |
||||
|
Columns: []TableViewColumn{ |
||||
|
{Title: "序号"}, |
||||
|
{Title: "终端EUI"}, |
||||
|
{Title: "网关ID"}, |
||||
|
{Title: "信号强度"}, |
||||
|
{Title: "信噪比"}, |
||||
|
{Title: "频率"}, |
||||
|
{Title: "计数"}, |
||||
|
{Title: "端口"}, |
||||
|
{Title: "HEX数据"}, |
||||
|
{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: "网关ID"}, |
||||
|
{Title: "频率"}, |
||||
|
{Title: "计数"}, |
||||
|
{Title: "端口"}, |
||||
|
{Title: "HEX数据"}, |
||||
|
{Title: "ASCII数据"}, |
||||
|
{Title: "时间"}, |
||||
|
}, |
||||
|
Model: mw.downModel, |
||||
|
OnItemActivated: mw.downTvItemActivated, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}.Create() |
||||
|
if err != nil { |
||||
|
panic("LoRaDTUMock窗口创建失败") |
||||
|
} |
||||
|
_ = mw.port.SetValue(1883) |
||||
|
dir,_ := os.Getwd() |
||||
|
mw.connConfFileName = dir + "/LoRaDTUMock.json" |
||||
|
mw.dtuConfFileName = dir + "/LoRaDTUConf.json" |
||||
|
data, err := ioutil.ReadFile(mw.connConfFileName) |
||||
|
if err == nil { |
||||
|
err = json.Unmarshal(data, &mw.connConf) |
||||
|
if err != nil { |
||||
|
msg := "配置文件格式错误:" + err.Error() |
||||
|
walk.MsgBox(mw, "错误", msg, walk.MsgBoxIconError) |
||||
|
return |
||||
|
} |
||||
|
_ = mw.host.SetText(mw.connConf.Host) |
||||
|
_ = mw.port.SetValue(float64(mw.connConf.Port)) |
||||
|
_ = mw.username.SetText(mw.connConf.Username) |
||||
|
_ = mw.password.SetText(mw.connConf.Password) |
||||
|
} |
||||
|
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() { |
||||
|
if mw.host.Text() != "" && mw.port.Value() > 0 { |
||||
|
opts := paho.NewClientOptions() |
||||
|
serverAddr := fmt.Sprintf("%s:%d",mw.host.Text(),int(mw.port.Value())) |
||||
|
if mw.ssl.Checked() { |
||||
|
if mw.connConf.CACert != "" { |
||||
|
serverAddr = fmt.Sprintf("ssl://%s:%d",mw.host.Text(),int(mw.port.Value())) |
||||
|
tlsconfig, err := newTLSConfig(mw.connConf.CACert, mw.connConf.TLSCert, mw.connConf.TLSKey) |
||||
|
if err != nil { |
||||
|
msg := "证书加载错误:" + err.Error() |
||||
|
walk.MsgBox(mw, "错误", msg, walk.MsgBoxIconError) |
||||
|
} |
||||
|
if tlsconfig != nil { |
||||
|
opts.SetTLSConfig(tlsconfig) |
||||
|
} |
||||
|
}else{ |
||||
|
msg := "证书未配置,服务端单向认证只需配置CA证书,双向认证还需配置客户端证书及秘钥" |
||||
|
walk.MsgBox(mw, "错误", msg, walk.MsgBoxIconError) |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
opts.AddBroker(serverAddr) |
||||
|
opts.SetUsername(mw.username.Text()) |
||||
|
opts.SetPassword(mw.password.Text()) |
||||
|
opts.SetConnectTimeout(5 * time.Second) |
||||
|
mw.mqttClient = paho.NewClient(opts) |
||||
|
token := mw.mqttClient.Connect() |
||||
|
if token.Wait() && token.Error() == nil { |
||||
|
mw.connConf.Host = mw.host.Text() |
||||
|
mw.connConf.Port = int(mw.port.Value()) |
||||
|
mw.connConf.Username = mw.username.Text() |
||||
|
mw.connConf.Password = mw.password.Text() |
||||
|
var confData bytes.Buffer |
||||
|
d,_ := json.Marshal(&mw.connConf) |
||||
|
_ = json.Indent(&confData, d, "", "\t") |
||||
|
_ = ioutil.WriteFile(mw.connConfFileName,confData.Bytes(),0644) |
||||
|
mw.host.SetEnabled(false) |
||||
|
mw.port.SetEnabled(false) |
||||
|
mw.username.SetEnabled(false) |
||||
|
mw.password.SetEnabled(false) |
||||
|
mw.disconnect.SetEnabled(true) |
||||
|
mw.connect.SetEnabled(false) |
||||
|
mw.caConf.SetEnabled(false) |
||||
|
topic := "gateway/+/command/#" |
||||
|
token := mw.mqttClient.Subscribe(topic,0, mw.HandleData) |
||||
|
if token.Wait() && token.Error() != nil { |
||||
|
msg := "订阅失败:" + token.Error().Error() |
||||
|
walk.MsgBox(mw, "错误", msg, walk.MsgBoxIconError) |
||||
|
} |
||||
|
}else{ |
||||
|
msg := "连接失败:" + token.Error().Error() |
||||
|
walk.MsgBox(mw, "错误", msg, walk.MsgBoxIconError) |
||||
|
} |
||||
|
}else{ |
||||
|
msg := "主机/IP不能为空,端口不能为0" |
||||
|
walk.MsgBox(mw, "错误", msg, walk.MsgBoxIconError) |
||||
|
} |
||||
|
}() |
||||
|
} |
||||
|
|
||||
|
func (mw *DTUMainWindow) Disconnect() { |
||||
|
mw.connect.SetEnabled(true) |
||||
|
mw.host.SetEnabled(true) |
||||
|
mw.port.SetEnabled(true) |
||||
|
mw.username.SetEnabled(true) |
||||
|
mw.password.SetEnabled(true) |
||||
|
mw.disconnect.SetEnabled(false) |
||||
|
mw.caConf.SetEnabled(true) |
||||
|
mw.mqttClient.Disconnect(0) |
||||
|
} |
||||
|
|
||||
|
func (mw *DTUMainWindow) DTUConfig() { |
||||
|
var dlg *walk.Dialog |
||||
|
var otaa *walk.CheckBox |
||||
|
var gatewayId,devEUI,devAddr,appKey,appSKey,nwkSKey *walk.LineEdit |
||||
|
var fPort,fCnt,freq *walk.NumberEdit |
||||
|
var msg *walk.TextEdit |
||||
|
var acceptPB, cancelPB *walk.PushButton |
||||
|
_ = Dialog{ |
||||
|
Title: "DTU配置", |
||||
|
Layout: VBox{}, |
||||
|
AssignTo: &dlg, |
||||
|
DefaultButton: &acceptPB, |
||||
|
CancelButton: &cancelPB, |
||||
|
MinSize: Size{400, 200}, |
||||
|
Children: []Widget{ |
||||
|
Composite{ |
||||
|
Layout:Grid{Columns: 2}, |
||||
|
Children:[]Widget{ |
||||
|
Label{Text:"入网方式:"}, |
||||
|
CheckBox{AssignTo: &otaa,Text:"OTAA入网",OnClicked: func() { |
||||
|
if otaa.Checked() { |
||||
|
appKey.SetEnabled(true) |
||||
|
devAddr.SetEnabled(false) |
||||
|
appSKey.SetEnabled(false) |
||||
|
nwkSKey.SetEnabled(false) |
||||
|
}else{ |
||||
|
appKey.SetEnabled(false) |
||||
|
devAddr.SetEnabled(true) |
||||
|
appSKey.SetEnabled(true) |
||||
|
nwkSKey.SetEnabled(true) |
||||
|
} |
||||
|
}}, |
||||
|
Label{Text:"网关ID:"}, |
||||
|
LineEdit{AssignTo:&gatewayId}, |
||||
|
Label{Text:"终端EUI:"}, |
||||
|
LineEdit{AssignTo:&devEUI}, |
||||
|
Label{Text:"终端地址:"}, |
||||
|
LineEdit{AssignTo:&devAddr}, |
||||
|
Label{Text:"应用秘钥:"}, |
||||
|
LineEdit{AssignTo:&appKey,Enabled:false}, |
||||
|
Label{Text:"应用会话秘钥:"}, |
||||
|
LineEdit{AssignTo:&appSKey}, |
||||
|
Label{Text:"网络会话秘钥:"}, |
||||
|
LineEdit{AssignTo:&nwkSKey}, |
||||
|
Label{Text:"端口:"}, |
||||
|
NumberEdit{AssignTo:&fPort}, |
||||
|
Label{Text:"计数:"}, |
||||
|
NumberEdit{AssignTo:&fCnt}, |
||||
|
Label{Text:"频率:"}, |
||||
|
NumberEdit{AssignTo:&freq,Decimals:2}, |
||||
|
Label{Text:"消息:"}, |
||||
|
TextEdit{AssignTo:&msg}, |
||||
|
}, |
||||
|
}, |
||||
|
Composite{ |
||||
|
Layout: HBox{}, |
||||
|
Children: []Widget{ |
||||
|
HSpacer{}, |
||||
|
PushButton{ |
||||
|
AssignTo: &acceptPB, |
||||
|
Text: "确定", |
||||
|
OnClicked: func() { |
||||
|
mw.dtuConf.OTAA = otaa.Checked() |
||||
|
mw.dtuConf.GatewayId = gatewayId.Text() |
||||
|
mw.dtuConf.DevEui = devEUI.Text() |
||||
|
mw.dtuConf.DevAddr = devAddr.Text() |
||||
|
mw.dtuConf.AppKey = appKey.Text() |
||||
|
mw.dtuConf.AppSKey = appSKey.Text() |
||||
|
mw.dtuConf.NwkSKey = nwkSKey.Text() |
||||
|
mw.dtuConf.FPort = uint8(fPort.Value()) |
||||
|
mw.dtuConf.FCnt = uint32(fCnt.Value()) |
||||
|
mw.dtuConf.Freq = freq.Value() |
||||
|
mw.dtuConf.msg = []byte(msg.Text()) |
||||
|
|
||||
|
var confData bytes.Buffer |
||||
|
d,_ := json.Marshal(&mw.dtuConf) |
||||
|
_ = json.Indent(&confData, d, "", "\t") |
||||
|
_ = ioutil.WriteFile(mw.dtuConfFileName,confData.Bytes(),0644) |
||||
|
dlg.Accept() |
||||
|
}, |
||||
|
}, |
||||
|
PushButton{ |
||||
|
AssignTo: &cancelPB, |
||||
|
Text: "取消", |
||||
|
OnClicked: func() { dlg.Cancel() }, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}.Create(mw) |
||||
|
data, err := ioutil.ReadFile(mw.dtuConfFileName) |
||||
|
if err == nil { |
||||
|
err = json.Unmarshal(data, &mw.dtuConf) |
||||
|
if err != nil { |
||||
|
msg := "配置文件格式错误:" + err.Error() |
||||
|
walk.MsgBox(mw, "错误", msg, walk.MsgBoxIconError) |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
otaa.SetChecked(mw.dtuConf.OTAA) |
||||
|
_ = gatewayId.SetText(mw.dtuConf.GatewayId) |
||||
|
_ = devEUI.SetText(mw.dtuConf.DevEui) |
||||
|
_ = devAddr.SetText(mw.dtuConf.DevAddr) |
||||
|
_ = appKey.SetText(mw.dtuConf.AppKey) |
||||
|
_ = appSKey.SetText(mw.dtuConf.AppSKey) |
||||
|
_ = nwkSKey.SetText(mw.dtuConf.NwkSKey) |
||||
|
_ = fPort.SetValue(float64(mw.dtuConf.FPort)) |
||||
|
_ = fCnt.SetValue(float64(mw.dtuConf.FCnt)) |
||||
|
_ = freq.SetValue(mw.dtuConf.Freq) |
||||
|
_ = msg.SetText(string(mw.dtuConf.msg)) |
||||
|
|
||||
|
dlg.Run() |
||||
|
} |
||||
|
func (mw *DTUMainWindow) SSL() { |
||||
|
if mw.ssl.Checked() { |
||||
|
mw.caConf.SetEnabled(true) |
||||
|
}else{ |
||||
|
mw.caConf.SetEnabled(false) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (mw *DTUMainWindow) ConnectConfig() { |
||||
|
var dlg *walk.Dialog |
||||
|
var caCert,tlsCert,tlsKey *walk.LineEdit |
||||
|
var acceptPB, cancelPB *walk.PushButton |
||||
|
_ = Dialog{ |
||||
|
Title: "连接配置", |
||||
|
Layout: VBox{}, |
||||
|
AssignTo: &dlg, |
||||
|
DefaultButton: &acceptPB, |
||||
|
CancelButton: &cancelPB, |
||||
|
MinSize: Size{400, 200}, |
||||
|
Children: []Widget{ |
||||
|
Composite{ |
||||
|
Layout:Grid{Columns: 3}, |
||||
|
Children:[]Widget{ |
||||
|
Label{Text:"CA证书:"}, |
||||
|
LineEdit{Text:Bind("CACert"),AssignTo:&caCert}, |
||||
|
PushButton{Text:"打开",OnClicked: func() { |
||||
|
dlg := new(walk.FileDialog) |
||||
|
dlg.Title = "请选择CA证书" |
||||
|
dlg.Filter = "CA证书 (*.crt)|*.crt|所有文件 (*.*)|*.*" |
||||
|
if ok, err := dlg.ShowOpen(mw); err != nil { |
||||
|
return |
||||
|
} else if !ok { |
||||
|
return |
||||
|
} |
||||
|
_ = caCert.SetText(dlg.FilePath) |
||||
|
}}, |
||||
|
Label{Text:"客户端证书:"}, |
||||
|
LineEdit{Text:Bind("TLSCert"),AssignTo:&tlsCert}, |
||||
|
PushButton{Text:"打开",OnClicked: func() { |
||||
|
dlg := new(walk.FileDialog) |
||||
|
dlg.Title = "请选择客户端证书" |
||||
|
dlg.Filter = "客户端证书 (*.crt)|*.crt|所有文件 (*.*)|*.*" |
||||
|
if ok, err := dlg.ShowOpen(mw); err != nil { |
||||
|
return |
||||
|
} else if !ok { |
||||
|
return |
||||
|
} |
||||
|
_ = tlsCert.SetText(dlg.FilePath) |
||||
|
}}, |
||||
|
Label{Text:"客户端证书秘钥:"}, |
||||
|
LineEdit{Text:Bind("TLSKey"),AssignTo:&tlsKey}, |
||||
|
PushButton{Text:"打开",OnClicked: func() { |
||||
|
dlg := new(walk.FileDialog) |
||||
|
dlg.Title = "请选择客户端证书秘钥" |
||||
|
dlg.Filter = "客户端证书秘钥 (*.key)|*.key|所有文件 (*.*)|*.*" |
||||
|
if ok, err := dlg.ShowOpen(mw); err != nil { |
||||
|
return |
||||
|
} else if !ok { |
||||
|
return |
||||
|
} |
||||
|
_ = tlsKey.SetText(dlg.FilePath) |
||||
|
}}, |
||||
|
}, |
||||
|
}, |
||||
|
Composite{ |
||||
|
Layout: HBox{}, |
||||
|
Children: []Widget{ |
||||
|
HSpacer{}, |
||||
|
PushButton{ |
||||
|
AssignTo: &acceptPB, |
||||
|
Text: "确定", |
||||
|
OnClicked: func() { |
||||
|
mw.connConf.CACert = caCert.Text() |
||||
|
mw.connConf.TLSCert = tlsCert.Text() |
||||
|
mw.connConf.TLSKey = tlsKey.Text() |
||||
|
dlg.Accept() |
||||
|
}, |
||||
|
}, |
||||
|
PushButton{ |
||||
|
AssignTo: &cancelPB, |
||||
|
Text: "取消", |
||||
|
OnClicked: func() { dlg.Cancel() }, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}.Create(mw) |
||||
|
_ = caCert.SetText(mw.connConf.CACert) |
||||
|
_ = tlsCert.SetText(mw.connConf.TLSCert) |
||||
|
_ = tlsKey.SetText(mw.connConf.TLSKey) |
||||
|
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) 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)) |
||||
|
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) |
||||
|
} |
||||
|
|
||||
|
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 |
||||
|
err := proto.Unmarshal(message.Payload(),&downlinkFrame) |
||||
|
if err == nil { |
||||
|
packet,err := packets.GetPullRespPacket(packets.ProtocolVersion2, uint16(rand.Uint32()),downlinkFrame) |
||||
|
if err == nil{ |
||||
|
var phy lorawan.PHYPayload |
||||
|
err = phy.UnmarshalBinary(packet.Payload.TXPK.Data) |
||||
|
if err == nil { |
||||
|
switch phy.MHDR.MType { |
||||
|
case lorawan.JoinAccept: |
||||
|
mw.HandleJoinAccept(&phy) |
||||
|
case lorawan.ConfirmedDataDown,lorawan.UnconfirmedDataDown: |
||||
|
mw.HandleDataDown(&phy) |
||||
|
default: |
||||
|
fmt.Println("未处理的帧") |
||||
|
} |
||||
|
var origData bytes.Buffer |
||||
|
jsonData,_ := phy.MarshalJSON() |
||||
|
_ = json.Indent(&origData, jsonData, "", " ") |
||||
|
dd := &model.DTUDown{ |
||||
|
Index: mw.downModel.Len() + 1, |
||||
|
DevEUI: mw.dtuConf.DevEui, |
||||
|
DevAddr: mw.dtuConf.DevAddr, |
||||
|
GatewayID: hex.EncodeToString(downlinkFrame.TxInfo.GatewayId), |
||||
|
Time:time.Now().Format("2006-01-02 15:04:05"), |
||||
|
OrigData:origData.String(), |
||||
|
} |
||||
|
if phy.MHDR.MType == lorawan.ConfirmedDataDown || phy.MHDR.MType == lorawan.UnconfirmedDataDown { |
||||
|
mpl := phy.MACPayload.(*lorawan.MACPayload) |
||||
|
if mpl.FPort != nil { |
||||
|
dd.FPort = *mpl.FPort |
||||
|
} |
||||
|
dd.FCnt = mpl.FHDR.FCnt |
||||
|
p,err := MarshalFRMPayload(mpl) |
||||
|
if err == nil { |
||||
|
dd.AsciiData = BytesToString(p) |
||||
|
dd.HexData = hex.EncodeToString(p) |
||||
|
} |
||||
|
} |
||||
|
mw.downModel.Items = append(mw.downModel.Items, dd) |
||||
|
mw.downModel.PublishRowsReset() |
||||
|
_ = mw.downTv.SetSelectedIndexes([]int{}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (mw *DTUMainWindow) HandleJoinAccept(phy *lorawan.PHYPayload){ |
||||
|
key := mw.dtuConf.AppKey |
||||
|
var aseKey lorawan.AES128Key |
||||
|
_ = aseKey.UnmarshalText([]byte(key)) |
||||
|
err := phy.DecryptJoinAcceptPayload(aseKey) |
||||
|
if err != nil { |
||||
|
fmt.Println(err) |
||||
|
} |
||||
|
jap,ok := phy.MACPayload.(*lorawan.JoinAcceptPayload) |
||||
|
if !ok { |
||||
|
fmt.Println("lorawan: MACPayload must be of type *JoinAcceptPayload") |
||||
|
} |
||||
|
mw.dtuConf.DevAddr = jap.DevAddr.String() |
||||
|
dn := mw.dtuConf.devNonce |
||||
|
appSKey,err := getAppSKey(aseKey,jap.HomeNetID,jap.JoinNonce,dn) |
||||
|
if err == nil { |
||||
|
mw.dtuConf.AppSKey = appSKey.String() |
||||
|
fmt.Println(mw.dtuConf.AppSKey) |
||||
|
} |
||||
|
nwkSKey,err := getNwkSKey(aseKey,jap.HomeNetID,jap.JoinNonce,dn) |
||||
|
if err == nil { |
||||
|
mw.dtuConf.NwkSKey = nwkSKey.String() |
||||
|
fmt.Println(mw.dtuConf.NwkSKey) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (mw *DTUMainWindow) HandleDataDown(phy *lorawan.PHYPayload){ |
||||
|
key := mw.dtuConf.NwkSKey |
||||
|
var aseKey lorawan.AES128Key |
||||
|
_ = aseKey.UnmarshalText([]byte(key)) |
||||
|
err := phy.DecryptFRMPayload(aseKey) |
||||
|
if err == nil { |
||||
|
mpl := phy.MACPayload.(*lorawan.MACPayload) |
||||
|
mw.dtuConf.DevAddr = mpl.FHDR.DevAddr.String() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (mw *DTUMainWindow) PushData(gatewayEUI string,event string, msg proto.Message) { |
||||
|
topic := fmt.Sprintf("gateway/%s/event/%s",gatewayEUI,event) |
||||
|
b, err := proto.Marshal(msg) |
||||
|
if err != nil { |
||||
|
fmt.Println("marshal message error") |
||||
|
} |
||||
|
|
||||
|
if token := mw.mqttClient.Publish(topic, 0, false, b); token.Wait() && token.Error() == nil { |
||||
|
fmt.Println("mqtt message ok") |
||||
|
}else{ |
||||
|
fmt.Println("mqtt message error") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (mw *DTUMainWindow) Send(){ |
||||
|
if mw.dtuConf.OTAA && mw.dtuConf.DevAddr == ""{ |
||||
|
packet,phy := mw.BuildJoin() |
||||
|
var origData bytes.Buffer |
||||
|
jsonData,_ := phy.MarshalJSON() |
||||
|
_ = json.Indent(&origData, jsonData, "", " ") |
||||
|
du := &model.DTUUp{ |
||||
|
Index:mw.upModel.Len() + 1, |
||||
|
DevEUI:mw.dtuConf.DevEui, |
||||
|
MType:phy.MHDR.MType.String(), |
||||
|
GatewayID:mw.dtuConf.GatewayId, |
||||
|
Rssi:packet.Payload.RXPK[0].RSSI, |
||||
|
LoRaSNR:packet.Payload.RXPK[0].LSNR, |
||||
|
Frequency:packet.Payload.RXPK[0].Freq, |
||||
|
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{}) |
||||
|
frames,_:= packet.GetUplinkFrames(true,false) |
||||
|
for j := range frames { |
||||
|
mw.PushData(mw.dtuConf.GatewayId,"up",&frames[j]) |
||||
|
} |
||||
|
fmt.Println("push join ") |
||||
|
for cnt := 0;mw.dtuConf.DevAddr == "" && cnt < 5;cnt ++ { |
||||
|
time.Sleep(time.Second) |
||||
|
} |
||||
|
if mw.dtuConf.DevAddr != "" { |
||||
|
fmt.Println("join ok") |
||||
|
}else{ |
||||
|
fmt.Println("join failed") |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
packet,phy := mw.BuildUpData() |
||||
|
var origData bytes.Buffer |
||||
|
jsonData,_ := phy.MarshalJSON() |
||||
|
_ = json.Indent(&origData, jsonData, "", " ") |
||||
|
du := &model.DTUUp{ |
||||
|
Index:mw.upModel.Len() + 1, |
||||
|
DevEUI:mw.dtuConf.DevEui, |
||||
|
MType:phy.MHDR.MType.String(), |
||||
|
GatewayID:mw.dtuConf.GatewayId, |
||||
|
Rssi:packet.Payload.RXPK[0].RSSI, |
||||
|
LoRaSNR:packet.Payload.RXPK[0].LSNR, |
||||
|
Frequency:packet.Payload.RXPK[0].Freq, |
||||
|
FCnt:mw.dtuConf.FCnt, |
||||
|
FPort:mw.dtuConf.FPort, |
||||
|
HexData:hex.EncodeToString(mw.dtuConf.msg), |
||||
|
AsciiData:BytesToString(mw.dtuConf.msg), |
||||
|
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{}) |
||||
|
frames,_:= packet.GetUplinkFrames(true,false) |
||||
|
for j := range frames { |
||||
|
mw.PushData(mw.dtuConf.GatewayId,"up",&frames[j]) |
||||
|
} |
||||
|
mw.dtuConf.FCnt ++ |
||||
|
var confData bytes.Buffer |
||||
|
d,_ := json.Marshal(&mw.dtuConf) |
||||
|
_ = json.Indent(&confData, d, "", "\t") |
||||
|
_ = 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() { |
||||
|
msg := "" |
||||
|
for _, i := range mw.downTv.SelectedIndexes() { |
||||
|
msg += mw.downModel.Items[i].OrigData + "\n" |
||||
|
} |
||||
|
walk.MsgBox(mw, "原始数据", msg, walk.MsgBoxOK) |
||||
|
} |
@ -0,0 +1,9 @@ |
|||||
|
{ |
||||
|
"host": "39.98.253.192", |
||||
|
"port": 1885, |
||||
|
"username": "", |
||||
|
"password": "", |
||||
|
"ca_cert": "", |
||||
|
"tls_cert": "", |
||||
|
"tls_key": "" |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> |
||||
|
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/> |
||||
|
<dependency> |
||||
|
<dependentAssembly> |
||||
|
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> |
||||
|
</dependentAssembly> |
||||
|
</dependency> |
||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3"> |
||||
|
<windowsSettings> |
||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness> |
||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware> |
||||
|
</windowsSettings> |
||||
|
</application> |
||||
|
</assembly> |
@ -0,0 +1,3 @@ |
|||||
|
rem set GOARCH=386 |
||||
|
set CGO_ENABLED=0 |
||||
|
go build -ldflags "-H windowsgui" |
@ -0,0 +1,14 @@ |
|||||
|
module LoRaDTUMock |
||||
|
|
||||
|
go 1.12 |
||||
|
|
||||
|
require ( |
||||
|
github.com/brocaar/loraserver v0.0.0-20190729122155-2f0bb9c308bc |
||||
|
github.com/brocaar/lorawan v0.0.0-20190709091804-c3a80883a8fa |
||||
|
github.com/eclipse/paho.mqtt.golang v1.2.0 |
||||
|
github.com/golang/protobuf v1.3.2 |
||||
|
github.com/lxn/walk v0.0.0-20191113135339-bf589de20b3c |
||||
|
github.com/lxn/win v0.0.0-20191106123917-121afc750dd3 |
||||
|
github.com/pkg/errors v0.8.1 |
||||
|
gopkg.in/Knetic/govaluate.v3 v3.0.0 // indirect |
||||
|
) |
@ -0,0 +1,595 @@ |
|||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= |
||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= |
||||
|
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= |
||||
|
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= |
||||
|
github.com/Azure/azure-amqp-common-go v1.1.4/go.mod h1:FhZtXirFANw40UXI2ntweO+VOkfaw8s6vZxUiRhLYW8= |
||||
|
github.com/Azure/azure-sdk-for-go v21.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= |
||||
|
github.com/Azure/azure-sdk-for-go v27.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= |
||||
|
github.com/Azure/azure-service-bus-go v0.5.1/go.mod h1:Tctgev//M0s8G6mdA+ZH9esoIXuiq7qEkxoDLZwfCrA= |
||||
|
github.com/Azure/go-autorest v11.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= |
||||
|
github.com/Azure/go-autorest v11.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= |
||||
|
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= |
||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= |
||||
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= |
||||
|
github.com/NickBall/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5/go.mod h1:w5D10RxC0NmPYxmQ438CC1S07zaC1zpvuNW7s5sUk2Q= |
||||
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= |
||||
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= |
||||
|
github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= |
||||
|
github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= |
||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= |
||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= |
||||
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= |
||||
|
github.com/apex/log v1.1.0/go.mod h1:yA770aXIDQrhVOIGurT/pVdfCpSq1GQV/auzMN5fzvY= |
||||
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= |
||||
|
github.com/aws/aws-sdk-go v1.15.64/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= |
||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= |
||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= |
||||
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= |
||||
|
github.com/brocaar/loraserver v0.0.0-20190729122155-2f0bb9c308bc h1:bum9Ye6oZBx+H1yHqZhlNy9V7CDf/fBCYadMpV9xcng= |
||||
|
github.com/brocaar/loraserver v0.0.0-20190729122155-2f0bb9c308bc/go.mod h1:nu05fgUCXdcEJQ7KJHMw5lHO5Efxq7j+g4r5g9PryhY= |
||||
|
github.com/brocaar/loraserver v2.5.0+incompatible h1:Fna4CF0jW2Vl4UpjLIhR5ifW4g+oZD/w3Dq09TiJ8Z8= |
||||
|
github.com/brocaar/loraserver v2.5.0+incompatible/go.mod h1:VBTim0YtfWAKehjJ6k17jCnG44DzXVdL4iu+hwxg2ik= |
||||
|
github.com/brocaar/lorawan v0.0.0-20190709091804-c3a80883a8fa h1:UcT94Q1RMA+lTAD0kxDY5RjkhagJgcoAjIKlKvs7A8o= |
||||
|
github.com/brocaar/lorawan v0.0.0-20190709091804-c3a80883a8fa/go.mod h1:Fm+51pxK6mZoAQjIaWJqPmnRuXecozsM5Mf9c+kr/ko= |
||||
|
github.com/brocaar/lorawan v0.0.0-20191115102621-6095d473cf60 h1:jecx8QFcsUAWZojNIqOZaoAWFwkBbd3VOHZ3kv6FQxE= |
||||
|
github.com/brocaar/lorawan v0.0.0-20191115102621-6095d473cf60/go.mod h1:VgyRGAJ/wl1JfqZZmNlCTM8fyaIKF11YvYAGIVtedL8= |
||||
|
github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= |
||||
|
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= |
||||
|
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= |
||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= |
||||
|
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= |
||||
|
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= |
||||
|
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= |
||||
|
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= |
||||
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= |
||||
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= |
||||
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= |
||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= |
||||
|
github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= |
||||
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= |
||||
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= |
||||
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= |
||||
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= |
||||
|
github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0= |
||||
|
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= |
||||
|
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= |
||||
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= |
||||
|
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= |
||||
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= |
||||
|
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= |
||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= |
||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= |
||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= |
||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= |
||||
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= |
||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= |
||||
|
github.com/gobuffalo/buffalo v0.12.8-0.20181004233540-fac9bb505aa8/go.mod h1:sLyT7/dceRXJUxSsE813JTQtA3Eb1vjxWfo/N//vXIY= |
||||
|
github.com/gobuffalo/buffalo v0.13.0/go.mod h1:Mjn1Ba9wpIbpbrD+lIDMy99pQ0H0LiddMIIDGse7qT4= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.0.2/go.mod h1:pOp/uF7X3IShFHyobahTkTLZaeUXwb0GrUTb9ngJWTs= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.0.4/go.mod h1:pWS1vjtQ6uD17MVFWf7i3zfThrEKWlI5+PYLw/NaDB4= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.4.3/go.mod h1:uCzTY0woez4nDMdQjkcOYKanngeUVRO2HZi7ezmAjWY= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.5.1/go.mod h1:jbmwSZK5+PiAP9cC09VQOrGMZFCa/P0UMlIS3O12r5w= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.6.4/go.mod h1:/+N1aophkA2jZ1ifB2O3Y9yGwu6gKOVMtUmJnbg+OZI= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.6.5/go.mod h1:0HVkbgrVs/MnPZ/FOseDMVanCTm2RNcdM0PuXcL1NNI= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.6.7/go.mod h1:ZGZRkzz2PiKWHs0z7QsPBOTo2EpcGRArMEym6ghKYgk= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.6.9/go.mod h1:yYlYTrPdMCz+6/+UaXg5Jm4gN3xhsvsQ2ygVatZV5vw= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.6.11/go.mod h1:eAA6xJIL8OuynJZ8amXjRmHND6YiusVAaJdHDN1Lu8Q= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.8.2/go.mod h1:9te6/VjEQ7pKp7lXlDIMqzxgGpjlKoAcAANdCgoR960= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.8.3/go.mod h1:IAWq6vjZJVXebIq2qGTLOdlXzmpyTZ5iJG5b59fza5U= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.9.4/go.mod h1:grCV6DGsQlVzQwk6XdgcL3ZPgLm9BVxlBmXPMF8oBHI= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.10.0/go.mod h1:4osg8d9s60txLuGwXnqH+RCjPHj9K466cDFRl3PErHI= |
||||
|
github.com/gobuffalo/buffalo-plugins v1.11.0/go.mod h1:rtIvAYRjYibgmWhnjKmo7OadtnxuMG5ZQLr25ozAzjg= |
||||
|
github.com/gobuffalo/buffalo-pop v1.0.5/go.mod h1:Fw/LfFDnSmB/vvQXPvcXEjzP98Tc+AudyNWUBWKCwQ8= |
||||
|
github.com/gobuffalo/envy v1.6.4/go.mod h1:Abh+Jfw475/NWtYMEt+hnJWRiC8INKWibIMyNt1w2Mc= |
||||
|
github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= |
||||
|
github.com/gobuffalo/envy v1.6.6/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= |
||||
|
github.com/gobuffalo/envy v1.6.7/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= |
||||
|
github.com/gobuffalo/envy v1.6.8/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= |
||||
|
github.com/gobuffalo/envy v1.6.9/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= |
||||
|
github.com/gobuffalo/envy v1.6.10/go.mod h1:X0CFllQjTV5ogsnUrg+Oks2yTI+PU2dGYBJOEI2D1Uo= |
||||
|
github.com/gobuffalo/envy v1.6.11/go.mod h1:Fiq52W7nrHGDggFPhn2ZCcHw4u/rqXkqo+i7FB6EAcg= |
||||
|
github.com/gobuffalo/envy v1.6.12/go.mod h1:qJNrJhKkZpEW0glh5xP2syQHH5kgdmgsKss2Kk8PTP0= |
||||
|
github.com/gobuffalo/events v1.0.3/go.mod h1:Txo8WmqScapa7zimEQIwgiJBvMECMe9gJjsKNPN3uZw= |
||||
|
github.com/gobuffalo/events v1.0.7/go.mod h1:z8txf6H9jWhQ5Scr7YPLWg/cgXBRj8Q4uYI+rsVCCSQ= |
||||
|
github.com/gobuffalo/events v1.0.8/go.mod h1:A5KyqT1sA+3GJiBE4QKZibse9mtOcI9nw8gGrDdqYGs= |
||||
|
github.com/gobuffalo/events v1.1.3/go.mod h1:9yPGWYv11GENtzrIRApwQRMYSbUgCsZ1w6R503fCfrk= |
||||
|
github.com/gobuffalo/events v1.1.4/go.mod h1:09/YRRgZHEOts5Isov+g9X2xajxdvOAcUuAHIX/O//A= |
||||
|
github.com/gobuffalo/events v1.1.5/go.mod h1:3YUSzgHfYctSjEjLCWbkXP6djH2M+MLaVRzb4ymbAK0= |
||||
|
github.com/gobuffalo/events v1.1.7/go.mod h1:6fGqxH2ing5XMb3EYRq9LEkVlyPGs4oO/eLzh+S8CxY= |
||||
|
github.com/gobuffalo/events v1.1.8/go.mod h1:UFy+W6X6VbCWS8k2iT81HYX65dMtiuVycMy04cplt/8= |
||||
|
github.com/gobuffalo/events v1.1.9/go.mod h1:/0nf8lMtP5TkgNbzYxR6Bl4GzBy5s5TebgNTdRfRbPM= |
||||
|
github.com/gobuffalo/fizz v1.0.12/go.mod h1:C0sltPxpYK8Ftvf64kbsQa2yiCZY4RZviurNxXdAKwc= |
||||
|
github.com/gobuffalo/flect v0.0.0-20180907193754-dc14d8acaf9f/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181002182613-4571df4b1daf/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181007231023-ae7ed6bfe683/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181018182602-fd24a256709f/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181019110701-3d6f0b585514/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181024204909-8f6be1a8c6c2/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181104133451-1f6e9779237a/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181114183036-47375f6d8328/go.mod h1:0HvNbHdfh+WOvDSIASqJOSxTOWSxCCUF++k/Y53v9rI= |
||||
|
github.com/gobuffalo/flect v0.0.0-20181210151238-24a2b68e0316/go.mod h1:en58vff74S9b99Eg42Dr+/9yPu437QjlNsO/hBYPuOk= |
||||
|
github.com/gobuffalo/flect v0.0.0-20190104192022-4af577e09bf2/go.mod h1:en58vff74S9b99Eg42Dr+/9yPu437QjlNsO/hBYPuOk= |
||||
|
github.com/gobuffalo/flect v0.0.0-20190117212819-a62e61d96794/go.mod h1:397QT6v05LkZkn07oJXXT6y9FCfwC8Pug0WA2/2mE9k= |
||||
|
github.com/gobuffalo/genny v0.0.0-20180924032338-7af3a40f2252/go.mod h1:tUTQOogrr7tAQnhajMSH6rv1BVev34H2sa1xNHMy94g= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181003150629-3786a0744c5d/go.mod h1:WAd8HmjMVrnkAZbmfgH5dLBUchsZfqzp/WS5sQz+uTM= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181005145118-318a41a134cc/go.mod h1:WAd8HmjMVrnkAZbmfgH5dLBUchsZfqzp/WS5sQz+uTM= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181007153042-b8de7d566757/go.mod h1:+oG5Ljrw04czAHbPXREwaFojJbpUvcIy4DiOnbEJFTA= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181012161047-33e5f43d83a6/go.mod h1:+oG5Ljrw04czAHbPXREwaFojJbpUvcIy4DiOnbEJFTA= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181017160347-90a774534246/go.mod h1:+oG5Ljrw04czAHbPXREwaFojJbpUvcIy4DiOnbEJFTA= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181024195656-51392254bf53/go.mod h1:o9GEH5gn5sCKLVB5rHFC4tq40rQ3VRUzmx6WwmaqISE= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181025145300-af3f81d526b8/go.mod h1:uZ1fFYvdcP8mu0B/Ynarf6dsGvp7QFIpk/QACUuFUVI= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181027191429-94d6cfb5c7fc/go.mod h1:x7SkrQQBx204Y+O9EwRXeszLJDTaWN0GnEasxgLrQTA= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181027195209-3887b7171c4f/go.mod h1:JbKx8HSWICu5zyqWOa0dVV1pbbXOHusrSzQUprW6g+w= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181106193839-7dcb0924caf1/go.mod h1:x61yHxvbDCgQ/7cOAbJCacZQuHgB0KMSzoYcw5debjU= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181107223128-f18346459dbe/go.mod h1:utQD3aKKEsdb03oR+Vi/6ztQb1j7pO10N3OBoowRcSU= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181114215459-0a4decd77f5d/go.mod h1:kN2KZ8VgXF9VIIOj/GM0Eo7YK+un4Q3tTreKOf0q1ng= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181119162812-e8ff4adce8bb/go.mod h1:BA9htSe4bZwBDJLe8CUkoqkypq3hn3+CkoHqVOW718E= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181127225641-2d959acc795b/go.mod h1:l54xLXNkteX/PdZ+HlgPk1qtcrgeOr3XUBBPDbH+7CQ= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181128191930-77e34f71ba2a/go.mod h1:FW/D9p7cEEOqxYA71/hnrkOWm62JZ5ZNxcNIVJEaWBU= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181203165245-fda8bcce96b1/go.mod h1:wpNSANu9UErftfiaAlz1pDZclrYzLtO5lALifODyjuM= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181203201232-849d2c9534ea/go.mod h1:wpNSANu9UErftfiaAlz1pDZclrYzLtO5lALifODyjuM= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181206121324-d6fb8a0dbe36/go.mod h1:wpNSANu9UErftfiaAlz1pDZclrYzLtO5lALifODyjuM= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181207164119-84844398a37d/go.mod h1:y0ysCHGGQf2T3vOhCrGHheYN54Y/REj0ayd0Suf4C/8= |
||||
|
github.com/gobuffalo/genny v0.0.0-20181211165820-e26c8466f14d/go.mod h1:sHnK+ZSU4e2feXP3PA29ouij6PUEiN+RCwECjCTB3yM= |
||||
|
github.com/gobuffalo/genny v0.0.0-20190104222617-a71664fc38e7/go.mod h1:QPsQ1FnhEsiU8f+O0qKWXz2RE4TiDqLVChWkBuh1WaY= |
||||
|
github.com/gobuffalo/genny v0.0.0-20190112155932-f31a84fcacf5/go.mod h1:CIaHCrSIuJ4il6ka3Hub4DR4adDrGoXGEEt2FbBxoIo= |
||||
|
github.com/gobuffalo/github_flavored_markdown v1.0.4/go.mod h1:uRowCdK+q8d/RF0Kt3/DSalaIXbb0De/dmTqMQdkQ4I= |
||||
|
github.com/gobuffalo/github_flavored_markdown v1.0.5/go.mod h1:U0643QShPF+OF2tJvYNiYDLDGDuQmJZXsf/bHOJPsMY= |
||||
|
github.com/gobuffalo/github_flavored_markdown v1.0.7/go.mod h1:w93Pd9Lz6LvyQXEG6DktTPHkOtCbr+arAD5mkwMzXLI= |
||||
|
github.com/gobuffalo/httptest v1.0.2/go.mod h1:7T1IbSrg60ankme0aDLVnEY0h056g9M1/ZvpVThtB7E= |
||||
|
github.com/gobuffalo/licenser v0.0.0-20180924033006-eae28e638a42/go.mod h1:Ubo90Np8gpsSZqNScZZkVXXAo5DGhTb+WYFIjlnog8w= |
||||
|
github.com/gobuffalo/licenser v0.0.0-20181025145548-437d89de4f75/go.mod h1:x3lEpYxkRG/XtGCUNkio+6RZ/dlOvLzTI9M1auIwFcw= |
||||
|
github.com/gobuffalo/licenser v0.0.0-20181027200154-58051a75da95/go.mod h1:BzhaaxGd1tq1+OLKObzgdCV9kqVhbTulxOpYbvMQWS0= |
||||
|
github.com/gobuffalo/licenser v0.0.0-20181109171355-91a2a7aac9a7/go.mod h1:m+Ygox92pi9bdg+gVaycvqE8RVSjZp7mWw75+K5NPHk= |
||||
|
github.com/gobuffalo/licenser v0.0.0-20181128165715-cc7305f8abed/go.mod h1:oU9F9UCE+AzI/MueCKZamsezGOOHfSirltllOVeRTAE= |
||||
|
github.com/gobuffalo/licenser v0.0.0-20181203160806-fe900bbede07/go.mod h1:ph6VDNvOzt1CdfaWC+9XwcBnlSTBz2j49PBwum6RFaU= |
||||
|
github.com/gobuffalo/licenser v0.0.0-20181211173111-f8a311c51159/go.mod h1:ve/Ue99DRuvnTaLq2zKa6F4KtHiYf7W046tDjuGYPfM= |
||||
|
github.com/gobuffalo/logger v0.0.0-20181022175615-46cfb361fc27/go.mod h1:8sQkgyhWipz1mIctHF4jTxmJh1Vxhp7mP8IqbljgJZo= |
||||
|
github.com/gobuffalo/logger v0.0.0-20181027144941-73d08d2bb969/go.mod h1:7uGg2duHKpWnN4+YmyKBdLXfhopkAdVM6H3nKbyFbz8= |
||||
|
github.com/gobuffalo/logger v0.0.0-20181027193913-9cf4dd0efe46/go.mod h1:7uGg2duHKpWnN4+YmyKBdLXfhopkAdVM6H3nKbyFbz8= |
||||
|
github.com/gobuffalo/logger v0.0.0-20181109185836-3feeab578c17/go.mod h1:oNErH0xLe+utO+OW8ptXMSA5DkiSEDW1u3zGIt8F9Ew= |
||||
|
github.com/gobuffalo/logger v0.0.0-20181117211126-8e9b89b7c264/go.mod h1:5etB91IE0uBlw9k756fVKZJdS+7M7ejVhmpXXiSFj0I= |
||||
|
github.com/gobuffalo/logger v0.0.0-20181127160119-5b956e21995c/go.mod h1:+HxKANrR9VGw9yN3aOAppJKvhO05ctDi63w4mDnKv2U= |
||||
|
github.com/gobuffalo/makr v1.1.5/go.mod h1:Y+o0btAH1kYAMDJW/TX3+oAXEu0bmSLLoC9mIFxtzOw= |
||||
|
github.com/gobuffalo/mapi v1.0.0/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= |
||||
|
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= |
||||
|
github.com/gobuffalo/meta v0.0.0-20181018155829-df62557efcd3/go.mod h1:XTTOhwMNryif3x9LkTTBO/Llrveezd71u3quLd0u7CM= |
||||
|
github.com/gobuffalo/meta v0.0.0-20181018192820-8c6cef77dab3/go.mod h1:E94EPzx9NERGCY69UWlcj6Hipf2uK/vnfrF4QD0plVE= |
||||
|
github.com/gobuffalo/meta v0.0.0-20181025145500-3a985a084b0a/go.mod h1:YDAKBud2FP7NZdruCSlmTmDOZbVSa6bpK7LJ/A/nlKg= |
||||
|
github.com/gobuffalo/meta v0.0.0-20181114191255-b130ebedd2f7/go.mod h1:K6cRZ29ozr4Btvsqkjvg5nDFTLOgTqf03KA70Ks0ypE= |
||||
|
github.com/gobuffalo/meta v0.0.0-20181127070345-0d7e59dd540b/go.mod h1:RLO7tMvE0IAKAM8wny1aN12pvEKn7EtkBLkUZR00Qf8= |
||||
|
github.com/gobuffalo/meta v0.0.0-20190120163247-50bbb1fa260d/go.mod h1:KKsH44nIK2gA8p0PJmRT9GvWJUdphkDUA8AJEvFWiqM= |
||||
|
github.com/gobuffalo/mw-basicauth v1.0.3/go.mod h1:dg7+ilMZOKnQFHDefUzUHufNyTswVUviCBgF244C1+0= |
||||
|
github.com/gobuffalo/mw-contenttype v0.0.0-20180802152300-74f5a47f4d56/go.mod h1:7EvcmzBbeCvFtQm5GqF9ys6QnCxz2UM1x0moiWLq1No= |
||||
|
github.com/gobuffalo/mw-csrf v0.0.0-20180802151833-446ff26e108b/go.mod h1:sbGtb8DmDZuDUQoxjr8hG1ZbLtZboD9xsn6p77ppcHo= |
||||
|
github.com/gobuffalo/mw-forcessl v0.0.0-20180802152810-73921ae7a130/go.mod h1:JvNHRj7bYNAMUr/5XMkZaDcw3jZhUZpsmzhd//FFWmQ= |
||||
|
github.com/gobuffalo/mw-i18n v0.0.0-20180802152014-e3060b7e13d6/go.mod h1:91AQfukc52A6hdfIfkxzyr+kpVYDodgAeT5cjX1UIj4= |
||||
|
github.com/gobuffalo/mw-paramlogger v0.0.0-20181005191442-d6ee392ec72e/go.mod h1:6OJr6VwSzgJMqWMj7TYmRUqzNe2LXu/W1rRW4MAz/ME= |
||||
|
github.com/gobuffalo/mw-tokenauth v0.0.0-20181001105134-8545f626c189/go.mod h1:UqBF00IfKvd39ni5+yI5MLMjAf4gX7cDKN/26zDOD6c= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181027182251-01ad393492c8/go.mod h1:SmdBdhj6uhOsg1Ui4SFAyrhuc7U4VCildosO5IDJ3lc= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181027190505-aafc0d02c411/go.mod h1:SmdBdhj6uhOsg1Ui4SFAyrhuc7U4VCildosO5IDJ3lc= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181027194105-7ae579e6d213/go.mod h1:SmdBdhj6uhOsg1Ui4SFAyrhuc7U4VCildosO5IDJ3lc= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181104210303-d376b15f8e96/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181111195323-b2e760a5f0ff/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181114190715-f25c5d2471d7/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181124090624-311c6248e5fb/go.mod h1:Foenia9ZvITEvG05ab6XpiD5EfBHPL8A6hush8SJ0o8= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181207120301-c49825f8f6f4/go.mod h1:LYc0TGKFBBFTRC9dg2pcRcMqGCTMD7T2BIMP7OBuQAA= |
||||
|
github.com/gobuffalo/packd v0.0.0-20181212173646-eca3b8fd6687/go.mod h1:LYc0TGKFBBFTRC9dg2pcRcMqGCTMD7T2BIMP7OBuQAA= |
||||
|
github.com/gobuffalo/packr v1.13.7/go.mod h1:KkinLIn/n6+3tVXMwg6KkNvWwVsrRAz4ph+jgpk3Z24= |
||||
|
github.com/gobuffalo/packr v1.15.0/go.mod h1:t5gXzEhIviQwVlNx/+3SfS07GS+cZ2hn76WLzPp6MGI= |
||||
|
github.com/gobuffalo/packr v1.15.1/go.mod h1:IeqicJ7jm8182yrVmNbM6PR4g79SjN9tZLH8KduZZwE= |
||||
|
github.com/gobuffalo/packr v1.19.0/go.mod h1:MstrNkfCQhd5o+Ct4IJ0skWlxN8emOq8DsoT1G98VIU= |
||||
|
github.com/gobuffalo/packr v1.20.0/go.mod h1:JDytk1t2gP+my1ig7iI4NcVaXr886+N0ecUga6884zw= |
||||
|
github.com/gobuffalo/packr v1.21.0/go.mod h1:H00jGfj1qFKxscFJSw8wcL4hpQtPe1PfU2wa6sg/SR0= |
||||
|
github.com/gobuffalo/packr v1.22.0/go.mod h1:Qr3Wtxr3+HuQEwWqlLnNW4t1oTvK+7Gc/Rnoi/lDFvA= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.8/go.mod h1:y60QCdzwuMwO2R49fdQhsjCPv7tLQFR0ayzxxla9zes= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.9/go.mod h1:fQqADRfZpEsgkc7c/K7aMew3n4aF1Kji7+lIZeR98Fc= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.10/go.mod h1:4CWWn4I5T3v4c1OsJ55HbHlUEKNWMITG5iIkdr4Px4w= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.11/go.mod h1:JoieH/3h3U4UmatmV93QmqyPUdf4wVM9HELaHEu+3fk= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.12/go.mod h1:FV1zZTsVFi1DSCboO36Xgs4pzCZBjB/tDV9Cz/lSaR8= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.13/go.mod h1:2Mp7GhBFMdJlOK8vGfl7SYtfMP3+5roE39ejlfjw0rA= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.14/go.mod h1:06otbrNvDKO1eNQ3b8hst+1010UooI2MFg+B2Ze4MV8= |
||||
|
github.com/gobuffalo/packr/v2 v2.0.0-rc.15/go.mod h1:IMe7H2nJvcKXSF90y4X1rjYIRlNMJYCxEhssBXNZwWs= |
||||
|
github.com/gobuffalo/plush v3.7.16+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plush v3.7.20+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plush v3.7.21+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plush v3.7.22+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plush v3.7.23+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plush v3.7.30+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plush v3.7.31+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plush v3.7.32+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI= |
||||
|
github.com/gobuffalo/plushgen v0.0.0-20181128164830-d29dcb966cb2/go.mod h1:r9QwptTFnuvSaSRjpSp4S2/4e2D3tJhARYbvEBcKSb4= |
||||
|
github.com/gobuffalo/plushgen v0.0.0-20181203163832-9fc4964505c2/go.mod h1:opEdT33AA2HdrIwK1aibqnTJDVVKXC02Bar/GT1YRVs= |
||||
|
github.com/gobuffalo/plushgen v0.0.0-20181207152837-eedb135bd51b/go.mod h1:Lcw7HQbEVm09sAQrCLzIxuhFbB3nAgp4c55E+UlynR0= |
||||
|
github.com/gobuffalo/plushgen v0.0.0-20190104222512-177cd2b872b3/go.mod h1:tYxCozi8X62bpZyKXYHw1ncx2ZtT2nFvG42kuLwYjoc= |
||||
|
github.com/gobuffalo/pop v4.8.2+incompatible/go.mod h1:DwBz3SD5SsHpTZiTubcsFWcVDpJWGsxjVjMPnkiThWg= |
||||
|
github.com/gobuffalo/pop v4.8.3+incompatible/go.mod h1:DwBz3SD5SsHpTZiTubcsFWcVDpJWGsxjVjMPnkiThWg= |
||||
|
github.com/gobuffalo/pop v4.8.4+incompatible/go.mod h1:DwBz3SD5SsHpTZiTubcsFWcVDpJWGsxjVjMPnkiThWg= |
||||
|
github.com/gobuffalo/release v1.0.35/go.mod h1:VtHFAKs61vO3wboCec5xr9JPTjYyWYcvaM3lclkc4x4= |
||||
|
github.com/gobuffalo/release v1.0.38/go.mod h1:VtHFAKs61vO3wboCec5xr9JPTjYyWYcvaM3lclkc4x4= |
||||
|
github.com/gobuffalo/release v1.0.42/go.mod h1:RPs7EtafH4oylgetOJpGP0yCZZUiO4vqHfTHJjSdpug= |
||||
|
github.com/gobuffalo/release v1.0.52/go.mod h1:RPs7EtafH4oylgetOJpGP0yCZZUiO4vqHfTHJjSdpug= |
||||
|
github.com/gobuffalo/release v1.0.53/go.mod h1:FdF257nd8rqhNaqtDWFGhxdJ/Ig4J7VcS3KL7n/a+aA= |
||||
|
github.com/gobuffalo/release v1.0.54/go.mod h1:Pe5/RxRa/BE8whDpGfRqSI7D1a0evGK1T4JDm339tJc= |
||||
|
github.com/gobuffalo/release v1.0.61/go.mod h1:mfIO38ujUNVDlBziIYqXquYfBF+8FDHUjKZgYC1Hj24= |
||||
|
github.com/gobuffalo/release v1.0.72/go.mod h1:NP5NXgg/IX3M5XmHmWR99D687/3Dt9qZtTK/Lbwc1hU= |
||||
|
github.com/gobuffalo/release v1.1.1/go.mod h1:Sluak1Xd6kcp6snkluR1jeXAogdJZpFFRzTYRs/2uwg= |
||||
|
github.com/gobuffalo/release v1.1.3/go.mod h1:CuXc5/m+4zuq8idoDt1l4va0AXAn/OSs08uHOfMVr8E= |
||||
|
github.com/gobuffalo/release v1.1.6/go.mod h1:18naWa3kBsqO0cItXZNJuefCKOENpbbUIqRL1g+p6z0= |
||||
|
github.com/gobuffalo/shoulders v1.0.1/go.mod h1:V33CcVmaQ4gRUmHKwq1fiTXuf8Gp/qjQBUL5tHPmvbA= |
||||
|
github.com/gobuffalo/syncx v0.0.0-20181120191700-98333ab04150/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= |
||||
|
github.com/gobuffalo/syncx v0.0.0-20181120194010-558ac7de985f/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= |
||||
|
github.com/gobuffalo/tags v2.0.11+incompatible/go.mod h1:9XmhOkyaB7UzvuY4UoZO4s67q8/xRMVJEaakauVQYeY= |
||||
|
github.com/gobuffalo/tags v2.0.14+incompatible/go.mod h1:9XmhOkyaB7UzvuY4UoZO4s67q8/xRMVJEaakauVQYeY= |
||||
|
github.com/gobuffalo/tags v2.0.15+incompatible/go.mod h1:9XmhOkyaB7UzvuY4UoZO4s67q8/xRMVJEaakauVQYeY= |
||||
|
github.com/gobuffalo/uuid v2.0.3+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw4cVi1RtSpnwYrxuvkfE= |
||||
|
github.com/gobuffalo/uuid v2.0.4+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw4cVi1RtSpnwYrxuvkfE= |
||||
|
github.com/gobuffalo/uuid v2.0.5+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw4cVi1RtSpnwYrxuvkfE= |
||||
|
github.com/gobuffalo/validate v2.0.3+incompatible/go.mod h1:N+EtDe0J8252BgfzQUChBgfd6L93m9weay53EWFVsMM= |
||||
|
github.com/gobuffalo/x v0.0.0-20181003152136-452098b06085/go.mod h1:WevpGD+5YOreDJznWevcn8NTmQEW5STSBgIkpkjzqXc= |
||||
|
github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdKWzMc4odGQQdG2e2DIEmANy5aSJ9yesY= |
||||
|
github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= |
||||
|
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= |
||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= |
||||
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= |
||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= |
||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= |
||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= |
||||
|
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= |
||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= |
||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= |
||||
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= |
||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= |
||||
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= |
||||
|
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= |
||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= |
||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= |
||||
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= |
||||
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= |
||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= |
||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= |
||||
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= |
||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= |
||||
|
github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f h1:4Gslotqbs16iAg+1KR/XdabIfq8TlAWHdwS5QJFksLc= |
||||
|
github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= |
||||
|
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= |
||||
|
github.com/goreleaser/goreleaser v0.106.0/go.mod h1:YCWszXb4t6HZ7gzeg5TcbPJC2Ad8cFvsknUS0CwS3yY= |
||||
|
github.com/goreleaser/nfpm v0.11.0/go.mod h1:F2yzin6cBAL9gb+mSiReuXdsfTrOQwDMsuSpULof+y4= |
||||
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= |
||||
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= |
||||
|
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= |
||||
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= |
||||
|
github.com/gorilla/sessions v1.1.2/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= |
||||
|
github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= |
||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= |
||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= |
||||
|
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= |
||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= |
||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= |
||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= |
||||
|
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= |
||||
|
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= |
||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= |
||||
|
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= |
||||
|
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= |
||||
|
github.com/jacobsa/crypto v0.0.0-20180924003735-d95898ceee07 h1:/PaS1RNKtbBEndIvzCqIgYh6GAH9ZFc8Mj4tVRVyfOA= |
||||
|
github.com/jacobsa/crypto v0.0.0-20180924003735-d95898ceee07/go.mod h1:LadVJg0XuawGk+8L1rYnIED8451UyNxEMdTWCEt5kmU= |
||||
|
github.com/jacobsa/crypto v0.0.0-20190317225127-9f44e2d11115 h1:YuDUUFNM21CAbyPOpOP8BicaTD/0klJEKt5p8yuw+uY= |
||||
|
github.com/jacobsa/crypto v0.0.0-20190317225127-9f44e2d11115/go.mod h1:LadVJg0XuawGk+8L1rYnIED8451UyNxEMdTWCEt5kmU= |
||||
|
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd h1:9GCSedGjMcLZCrusBZuo4tyKLpKUPenUUqi34AkuFmA= |
||||
|
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd/go.mod h1:TlmyIZDpGmwRoTWiakdr+HA1Tukze6C6XbRVidYq02M= |
||||
|
github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff h1:2xRHTvkpJ5zJmglXLRqHiZQNjUoOkhUyhTAhEQvPAWw= |
||||
|
github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff/go.mod h1:gJWba/XXGl0UoOmBQKRWCJdHrr3nE0T65t6ioaj3mLI= |
||||
|
github.com/jacobsa/ogletest v0.0.0-20170503003838-80d50a735a11 h1:BMb8s3ENQLt5ulwVIHVDWFHp8eIXmbfSExkvdn9qMXI= |
||||
|
github.com/jacobsa/ogletest v0.0.0-20170503003838-80d50a735a11/go.mod h1:+DBdDyfoO2McrOyDemRBq0q9CMEByef7sYl7JH5Q3BI= |
||||
|
github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb h1:uSWBjJdMf47kQlXMwWEfmc864bA1wAC+Kl3ApryuG9Y= |
||||
|
github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb/go.mod h1:ivcmUvxXWjb27NsPEaiYK7AidlZXS7oQ5PowUS9z3I4= |
||||
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= |
||||
|
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU= |
||||
|
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= |
||||
|
github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= |
||||
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= |
||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= |
||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= |
||||
|
github.com/jteeuwen/go-bindata v3.0.7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs= |
||||
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= |
||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= |
||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= |
||||
|
github.com/kamilsk/retry/v4 v4.0.0/go.mod h1:0af33qDvzbhQqdOBi7iOjEpmP4brbPmNZpo7chYlgcc= |
||||
|
github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= |
||||
|
github.com/karrick/godirwalk v1.7.7/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= |
||||
|
github.com/karrick/godirwalk v1.7.8/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= |
||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= |
||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= |
||||
|
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= |
||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= |
||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= |
||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= |
||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= |
||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= |
||||
|
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= |
||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= |
||||
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= |
||||
|
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= |
||||
|
github.com/lxn/walk v0.0.0-20191113135339-bf589de20b3c h1:4pJw1uBKndwiBBJpcbqP1Bf90YfqTJUsHG9DVoAfIQ8= |
||||
|
github.com/lxn/walk v0.0.0-20191113135339-bf589de20b3c/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= |
||||
|
github.com/lxn/win v0.0.0-20191106123917-121afc750dd3 h1:DvGEvKK/Qnhph/EgdBN9zXA7pEosgJ0k57ojII51JAo= |
||||
|
github.com/lxn/win v0.0.0-20191106123917-121afc750dd3/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA= |
||||
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= |
||||
|
github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= |
||||
|
github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= |
||||
|
github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c= |
||||
|
github.com/markbates/grift v1.0.4/go.mod h1:wbmtW74veyx+cgfwFhlnnMWqhoz55rnHR47oMXzsyVs= |
||||
|
github.com/markbates/hmax v1.0.0/go.mod h1:cOkR9dktiESxIMu+65oc/r/bdY4bE8zZw3OLhLx0X2c= |
||||
|
github.com/markbates/inflect v1.0.0/go.mod h1:oTeZL2KHA7CUX6X+fovmK9OvIOFuqu0TwdQrZjLTh88= |
||||
|
github.com/markbates/inflect v1.0.1/go.mod h1:uv3UVNBe5qBIfCm8O8Q+DW+S1EopeyINj+Ikhc7rnCk= |
||||
|
github.com/markbates/inflect v1.0.3/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs= |
||||
|
github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs= |
||||
|
github.com/markbates/oncer v0.0.0-20180924031910-e862a676800b/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= |
||||
|
github.com/markbates/oncer v0.0.0-20180924034138-723ad0170a46/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= |
||||
|
github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= |
||||
|
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= |
||||
|
github.com/markbates/refresh v1.4.10/go.mod h1:NDPHvotuZmTmesXxr95C9bjlw1/0frJwtME2dzcVKhc= |
||||
|
github.com/markbates/safe v1.0.0/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= |
||||
|
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= |
||||
|
github.com/markbates/sigtx v1.0.0/go.mod h1:QF1Hv6Ic6Ca6W+T+DL0Y/ypborFKyvUY9HmuCD4VeTc= |
||||
|
github.com/markbates/willie v1.0.9/go.mod h1:fsrFVWl91+gXpx/6dv715j7i11fYPfZ9ZGfH0DQzY7w= |
||||
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= |
||||
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= |
||||
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= |
||||
|
github.com/mattn/go-zglob v0.0.0-20171230104132-4959821b4817/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= |
||||
|
github.com/mattn/go-zglob v0.0.0-20180803001819-2ea3427bfa53/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= |
||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= |
||||
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= |
||||
|
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= |
||||
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= |
||||
|
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= |
||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= |
||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= |
||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= |
||||
|
github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q= |
||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= |
||||
|
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= |
||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= |
||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= |
||||
|
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= |
||||
|
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= |
||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= |
||||
|
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= |
||||
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= |
||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= |
||||
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= |
||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= |
||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= |
||||
|
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= |
||||
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= |
||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= |
||||
|
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= |
||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= |
||||
|
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= |
||||
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= |
||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= |
||||
|
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= |
||||
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= |
||||
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= |
||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= |
||||
|
github.com/rogpeppe/go-internal v1.0.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= |
||||
|
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= |
||||
|
github.com/rubenv/sql-migrate v0.0.0-20181213081019-5a8808c14925/go.mod h1:WS0rl9eEliYI8DPnr3TOwz4439pay+qNgzJoVya/DmY= |
||||
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= |
||||
|
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= |
||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= |
||||
|
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= |
||||
|
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= |
||||
|
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= |
||||
|
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= |
||||
|
github.com/shurcooL/highlight_go v0.0.0-20170515013102-78fb10f4a5f8/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= |
||||
|
github.com/shurcooL/octicon v0.0.0-20180602230221-c42b0e3b24d9/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= |
||||
|
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= |
||||
|
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= |
||||
|
github.com/sirupsen/logrus v1.1.0/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= |
||||
|
github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= |
||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= |
||||
|
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= |
||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= |
||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= |
||||
|
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 h1:hBSHahWMEgzwRyS6dRpxY0XyjZsHyQ61s084wo5PJe0= |
||||
|
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= |
||||
|
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= |
||||
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= |
||||
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= |
||||
|
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= |
||||
|
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= |
||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= |
||||
|
github.com/spf13/afero v1.2.0/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= |
||||
|
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= |
||||
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= |
||||
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= |
||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= |
||||
|
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= |
||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= |
||||
|
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= |
||||
|
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= |
||||
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= |
||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= |
||||
|
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= |
||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= |
||||
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= |
||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= |
||||
|
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= |
||||
|
github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= |
||||
|
github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= |
||||
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= |
||||
|
github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= |
||||
|
github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= |
||||
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= |
||||
|
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= |
||||
|
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= |
||||
|
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= |
||||
|
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= |
||||
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= |
||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181024171144-74cb1d3d52f4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181025113841-85e1b3f9139a/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20190102171810-8d7daa0c54b3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
||||
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
||||
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= |
||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= |
||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= |
||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= |
||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= |
||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= |
||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20180921000356-2f5d2388922f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181017193950-04a2e542c03f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181207154023-610586996380/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
||||
|
golang.org/x/net v0.0.0-20190322120337-addf6b3196f6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
||||
|
golang.org/x/net v0.0.0-20190328230028-74de082e2cca h1:hyA6yiAgbUwuWqtscNvWAI7U1CtlaD1KilQ6iudt1aI= |
||||
|
golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= |
||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= |
||||
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= |
||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= |
||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
|
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20180921163948-d47a0f339242/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20180927150500-dad3d9fb7b6e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181005133103-4497e2df6f9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181011152604-fa43e7bc11ba/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181022134430-8a28ead16f52/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181024145615-5cd93ef61a7c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181025063200-d989b31c8746/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181026064943-731415f00dce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181030150119-7e31e0c00fa0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181106135930-3a76605856fd/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
|
golang.org/x/sys v0.0.0-20190402054613-e4093980e83e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
|
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= |
||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= |
||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= |
||||
|
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181003024731-2f84ea8ef872/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181006002542-f60d9635b16a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181008205924-a2b3f7f249e9/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181013182035-5e66757b835f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181017214349-06f26fdaaa28/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181024171208-a2dc47679d30/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181026183834-f60e5f99f081/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181105230042-78dc5bac0cac/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181107215632-34b416bd17b3/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181114190951-94339b83286c/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181119130350-139d099f6620/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181127195227-b4e97c0ed882/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181127232545-e782529d0ddd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181203210056-e5f3ab76ea4b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181205224935-3576414c54a4/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181206194817-bcd4e47d0288/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181207183836-8bc39b988060/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20181212172921-837e80568c09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20190102213336-ca9055ed7d04/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20190104182027-498d95493402/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20190111214448-fc1d57b08d7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20190118193359-16909d206f00/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= |
||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= |
||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= |
||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= |
||||
|
golang.org/x/tools v0.0.0-20190708203411-c8855242db9c/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= |
||||
|
gonum.org/v1/gonum v0.0.0-20190115205657-1b07048b32c6/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= |
||||
|
gonum.org/v1/netlib v0.0.0-20190219113230-9992c5f5eae4/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= |
||||
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= |
||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= |
||||
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= |
||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= |
||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= |
||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= |
||||
|
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= |
||||
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= |
||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= |
||||
|
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= |
||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= |
||||
|
gopkg.in/Knetic/govaluate.v3 v3.0.0 h1:18mUyIt4ZlRlFZAAfVetz4/rzlJs9yhN+U02F4u1AOc= |
||||
|
gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E= |
||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= |
||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= |
||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= |
||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= |
||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= |
||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= |
||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= |
||||
|
gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= |
||||
|
gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= |
||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= |
||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= |
||||
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= |
||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
||||
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= |
||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= |
||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= |
||||
|
pack.ag/amqp v0.8.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= |
||||
|
pack.ag/amqp v0.11.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= |
@ -0,0 +1,107 @@ |
|||||
|
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) |
||||
|
} |
@ -0,0 +1,119 @@ |
|||||
|
package model |
||||
|
|
||||
|
import ( |
||||
|
"github.com/lxn/walk" |
||||
|
"sort" |
||||
|
) |
||||
|
|
||||
|
type DTUUp struct { |
||||
|
Index int |
||||
|
DevEUI string |
||||
|
MType string |
||||
|
GatewayID string |
||||
|
Rssi int16 |
||||
|
LoRaSNR float64 |
||||
|
Frequency float64 |
||||
|
FCnt uint32 |
||||
|
FPort uint8 |
||||
|
HexData string |
||||
|
AsciiData string |
||||
|
Time string |
||||
|
checked bool |
||||
|
OrigData string |
||||
|
} |
||||
|
|
||||
|
type DTUUpModel struct { |
||||
|
walk.TableModelBase |
||||
|
walk.SorterBase |
||||
|
SortColumn int |
||||
|
SortOrder walk.SortOrder |
||||
|
Items []*DTUUp |
||||
|
} |
||||
|
|
||||
|
func (m *DTUUpModel) RowCount() int { |
||||
|
return len(m.Items) |
||||
|
} |
||||
|
|
||||
|
func (m *DTUUpModel) 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.GatewayID |
||||
|
case 4: |
||||
|
return item.Rssi |
||||
|
case 5: |
||||
|
return item.LoRaSNR |
||||
|
case 6: |
||||
|
return item.Frequency |
||||
|
case 7: |
||||
|
return item.FCnt |
||||
|
case 8: |
||||
|
return item.FPort |
||||
|
case 9: |
||||
|
return item.HexData |
||||
|
case 10: |
||||
|
return item.AsciiData |
||||
|
case 11: |
||||
|
return item.Time |
||||
|
} |
||||
|
panic("unexpected col") |
||||
|
} |
||||
|
|
||||
|
func (m *DTUUpModel) Checked(row int) bool { |
||||
|
return m.Items[row].checked |
||||
|
} |
||||
|
|
||||
|
func (m *DTUUpModel) SetChecked(row int, checked bool) error { |
||||
|
m.Items[row].checked = checked |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
func (m *DTUUpModel) 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 { |
||||
|
return len(m.Items) |
||||
|
} |
||||
|
|
||||
|
func (m *DTUUpModel) 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) |
||||
|
case 4: |
||||
|
return c(a.Rssi < b.Rssi) |
||||
|
case 5: |
||||
|
return c(a.LoRaSNR < b.LoRaSNR) |
||||
|
case 6: |
||||
|
return c(a.Frequency < b.Frequency) |
||||
|
default: |
||||
|
return false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (m *DTUUpModel) Swap(i, j int) { |
||||
|
m.Items[i], m.Items[j] = m.Items[j], m.Items[i] |
||||
|
} |
||||
|
|
||||
|
func NewDTUUpModel() *DTUUpModel { |
||||
|
return new(DTUUpModel) |
||||
|
} |
@ -0,0 +1,126 @@ |
|||||
|
//go:generate stringer -type=PacketType
|
||||
|
|
||||
|
package packets |
||||
|
|
||||
|
import ( |
||||
|
"errors" |
||||
|
"strconv" |
||||
|
"strings" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
// PacketType defines the packet type.
|
||||
|
type PacketType byte |
||||
|
|
||||
|
// Available packet types
|
||||
|
const ( |
||||
|
PushData PacketType = iota |
||||
|
PushACK |
||||
|
PullData |
||||
|
PullResp |
||||
|
PullACK |
||||
|
TXACK |
||||
|
) |
||||
|
|
||||
|
// Protocol versions
|
||||
|
const ( |
||||
|
ProtocolVersion1 uint8 = 0x01 |
||||
|
ProtocolVersion2 uint8 = 0x02 |
||||
|
) |
||||
|
|
||||
|
// Errors
|
||||
|
var ( |
||||
|
ErrInvalidProtocolVersion = errors.New("gateway: invalid protocol version") |
||||
|
) |
||||
|
|
||||
|
// GetPacketType returns the packet type for the given packet data.
|
||||
|
func GetPacketType(data []byte) (PacketType, error) { |
||||
|
if len(data) < 4 { |
||||
|
return PacketType(0), errors.New("gateway: at least 4 bytes of data are expected") |
||||
|
} |
||||
|
|
||||
|
if !protocolSupported(data[0]) { |
||||
|
return PacketType(0), ErrInvalidProtocolVersion |
||||
|
} |
||||
|
|
||||
|
return PacketType(data[3]), nil |
||||
|
} |
||||
|
|
||||
|
func protocolSupported(p uint8) bool { |
||||
|
if p == ProtocolVersion1 || p == ProtocolVersion2 { |
||||
|
return true |
||||
|
} |
||||
|
return false |
||||
|
} |
||||
|
|
||||
|
// ExpandedTime implements time.Time but (un)marshals to and from
|
||||
|
// ISO 8601 'expanded' format.
|
||||
|
type ExpandedTime time.Time |
||||
|
|
||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||
|
func (t ExpandedTime) MarshalJSON() ([]byte, error) { |
||||
|
return []byte(time.Time(t).UTC().Format(`"2006-01-02 15:04:05 MST"`)), nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
|
func (t *ExpandedTime) UnmarshalJSON(data []byte) error { |
||||
|
t2, err := time.Parse(`"2006-01-02 15:04:05 MST"`, string(data)) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
*t = ExpandedTime(t2) |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// CompactTime implements time.Time but (un)marshals to and from
|
||||
|
// ISO 8601 'compact' format.
|
||||
|
type CompactTime time.Time |
||||
|
|
||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||
|
func (t CompactTime) MarshalJSON() ([]byte, error) { |
||||
|
t2 := time.Time(t) |
||||
|
if t2.IsZero() { |
||||
|
return []byte("null"), nil |
||||
|
} |
||||
|
return []byte(t2.UTC().Format(`"` + time.RFC3339Nano + `"`)), nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
|
func (t *CompactTime) UnmarshalJSON(data []byte) error { |
||||
|
if string(data) == `""` { |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
t2, err := time.Parse(`"`+time.RFC3339Nano+`"`, string(data)) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
*t = CompactTime(t2) |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// DatR implements the data rate which can be either a string (LoRa identifier)
|
||||
|
// or an unsigned integer in case of FSK (bits per second).
|
||||
|
type DatR struct { |
||||
|
LoRa string |
||||
|
FSK uint32 |
||||
|
} |
||||
|
|
||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||
|
func (d DatR) MarshalJSON() ([]byte, error) { |
||||
|
if d.LoRa != "" { |
||||
|
return []byte(`"` + d.LoRa + `"`), nil |
||||
|
} |
||||
|
return []byte(strconv.FormatUint(uint64(d.FSK), 10)), nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
|
func (d *DatR) UnmarshalJSON(data []byte) error { |
||||
|
i, err := strconv.ParseUint(string(data), 10, 32) |
||||
|
if err != nil { |
||||
|
d.LoRa = strings.Trim(string(data), `"`) |
||||
|
return nil |
||||
|
} |
||||
|
d.FSK = uint32(i) |
||||
|
return nil |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
// Code generated by "stringer -type=PacketType"; DO NOT EDIT.
|
||||
|
|
||||
|
package packets |
||||
|
|
||||
|
import "strconv" |
||||
|
|
||||
|
const _PacketType_name = "PushDataPushACKPullDataPullRespPullACKTXACK" |
||||
|
|
||||
|
var _PacketType_index = [...]uint8{0, 8, 15, 23, 31, 38, 43} |
||||
|
|
||||
|
func (i PacketType) String() string { |
||||
|
if i >= PacketType(len(_PacketType_index)-1) { |
||||
|
return "PacketType(" + strconv.FormatInt(int64(i), 10) + ")" |
||||
|
} |
||||
|
return _PacketType_name[_PacketType_index[i]:_PacketType_index[i+1]] |
||||
|
} |
@ -0,0 +1,38 @@ |
|||||
|
package packets |
||||
|
|
||||
|
import ( |
||||
|
"encoding/binary" |
||||
|
"errors" |
||||
|
) |
||||
|
|
||||
|
// PullACKPacket is used by the server to confirm that the network route is
|
||||
|
// open and that the server can send PULL_RESP packets at any time.
|
||||
|
type PullACKPacket struct { |
||||
|
ProtocolVersion uint8 |
||||
|
RandomToken uint16 |
||||
|
} |
||||
|
|
||||
|
// MarshalBinary marshals the object in binary form.
|
||||
|
func (p PullACKPacket) MarshalBinary() ([]byte, error) { |
||||
|
out := make([]byte, 4) |
||||
|
out[0] = p.ProtocolVersion |
||||
|
binary.LittleEndian.PutUint16(out[1:3], p.RandomToken) |
||||
|
out[3] = byte(PullACK) |
||||
|
return out, nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalBinary decodes the object from binary form.
|
||||
|
func (p *PullACKPacket) UnmarshalBinary(data []byte) error { |
||||
|
if len(data) != 4 { |
||||
|
return errors.New("gateway: 4 bytes of data are expected") |
||||
|
} |
||||
|
if data[3] != byte(PullACK) { |
||||
|
return errors.New("gateway: identifier mismatch (PULL_ACK expected)") |
||||
|
} |
||||
|
if !protocolSupported(data[0]) { |
||||
|
return ErrInvalidProtocolVersion |
||||
|
} |
||||
|
p.ProtocolVersion = data[0] |
||||
|
p.RandomToken = binary.LittleEndian.Uint16(data[1:3]) |
||||
|
return nil |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package packets |
||||
|
|
||||
|
import ( |
||||
|
"encoding/binary" |
||||
|
"errors" |
||||
|
) |
||||
|
|
||||
|
// PullDataPacket is used by the gateway to poll data from the server.
|
||||
|
type PullDataPacket struct { |
||||
|
ProtocolVersion uint8 |
||||
|
RandomToken uint16 |
||||
|
GatewayMAC [8]byte |
||||
|
} |
||||
|
|
||||
|
// MarshalBinary marshals the object in binary form.
|
||||
|
func (p PullDataPacket) MarshalBinary() ([]byte, error) { |
||||
|
out := make([]byte, 4, 12) |
||||
|
out[0] = p.ProtocolVersion |
||||
|
binary.LittleEndian.PutUint16(out[1:3], p.RandomToken) |
||||
|
out[3] = byte(PullData) |
||||
|
out = append(out, p.GatewayMAC[0:len(p.GatewayMAC)]...) |
||||
|
return out, nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalBinary decodes the object from binary form.
|
||||
|
func (p *PullDataPacket) UnmarshalBinary(data []byte) error { |
||||
|
if len(data) != 12 { |
||||
|
return errors.New("gateway: 12 bytes of data are expected") |
||||
|
} |
||||
|
if data[3] != byte(PullData) { |
||||
|
return errors.New("gateway: identifier mismatch (PULL_DATA expected)") |
||||
|
} |
||||
|
|
||||
|
if !protocolSupported(data[0]) { |
||||
|
return ErrInvalidProtocolVersion |
||||
|
} |
||||
|
p.ProtocolVersion = data[0] |
||||
|
p.RandomToken = binary.LittleEndian.Uint16(data[1:3]) |
||||
|
for i := 0; i < 8; i++ { |
||||
|
p.GatewayMAC[i] = data[4+i] |
||||
|
} |
||||
|
return nil |
||||
|
} |
@ -0,0 +1,162 @@ |
|||||
|
package packets |
||||
|
|
||||
|
import ( |
||||
|
"encoding/binary" |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/golang/protobuf/ptypes" |
||||
|
"github.com/pkg/errors" |
||||
|
|
||||
|
"github.com/brocaar/loraserver/api/common" |
||||
|
"github.com/brocaar/loraserver/api/gw" |
||||
|
) |
||||
|
|
||||
|
// PullRespPacket is used by the server to send RF packets and associated
|
||||
|
// metadata that will have to be emitted by the gateway.
|
||||
|
type PullRespPacket struct { |
||||
|
ProtocolVersion uint8 |
||||
|
RandomToken uint16 |
||||
|
Payload PullRespPayload |
||||
|
} |
||||
|
|
||||
|
// MarshalBinary marshals the object in binary form.
|
||||
|
func (p PullRespPacket) MarshalBinary() ([]byte, error) { |
||||
|
pb, err := json.Marshal(&p.Payload) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
out := make([]byte, 4, 4+len(pb)) |
||||
|
out[0] = p.ProtocolVersion |
||||
|
|
||||
|
if p.ProtocolVersion != ProtocolVersion1 { |
||||
|
// these two bytes are unused in ProtocolVersion1
|
||||
|
binary.LittleEndian.PutUint16(out[1:3], p.RandomToken) |
||||
|
} |
||||
|
out[3] = byte(PullResp) |
||||
|
out = append(out, pb...) |
||||
|
return out, nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalBinary decodes the object from binary form.
|
||||
|
func (p *PullRespPacket) UnmarshalBinary(data []byte) error { |
||||
|
if len(data) < 5 { |
||||
|
return errors.New("gateway: at least 5 bytes of data are expected") |
||||
|
} |
||||
|
if data[3] != byte(PullResp) { |
||||
|
return errors.New("gateway: identifier mismatch (PULL_RESP expected)") |
||||
|
} |
||||
|
if !protocolSupported(data[0]) { |
||||
|
return ErrInvalidProtocolVersion |
||||
|
} |
||||
|
p.ProtocolVersion = data[0] |
||||
|
p.RandomToken = binary.LittleEndian.Uint16(data[1:3]) |
||||
|
return json.Unmarshal(data[4:], &p.Payload) |
||||
|
} |
||||
|
|
||||
|
// PullRespPayload represents the downstream JSON data structure.
|
||||
|
type PullRespPayload struct { |
||||
|
TXPK TXPK `json:"txpk"` |
||||
|
} |
||||
|
|
||||
|
// TXPK contains a RF packet to be emitted and associated metadata.
|
||||
|
type TXPK struct { |
||||
|
Imme bool `json:"imme"` // Send packet immediately (will ignore tmst & time)
|
||||
|
RFCh uint8 `json:"rfch"` // Concentrator "RF chain" used for TX (unsigned integer)
|
||||
|
Powe uint8 `json:"powe"` // TX output power in dBm (unsigned integer, dBm precision)
|
||||
|
Ant uint8 `json:"ant"` // Antenna number on which signal has been received
|
||||
|
Brd uint32 `json:"brd"` // Concentrator board used for RX (unsigned integer)
|
||||
|
Tmst *uint32 `json:"tmst,omitempty"` // Send packet on a certain timestamp value (will ignore time)
|
||||
|
Tmms *int64 `json:"tmms,omitempty"` // Send packet at a certain GPS time (GPS synchronization required)
|
||||
|
Freq float64 `json:"freq"` // TX central frequency in MHz (unsigned float, Hz precision)
|
||||
|
Modu string `json:"modu"` // Modulation identifier "LORA" or "FSK"
|
||||
|
DatR DatR `json:"datr"` // LoRa datarate identifier (eg. SF12BW500) || FSK datarate (unsigned, in bits per second)
|
||||
|
CodR string `json:"codr,omitempty"` // LoRa ECC coding rate identifier
|
||||
|
FDev uint16 `json:"fdev,omitempty"` // FSK frequency deviation (unsigned integer, in Hz)
|
||||
|
NCRC bool `json:"ncrc,omitempty"` // If true, disable the CRC of the physical layer (optional)
|
||||
|
IPol bool `json:"ipol"` // Lora modulation polarization inversion
|
||||
|
Prea uint16 `json:"prea,omitempty"` // RF preamble size (unsigned integer)
|
||||
|
Size uint16 `json:"size"` // RF packet payload size in bytes (unsigned integer)
|
||||
|
Data []byte `json:"data"` // Base64 encoded RF packet payload, padding optional
|
||||
|
} |
||||
|
|
||||
|
// GetPullRespPacket returns a PullRespPacket for the given gw.DownlinkFrame.
|
||||
|
func GetPullRespPacket(protoVersion uint8, randomToken uint16, frame gw.DownlinkFrame) (PullRespPacket, error) { |
||||
|
packet := PullRespPacket{ |
||||
|
ProtocolVersion: protoVersion, |
||||
|
RandomToken: randomToken, |
||||
|
Payload: PullRespPayload{ |
||||
|
TXPK: TXPK{ |
||||
|
Freq: float64(frame.TxInfo.Frequency) / 1000000, |
||||
|
Powe: uint8(frame.TxInfo.Power), |
||||
|
Modu: frame.TxInfo.Modulation.String(), |
||||
|
Size: uint16(len(frame.PhyPayload)), |
||||
|
Data: frame.PhyPayload, |
||||
|
Ant: uint8(frame.TxInfo.Antenna), |
||||
|
Brd: uint32(frame.TxInfo.Board), |
||||
|
}, |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
if frame.TxInfo.Modulation == common.Modulation_LORA { |
||||
|
modInfo := frame.TxInfo.GetLoraModulationInfo() |
||||
|
if modInfo == nil { |
||||
|
return packet, errors.New("gateway: lora_modulation_info must not be nil") |
||||
|
} |
||||
|
packet.Payload.TXPK.DatR.LoRa = fmt.Sprintf("SF%dBW%d", modInfo.SpreadingFactor, modInfo.Bandwidth) |
||||
|
packet.Payload.TXPK.CodR = modInfo.CodeRate |
||||
|
packet.Payload.TXPK.IPol = modInfo.PolarizationInversion |
||||
|
} |
||||
|
|
||||
|
if frame.TxInfo.Modulation == common.Modulation_FSK { |
||||
|
modInfo := frame.TxInfo.GetFskModulationInfo() |
||||
|
if modInfo == nil { |
||||
|
return packet, errors.New("gateway: fsk_modulation_info must not be nil") |
||||
|
} |
||||
|
packet.Payload.TXPK.DatR.FSK = modInfo.Bitrate |
||||
|
packet.Payload.TXPK.FDev = uint16(modInfo.Bitrate / 2) // TODO: is this correct?!
|
||||
|
} |
||||
|
|
||||
|
switch frame.TxInfo.Timing { |
||||
|
case gw.DownlinkTiming_IMMEDIATELY: |
||||
|
packet.Payload.TXPK.Imme = true |
||||
|
|
||||
|
case gw.DownlinkTiming_DELAY: |
||||
|
timingInfo := frame.TxInfo.GetDelayTimingInfo() |
||||
|
if timingInfo == nil { |
||||
|
return packet, errors.New("delay_timing_info must not be nil") |
||||
|
} |
||||
|
|
||||
|
delay, err := ptypes.Duration(timingInfo.Delay) |
||||
|
if err != nil { |
||||
|
return packet, errors.Wrap(err, "get delay duration error") |
||||
|
} |
||||
|
|
||||
|
if len(frame.TxInfo.Context) < 4 { |
||||
|
return packet, fmt.Errorf("context must contain at least 4 bytes, got: %d", len(frame.TxInfo.Context)) |
||||
|
} |
||||
|
timestamp := binary.BigEndian.Uint32(frame.TxInfo.Context[0:4]) |
||||
|
timestamp += uint32(delay / time.Microsecond) |
||||
|
packet.Payload.TXPK.Tmst = ×tamp |
||||
|
|
||||
|
case gw.DownlinkTiming_GPS_EPOCH: |
||||
|
timingInfo := frame.TxInfo.GetGpsEpochTimingInfo() |
||||
|
if timingInfo == nil { |
||||
|
return packet, errors.New("gps_epoch_timing must not be nil") |
||||
|
} |
||||
|
|
||||
|
dur, err := ptypes.Duration(timingInfo.TimeSinceGpsEpoch) |
||||
|
if err != nil { |
||||
|
return packet, errors.Wrap(err, "parse time_since_gps_epoch error") |
||||
|
} |
||||
|
|
||||
|
durMS := int64(dur / time.Millisecond) |
||||
|
packet.Payload.TXPK.Tmms = &durMS |
||||
|
|
||||
|
default: |
||||
|
return packet, fmt.Errorf("unexpected downlink timing: %s", frame.TxInfo.Timing) |
||||
|
} |
||||
|
|
||||
|
return packet, nil |
||||
|
} |
@ -0,0 +1,39 @@ |
|||||
|
package packets |
||||
|
|
||||
|
import ( |
||||
|
"encoding/binary" |
||||
|
"errors" |
||||
|
) |
||||
|
|
||||
|
// PushACKPacket is used by the server to acknowledge immediately all the
|
||||
|
// PUSH_DATA packets received.
|
||||
|
type PushACKPacket struct { |
||||
|
ProtocolVersion uint8 |
||||
|
RandomToken uint16 |
||||
|
} |
||||
|
|
||||
|
// MarshalBinary marshals the object in binary form.
|
||||
|
func (p PushACKPacket) MarshalBinary() ([]byte, error) { |
||||
|
out := make([]byte, 4) |
||||
|
out[0] = p.ProtocolVersion |
||||
|
binary.LittleEndian.PutUint16(out[1:3], p.RandomToken) |
||||
|
out[3] = byte(PushACK) |
||||
|
return out, nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalBinary decodes the object from binary form.
|
||||
|
func (p *PushACKPacket) UnmarshalBinary(data []byte) error { |
||||
|
if len(data) != 4 { |
||||
|
return errors.New("gateway: 4 bytes of data are expected") |
||||
|
} |
||||
|
if data[3] != byte(PushACK) { |
||||
|
return errors.New("gateway: identifier mismatch (PUSH_ACK expected)") |
||||
|
} |
||||
|
|
||||
|
if !protocolSupported(data[0]) { |
||||
|
return ErrInvalidProtocolVersion |
||||
|
} |
||||
|
p.ProtocolVersion = data[0] |
||||
|
p.RandomToken = binary.LittleEndian.Uint16(data[1:3]) |
||||
|
return nil |
||||
|
} |
@ -0,0 +1,283 @@ |
|||||
|
package packets |
||||
|
|
||||
|
import ( |
||||
|
"encoding/binary" |
||||
|
"encoding/json" |
||||
|
"regexp" |
||||
|
"strconv" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/golang/protobuf/ptypes" |
||||
|
"github.com/pkg/errors" |
||||
|
|
||||
|
"github.com/brocaar/loraserver/api/common" |
||||
|
"github.com/brocaar/loraserver/api/gw" |
||||
|
"github.com/brocaar/lorawan" |
||||
|
) |
||||
|
|
||||
|
// loRaDataRateRegex contains a regexp for parsing the data-rate string.
|
||||
|
var loRaDataRateRegex = regexp.MustCompile(`SF(\d+)BW(\d+)`) |
||||
|
|
||||
|
// PushDataPacket type is used by the gateway mainly to forward the RF packets
|
||||
|
// received, and associated metadata, to the server.
|
||||
|
type PushDataPacket struct { |
||||
|
ProtocolVersion uint8 |
||||
|
RandomToken uint16 |
||||
|
GatewayMAC lorawan.EUI64 |
||||
|
Payload PushDataPayload |
||||
|
} |
||||
|
|
||||
|
// MarshalBinary encodes the packet into binary form compatible with the
|
||||
|
// Semtech UDP protocol.
|
||||
|
func (p PushDataPacket) MarshalBinary() ([]byte, error) { |
||||
|
pb, err := json.Marshal(&p.Payload) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
out := make([]byte, 4, len(pb)+12) |
||||
|
out[0] = p.ProtocolVersion |
||||
|
binary.LittleEndian.PutUint16(out[1:3], p.RandomToken) |
||||
|
out[3] = byte(PushData) |
||||
|
out = append(out, p.GatewayMAC[0:len(p.GatewayMAC)]...) |
||||
|
out = append(out, pb...) |
||||
|
return out, nil |
||||
|
} |
||||
|
|
||||
|
// GetGatewayStats returns the gw.GatewayStats object (if the packet contains stats).
|
||||
|
func (p PushDataPacket) GetGatewayStats() (*gw.GatewayStats, error) { |
||||
|
if p.Payload.Stat == nil { |
||||
|
return nil, nil |
||||
|
} |
||||
|
|
||||
|
stats := gw.GatewayStats{ |
||||
|
GatewayId: p.GatewayMAC[:], |
||||
|
RxPacketsReceived: p.Payload.Stat.RXNb, |
||||
|
RxPacketsReceivedOk: p.Payload.Stat.RXOK, |
||||
|
TxPacketsEmitted: p.Payload.Stat.TXNb, |
||||
|
TxPacketsReceived: p.Payload.Stat.DWNb, |
||||
|
} |
||||
|
|
||||
|
// time
|
||||
|
ts, err := ptypes.TimestampProto(time.Time(p.Payload.Stat.Time)) |
||||
|
if err != nil { |
||||
|
return nil, errors.Wrap(err, "timestamp proto error") |
||||
|
} |
||||
|
stats.Time = ts |
||||
|
|
||||
|
// location
|
||||
|
if p.Payload.Stat.Lati != 0 && p.Payload.Stat.Long != 0 && p.Payload.Stat.Alti != 0 { |
||||
|
stats.Location = &common.Location{ |
||||
|
Latitude: p.Payload.Stat.Lati, |
||||
|
Longitude: p.Payload.Stat.Long, |
||||
|
Altitude: float64(p.Payload.Stat.Alti), |
||||
|
Source: common.LocationSource_GPS, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return &stats, nil |
||||
|
} |
||||
|
|
||||
|
// GetUplinkFrames returns a slice of gw.UplinkFrame.
|
||||
|
func (p PushDataPacket) GetUplinkFrames(skipCRCCheck bool, FakeRxInfoTime bool) ([]gw.UplinkFrame, error) { |
||||
|
var frames []gw.UplinkFrame |
||||
|
|
||||
|
for i := range p.Payload.RXPK { |
||||
|
// validate CRC
|
||||
|
if p.Payload.RXPK[i].Stat != 1 && !skipCRCCheck { |
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
if len(p.Payload.RXPK[i].RSig) == 0 { |
||||
|
frame, err := getUplinkFrame(p.GatewayMAC[:], p.Payload.RXPK[i], FakeRxInfoTime) |
||||
|
if err != nil { |
||||
|
return nil, errors.Wrap(err, "gateway: get uplink frame error") |
||||
|
} |
||||
|
frames = append(frames, frame) |
||||
|
} else { |
||||
|
for j := range p.Payload.RXPK[i].RSig { |
||||
|
frame, err := getUplinkFrame(p.GatewayMAC[:], p.Payload.RXPK[i], FakeRxInfoTime) |
||||
|
if err != nil { |
||||
|
return nil, errors.Wrap(err, "gateway: get uplink frame error") |
||||
|
} |
||||
|
frame = setUplinkFrameRSig(frame, p.Payload.RXPK[i], p.Payload.RXPK[i].RSig[j]) |
||||
|
frames = append(frames, frame) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return frames, nil |
||||
|
} |
||||
|
|
||||
|
func setUplinkFrameRSig(frame gw.UplinkFrame, rxPK RXPK, rSig RSig) gw.UplinkFrame { |
||||
|
frame.RxInfo.Antenna = uint32(rSig.Ant) |
||||
|
frame.RxInfo.Channel = uint32(rSig.Chan) |
||||
|
frame.RxInfo.Rssi = int32(rSig.RSSIC) |
||||
|
frame.RxInfo.LoraSnr = rSig.LSNR |
||||
|
|
||||
|
if len(rSig.ETime) != 0 { |
||||
|
frame.RxInfo.FineTimestampType = gw.FineTimestampType_ENCRYPTED |
||||
|
frame.RxInfo.FineTimestamp = &gw.UplinkRXInfo_EncryptedFineTimestamp{ |
||||
|
EncryptedFineTimestamp: &gw.EncryptedFineTimestamp{ |
||||
|
EncryptedNs: rSig.ETime, |
||||
|
AesKeyIndex: uint32(rxPK.AESK), |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return frame |
||||
|
} |
||||
|
|
||||
|
func getUplinkFrame(gatewayID []byte, rxpk RXPK, FakeRxInfoTime bool) (gw.UplinkFrame, error) { |
||||
|
frame := gw.UplinkFrame{ |
||||
|
PhyPayload: rxpk.Data, |
||||
|
TxInfo: &gw.UplinkTXInfo{ |
||||
|
Frequency: uint32(rxpk.Freq * 1000000), |
||||
|
}, |
||||
|
RxInfo: &gw.UplinkRXInfo{ |
||||
|
GatewayId: gatewayID, |
||||
|
Rssi: int32(rxpk.RSSI), |
||||
|
LoraSnr: rxpk.LSNR, |
||||
|
Channel: uint32(rxpk.Chan), |
||||
|
RfChain: uint32(rxpk.RFCh), |
||||
|
Board: uint32(rxpk.Brd), |
||||
|
Context: make([]byte, 4), |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
// Context
|
||||
|
binary.BigEndian.PutUint32(frame.RxInfo.Context, rxpk.Tmst) |
||||
|
|
||||
|
// Time.
|
||||
|
if rxpk.Time != nil && !time.Time(*rxpk.Time).IsZero() { |
||||
|
ts, err := ptypes.TimestampProto(time.Time(*rxpk.Time)) |
||||
|
if err != nil { |
||||
|
return frame, errors.Wrap(err, "gateway: timestamp proto error") |
||||
|
} |
||||
|
frame.RxInfo.Time = ts |
||||
|
} else if FakeRxInfoTime { |
||||
|
ts, _ := ptypes.TimestampProto(time.Now().UTC()) |
||||
|
frame.RxInfo.Time = ts |
||||
|
} |
||||
|
|
||||
|
// Time since GPS epoch
|
||||
|
if rxpk.Tmms != nil { |
||||
|
d := time.Duration(*rxpk.Tmms) * time.Millisecond |
||||
|
frame.RxInfo.TimeSinceGpsEpoch = ptypes.DurationProto(d) |
||||
|
} |
||||
|
|
||||
|
// LoRa data-rate
|
||||
|
if rxpk.DatR.LoRa != "" { |
||||
|
frame.TxInfo.Modulation = common.Modulation_LORA |
||||
|
|
||||
|
match := loRaDataRateRegex.FindStringSubmatch(rxpk.DatR.LoRa) |
||||
|
// parse e.g. SF12BW250 into separate variables
|
||||
|
if len(match) != 3 { |
||||
|
return frame, errors.New("gateway: could not parse LoRa data-rate") |
||||
|
} |
||||
|
|
||||
|
// cast variables to ints
|
||||
|
sf, err := strconv.Atoi(match[1]) |
||||
|
if err != nil { |
||||
|
return frame, errors.Wrap(err, "gateway: could not convert sf to int") |
||||
|
} |
||||
|
|
||||
|
bw, err := strconv.Atoi(match[2]) |
||||
|
if err != nil { |
||||
|
return frame, errors.Wrap(err, "gateway: could not parse bandwidth to int") |
||||
|
} |
||||
|
|
||||
|
frame.TxInfo.ModulationInfo = &gw.UplinkTXInfo_LoraModulationInfo{ |
||||
|
LoraModulationInfo: &gw.LoRaModulationInfo{ |
||||
|
Bandwidth: uint32(bw), |
||||
|
SpreadingFactor: uint32(sf), |
||||
|
CodeRate: rxpk.CodR, |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// FSK data-rate
|
||||
|
if rxpk.DatR.FSK != 0 { |
||||
|
frame.TxInfo.Modulation = common.Modulation_FSK |
||||
|
|
||||
|
frame.TxInfo.ModulationInfo = &gw.UplinkTXInfo_FskModulationInfo{ |
||||
|
FskModulationInfo: &gw.FSKModulationInfo{ |
||||
|
Bitrate: uint32(rxpk.DatR.FSK), |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return frame, nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalBinary decodes the packet from Semtech UDP binary form.
|
||||
|
func (p *PushDataPacket) UnmarshalBinary(data []byte) error { |
||||
|
if len(data) < 13 { |
||||
|
return errors.New("gateway: at least 13 bytes are expected") |
||||
|
} |
||||
|
if data[3] != byte(PushData) { |
||||
|
return errors.New("gateway: identifier mismatch (PUSH_DATA expected)") |
||||
|
} |
||||
|
|
||||
|
if !protocolSupported(data[0]) { |
||||
|
return ErrInvalidProtocolVersion |
||||
|
} |
||||
|
|
||||
|
p.ProtocolVersion = data[0] |
||||
|
p.RandomToken = binary.LittleEndian.Uint16(data[1:3]) |
||||
|
for i := 0; i < 8; i++ { |
||||
|
p.GatewayMAC[i] = data[4+i] |
||||
|
} |
||||
|
|
||||
|
return json.Unmarshal(data[12:], &p.Payload) |
||||
|
} |
||||
|
|
||||
|
// PushDataPayload represents the upstream JSON data structure.
|
||||
|
type PushDataPayload struct { |
||||
|
RXPK []RXPK `json:"rxpk,omitempty"` |
||||
|
Stat *Stat `json:"stat,omitempty"` |
||||
|
} |
||||
|
|
||||
|
// Stat contains the status of the gateway.
|
||||
|
type Stat struct { |
||||
|
Time ExpandedTime `json:"time"` // UTC 'system' time of the gateway, ISO 8601 'expanded' format (e.g 2014-01-12 08:59:28 GMT)
|
||||
|
Lati float64 `json:"lati"` // GPS latitude of the gateway in degree (float, N is +)
|
||||
|
Long float64 `json:"long"` // GPS latitude of the gateway in degree (float, E is +)
|
||||
|
Alti int32 `json:"alti"` // GPS altitude of the gateway in meter RX (integer)
|
||||
|
RXNb uint32 `json:"rxnb"` // Number of radio packets received (unsigned integer)
|
||||
|
RXOK uint32 `json:"rxok"` // Number of radio packets received with a valid PHY CRC
|
||||
|
RXFW uint32 `json:"rxfw"` // Number of radio packets forwarded (unsigned integer)
|
||||
|
ACKR float64 `json:"ackr"` // Percentage of upstream datagrams that were acknowledged
|
||||
|
DWNb uint32 `json:"dwnb"` // Number of downlink datagrams received (unsigned integer)
|
||||
|
TXNb uint32 `json:"txnb"` // Number of packets emitted (unsigned integer)
|
||||
|
} |
||||
|
|
||||
|
// RXPK contain a RF packet and associated metadata.
|
||||
|
type RXPK struct { |
||||
|
Time *CompactTime `json:"time"` // UTC time of pkt RX, us precision, ISO 8601 'compact' format (e.g. 2013-03-31T16:21:17.528002Z)
|
||||
|
Tmms *int64 `json:"tmms"` // GPS time of pkt RX, number of milliseconds since 06.Jan.1980
|
||||
|
Tmst uint32 `json:"tmst"` // Internal timestamp of "RX finished" event (32b unsigned)
|
||||
|
AESK uint8 `json:"aesk"` //AES key index used for encrypting fine timestamps
|
||||
|
Chan uint8 `json:"chan"` // Concentrator "IF" channel used for RX (unsigned integer)
|
||||
|
RFCh uint8 `json:"rfch"` // Concentrator "RF chain" used for RX (unsigned integer)
|
||||
|
Stat int8 `json:"stat"` // CRC status: 1 = OK, -1 = fail, 0 = no CRC
|
||||
|
Freq float64 `json:"freq"` // RX central frequency in MHz (unsigned float, Hz precision)
|
||||
|
Brd uint32 `json:"brd"` // Concentrator board used for RX (unsigned integer)
|
||||
|
RSSI int16 `json:"rssi"` // RSSI in dBm (signed integer, 1 dB precision)
|
||||
|
Size uint16 `json:"size"` // RF packet payload size in bytes (unsigned integer)
|
||||
|
DatR DatR `json:"datr"` // LoRa datarate identifier (eg. SF12BW500) || FSK datarate (unsigned, in bits per second)
|
||||
|
Modu string `json:"modu"` // Modulation identifier "LORA" or "FSK"
|
||||
|
CodR string `json:"codr"` // LoRa ECC coding rate identifier
|
||||
|
LSNR float64 `json:"lsnr"` // Lora SNR ratio in dB (signed float, 0.1 dB precision)
|
||||
|
Data []byte `json:"data"` // Base64 encoded RF packet payload, padded
|
||||
|
RSig []RSig `json:"rsig"` // Received signal information, per antenna (Optional)
|
||||
|
} |
||||
|
|
||||
|
// RSig contains the received signal information per antenna.
|
||||
|
type RSig struct { |
||||
|
Ant uint8 `json:"ant"` // Antenna number on which signal has been received
|
||||
|
Chan uint8 `json:"chan"` // Concentrator "IF" channel used for RX (unsigned integer)
|
||||
|
RSSIC int16 `json:"rssic"` // RSSI in dBm of the channel (signed integer, 1 dB precision)
|
||||
|
LSNR float64 `json:"lsnr"` // Lora SNR ratio in dB (signed float, 0.1 dB precision)
|
||||
|
ETime []byte `json:"etime"` // Encrypted 'main' fine timestamp, ns precision [0..999999999] (Optional)
|
||||
|
} |
@ -0,0 +1,73 @@ |
|||||
|
package packets |
||||
|
|
||||
|
import ( |
||||
|
"encoding/binary" |
||||
|
"encoding/json" |
||||
|
"errors" |
||||
|
|
||||
|
"github.com/brocaar/lorawan" |
||||
|
) |
||||
|
|
||||
|
// TXACKPacket is used by the gateway to send a feedback to the server
|
||||
|
// to inform if a downlink request has been accepted or rejected by the
|
||||
|
// gateway.
|
||||
|
type TXACKPacket struct { |
||||
|
ProtocolVersion uint8 |
||||
|
RandomToken uint16 |
||||
|
GatewayMAC lorawan.EUI64 |
||||
|
Payload *TXACKPayload |
||||
|
} |
||||
|
|
||||
|
// MarshalBinary marshals the object into binary form.
|
||||
|
func (p TXACKPacket) MarshalBinary() ([]byte, error) { |
||||
|
var pb []byte |
||||
|
if p.Payload != nil { |
||||
|
var err error |
||||
|
pb, err = json.Marshal(p.Payload) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
out := make([]byte, 4, len(pb)+12) |
||||
|
out[0] = p.ProtocolVersion |
||||
|
binary.LittleEndian.PutUint16(out[1:3], p.RandomToken) |
||||
|
out[3] = byte(TXACK) |
||||
|
out = append(out, p.GatewayMAC[:]...) |
||||
|
out = append(out, pb...) |
||||
|
return out, nil |
||||
|
} |
||||
|
|
||||
|
// UnmarshalBinary decodes the object from binary form.
|
||||
|
func (p *TXACKPacket) UnmarshalBinary(data []byte) error { |
||||
|
if len(data) < 12 { |
||||
|
return errors.New("gateway: at least 12 bytes of data are expected") |
||||
|
} |
||||
|
if data[3] != byte(TXACK) { |
||||
|
return errors.New("gateway: identifier mismatch (TXACK expected)") |
||||
|
} |
||||
|
if !protocolSupported(data[0]) { |
||||
|
return ErrInvalidProtocolVersion |
||||
|
} |
||||
|
p.ProtocolVersion = data[0] |
||||
|
p.RandomToken = binary.LittleEndian.Uint16(data[1:3]) |
||||
|
for i := 0; i < 8; i++ { |
||||
|
p.GatewayMAC[i] = data[4+i] |
||||
|
} |
||||
|
if len(data) > 13 { // the min payload + the length of at least "{}"
|
||||
|
p.Payload = &TXACKPayload{} |
||||
|
return json.Unmarshal(data[12:], p.Payload) |
||||
|
} |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// TXACKPayload contains the TXACKPacket payload.
|
||||
|
type TXACKPayload struct { |
||||
|
TXPKACK TXPKACK `json:"txpk_ack"` |
||||
|
} |
||||
|
|
||||
|
// TXPKACK contains the status information of the associated PULL_RESP
|
||||
|
// packet.
|
||||
|
type TXPKACK struct { |
||||
|
Error string `json:"error"` |
||||
|
} |
Binary file not shown.
@ -0,0 +1 @@ |
|||||
|
rsrc -manifest LoRaDTUMock.manifest -ico dot.ico -o rsrc.syso |
Loading…
Reference in new issue