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 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) }