Ejemplo n.º 1
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
}
Ejemplo n.º 2
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)
}