EMQをラズベリーパイで使ってみる

# はじめに
AWS IoT Core、mosquitoなどなど様々なMQTTブローカーが存在しますが、今回はEMQXとラズベリーパイでMQTT通信を試してみたいと思います。

こちらの内容を少し抜き出し・追記した内容になります。

https://www.emqx.com/ja/blog/use-mqtt-with-raspberry-pi

# 準備
機材：ラズベリーパイ 3b+
wifi,SSHにてアクセスできるように準備済み。

```
 $ python3 --version 
Python 3.9.2
```

```
 $ pip --version
pip 20.3.4 from /usr/lib/python3/dist-packages/pip (python 3.9)
```

# Paho Pythonライブラリをインストール

gitがなければ
```
$ sudo apt-get install git-all
```

```
git clone https://github.com/eclipse/paho.mqtt.python 
cd paho.mqtt.python 
python3 setup.py install
```

```
pip install paho-mqtt
```

# 接続確認
まずは接続確認してみましょう。

```python
# test_connect.py 
import paho.mqtt.client as mqtt 

# The callback function. It will be triggered when trying to connect to the MQTT broker
# client is the client instance connected this time
# userdata is users' information, usually empty. If it is needed, you can set it through user_data_set function.
# flags save the dictionary of broker response flag.
# rc is the response code.
# Generally, we only need to pay attention to whether the response code is 0.
def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connected success")
    else:
        print(f"Connected fail with code {rc}")

client = mqtt.Client() 
client.on_connect = on_connect 
client.connect("broker.emqx.io", 1883, 60) 
client.loop_forever()

```

## 結果

```
Connected success
```


##   AttributeError: 'Client' object has no attribute '_on_pre_connect'　というエラーが出る場合

pip3とpipが競合している可能性があります。


### Paho MQTTライブラリのアップデート

```
pip install --upgrade paho-mqtt
```

### ライブラリの再インストール

```
pip uninstall paho-mqtt
pip install paho-mqtt
```


# MQTTブローカーの準備
いくつか方法はありますが、今回はテストなので無料テストクライアントを使います。

https://www.emqx.com/en/mqtt/public-mqtt5-broker

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/8fb73892-509f-ddf7-a904-3b8173d191af.png)

# サブスクライブしてみる(サーバー→デバイス)

## トピック作成

`raspberry/topic`というトピックを作成しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/33078669-dd9c-cd24-d530-f5b109d09ef5.png)

## コード作成
ラズベリーパイで下記ファイルを作成してください。

```python
# subscriber.py
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")
    # Subscribe, which need to put into on_connect
    # If reconnect after losing the connection with the broker, it will continue to subscribe to the raspberry/topic topic
    client.subscribe("raspberry/topic")

# The callback function, it will be triggered when receiving messages
def on_message(client, userdata, msg):
    print(f"{msg.topic} {msg.payload}")

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

# Set the will message, when the Raspberry Pi is powered off, or the network is interrupted abnormally, it will send the will message to other clients
client.will_set('raspberry/status', b'{"status": "Off"}')

# Create connection, the three parameters are broker address, broker port number, and keep-alive time respectively
client.connect("broker.emqx.io", 1883, 60)

# Set the network loop blocking, it will not actively end the program before calling disconnect() or the program crash
client.loop_forever()

```

## 実行

①`subscriber.py`を実行します

```
$ /bin/python3 /home/NariPi/paho.mqtt.python/subscriber.py
Connected with result code 0
```

②トピックを入力した上で適当なメッセージを送信します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/4c8e559f-ff75-d2a3-5a65-92c2187308ce.png)

③メッセージが受信される

```
Connected with result code 0
raspberry/topic b'{\n  "msg": "hello pi!"\n}'
```

※自分が送信していないメッセージが送られてきますが、こちらはサンプルトピックなので他人が送信しているメッセージかと思われます。※

# パブリッシュしてみる(デバイス→サーバー)

```python
import paho.mqtt.client as mqtt
import time

def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")

    # Send a message to the raspberry/topic every 1 second, 5 times in a row
    for i in range(5):
        # The four parameters are topic, sending content, QoS and whether retaining the message respectively
        client.publish('raspberry/topic', payload=i, qos=0, retain=False)
        print(f"send {i} to raspberry/topic")

client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.emqx.io", 1883, 60)

client.loop_forever()

```

## 実行

実行するとトピックにこのようなメッセージが送信されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/66703b13-4352-3974-de1d-e8ad687cbeb6.png)