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") } }
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 }
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) }
// 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) }
func getLogger(t *testing.T, tag string) log.Interface { return apex.Wrap(tt.GetLogger(t, tag)) }
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) } }
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) }
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) } }