Raspberry上でPythonでBlynkと同時に他の処理をさせてみた(threadingを使って実現)

背景

Raspberry上でIOTのツールを作成しているが、Blynkと同時に他の処理(ディスプレイの表示とか、時計を使った処理とか、タイマーを使った処理とか)を行おうとすると、なかなかうまくいかない。

ArduinoでCを使って Blynkを使う時には、

void loop()
{
  Blynk.run();
  timer.run();
  yield();
}

のような記述で、Blynk.run()を走らせながら、他の処理もLoopとして回すことが簡単にできるのに対し、PythonでBlynkを使う時に、Blynk.run()を実行すると、この関数からは永遠に戻ってこないため、ループが作れない。

これは仕様っぽくて、確かにBlynkを使ったPythonの参考例(githubのここ)を見ても、”# Start Blynk (this call should never return)”というコメントが記載されている。要するに、行ったきりなので、何か他の事をループとしてやらせようとすると、Threadを使って、別プロセスとして起動することが必要っぽい。

Google検索で、調べてみても、海外の投稿の中に、色々やってみたけど、PythonのBlynkは、ArduinoのBlynkに比べて、そういうのが未成熟という記述があり、「代わりに、MQTTを使ったらうまくいくよ」という内容の結論で終わっていた。

追記:

別の記事を見ていたら、このサイトに、Threadを使って、BlynkをPythonから使う例が掲載されていた。今晩試してみることにする。タイマーでの1秒毎の処理と、BlynkのVirtual Writeをthreadで走らせる形。

うまく出来た。

このサイトのやり方を真似て、threadingを使ったら、すぐにうまく出来た。なぁーんだ。

t2のThreadがユーザープログラムなので、ここで好きなプログラムを書けば、Blynk.run()が動いている状態で、問題なく動作させることができる。sleep()で待とうが、グリグリとloopを回そうが、自由にthreadで動かせる。

ここでは、一秒毎に、GPIOをトグルして、かつVirtual Pinに ms() //1000の値を送ることが出来ている。当然、スマホのBlynkアプリからのVirtual Writeに対しても問題なく反応している。

#!/usr/bin/python3
# using thread with another way
#
import BlynkLib
import time
from time import sleep
import RPi.GPIO as GPIO
import threading

BLYNK_AUTH = 'b7*****************************1c'

GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.OUT)
pin24 = True

blynk = BlynkLib.Blynk(BLYNK_AUTH)

def my_user_task():
    global pin24
    value=0
    while True:
        blynk.virtual_write(4, str(value))
        value += 1
        blynk.virtual_write(5, time.ticks_ms() //1000)
        if pin24 == True:
            pin24 = False
        else:
            pin24 = True
        GPIO.output(24, pin24)
        sleep(1)

def startBlynk():
    blynk.run() # never returns

@blynk.VIRTUAL_WRITE(1)
def my_write_handler(value):
    pass

@blynk.VIRTUAL_WRITE(0)
def my_write_handler(value):
    if value == '1':
        GPIO.output(24, True)
    else:
        GPIO.output(24, False)

if __name__ == "__main__":
    th1 = threading.Thread(name='blynk', target=startBlynk)
    th2 = threading.Thread(name='user_task', target=my_user_task)
    th1.start()  #start Blynk. blynk.run() never returns but it does not block the user task.
    th2.start()

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください