1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-05-01 13:48:56 +08:00
Dušan Borovčanin b8be18129c
MF-1079 - Add MQTT forwarder (#1164)
* Add MQTT forwarder

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Cleanup forwarder code

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Use MQTT Publisher in MQTT forwarder

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Cleanup MQTT messaging

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Add Paho client timeout errors

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Simplify MQTT fowarder

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Fix naming in main method

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Use interface and struct instead of function

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Use Mainflux errors package

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Rename `tkn` to `token`

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Use "/" instead of "." as topic separator

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Use async MQTT Publisher

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Fix timeout errors messages

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Add connect token check

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Rename package alias

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2020-05-07 09:34:09 +02:00

87 lines
2.0 KiB
Go

// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
package mqtt
import (
"fmt"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/gogo/protobuf/proto"
"github.com/mainflux/mainflux/errors"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/messaging"
)
var _ messaging.Publisher = (*publisher)(nil)
var (
errSubscribeTimeout = errors.New("failed to subscribe due to timeout reached")
errUnsubscribeTimeout = errors.New("failed to unsubscribe due to timeout reached")
)
type subscriber struct {
client mqtt.Client
timeout time.Duration
logger log.Logger
}
// NewSubscriber returns a new MQTT message subscriber.
func NewSubscriber(address string, timeout time.Duration, logger log.Logger) (messaging.Subscriber, error) {
client, err := newClient(address, timeout)
if err != nil {
return nil, err
}
ret := subscriber{
client: client,
timeout: timeout,
logger: logger,
}
return ret, nil
}
func (sub subscriber) Subscribe(topic string, handler messaging.MessageHandler) error {
token := sub.client.Subscribe(topic, qos, sub.mqttHandler(handler))
if token.Error() != nil {
return token.Error()
}
ok := token.WaitTimeout(sub.timeout)
if ok && token.Error() != nil {
return token.Error()
}
if !ok {
return errSubscribeTimeout
}
return nil
}
func (sub subscriber) Unsubscribe(topic string) error {
token := sub.client.Unsubscribe(topic)
if token.Error() != nil {
return token.Error()
}
ok := token.WaitTimeout(sub.timeout)
if ok && token.Error() != nil {
return token.Error()
}
if !ok {
return errUnsubscribeTimeout
}
return nil
}
func (sub subscriber) mqttHandler(h messaging.MessageHandler) mqtt.MessageHandler {
return func(c mqtt.Client, m mqtt.Message) {
var msg messaging.Message
if err := proto.Unmarshal(m.Payload(), &msg); err != nil {
sub.logger.Warn(fmt.Sprintf("Failed to unmarshal received message: %s", err))
return
}
if err := h(msg); err != nil {
sub.logger.Warn(fmt.Sprintf("Failed to handle Mainflux message: %s", err))
}
}
}