// FlushTXPayloadQueue flushes the tx payload queue for the given DevEUI. func (a *NodeAPI) FlushTXPayloadQueue(ctx context.Context, req *pb.FlushTXPayloadQueueRequest) (*pb.FlushTXPayloadQueueResponse, error) { var eui lorawan.EUI64 if err := eui.UnmarshalText([]byte(req.DevEUI)); err != nil { return nil, err } if err := storage.FlushTXPayloadQueue(a.ctx.RedisPool, eui); err != nil { return nil, err } return &pb.FlushTXPayloadQueueResponse{}, nil }
// Update updates the given Application. func (a *ApplicationAPI) Update(ctx context.Context, req *pb.UpdateApplicationRequest) (*pb.UpdateApplicationResponse, error) { var eui lorawan.EUI64 if err := eui.UnmarshalText([]byte(req.AppEUI)); err != nil { return nil, err } if err := storage.UpdateApplication(a.ctx.DB, models.Application{AppEUI: eui, Name: req.Name}); err != nil { return nil, err } return &pb.UpdateApplicationResponse{}, nil }
// Delete deletes the application for the given AppEUI. func (a *ApplicationAPI) Delete(ctx context.Context, req *pb.DeleteApplicationRequest) (*pb.DeleteApplicationResponse, error) { var eui lorawan.EUI64 if err := eui.UnmarshalText([]byte(req.AppEUI)); err != nil { return nil, err } if err := storage.DeleteApplication(a.ctx.DB, eui); err != nil { return nil, err } return &pb.DeleteApplicationResponse{}, nil }
// UnSubscribeGatewayTX unsubscribes the backend from the gateway TXPacket // topic. func (b *Backend) UnSubscribeGatewayTX(mac lorawan.EUI64) error { defer b.mutex.Unlock() b.mutex.Lock() topic := fmt.Sprintf("gateway/%s/tx", mac.String()) log.WithField("topic", topic).Info("backend/mqttpubsub: unsubscribing from topic") if token := b.conn.Unsubscribe(topic); token.Wait() && token.Error() != nil { return token.Error() } delete(b.gateways, mac) return nil }
// SubscribeGatewayTX subscribes the backend to the gateway TXPacket // topic (packets the gateway needs to transmit). func (b *Backend) SubscribeGatewayTX(mac lorawan.EUI64) error { defer b.mutex.Unlock() b.mutex.Lock() topic := fmt.Sprintf("gateway/%s/tx", mac.String()) log.WithField("topic", topic).Info("backend/mqttpubsub: subscribing to topic") if token := b.conn.Subscribe(topic, 0, b.txPacketHandler); token.Wait() && token.Error() != nil { return token.Error() } b.gateways[mac] = struct{}{} return nil }
// GetByDevEUI returns the node-session matching the given DevEUI. func (a *NodeSessionAPI) GetByDevEUI(ctx context.Context, req *pb.GetNodeSessionByDevEUIRequest) (*pb.GetNodeSessionResponse, error) { var eui lorawan.EUI64 if err := eui.UnmarshalText([]byte(req.DevEUI)); err != nil { return nil, err } ns, err := storage.GetNodeSessionByDevEUI(a.ctx.RedisPool, eui) if err != nil { return nil, err } return a.nodeSessionToResponse(ns) }
// GetListByAppEUI returns a list of nodes (given an AppEUI, limit and offset). func (a *NodeAPI) ListByAppEUI(ctx context.Context, req *pb.ListNodeByAppEUIRequest) (*pb.ListNodeResponse, error) { var eui lorawan.EUI64 if err := eui.UnmarshalText([]byte(req.AppEUI)); err != nil { return nil, err } nodes, err := storage.GetNodesForAppEUI(a.ctx.DB, eui, int(req.Limit), int(req.Offset)) if err != nil { return nil, err } count, err := storage.GetNodesForAppEUICount(a.ctx.DB, eui) if err != nil { return nil, err } return a.returnList(count, nodes) }
// Get returns the Application for the given AppEUI. func (a *ApplicationAPI) Get(ctx context.Context, req *pb.GetApplicationRequest) (*pb.GetApplicationResponse, error) { var eui lorawan.EUI64 if err := eui.UnmarshalText([]byte(req.AppEUI)); err != nil { return nil, err } app, err := storage.GetApplication(a.ctx.DB, eui) if err != nil { return nil, err } b, err := app.AppEUI.MarshalText() if err != nil { return nil, err } return &pb.GetApplicationResponse{ AppEUI: string(b), Name: app.Name, }, nil }
// Create creates the given Node. func (a *NodeAPI) Create(ctx context.Context, req *pb.CreateNodeRequest) (*pb.CreateNodeResponse, error) { var appEUI, devEUI lorawan.EUI64 var appKey lorawan.AES128Key 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 := appKey.UnmarshalText([]byte(req.AppKey)); err != nil { return nil, err } node := models.Node{ DevEUI: devEUI, AppEUI: appEUI, AppKey: appKey, RXDelay: uint8(req.RxDelay), RX1DROffset: uint8(req.Rx1DROffset), } if req.ChannelListID > 0 { node.ChannelListID = &req.ChannelListID } if err := storage.CreateNode(a.ctx.DB, node); err != nil { return nil, err } return &pb.CreateNodeResponse{}, nil }
// Update updates the node matching the given DevEUI. func (a *NodeAPI) Update(ctx context.Context, req *pb.UpdateNodeRequest) (*pb.UpdateNodeResponse, error) { var appEUI, devEUI lorawan.EUI64 var appKey lorawan.AES128Key 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 := appKey.UnmarshalText([]byte(req.AppKey)); err != nil { return nil, err } node, err := storage.GetNode(a.ctx.DB, devEUI) if err != nil { return nil, err } node.AppEUI = appEUI node.AppKey = appKey node.RXDelay = uint8(req.RxDelay) node.RX1DROffset = uint8(req.Rx1DROffset) if req.ChannelListID > 0 { node.ChannelListID = &req.ChannelListID } else { node.ChannelListID = nil } if err := storage.UpdateNode(a.ctx.DB, node); err != nil { return nil, err } return &pb.UpdateNodeResponse{}, nil }
// Get returns the Node for the given DevEUI. func (a *NodeAPI) Get(ctx context.Context, req *pb.GetNodeRequest) (*pb.GetNodeResponse, error) { var eui lorawan.EUI64 if err := eui.UnmarshalText([]byte(req.DevEUI)); err != nil { return nil, err } node, err := storage.GetNode(a.ctx.DB, eui) if err != nil { return nil, err } devEUI, err := node.DevEUI.MarshalText() if err != nil { return nil, err } appEUI, err := node.AppEUI.MarshalText() if err != nil { return nil, err } appKey, err := node.AppKey.MarshalText() if err != nil { return nil, err } resp := pb.GetNodeResponse{ DevEUI: string(devEUI), AppEUI: string(appEUI), AppKey: string(appKey), RxDelay: uint32(node.RXDelay), Rx1DROffset: uint32(node.RX1DROffset), } if node.ChannelListID != nil { resp.ChannelListID = *node.ChannelListID } return &resp, nil }
// 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 }
// PublishGatewayStats publishes a GatewayStatsPacket to the MQTT broker. func (b *Backend) PublishGatewayStats(mac lorawan.EUI64, stats models.GatewayStatsPacket) error { topic := fmt.Sprintf("gateway/%s/stats", mac.String()) return b.publish(topic, stats) }
// PublishGatewayRX publishes a RX packet to the MQTT broker. func (b *Backend) PublishGatewayRX(mac lorawan.EUI64, rxPacket models.RXPacket) error { topic := fmt.Sprintf("gateway/%s/rx", mac.String()) return b.publish(topic, rxPacket) }