Example #1
0
// Create creates the given node-session. The DevAddr must contain the same NwkID as the configured NetID. Node-sessions will expire automatically after the configured TTL.
func (a *NodeSessionAPI) Create(ctx context.Context, req *pb.CreateNodeSessionRequest) (*pb.CreateNodeSessionResponse, error) {
	var appEUI, devEUI lorawan.EUI64
	var appSKey, nwkSKey lorawan.AES128Key
	var devAddr lorawan.DevAddr

	if err := appEUI.UnmarshalText([]byte(req.AppEUI)); err != nil {
		return nil, err
	}
	if err := devEUI.UnmarshalText([]byte(req.DevEUI)); err != nil {
		return nil, err
	}
	if err := appSKey.UnmarshalText([]byte(req.AppSKey)); err != nil {
		return nil, err
	}
	if err := nwkSKey.UnmarshalText([]byte(req.NwkSKey)); err != nil {
		return nil, err
	}
	if err := devAddr.UnmarshalText([]byte(req.DevAddr)); err != nil {
		return nil, err
	}

	var cFList *lorawan.CFList
	if len(req.CFList) > len(cFList) {
		return nil, fmt.Errorf("max CFList channels is %d", len(cFList))
	}
	if len(req.CFList) > 0 {
		cFList = &lorawan.CFList{}
		for i, f := range req.CFList {
			cFList[i] = f
		}
	}

	ns := models.NodeSession{
		DevAddr:     devAddr,
		AppEUI:      appEUI,
		DevEUI:      devEUI,
		AppSKey:     appSKey,
		NwkSKey:     nwkSKey,
		FCntUp:      req.FCntUp,
		FCntDown:    req.FCntDown,
		RXDelay:     uint8(req.RxDelay),
		RX1DROffset: uint8(req.Rx1DROffset),
		CFList:      cFList,
	}

	if err := a.validateNodeSession(ns); err != nil {
		return nil, err
	}

	if err := storage.CreateNodeSession(a.ctx.RedisPool, ns); err != nil {
		return nil, err
	}

	return &pb.CreateNodeSessionResponse{}, nil
}
Example #2
0
// Delete deletes the node-session matching the given DevAddr.
func (a *NodeSessionAPI) Delete(ctx context.Context, req *pb.DeleteNodeSessionRequest) (*pb.DeleteNodeSessionResponse, error) {
	var devAddr lorawan.DevAddr
	if err := devAddr.UnmarshalText([]byte(req.DevAddr)); err != nil {
		return nil, err
	}

	if err := storage.DeleteNodeSession(a.ctx.RedisPool, devAddr); err != nil {
		return nil, err
	}

	return &pb.DeleteNodeSessionResponse{}, nil
}
Example #3
0
// Get returns the node-session matching the given DevAddr.
func (a *NodeSessionAPI) Get(ctx context.Context, req *pb.GetNodeSessionRequest) (*pb.GetNodeSessionResponse, error) {
	var devAddr lorawan.DevAddr
	if err := devAddr.UnmarshalText([]byte(req.DevAddr)); err != nil {
		return nil, err
	}

	ns, err := storage.GetNodeSession(a.ctx.RedisPool, devAddr)
	if err != nil {
		return nil, err
	}

	return a.nodeSessionToResponse(ns)
}
Example #4
0
// getRandomDevAddr returns a random free DevAddr. Note that the 7 MSB will be
// set to the NwkID (based on the configured NetID).
// TODO: handle collission with retry?
func getRandomDevAddr(p *redis.Pool, netID lorawan.NetID) (lorawan.DevAddr, error) {
	var d lorawan.DevAddr
	b := make([]byte, len(d))
	if _, err := rand.Read(b); err != nil {
		return d, fmt.Errorf("could not read from random reader: %s", err)
	}
	copy(d[:], b)
	d[0] = d[0] & 1                    // zero out 7 msb
	d[0] = d[0] ^ (netID.NwkID() << 1) // set 7 msb to NwkID

	c := p.Get()
	defer c.Close()

	key := "node_session_" + d.String()
	val, err := redis.Int(c.Do("EXISTS", key))
	if err != nil {
		return lorawan.DevAddr{}, fmt.Errorf("test DevAddr %s exist error: %s", d, err)
	}
	if val == 1 {
		return lorawan.DevAddr{}, fmt.Errorf("DevAddr %s already exists", d)
	}
	return d, nil
}