Ruby で MQTT(MQTTS) で動かしてみる

前回、Deno でMQTT(MQTTS) を試していたら Ruby はどうなのかということが気になった。
なので、確認しておく。

参考

実装

とりあえず導入

1
$ gem install mqtt

実装は次の通り。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
require 'mqtt'

client = MQTT::Client.new("mqtts://localhost:8883")
client.username = "user1"
client.password = "XXXXX"
client.cert_file = './certs/client.crt'
client.key_file = './certs/client.key'
client.ca_file = './certs/localhost.crt'
client.connect()

client.subscribe( 'topic/1' )

# ブロックで、受信処理させると、publishができない
client.get do |topic,message|
p "topic: #{topic}, message: #{message}"
end

loop do
sleep 1
client.publish("topic/2", "from publish2 on ruby", )
end

とここで問題なのが、client.get が後続の処理をブロックしてしまうために、一向に publish が呼ばれない。
ブロックではない client.get も受信を待ってしまう。
JSのような、1プロセスで送受信を非同期に行うのは少々苦しいものでした。

この辺りは、言語の特性めいたものを感じます。

Thread で、送信/受信を並列化

Thread を使って、受信側を別スレッドで操作させると次のようになる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
require 'mqtt'

client = MQTT::Client.new("mqtts://localhost:8883")
client.username = "user1"
client.password = "XXXXX"
client.cert_file = './certs/client.crt'
client.key_file = './certs/client.key'
client.ca_file = './certs/localhost.crt'
client.connect()

client.subscribe( 'topic/1' )

Thread.new do
client.get do |topic,message|
p "topic: #{topic}, message: #{message}"
end
end

loop do
sleep 1
client.publish("topic/2", "from publish2 on ruby")
end

本来欲しかった動作をするようになりました。

Ractor でもできないものかとトライしてみましたが、用途違いの感じ。


MQTTS を Ruby 使ってみた。
送受信を両方できるようにするところで、スレッドを使うであるとかの手段を取る必要があるのはポイント。

PahoMqtt は MQTT.js ライクに記述ができそう。
しかし5年メンテもされていないようなので、積極的に使う必要は無さそうです。

では。