トマトの液肥を離れた所から制御してみる

IMG_5727.jpeg

ミニビニールハウスでトマトを栽培しています。

そのトマトに液肥を与える作業をリモート制御したり、自動化したりするための仕組みを試作してみました。

IMG_5728.jpeg

内容としては、

(1)液肥は予め作成してタンクに入れておく

(2)タンクからトマトへの給水には、DC12Vの簡易な安いポンプを使う

(3)離れた場所からポンプのオン・オフを行う

(4)指定したスケジュールでオン・オフができる

といったものを目指します。

前提としてLoRaWANの利用ができていることが必要です。


離れた所からポンプのオン・オフを行うために、無線通信でオンとオフを切替制御できる機器が必要です。

ここにはDragino社のLT-22222-Lという機器を使用します。

下の写真で青い機器がLT-22222-Lです。

IMG_5684.jpeg

この機器にはリレー出力端子が2ポートありますので、そのうちの1つを使ってポンプを制御します。

写真ではポンプが2つ入っていますが下側の細いチューブが繋がっている方になります。

IMG_5729.jpeg

使用しているLoRaWANの無線通信では、機器からサーバへのデータ通信はアップリンク、サーバから機器への通信はダウンリンクと呼びます。

今回のリレー制御はこのダウンリンクを使ってサーバからON /OFFの切替メッセージを送ることによって実行されます。

ダウンリンクのメッセージ送信はLoRaWANのコンソール画面(The Things Stack のコンソール画面)から送信することも可能ですがコンソール画面を開いてコマンドを入力するのは手間が掛かりますので、専用のWebページやアプリなどから簡単に出来るようにしたいと思いました。

下の画面がコンソールのメッセージ送信の画面です。ここでペイロードにコマンドを入力して送信することができます。

スクリーンショット 2022-05-10 17.54.05.png


The Things Stackではメッセージの送信をMQTTやWebhookなどを利用して外部サービスから操作できるようになっています。

今回のシステムではMQTTを使用してメッセージ送信を行うようにしました。

TTSが提供しているMQTTサーバに対してSubscribeすると機器からのアップリンクメッセージが取得できます。

Publishでメッセージを送信するとダウンリンクのメッセージになります。

TTSのMQTTサーバについては以下のリンクから参照してください。

https://www.thethingsindustries.com/docs/integrations/mqtt/

MQTTサーバのアドレスや接続認証情報、APIキーの生成などはコンソールのアプリケーションでインテグレーションからMQTTを選択すると確認できます。

スクリーンショット 2022-05-10 17.29.11.png

MQTTサーバとのメッセージ通信には色々な方法がありますが、今回はWeb経由で制御をしたいということでWebサーバを作成してそこからMQTTメッセージ処理を行うようにしました。

具体的には、Node.jsというJavaScriptベースのWebアプリケーション構築プラットフォームを使ってWebアプリケーションを作成しました。

PublishのためのJavaScriptコードは以下のようになっています。このサンプルはMQTTサーバに接続したら1回だけダウンリンクのメッセージを送ります。

const mqtt = require('mqtt')

const host = 'au1.cloud.thethings.network'

const port = '1883'

const clientId = 'niigata-ttn-test'

const credentials = 'app1@ttn'

const key = 'NNSXS.VNADRI..........CWJ7CUKSWA'

const connectUrl = `mqtt://${host}:${port}`

 

const client = mqtt.connect(connectUrl, {

 clientId,

 clean: true,

 connectTimeout: 4000,

 username: credentials,

 password: key,

 reconnectPeriod: 1000,

})

 

const topic_up = 'v3/app1@ttn/devices/{deviceId}/up'

const topic_push = 'v3/app1@ttn/devices/{deviceId}/down/push'

client.on('connect', () => {

 console.log('Connected')

 client.publish(topic_push, JSON.stringify({

  "downlinks": [{

  "f_port": 15,

  "frm_payload": "AwER",

  "priority": "NORMAL",

  "confirmed": true

 }]}), {},(error) => {

   console.log(`Publish to topic '${topic_push}'`)

   if (error) {

     console.log(error)

   }

  })

})

 

client.on('message', (topic, payload) => {

 console.log('Received Message:', topic, payload.toString())

})


 


MQTTでダウンリンクメッセージを送ることが確認できたので、次にWebアプリケーションを作成して、ブラウザやHttpクライアントからのリクエストに応じてMQTTメッセージを送れるようにします。

JavaScriptのコードにWebアプリケーションの機能を追加します。

const mqtt = require('mqtt')

const ejs = require('ejs')

const host = 'au1.cloud.thethings.network'

const port = '1883'

const clientId = 'niigata-ttn-test'

const credentials = 'app1@ttn'

 

const key = 'NNSXS.VNADRI..........CWJ7CUKSWA'

 

const connectUrl = `mqtt://${host}:${port}`

 

const client = mqtt.connect(connectUrl, {clientId,clean: true,connectTimeout: 4000,username: credentials,password: key,reconnectPeriod: 1000,

})

 

const topic_up = 'v3/app1@ttn/devices/{deviceId}/up'

const topic_push = 'v3/app1@ttn/devices/{deviceId}/down/push'

client.on('connect', () => {

  console.log('Connected')

  client.subscribe([topic_up], () => {

  console.log(`Subscribe to topic '${topic_up}'`)

  })

})

 

client.on('message', (topic, payload) => {

  console.log('Received Message:', topic, payload.toString())

})

 

/** Webサーバの生成 */

var hostname = '127.0.0.1'

var http_port = 8080

var server = http.createServer()

/** */

server.on('request', function(req, res) {

  req.setEncoding('utf-8')

  req.on('data',function(chunk){

    console.log(chunk)

 })

 var url_parse = url.parse(req.url)

 console.log("req:" + url_parse.query)

 if (url_parse.pathname === "/test" && req.method === "GET") {

    res.writeHead(200, {"Content-Type": "text/html"});

    var querys = url_parse.query.split('&')

    var payload_msg = ""

    var html_msg = ""

    var params = querys[0].split('=')

    if (params[1] == '0') {

        payload_msg = "AwAR"

        html_msg = "<h1>Relay OFF !!</h1>"

    } else {

        payload_msg = "AwER"

        html_msg = "<h1>Relay ON !!</h1>"

    }

    client.publish(topic_push,

    JSON.stringify({"downlinks": [{"f_port": 15,"frm_payload": payload_msg,"priority": "NORMAL","confirmed": true}]}),{},

    (error) => {

        console.log(`Publish to topic '${topic_push}'`). 

        if (error) {

            console.log(error)

        }

    })

  const responseMessage = html_msg;

  res.write(responseMessage);

  res.end();

  console.log(`Sent a response : ${responseMessage}`);

}

});

 

/** */

server.listen(http_port, function() {//サーバ起動時に呼ばれる

    console.log(`Server runnning at http://${hostname}:${http_port}/`);

});

/** */

 

上のサンプルではHttpクライアントからGETでhttp://127.0.0.1:8080/test?relay1=1というURLにアクセスするとリレーをONするダウンリンクメッセージがMQTTサーバへ送信されます。

http://127.0.0.1:8080/test?relay1=0にアクセスするとOFFのメッセージが送信されます。

サンプルではlocalhostで動かしているので外部からはアクセス出来ませんが、クラウドサーバや公開サーバで動かすようにすればどこからでもリモート制御できるようになります。

但しその場合は不正アクセスされないように注意してください。

NodeJSのサーバを起動してブラウザからGETリクエストすると、リクエストを処理してダウンリンクメッセージが送信されました。

IMG_5721.jpeg

TTSコンソールでメッセージを確認。

IMG_5722.jpeg


PCを開いてブラウザからアクセスするかわりにボタンSWを押すだけで同じ事ができるようにラズパイを使って試作してみました。

IMG_5724.jpeg

ラズパイにブレッドボードに作成した押しボタンとLEDの回路を接続してあります。

pythonプログラムを作成して、押しボタンの状態を読み取るようにします。

緑のボタンを押すとリレーをONにするGETリクエストを送信してLEDを点灯、黒のボタンを押すとOFFのGETリクエストを送信してLEDを消灯します。


現状はここまでですが、Webアプリケーションに機能を追加して、スケジュール設定してONとOFFを実行するなど便利にしたいと考えています。