Skip to content

Commit

Permalink
dev: Work on firefly package
Browse files Browse the repository at this point in the history
  • Loading branch information
happyRip committed Sep 16, 2022
1 parent bc136d7 commit 216881e
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 32 deletions.
43 changes: 32 additions & 11 deletions pkg/source/firefly/config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package firefly

import (
"crypto/x509"
"fmt"
"net/http"
"os"

"github.com/TheThingsNetwork/go-utils/handlers/cli"
Expand All @@ -14,23 +16,26 @@ import (
)

type config struct {
// appID string
apiURL string
apiKey string
apiURL string

joinEUI string

appID string
frequencyPlanID string
joinEUI string
macVersion string

dryRun bool
withSession bool
}

var logger *apex.Logger

func flagSet() *pflag.FlagSet {
flags := &pflag.FlagSet{}
// flags.String(flagWithPrefix("app-id"), os.Getenv("FIREFLY_APP_ID"), "Firefly app ID")
flags.String(flagWithPrefix("app-id"), os.Getenv("FIREFLY_APP_ID"), "Firefly app ID")
flags.String(flagWithPrefix("api-url"), os.Getenv("FIREFLY_API_URL"), "Firefly API URL")
flags.String(flagWithPrefix("api-key"), os.Getenv("FIREFLY_API_KEY"), "Firefly API key")
flags.String(flagWithPrefix("ca-file"), os.Getenv("FIREFLY_CA_FILE"), "Firefly CA file for TLS (optional)")
flags.String(flagWithPrefix("join-eui"), os.Getenv("JOIN_EUI"), "JoinEUI of exported devices")
return flags
}
Expand All @@ -55,10 +60,10 @@ func getConfig(flags *pflag.FlagSet) (*config, error) {
}
api.SetLogger(logger)
ttnlog.Set(ttnapex.Wrap(logger))
// appID := stringFlag(flagWithPrefix("app-id"))
// if appID == "" {
// return nil, errNoAppID
// }
appID := stringFlag(flagWithPrefix("app-id"))
if appID == "" {
return nil, errNoAppID
}
apiURL := stringFlag(flagWithPrefix("api-url"))
if apiURL == "" {
return nil, errNoAPIURL
Expand All @@ -73,12 +78,28 @@ func getConfig(flags *pflag.FlagSet) (*config, error) {
if joinEUI == "" {
return nil, errNoJoinEUI
}
if caPath := stringFlag(flagWithPrefix("ca-file")); caPath != "" {
pemBytes, err := os.ReadFile(caPath)
if err != nil {
return nil, err
}
rootCAs := http.DefaultTransport.(*http.Transport).TLSClientConfig.RootCAs
if rootCAs == nil {
if rootCAs, err = x509.SystemCertPool(); err != nil {
rootCAs = x509.NewCertPool()
}
}
rootCAs.AppendCertsFromPEM(pemBytes)
http.DefaultTransport.(*http.Transport).TLSClientConfig.RootCAs = rootCAs
}
return &config{
// appID: appID,
apiURL: apiURL,
apiKey: apiKey,
apiURL: apiURL,

appID: appID,
joinEUI: joinEUI,

dryRun: boolFlag("dry-run"),
}, nil
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/source/firefly/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package firefly
import "go.thethings.network/lorawan-stack/v3/pkg/errors"

var (
// errNoAppID = errors.DefineInvalidArgument("no_app_id", "no app id")
errNoAPIURL = errors.DefineInvalidArgument("no_api_url", "no api url")
errNoAPIKEY = errors.DefineInvalidArgument("no_api_key", "no api key")
errNoAPIURL = errors.DefineInvalidArgument("no_api_url", "no api url")
errNoAppID = errors.DefineInvalidArgument("no_app_id", "no app id")
errNoJoinEUI = errors.DefineInvalidArgument("no_join_eui", "no join eui")
)
76 changes: 57 additions & 19 deletions pkg/source/firefly/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ package firefly

import (
"context"
"fmt"
"strings"

pbtypes "github.com/gogo/protobuf/types"
"github.com/spf13/pflag"
"go.thethings.network/lorawan-stack/v3/pkg/log"
"go.thethings.network/lorawan-stack/v3/pkg/ttnpb"
"go.thethings.network/lorawan-stack/v3/pkg/types"

"go.thethings.network/lorawan-stack-migrate/pkg/source"
"go.thethings.network/lorawan-stack-migrate/pkg/source/firefly/api"
"go.thethings.network/lorawan-stack-migrate/pkg/source/firefly/devices"
)

Expand Down Expand Up @@ -44,15 +46,22 @@ func (s Source) ExportDevice(devEUI string) (*ttnpb.EndDevice, error) {
// Formatters: &ttnpb.MessagePayloadFormatters{},
FrequencyPlanId: s.config.frequencyPlanID,
Ids: &ttnpb.EndDeviceIdentifiers{
ApplicationIds: &ttnpb.ApplicationIdentifiers{ApplicationId: fmt.Sprintf("firefly-%v", ffdev.OrganizationID)},
ApplicationIds: &ttnpb.ApplicationIdentifiers{ApplicationId: "firefly-" + s.config.appID},
DeviceId: "eui-" + strings.ToLower(ffdev.EUI),
},
MacSettings: &ttnpb.MACSettings{Rx2DataRateIndex: &ttnpb.DataRateIndexValue{Value: ttnpb.DataRateIndex(ffdev.Rx2DataRate)}},
LorawanVersion: ttnpb.MACVersion_MAC_V1_0_2,
LorawanPhyVersion: ttnpb.PHYVersion_RP001_V1_0_2_REV_B,
MacSettings: &ttnpb.MACSettings{
Rx2DataRateIndex: &ttnpb.DataRateIndexValue{Value: ttnpb.DataRateIndex(ffdev.Rx2DataRate)},
StatusCountPeriodicity: &pbtypes.UInt32Value{Value: 0},
StatusTimePeriodicity: pbtypes.DurationProto(0),
},
// MacState: &ttnpb.MACState{},
RootKeys: &ttnpb.RootKeys{AppKey: &ttnpb.KeyEnvelope{}},
Session: &ttnpb.Session{Keys: &ttnpb.SessionKeys{AppSKey: &ttnpb.KeyEnvelope{}, NwkSEncKey: &ttnpb.KeyEnvelope{}}},
RootKeys: &ttnpb.RootKeys{},
SupportsClassC: ffdev.ClassC,
SupportsJoin: ffdev.ApplicationKey != "",
}
v3dev.Attributes = make(map[string]string)
v3dev.Ids.DevEui, err = unmarshalTextToBytes(&types.EUI64{}, ffdev.EUI)
if err != nil {
return nil, err
Expand All @@ -61,30 +70,59 @@ func (s Source) ExportDevice(devEUI string) (*ttnpb.EndDevice, error) {
if err != nil {
return nil, err
}
v3dev.RootKeys.AppKey.Key, err = unmarshalTextToBytes(&types.AES128Key{}, ffdev.ApplicationKey)
if err != nil {
return nil, err
}
v3dev.Session.DevAddr, err = unmarshalTextToBytes(&types.DevAddr{}, ffdev.Address)
if err != nil {
return nil, err
if v3dev.SupportsJoin {
v3dev.RootKeys.AppKey = &ttnpb.KeyEnvelope{}
v3dev.RootKeys.AppKey.Key, err = unmarshalTextToBytes(&types.AES128Key{}, ffdev.ApplicationKey)
if err != nil {
return nil, err
}
}
v3dev.Session.Keys.AppSKey.Key, err = unmarshalTextToBytes(&types.AES128Key{}, ffdev.ApplicationSessionKey)
if err != nil {
return nil, err
hasSession := ffdev.Address != "" && ffdev.NetworkSessionKey != "" && ffdev.ApplicationSessionKey != ""
if hasSession || !v3dev.SupportsJoin {
v3dev.Session = &ttnpb.Session{Keys: &ttnpb.SessionKeys{AppSKey: &ttnpb.KeyEnvelope{}, NwkSEncKey: &ttnpb.KeyEnvelope{}}}
v3dev.Session.DevAddr, err = unmarshalTextToBytes(&types.DevAddr{}, ffdev.Address)
if err != nil {
return nil, err
}
v3dev.Session.Keys.AppSKey.Key, err = unmarshalTextToBytes(&types.AES128Key{}, ffdev.ApplicationSessionKey)
if err != nil {
return nil, err
}
v3dev.Session.Keys.NwkSEncKey.Key, err = unmarshalTextToBytes(&types.AES128Key{}, ffdev.NetworkSessionKey)
if err != nil {
return nil, err
}
v3dev.Session.LastAFCntDown = uint32(ffdev.FrameCounter)
v3dev.Session.LastNFCntDown = uint32(ffdev.FrameCounter)
packet, err := devices.GetLastPacket()
if err != nil {
return nil, err
}
v3dev.Session.LastFCntUp = uint32(packet.FCnt)
}
v3dev.Session.Keys.NwkSEncKey.Key, err = unmarshalTextToBytes(&types.AES128Key{}, ffdev.NetworkSessionKey)
if err != nil {
return nil, err

if !s.config.dryRun {
log.FromContext(s.ctx).WithFields(log.Fields(
"device_id", ffdev.Name,
"device_eui", ffdev.EUI,
)).Info("Clearing device keys")
r, err := api.PutDeviceUpdate(devEUI, map[string]string{
"address": "", "application_key": "", "application_session_key": "",
})
if err != nil {
return nil, err
}
r.Body.Close()
}

return v3dev, nil
}

// RangeDevices implements the source.Source interface.
func (s Source) RangeDevices(appID string, f func(source.Source, string) error) error {
// req, err := http.Get(fmt.Sprintf("http://%s/api/v1/applications/%s/euis?auth=%s", s.config.apiURL, appID, s.config.apiKey))
var (
devs []*devices.Device
devs []devices.Device
err error
)
logger.WithField("app-id", appID).Debug("App ID")
Expand Down

0 comments on commit 216881e

Please sign in to comment.