CC2650 launchpad + RPI + CC2650 sensor tag 构造MQTT控制蓝牙节点

经过一番折腾,总算跑通了MQTT控制蓝牙节点的程序。目前来说,基于6lbr的这个服务来控制蓝牙节点还存在问题,也有可能是cc26x0-web-demo这个样例程序本身的问题。但是不管如何,我的当前的目标就是通过MQTT来控制蓝牙节点,这个目的算法达成了。但是cc26x0-web-demo为什么没有成功,只能留到以后再解决了。

总结来说,是利用以下几个相关的程序的:

  1. contiki-ng/examples/rpl-border-router, 这个程序运行在RPI上,使用的是native模式,且RPI上要运行mqtt broker,从而完成对MQTT消息的转发。
  2. contiki-ng/examples/slip-radio, 这个程序烧写在CC2650 launch pad上,这里的节点主要就是作为radio的收发部分, 仅仅运行了物理层以及MAC层的代码,再往上层的代码就不运行了。
  3. contiki-ng/examples/mqtt-client, 这个程序烧写在CC2650 sensortag上,主要是MQTT的client,它里面包含了MQTT的publish以及subscribe的部分。

获取contiki-ng项目

$ git clone git@github.com:contiki-ng/contiki-ng.git
$ cd contiki-ng
$ git submodule update --init --recursive

烧写在RPI上的rpl-border-router

  1. 在RPI上,
    make TARGET=native  
    
  2. 设置一会连接的专门用来收发radio的程序串口

    sudo ./border-router.native fd00::1/64 -s /dev/ttyACM0
    

    /dev/ttyACM0,这个部分根据实际情况来,如果是CC2650设备,一般是这个。

  3. 安装mqtt在RPI上,

    sudo apt-get update
    sudo apt-get install mosquitto
    sudo apt-get install mosquitto-clients
    
  4. 设置RPI上的地址长度
  5. 完成桥接地址的设置

    iface eth0 inet static
    address 0.0.0.0
    
    auto br0
    iface br0 inet dhcp
    bridge_ports eth0
    bridge_stp off
    up echo 0 > /sys/devices/virtual/net/br0/bridge/multicast_snooping
    post-up ip link set br0 address `ip link show eth0 | grep ether | awk '{print $2}'`
    
  6. Reboot,从而启用网络设置。

注意:如果RPI上安装过6lbr的话,需要先把6lbr服务关闭,因为他们会占用同一个slip-radio串口。
service 6lbr stop.

烧写在CC2650 launch pad上的slip-radio

  1. build the slip-radio first.
     make TARGET=simplelink BOARD=launchpad/cc2650 slip-radio
    
    最新的contiki-ng版本要使用simplelink来烧写,如果上面的不行,就使用这个编译方式:make TARGET=srf06-cc26xx BOARD=launchpad/cc2650 slip-radio
  2. 拷贝slip-radio.bin到TI programmer flash里面烧写。

  1. 将CC2650 launch pad连接到RPI上。

烧写在CC2650 sensortag中的MQTT client

  1. 查看RPI上global的ipv6 地址,比如,我的这里是这样

    br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
          inet6 fe80::ba27:ebff:fe91:106  prefixlen 64  scopeid 0x20<link>
          inet6 bbbb::ba27:ebff:fe91:106  prefixlen 64  scopeid 0x0<global>
          ether b8:27:eb:91:01:06  txqueuelen 1000  (Ethernet)
          RX packets 5439  bytes 304292 (297.1 KiB)
          RX errors 0  dropped 0  overruns 0  frame 0
          TX packets 37  bytes 5937 (5.7 KiB)
          TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
          ether b8:27:eb:91:01:06  txqueuelen 1000  (Ethernet)
          RX packets 5432  bytes 306558 (299.3 KiB)
          RX errors 0  dropped 11  overruns 0  frame 0
          TX packets 58  bytes 9501 (9.2 KiB)
          TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
          inet 127.0.0.1  netmask 255.0.0.0
          inet6 ::1  prefixlen 128  scopeid 0x10<host>
          loop  txqueuelen 1000  (Local Loopback)
          RX packets 0  bytes 0 (0.0 B)
          RX errors 0  dropped 0  overruns 0  frame 0
          TX packets 0  bytes 0 (0.0 B)
          TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
          inet 127.0.1.1  netmask 255.255.255.255  destination 127.0.1.1
          inet6 fd00::1  prefixlen 64  scopeid 0x0<global>
          inet6 fe80::b344:c02d:22ca:aeeb  prefixlen 64  scopeid 0x20<link>
          unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500
    
  2. 在project_conf.h里面修改MQTT_CLIENT_CONF_BROKER_IP_ADDR的值为RPI地址

    #define MQTT_CLIENT_CONF_BROKER_IP_ADDR "bbbb::ba27:ebff:fe91:106"
    
  3. 为了能够通过MQTT来控制CC2650 sensortag,我们需要使得MQTT_CLIENT_CONF_ORG_ID不等于quickstart,所以在project_conf.h中,再把这个修改了。比如:
    //#define MQTT_CLIENT_CONF_ORG_ID "quickstart"
    #define MQTT_CLIENT_CONF_ORG_ID "q22start"
    
  4. Finally, build the mqtt-client
    make TARGET=cc26x0-cc13x0 BOARD=sensortag/cc2650 mqtt-client
    

验证结果

  1. 在RPI上首先验证节点之间的连通性,运行如下命令查看RPI的地址,

    pi@raspberrypi:~/pure-contiki-ng/contiki-ng/examples/rpl-border-router $ sudo ./border-router.native fd00::1/64 -s /dev/ttyACM0 
    [INFO: Main      ] Starting Contiki-NG-develop/v4.2-50-g2b0c2d5e4-dirty
    [INFO: Main      ] - Routing: RPL Lite
    [INFO: Main      ] - Net: sicslowpan
    [INFO: Main      ] - MAC: br-mac
    [INFO: Main      ] - 802.15.4 PANID: 0xabcd
    [INFO: Main      ] - 802.15.4 Default channel: 26
    [INFO: Main      ] Node ID: 1800
    [INFO: Main      ] Link-layer address: 0102.0304.0506.0708
    [INFO: Main      ] Tentative link-local IPv6 address: fe80::302:304:506:708
    [INFO: Native    ] Added global IPv6 address fd00::302:304:506:708
    [INFO: RPL BR    ] Contiki-NG Border Router started
    [INFO: BR        ] RPL-Border router started
    ********SLIP started on ``/dev/ttyACM0''
    opened tun device ``/dev/tun0''
    ifconfig tun0 inet `hostname` up
    ifconfig tun0 add fd00::1/64
    ifconfig tun0
    
    tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
          inet 127.0.1.1  netmask 255.255.255.255  destination 127.0.1.1
          inet6 fd00::1  prefixlen 64  scopeid 0x0<global>
          inet6 fe80::b344:c02d:22ca:aeeb  prefixlen 64  scopeid 0x20<link>
          unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)
          RX packets 0  bytes 0 (0.0 B)
          RX errors 0  dropped 0  overruns 0  frame 0
          TX packets 0  bytes 0 (0.0 B)
          TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    [INFO: BR        ] Setting prefix fd00::1
    [INFO: BR        ] Server IPv6 addresses:
    [INFO: BR        ]   fd00::212:4b00:b23:1102
    [INFO: BR        ]   fe80::212:4b00:b23:1102
    
  2. 接着利用wget获取sensortag地址。

    $ wget -6 “http://[ fd00::212:4b00:b23:1102]”
    <html>
    <head>
      <title>Contiki-NG</title>
    </head>
    <body>
    Neighbors
    <ul>
      <li>fe80::212:4b00:c31:8d82</li>
    </ul>
    Routing links
    <ul>
      <li>fd00::212:4b00:c31:8d82 (parent: fd00::212:4b00:b23:1102) 1800s</li>
    </ul>
    </body>
    </html>
    
  3. Ping一下sensortag,发现可以ping通,那么就测试通信成功了。

  4. 在RPI上运行如下命令,来订阅该MQTT样例的默认topic

    mosquitto_sub –h bbbb::ba27:ebff:fe91:106 -t iot-2/evt/status/fmt/json
    

    我们应当看到如下输出:

    pi@raspberrypi:~/pure-contiki-ng/contiki-ng/examples/rpl-border-router $ mosquitto_sub -h bbbb::ba27:ebff:fe91:106  -t iot-2/evt/status/fmt/json
    {"d":{"Platform":"cc26x0-cc13x0","Board":"sensortag/cc2650","Seq #":1,"Uptime (sec)":53,"Def Route":"fe80::212:4b00:b23:1102","RSSI (dBm)":134217728,"On-Chip Temp (mC)":29,"Volt (mV)":3273}}
    {"d":{"Platform":"cc26x0-cc13x0","Board":"sensortag/cc2650","Seq #":2,"Uptime (sec)":83,"Def Route":"fe80::212:4b00:b23:1102","RSSI (dBm)":-42,"On-Chip Temp (mC)":29,"Volt (mV)":3273}}
    {"d":{"Platform":"cc26x0-cc13x0","Board":"sensortag/cc2650","Seq #":3,"Uptime (sec)":113,"Def Route":"fe80::212:4b00:b23:1102","RSSI (dBm)":-38,"On-Chip Temp (mC)":29,"Volt (mV)":3273}}
    {"d":{"Platform":"cc26x0-cc13x0","Board":"sensortag/cc2650","Seq #":4,"Uptime (sec)":143,"Def Route":"fe80::212:4b00:b23:1102","RSSI (dBm)":-36,"On-Chip Temp (mC)":29,"Volt (mV)":3273}}
    
  5. 在RPI打开另一窗口,我们运行如下命令,发送修改sensor tag灯状态的命令
    mosquitto_pub –h bbbb::ba27:ebff:fe91:106 –m “1” -t iot-2/evt/leds/fmt/json
    mosquitto_pub –h bbbb::ba27:ebff:fe91:106 –m “0” -t iot-2/evt/leds/fmt/json
    
    这个时候,我们应当看到sensortag的红色的灯根据我们消息的不同,变换亮灭。

一些坑:

  1. 尝试直接利用主机连接CC2650 launch pad,但是主机设置桥接网卡存在一些问题,因此在RPI上测试了。如果桥接网卡测试成功,也是可以直接把RPI替换的。
  2. 通过6lbr这个服务器来搭建的实验一直没有成功,所以就改成了利用原生的rpl-border-router来测试。问了超多问题在这个issue里面,尝试很多方式,还是没有成功can not set the configurations on mqtt of cc26xx-web-demo, get bad request,希望基于目前完成的部分,以后有需要再研究吧。
Contents
  1. 1. 获取contiki-ng项目
  2. 2. 烧写在RPI上的rpl-border-router
  3. 3. 烧写在CC2650 launch pad上的slip-radio
  4. 4. 烧写在CC2650 sensortag中的MQTT client
  5. 5. 验证结果