Beispiel #1
0
func ExampleNewClient() {
	ctx := apex.Wrap(log.WithField("Example", "NewClient"))
	exampleClient := NewClient(ctx, "ttnctl", "my-app-id", "my-access-key", "eu.thethings.network:1883")
	err := exampleClient.Connect()
	if err != nil {
		ctx.WithError(err).Fatal("Could not connect")
	}
}
Beispiel #2
0
func (h *handler) HandleAMQP(username, password, host, exchange, downlinkQueue string) error {
	h.amqpClient = amqp.NewClient(apex.Wrap(h.Ctx), username, password, host)

	err := h.amqpClient.Connect()
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			h.amqpClient.Disconnect()
		}
	}()

	h.amqpUp = make(chan *types.UplinkMessage)

	subscriber := h.amqpClient.NewSubscriber(h.amqpExchange, downlinkQueue, downlinkQueue != "", downlinkQueue == "")
	err = subscriber.Open()
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			subscriber.Close()
		}
	}()
	err = subscriber.SubscribeDownlink(func(_ amqp.Subscriber, _, _ string, req types.DownlinkMessage) {
		h.EnqueueDownlink(&req)
	})
	if err != nil {
		return err
	}

	ctx := h.Ctx.WithField("Protocol", "AMQP")

	go func() {
		publisher := h.amqpClient.NewPublisher(h.amqpExchange)
		err := publisher.Open()
		if err != nil {
			ctx.WithError(err).Error("Could not open publisher channel")
			return
		}
		defer publisher.Close()

		for up := range h.amqpUp {
			ctx.WithFields(log.Fields{
				"DevID": up.DevID,
				"AppID": up.AppID,
			}).Debug("Publish Uplink")
			err := publisher.PublishUplink(*up)
			if err != nil {
				ctx.WithError(err).Warn("Could not publish Uplink")
			}
		}
	}()

	return nil
}
Beispiel #3
0
func (b *broker) RegisterRPC(s *grpc.Server) {
	server := &brokerRPC{broker: b}
	server.SetLogger(apex.Wrap(b.Ctx))
	server.RouterAssociateChanFunc = server.associateRouter
	server.HandlerPublishChanFunc = server.getHandlerPublish
	server.HandlerSubscribeChanFunc = server.getHandlerSubscribe

	// TODO: Monitor actual rates and configure sensible limits
	server.routerUpRate = ratelimit.NewRegistry(1000, time.Second)
	server.handlerDownRate = ratelimit.NewRegistry(125, time.Second) // one eight of uplink

	pb.RegisterBrokerServer(s, server)
}
Beispiel #4
0
// RegisterRPC registers this router as a RouterServer (github.com/TheThingsNetwork/ttn/api/router)
func (r *router) RegisterRPC(s *grpc.Server) {
	server := &routerRPC{router: r}
	server.SetLogger(apex.Wrap(r.Ctx))
	server.UplinkChanFunc = server.getUplink
	server.DownlinkChanFunc = server.getDownlink
	server.GatewayStatusChanFunc = server.getGatewayStatus

	// TODO: Monitor actual rates and configure sensible limits
	//
	// The current values are based on the following:
	// - 20 byte messages on all 6 orthogonal SFs at the same time -> ~1500 msgs/minute
	// - 8 channels at 5% utilization: 600 msgs/minute
	// - let's double that and round it to 1500/minute

	server.uplinkRate = ratelimit.NewRegistry(1500, time.Minute) // includes activations
	server.statusRate = ratelimit.NewRegistry(10, time.Minute)   // 10 per minute (pkt fwd default is 2 per minute)

	pb.RegisterRouterServer(s, server)
}
Beispiel #5
0
func getLogger(t *testing.T, tag string) log.Interface {
	return apex.Wrap(tt.GetLogger(t, tag))
}
Beispiel #6
0
func (h *handler) HandleMQTT(username, password string, mqttBrokers ...string) error {
	h.mqttClient = mqtt.NewClient(apex.Wrap(h.Ctx), "ttnhdl", username, password, mqttBrokers...)

	err := h.mqttClient.Connect()
	if err != nil {
		return err
	}

	h.mqttUp = make(chan *types.UplinkMessage, MQTTBufferSize)
	h.mqttEvent = make(chan *types.DeviceEvent, MQTTBufferSize)

	token := h.mqttClient.SubscribeDownlink(func(client mqtt.Client, appID string, devID string, msg types.DownlinkMessage) {
		down := &msg
		down.DevID = devID
		down.AppID = appID
		go h.EnqueueDownlink(down)
	})
	token.Wait()
	if token.Error() != nil {
		return err
	}

	ctx := h.Ctx.WithField("Protocol", "MQTT")

	go func() {
		for up := range h.mqttUp {
			ctx.WithFields(log.Fields{
				"DevID": up.DevID,
				"AppID": up.AppID,
			}).Debug("Publish Uplink")
			upToken := h.mqttClient.PublishUplink(*up)
			go func() {
				if upToken.WaitTimeout(MQTTTimeout) {
					if upToken.Error() != nil {
						ctx.WithError(upToken.Error()).Warn("Could not publish Uplink")
					}
				} else {
					ctx.Warn("Uplink publish timeout")
				}
			}()
			if len(up.PayloadFields) > 0 {
				fieldsToken := h.mqttClient.PublishUplinkFields(up.AppID, up.DevID, up.PayloadFields)
				go func() {
					if fieldsToken.WaitTimeout(MQTTTimeout) {
						if fieldsToken.Error() != nil {
							ctx.WithError(fieldsToken.Error()).Warn("Could not publish Uplink Fields")
						}
					} else {
						ctx.Warn("Uplink Fields publish timeout")
					}
				}()
			}
		}
	}()

	go func() {
		for event := range h.mqttEvent {
			h.Ctx.WithFields(log.Fields{
				"DevID": event.DevID,
				"AppID": event.AppID,
				"Event": event.Event,
			}).Debug("Publish Event")
			var token mqtt.Token
			if event.DevID == "" {
				token = h.mqttClient.PublishAppEvent(event.AppID, event.Event, event.Data)
			} else {
				token = h.mqttClient.PublishDeviceEvent(event.AppID, event.DevID, event.Event, event.Data)
			}
			go func() {
				if token.WaitTimeout(MQTTTimeout) {
					if token.Error() != nil {
						h.Ctx.WithError(token.Error()).Warn("Could not publish Event")
					}
				} else {
					h.Ctx.Warn("Event publish timeout")
				}
			}()
		}
	}()

	return nil
}
func TestHandlerBrokerCommunication(t *testing.T) {
	a := New(t)

	ctx := GetLogger(t, "TestHandlerBrokerCommunication")
	log.Set(apex.Wrap(ctx))

	brk := newTestBroker()
	rand.Seed(time.Now().UnixNano())
	port := rand.Intn(1000) + 10000
	go brk.Serve(port)

	conn, _ := api.Dial(fmt.Sprintf("localhost:%d", port))

	{
		brk.HandlerPublishChanFunc = func(md metadata.MD) (chan *DownlinkMessage, error) {
			ch := make(chan *DownlinkMessage, 1)
			go func() {
				ctx.Info("[SERVER] Channel opened")
				for message := range ch {
					ctx.WithField("Message", message).Info("[SERVER] Received Downlink")
				}
				ctx.Info("[SERVER] Channel closed")
			}()
			return ch, nil
		}

		brkClient := NewBrokerClient(conn)
		downlink := NewMonitoredHandlerPublishStream(brkClient, func() context.Context {
			return context.Background()
		})

		err := downlink.Send(&DownlinkMessage{
			Payload: []byte{1, 2, 3, 4},
		})

		a.So(err, ShouldBeNil)

		time.Sleep(10 * time.Millisecond)

		downlink.Close()

		time.Sleep(10 * time.Millisecond)
	}

	{
		brk.HandlerSubscribeChanFunc = func(md metadata.MD) (<-chan *DeduplicatedUplinkMessage, func(), error) {
			ch := make(chan *DeduplicatedUplinkMessage, 1)
			stop := make(chan struct{})
			cancel := func() {
				ctx.Info("[SERVER] Canceling uplink")
				close(stop)
			}
			go func() {
			loop:
				for {
					select {
					case <-stop:
						break loop
					case <-time.After(5 * time.Millisecond):
						ctx.Info("[SERVER] Sending Uplink")
						ch <- &DeduplicatedUplinkMessage{
							Payload: []byte{1, 2, 3, 4},
						}
					}
				}
				close(ch)
				ctx.Info("[SERVER] Closed Uplink")
			}()
			return ch, cancel, nil
		}

		brkClient := NewBrokerClient(conn)
		uplink := NewMonitoredHandlerSubscribeStream(brkClient, func() context.Context {
			return context.Background()
		})

		ch := uplink.Channel()

		go func() {
			for uplink := range ch {
				ctx.WithField("Uplink", uplink).Info("[CLIENT] Received Uplink")
			}
			ctx.Info("[CLIENT] Closed Uplink")
		}()

		time.Sleep(10 * time.Millisecond)

		uplink.Close()

		time.Sleep(10 * time.Millisecond)
	}

}
Beispiel #8
0
func TestHandleMQTT(t *testing.T) {
	host := os.Getenv("MQTT_ADDRESS")
	if host == "" {
		host = "localhost:1883"
	}

	a := New(t)
	var wg WaitGroup
	c := mqtt.NewClient(apex.Wrap(GetLogger(t, "TestHandleMQTT")), "test", "", "", fmt.Sprintf("tcp://%s", host))
	err := c.Connect()
	a.So(err, ShouldBeNil)
	appID := "handler-mqtt-app1"
	devID := "handler-mqtt-dev1"
	h := &handler{
		Component: &component.Component{Ctx: GetLogger(t, "TestHandleMQTT")},
		devices:   device.NewRedisDeviceStore(GetRedisClient(), "handler-test-handle-mqtt"),
	}
	h.devices.Set(&device.Device{
		AppID: appID,
		DevID: devID,
	})
	defer func() {
		h.devices.Delete(appID, devID)
	}()
	err = h.HandleMQTT("", "", fmt.Sprintf("tcp://%s", host))
	a.So(err, ShouldBeNil)

	c.PublishDownlink(types.DownlinkMessage{
		AppID:      appID,
		DevID:      devID,
		PayloadRaw: []byte{0xAA, 0xBC},
	}).Wait()
	<-time.After(50 * time.Millisecond)
	dev, _ := h.devices.Get(appID, devID)
	a.So(dev.NextDownlink, ShouldNotBeNil)

	wg.Add(1)
	c.SubscribeDeviceUplink(appID, devID, func(client mqtt.Client, r_appID string, r_devID string, req types.UplinkMessage) {
		a.So(r_appID, ShouldEqual, appID)
		a.So(r_devID, ShouldEqual, devID)
		a.So(req.PayloadRaw, ShouldResemble, []byte{0xAA, 0xBC})
		wg.Done()
	}).Wait()

	h.mqttUp <- &types.UplinkMessage{
		DevID:      devID,
		AppID:      appID,
		PayloadRaw: []byte{0xAA, 0xBC},
		PayloadFields: map[string]interface{}{
			"field": "value",
		},
	}

	wg.Add(1)
	c.SubscribeDeviceActivations(appID, devID, func(client mqtt.Client, r_appID string, r_devID string, req types.Activation) {
		a.So(r_appID, ShouldEqual, appID)
		a.So(r_devID, ShouldEqual, devID)
		wg.Done()
	}).Wait()

	h.mqttEvent <- &types.DeviceEvent{
		DevID: devID,
		AppID: appID,
		Event: types.ActivationEvent,
	}

	a.So(wg.WaitFor(200*time.Millisecond), ShouldBeNil)
}
Beispiel #9
0
			esClient.HTTPClient = &http.Client{
				Timeout: 5 * time.Second,
			}
			logHandlers = append(logHandlers, levelHandler.New(esHandler.New(&esHandler.Config{
				Client:     esClient,
				Prefix:     cmd.Name(),
				BufferSize: 10,
			}), logLevel))
		}

		ctx = &log.Logger{
			Handler: multiHandler.New(logHandlers...),
		}

		// Set the API/gRPC logger
		ttnlog.Set(apex.Wrap(ctx))
		grpclog.SetLogger(grpc.Wrap(ttnlog.Get()))

		ctx.WithFields(log.Fields{
			"ComponentID":              viper.GetString("id"),
			"Description":              viper.GetString("description"),
			"Discovery Server Address": viper.GetString("discovery-address"),
			"Auth Servers":             viper.GetStringMapString("auth-servers"),
			"Monitors":                 viper.GetStringMapString("monitor-servers"),
		}).Info("Initializing The Things Network")
	},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {
		if logFile != nil {
			logFile.Close()
		}
	},
func TestRouterCommunication(t *testing.T) {
	a := New(t)

	ctx := GetLogger(t, "TestRouterCommunication")
	log.Set(apex.Wrap(ctx))

	rtr := newTestRouter()
	rand.Seed(time.Now().UnixNano())
	port := rand.Intn(1000) + 10000
	go rtr.Serve(port)

	conn, _ := api.Dial(fmt.Sprintf("localhost:%d", port))

	{
		rtr.UplinkChanFunc = func(md metadata.MD) (chan *UplinkMessage, error) {
			ch := make(chan *UplinkMessage, 1)
			go func() {
				ctx.Info("[SERVER] Channel opened")
				for message := range ch {
					ctx.WithField("Message", message).Info("[SERVER] Received Uplink")
				}
				ctx.Info("[SERVER] Channel closed")
			}()
			return ch, nil
		}

		rtrClient := NewRouterClient(conn)
		gtwClient := NewRouterClientForGateway(rtrClient, "dev", "token")
		uplink := NewMonitoredUplinkStream(gtwClient)

		err := uplink.Send(&UplinkMessage{
			Payload: []byte{1, 2, 3, 4},
			ProtocolMetadata: &protocol.RxMetadata{Protocol: &protocol.RxMetadata_Lorawan{Lorawan: &lorawan.Metadata{
				Modulation: lorawan.Modulation_LORA,
				DataRate:   "SF7BW125",
				CodingRate: "4/7",
			}}},
			GatewayMetadata: &gateway.RxMetadata{
				GatewayId: "dev",
			},
		})

		a.So(err, ShouldBeNil)

		time.Sleep(10 * time.Millisecond)

		uplink.Close()

		time.Sleep(10 * time.Millisecond)

		gtwClient.Close()

		time.Sleep(10 * time.Millisecond)
	}

	{
		rtr.GatewayStatusChanFunc = func(md metadata.MD) (chan *gateway.Status, error) {
			ch := make(chan *gateway.Status, 1)
			go func() {
				ctx.Info("[SERVER] Channel opened")
				for message := range ch {
					ctx.WithField("Message", message).Info("[SERVER] Received GatewayStatus")
				}
				ctx.Info("[SERVER] Channel closed")
			}()
			return ch, nil
		}

		rtrClient := NewRouterClient(conn)
		gtwClient := NewRouterClientForGateway(rtrClient, "dev", "token")
		status := NewMonitoredGatewayStatusStream(gtwClient)

		err := status.Send(&gateway.Status{Time: time.Now().UnixNano()})

		a.So(err, ShouldBeNil)

		time.Sleep(10 * time.Millisecond)

		status.Close()

		time.Sleep(10 * time.Millisecond)

		gtwClient.Close()

		time.Sleep(10 * time.Millisecond)
	}

	{
		rtr.DownlinkChanFunc = func(md metadata.MD) (<-chan *DownlinkMessage, func(), error) {
			ch := make(chan *DownlinkMessage, 1)
			stop := make(chan struct{})
			cancel := func() {
				ctx.Info("[SERVER] Canceling downlink")
				close(stop)
			}
			go func() {
			loop:
				for {
					select {
					case <-stop:
						break loop
					case <-time.After(5 * time.Millisecond):
						ctx.Info("[SERVER] Sending Downlink")
						ch <- &DownlinkMessage{
							Payload: []byte{1, 2, 3, 4},
						}
					}
				}
				close(ch)
				ctx.Info("[SERVER] Closed Downlink")
			}()
			return ch, cancel, nil
		}

		rtrClient := NewRouterClient(conn)
		gtwClient := NewRouterClientForGateway(rtrClient, "dev", "token")
		downlink := NewMonitoredDownlinkStream(gtwClient)

		ch := downlink.Channel()

		go func() {
			for downlink := range ch {
				ctx.WithField("Downlink", downlink).Info("[CLIENT] Received Downlink")
			}
			ctx.Info("[CLIENT] Closed Downlink")
		}()

		time.Sleep(10 * time.Millisecond)

		downlink.Close()

		time.Sleep(10 * time.Millisecond)

		gtwClient.Close()

		time.Sleep(10 * time.Millisecond)
	}

}