Exemple #1
0
// Bytes returns the bytes
func (m *Message) Bytes() []byte {
	if m.FPort == 0 {
		m.FPort = 1
	}
	macPayload := &lorawan.MACPayload{}
	macPayload.FHDR = lorawan.FHDR{
		DevAddr: lorawan.DevAddr(m.devAddr),
		FCnt:    uint32(m.FCnt),
	}
	macPayload.FPort = pointer.Uint8(uint8(m.FPort))
	macPayload.FRMPayload = []lorawan.Payload{&lorawan.DataPayload{Bytes: m.Payload}}
	phyPayload := &lorawan.PHYPayload{}
	phyPayload.MHDR = lorawan.MHDR{
		MType: lorawan.UnconfirmedDataUp,
		Major: lorawan.LoRaWANR1,
	}
	if m.confirmed {
		phyPayload.MHDR.MType = lorawan.ConfirmedDataUp
	}
	phyPayload.MACPayload = macPayload
	phyPayload.EncryptFRMPayload(lorawan.AES128Key(m.appSKey))
	phyPayload.SetMIC(lorawan.AES128Key(m.nwkSKey))
	uplinkBytes, _ := phyPayload.MarshalBinary()
	return uplinkBytes
}
Exemple #2
0
// newReferenceUplink returns a default uplink message
func newReferenceUplink() *pb.UplinkMessage {
	gtwID := "eui-0102030405060708"

	phy := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.UnconfirmedDataUp,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.MACPayload{
			FHDR: lorawan.FHDR{
				DevAddr: lorawan.DevAddr([4]byte{1, 2, 3, 4}),
			},
		},
	}
	bytes, _ := phy.MarshalBinary()

	up := &pb.UplinkMessage{
		Payload: bytes,
		ProtocolMetadata: &pb_protocol.RxMetadata{Protocol: &pb_protocol.RxMetadata_Lorawan{Lorawan: &pb_lorawan.Metadata{
			CodingRate: "4/5",
			DataRate:   "SF7BW125",
			Modulation: pb_lorawan.Modulation_LORA,
		}}},
		GatewayMetadata: &pb_gateway.RxMetadata{
			GatewayId: gtwID,
			Timestamp: 100,
			Frequency: 868100000,
			Rssi:      -25.0,
			Snr:       5.0,
		},
	}
	return up
}
Exemple #3
0
func (n *networkServer) HandleDownlink(message *pb_broker.DownlinkMessage) (*pb_broker.DownlinkMessage, error) {
	// Get Device
	dev, err := n.devices.Get(*message.AppEui, *message.DevEui)
	if err != nil {
		return nil, err
	}

	n.status.downlink.Mark(1)

	dev.StartUpdate()

	if dev.AppID != message.AppId || dev.DevID != message.DevId {
		return nil, errors.NewErrInvalidArgument("Downlink", "AppID and DevID do not match AppEUI and DevEUI")
	}

	// Unmarshal LoRaWAN Payload
	var phyPayload lorawan.PHYPayload
	err = phyPayload.UnmarshalBinary(message.Payload)
	if err != nil {
		return nil, err
	}
	macPayload, ok := phyPayload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return nil, errors.NewErrInvalidArgument("Downlink", "does not contain a MAC payload")
	}

	// Set DevAddr
	macPayload.FHDR.DevAddr = lorawan.DevAddr(dev.DevAddr)

	// FIRST set and THEN increment FCntDown
	// TODO: For confirmed downlink, FCntDown should be incremented AFTER ACK
	macPayload.FHDR.FCnt = dev.FCntDown
	dev.FCntDown++
	err = n.devices.Set(dev)
	if err != nil {
		return nil, err
	}

	// Sign MIC
	phyPayload.SetMIC(lorawan.AES128Key(dev.NwkSKey))

	// Update message
	bytes, err := phyPayload.MarshalBinary()
	if err != nil {
		return nil, err
	}
	message.Payload = bytes

	return message, nil
}
// Payload converts the MACPayload to a lorawan.Payload
func (msg *Message_MacPayload) Payload() lorawan.Payload {
	m := *msg.MacPayload
	var mac lorawan.MACPayload
	mac.FHDR.DevAddr = lorawan.DevAddr(m.DevAddr)
	mac.FHDR.FCtrl.ADR = m.Adr
	mac.FHDR.FCtrl.ADRACKReq = m.AdrAckReq
	mac.FHDR.FCtrl.ACK = m.Ack
	mac.FHDR.FCtrl.FPending = m.FPending
	mac.FHDR.FCnt = m.FCnt
	for _, cmd := range m.FOpts {
		mac.FHDR.FOpts = append(mac.FHDR.FOpts, cmd.MACCommand())
	}
	if m.FPort >= 0 {
		fPort := uint8(m.FPort)
		mac.FPort = &fPort
	}
	mac.FRMPayload = []lorawan.Payload{
		&lorawan.DataPayload{Bytes: m.FrmPayload},
	}
	return &mac
}
// Payload converts the JoinAcceptPayload to a lorawan.Payload
func (msg *Message_JoinAcceptPayload) Payload() lorawan.Payload {
	m := *msg.JoinAcceptPayload
	if len(m.Encrypted) != 0 {
		return &lorawan.DataPayload{Bytes: m.Encrypted}
	}
	var mac lorawan.JoinAcceptPayload
	mac.AppNonce = m.AppNonce
	mac.NetID = m.NetId
	mac.DevAddr = lorawan.DevAddr(m.DevAddr)
	mac.DLSettings.RX1DROffset = uint8(m.Rx1DrOffset)
	mac.DLSettings.RX2DataRate = uint8(m.Rx2Dr)
	mac.RXDelay = uint8(m.RxDelay)
	if m.CfList != nil && len(m.CfList.Freq) == 5 {
		mac.CFList = &lorawan.CFList{
			m.CfList.Freq[0],
			m.CfList.Freq[1],
			m.CfList.Freq[2],
			m.CfList.Freq[3],
			m.CfList.Freq[4],
		}
	}
	return &mac
}
Exemple #6
0
func TestHandleUplink(t *testing.T) {
	a := New(t)
	ns := &networkServer{
		devices: device.NewRedisDeviceStore(GetRedisClient(), "ns-test-handle-uplink"),
	}
	ns.InitStatus()

	appEUI := types.AppEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8))
	devEUI := types.DevEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8))
	devAddr := getDevAddr(1, 2, 3, 4)

	// Device Not Found
	message := &pb_broker.DeduplicatedUplinkMessage{
		AppEui:  &appEUI,
		DevEui:  &devEUI,
		Payload: []byte{},
	}
	_, err := ns.HandleUplink(message)
	a.So(err, ShouldNotBeNil)

	ns.devices.Set(&device.Device{
		DevAddr: devAddr,
		AppEUI:  appEUI,
		DevEUI:  devEUI,
	})
	defer func() {
		ns.devices.Delete(appEUI, devEUI)
	}()

	// Invalid Payload
	message = &pb_broker.DeduplicatedUplinkMessage{
		AppEui:  &appEUI,
		DevEui:  &devEUI,
		Payload: []byte{},
	}
	_, err = ns.HandleUplink(message)
	a.So(err, ShouldNotBeNil)

	phy := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.UnconfirmedDataUp,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.MACPayload{
			FHDR: lorawan.FHDR{
				DevAddr: lorawan.DevAddr([4]byte{1, 2, 3, 4}),
				FCnt:    1,
				FCtrl: lorawan.FCtrl{
					ADR:       true,
					ADRACKReq: true,
				},
				FOpts: []lorawan.MACCommand{
					lorawan.MACCommand{CID: lorawan.LinkCheckReq},
				},
			},
		},
	}
	bytes, _ := phy.MarshalBinary()

	// Valid Uplink
	message = &pb_broker.DeduplicatedUplinkMessage{
		AppEui:           &appEUI,
		DevEui:           &devEUI,
		Payload:          bytes,
		ResponseTemplate: &pb_broker.DownlinkMessage{},
		GatewayMetadata: []*pb_gateway.RxMetadata{
			&pb_gateway.RxMetadata{},
		},
		ProtocolMetadata: &pb_protocol.RxMetadata{Protocol: &pb_protocol.RxMetadata_Lorawan{
			Lorawan: &pb_lorawan.Metadata{
				DataRate: "SF7BW125",
			},
		}},
	}
	res, err := ns.HandleUplink(message)
	a.So(err, ShouldBeNil)
	a.So(res.ResponseTemplate, ShouldNotBeNil)

	// LoRaWAN: Unmarshal
	var phyPayload lorawan.PHYPayload
	phyPayload.UnmarshalBinary(res.ResponseTemplate.Payload)
	macPayload, _ := phyPayload.MACPayload.(*lorawan.MACPayload)

	// ResponseTemplate DevAddr should match
	a.So([4]byte(macPayload.FHDR.DevAddr), ShouldEqual, [4]byte(devAddr))

	// ResponseTemplate should ACK the ADRACKReq
	a.So(macPayload.FHDR.FCtrl.ACK, ShouldBeTrue)
	a.So(macPayload.FHDR.FOpts, ShouldHaveLength, 1)
	a.So(macPayload.FHDR.FOpts[0].Payload, ShouldResemble, &lorawan.LinkCheckAnsPayload{GwCnt: 1, Margin: 7})

	// Frame Counter should have been updated
	dev, _ := ns.devices.Get(appEUI, devEUI)
	a.So(dev.FCntUp, ShouldEqual, 1)
	a.So(time.Now().Sub(dev.LastSeen), ShouldBeLessThan, 1*time.Second)
}
Exemple #7
0
func (n *networkServer) HandlePrepareActivation(activation *pb_broker.DeduplicatedDeviceActivationRequest) (*pb_broker.DeduplicatedDeviceActivationRequest, error) {
	if activation.AppEui == nil || activation.DevEui == nil {
		return nil, errors.NewErrInvalidArgument("Activation", "missing AppEUI or DevEUI")
	}
	dev, err := n.devices.Get(*activation.AppEui, *activation.DevEui)
	if err != nil {
		return nil, err
	}
	activation.AppId = dev.AppID
	activation.DevId = dev.DevID

	// Get activation constraints (for DevAddr prefix selection)
	activationConstraints := strings.Split(dev.Options.ActivationConstraints, ",")
	if len(activationConstraints) == 1 && activationConstraints[0] == "" {
		activationConstraints = []string{}
	}
	activationConstraints = append(activationConstraints, "otaa")

	// Build activation metadata if not present
	if meta := activation.GetActivationMetadata(); meta == nil {
		activation.ActivationMetadata = &pb_protocol.ActivationMetadata{}
	}
	// Build lorawan metadata if not present
	if lorawan := activation.ActivationMetadata.GetLorawan(); lorawan == nil {
		return nil, errors.NewErrInvalidArgument("Activation", "missing LoRaWAN metadata")
	}

	// Build response template if not present
	if pld := activation.GetResponseTemplate(); pld == nil {
		return nil, errors.NewErrInvalidArgument("Activation", "missing response template")
	}
	lorawanMeta := activation.ActivationMetadata.GetLorawan()

	// Get a random device address
	devAddr, err := n.getDevAddr(activationConstraints...)
	if err != nil {
		return nil, err
	}

	// Set the DevAddr in the Activation Metadata
	lorawanMeta.DevAddr = &devAddr

	// Build JoinAccept Payload
	phy := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.JoinAccept,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.JoinAcceptPayload{
			NetID:      n.netID,
			DLSettings: lorawan.DLSettings{RX2DataRate: uint8(lorawanMeta.Rx2Dr), RX1DROffset: uint8(lorawanMeta.Rx1DrOffset)},
			RXDelay:    uint8(lorawanMeta.RxDelay),
			DevAddr:    lorawan.DevAddr(devAddr),
		},
	}
	if lorawanMeta.CfList != nil {
		var cfList lorawan.CFList
		for i, cfListItem := range lorawanMeta.CfList.Freq {
			cfList[i] = cfListItem
		}
		phy.MACPayload.(*lorawan.JoinAcceptPayload).CFList = &cfList
	}

	// Set the Payload
	phyBytes, err := phy.MarshalBinary()
	if err != nil {
		return nil, err
	}
	activation.ResponseTemplate.Payload = phyBytes

	return activation, nil
}
Exemple #8
0
func TestHandleUplink(t *testing.T) {
	a := New(t)

	b := getTestBroker(t)

	gtwID := "eui-0102030405060708"

	// Invalid Payload
	err := b.HandleUplink(&pb.UplinkMessage{
		Payload:          []byte{0x01, 0x02, 0x03},
		GatewayMetadata:  &gateway.RxMetadata{Snr: 1.2, GatewayId: gtwID},
		ProtocolMetadata: &protocol.RxMetadata{},
	})
	a.So(err, ShouldNotBeNil)

	// Valid Payload
	phy := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.UnconfirmedDataUp,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.MACPayload{
			FHDR: lorawan.FHDR{
				DevAddr: lorawan.DevAddr([4]byte{1, 2, 3, 4}),
				FCnt:    1,
			},
		},
	}
	bytes, _ := phy.MarshalBinary()

	// Device not found
	b.uplinkDeduplicator = NewDeduplicator(10 * time.Millisecond)
	b.ns.EXPECT().GetDevices(gomock.Any(), gomock.Any()).Return(&pb_networkserver.DevicesResponse{
		Results: []*pb_lorawan.Device{},
	}, nil)
	err = b.HandleUplink(&pb.UplinkMessage{
		Payload:          bytes,
		GatewayMetadata:  &gateway.RxMetadata{Snr: 1.2, GatewayId: gtwID},
		ProtocolMetadata: &protocol.RxMetadata{Protocol: &protocol.RxMetadata_Lorawan{Lorawan: &pb_lorawan.Metadata{}}},
	})
	a.So(err, ShouldHaveSameTypeAs, &errors.ErrNotFound{})

	devEUI := types.DevEUI{1, 2, 3, 4, 5, 6, 7, 8}
	wrongDevEUI := types.DevEUI{1, 2, 3, 4, 5, 6, 7, 9}
	appEUI := types.AppEUI{1, 2, 3, 4, 5, 6, 7, 8}
	appID := "appid-1"
	nwkSKey := types.NwkSKey{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}

	// Add devices
	b = getTestBroker(t)
	nsResponse := &pb_networkserver.DevicesResponse{
		Results: []*pb_lorawan.Device{
			&pb_lorawan.Device{
				DevEui:  &wrongDevEUI,
				AppEui:  &appEUI,
				AppId:   appID,
				NwkSKey: &nwkSKey,
				FCntUp:  4,
			},
			&pb_lorawan.Device{
				DevEui:  &devEUI,
				AppEui:  &appEUI,
				AppId:   appID,
				NwkSKey: &nwkSKey,
				FCntUp:  3,
			},
		},
	}
	b.handlers["handlerID"] = &handler{uplink: make(chan *pb.DeduplicatedUplinkMessage, 10)}

	// Device doesn't match
	b.uplinkDeduplicator = NewDeduplicator(10 * time.Millisecond)
	b.ns.EXPECT().GetDevices(gomock.Any(), gomock.Any()).Return(nsResponse, nil)
	err = b.HandleUplink(&pb.UplinkMessage{
		Payload:          bytes,
		GatewayMetadata:  &gateway.RxMetadata{Snr: 1.2, GatewayId: gtwID},
		ProtocolMetadata: &protocol.RxMetadata{Protocol: &protocol.RxMetadata_Lorawan{Lorawan: &pb_lorawan.Metadata{}}},
	})
	a.So(err, ShouldHaveSameTypeAs, &errors.ErrNotFound{})

	phy.SetMIC(lorawan.AES128Key{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8})
	bytes, _ = phy.MarshalBinary()

	// Wrong FCnt
	b.uplinkDeduplicator = NewDeduplicator(10 * time.Millisecond)
	b.ns.EXPECT().GetDevices(gomock.Any(), gomock.Any()).Return(nsResponse, nil)
	err = b.HandleUplink(&pb.UplinkMessage{
		Payload:          bytes,
		GatewayMetadata:  &gateway.RxMetadata{Snr: 1.2, GatewayId: gtwID},
		ProtocolMetadata: &protocol.RxMetadata{Protocol: &protocol.RxMetadata_Lorawan{Lorawan: &pb_lorawan.Metadata{}}},
	})
	a.So(err, ShouldHaveSameTypeAs, &errors.ErrNotFound{})

	// Disable FCnt Check
	b.uplinkDeduplicator = NewDeduplicator(10 * time.Millisecond)
	nsResponse.Results[0].DisableFCntCheck = true
	b.ns.EXPECT().GetDevices(gomock.Any(), gomock.Any()).Return(nsResponse, nil)
	b.ns.EXPECT().Uplink(gomock.Any(), gomock.Any())
	b.discovery.EXPECT().GetAllHandlersForAppID("appid-1").Return([]*pb_discovery.Announcement{
		&pb_discovery.Announcement{
			Id: "handlerID",
		},
	}, nil)
	err = b.HandleUplink(&pb.UplinkMessage{
		Payload:          bytes,
		GatewayMetadata:  &gateway.RxMetadata{Snr: 1.2, GatewayId: gtwID},
		ProtocolMetadata: &protocol.RxMetadata{Protocol: &protocol.RxMetadata_Lorawan{Lorawan: &pb_lorawan.Metadata{}}},
	})
	a.So(err, ShouldBeNil)

	// OK FCnt
	b.uplinkDeduplicator = NewDeduplicator(10 * time.Millisecond)
	nsResponse.Results[0].FCntUp = 0
	nsResponse.Results[0].DisableFCntCheck = false
	b.ns.EXPECT().GetDevices(gomock.Any(), gomock.Any()).Return(nsResponse, nil)
	b.ns.EXPECT().Uplink(gomock.Any(), gomock.Any())
	b.discovery.EXPECT().GetAllHandlersForAppID("appid-1").Return([]*pb_discovery.Announcement{
		&pb_discovery.Announcement{
			Id: "handlerID",
		},
	}, nil)
	err = b.HandleUplink(&pb.UplinkMessage{
		Payload:          bytes,
		GatewayMetadata:  &gateway.RxMetadata{Snr: 1.2, GatewayId: gtwID},
		ProtocolMetadata: &protocol.RxMetadata{Protocol: &protocol.RxMetadata_Lorawan{Lorawan: &pb_lorawan.Metadata{}}},
	})
	a.So(err, ShouldBeNil)
}