Meshblu的调试和MQTT-HTTP桥接所需的Redis

我重建了几次Meshblu容器并进行操作之后,MQTT-HTTP桥突然无法工作。起初,我在Node.js代码中随意地使用console.log进行调试,但由于在Meshblu中使用了debug包,我决定尝试利用它。最终,导致MQTT-HTTP桥无法工作的原因是缺少与Redis的协作配置。

调试包

在Meshblu的某些代码中,已经引入了debug模块。它将参数作为名称来创建一个debug函数。

var debug = require('debug')('worker');

setInterval(function(){
  debug('doing some work');
}, 1000);

如果要启用调试,需要在DEBUG环境变量中设置debug函数参数的名称。

DEBUG=worker node example/app

如果要设置多个选项,应使用逗号进行分隔。

DEBUG=worker,http node example/app

使用方法

在Mesublu的情况下,debug函数的创建方式如下所示。

var debug = require('debug')('meshblu:sendMessage');

由于Node.js程序是通过Supervisor执行的,因此需要在supervisor.conf文件中添加环境变量。

[program:node]
environment=DEBUG="meshblu:sendMessage"
command=/usr/bin/node /var/www/server.js --http --coap --mqtt

在想要进行调试的地方,使用debug函数。

            debug('Sending message', emitMsg);
            debug('protocol',check.protocol);
            if(check.protocol === 'mqtt'){
              mqttEmitter(check.uuid, wrapMqttMessage(topic, emitMsg), {qos: data.qos || DEFAULT_QO\
S});
            }
            else{
              socketEmitter(check.uuid, topic, emitMsg);
            }

当设置了docker logs,会显示调试信息。

$ docker logs -f meshblu
Wed, 25 Mar 2015 14:30:53 GMT meshblu:sendMessage Sending message { devices: [ 'my-iot' ],
  payload: { yello: 'on' },
  fromUuid: 'temp-sens' }
Wed, 25 Mar 2015 14:30:53 GMT meshblu:sendMessage protocol undefined

启用Redis

调试时发现 mqttServer.js 的 socketEmitter 函数似乎没有触发 emit。该函数在将协议设置为 HTTP 的设备从 MQTT 到 HTTP 进行桥接时执行。之所以没有桥接成功是因为无法从 config.js 读取 Redis 的配置。

  if(config.redis && config.redis.host){
    var redis = require('./redis');
    io = require('socket.io-emitter')(redis.client);
  }
...
  function socketEmitter(uuid, topic, data){
    if(io){
      io.in(uuid).emit(topic, data);
    }
  }

Redis的配置值是从环境变量中读取的。

  redis: {
    host: process.env.REDIS_HOST,
    port: parseInt(process.env.REDIS_PORT),
    password: process.env.REDIS_PASSWORD
  },

在运行Docker时,将Redis的配置添加到环境变量中并启动。

 docker run -d --name meshblu \
  -p 3000:3000 \
  -p 4443:4443 \
  -p 5683:5683 \
  -p 1883:1883 \
  -e PORT=3000 \
  -e MQTT_PORT=1883 \
  -e MQTT_PASSWORD=skynetpass \
  -e MONGODB_URI=mongodb://localhost:27017/skynet \
  -e REDIS_HOST=localhost \
  -e REDIS_PASSWORD=localhost \
  -e SSL_PORT=4443 \
  -e SSL_CERT=/opt/meshblu/certs/server.crt \
  -e SSL_KEY=/opt/meshblu/certs/server.key \
  -v $PWD:/var/www \
  -v $PWD/docker:/etc/supervisor/conf.d \
  -v $HOME/docker_apps/certs/meshblu:/opt/meshblu/certs \
  meshblu

发布/订阅

首先,将publish和subscribe设备的UUID/TOKEN设置为环境变量,并添加到~/.bashrc文件中。

export TEMP_SENS_UUID=temp-sens
export TEMP_SENS_TOKEN=123
export MY_IOT_UUID=my-iot
export MY_IOT_TOKEN=456

起初,通过curl进行订阅操作。

$ curl -X GET \
  "http://localhost:3000/subscribe" \
  --insecure \
  --header "meshblu_auth_uuid: $MY_IOT_UUID" \
  --header "meshblu_auth_token: $MY_IOT_TOKEN"

接下来,打开一个新的终端窗口,并从Mosquitto进行发布操作。

$ mosquitto_pub \
  -h localhost  \
  -p 1883 \
  -t message \
  -m '{"devices": ["'"$MY_IOT_UUID"'"], "payload": {"yello":"on"}}' \
  -u $TEMP_SENS_UUID \
  -P $TEMP_SENS_TOKEN \
  -d
Client mosqpub/39356-minion1.c sending CONNECT
Client mosqpub/39356-minion1.c received CONNACK
Client mosqpub/39356-minion1.c sending PUBLISH (d0, q0, r0, m1, 'message', ... (50 bytes))
Client mosqpub/39356-minion1.c sending DISCONNECT

消息已在订阅的shell中通过curl输出。

{"devices":["my-iot"],"payload":{"yello":"on"},"fromUuid":"temp-sens"},