@uhpa (村瀬 陽一)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【ご教示願います】WebからラズパイのLEDを制御する方法について

解決したいこと

blynk2.0をbullseyeベースのRaspberry Pi OSで正式には使えないこと、をQiitaにてご教示頂き、それでは、Webから制御したい、考え、以下の情報を参照し、その追加仕様の実現を進めていますが、実現できず=試行錯誤しております。
ご知見のある方は、対応方法をご教示頂けませんでしょうか。

参照情報

自身が試した追加仕様

①Webブラウザでに、以下のようなラジオボタンを作り、ラズパイに接続したLEDの制御をする
image.png
②各ラジオボタンが押されたら、直ちに、押された状態にLEDの状態が変更となる
*場合の例は以下の通り
 場合1:LEDが消灯していて、ラジオボタンLED点灯が押されたらLEDが点灯
 場合2:LEDが消灯していて、ラジオボタンLED点滅が押されたらLEDが点滅、その後、ラジオボタンLED点灯が押されたらLEDが点灯)

実現できていないこと

場合2において、LEDが点滅中に、ラジオボタンLED点灯が押した場合に、直ちにLEDを点灯とならない。
 →ラジオボタンLED点灯が押しても、点滅の5回が継続し、LEDが消灯してから、再び、ラジオボタンLED点灯が押すとLEDは点灯する、といった動作をすることもある(ラジオボタンを押すタイミングでも幾つかの状態を確認)

*LEDの5回の点滅が完了してからラジオボタンLED点灯が押した場合は、LEDを点灯と、正しい動作。
*ラジオボタンLEDの点灯とラジオボタンLEDの消灯の2つみであれば、LEDの点灯と消灯は、即座になされる、正しい動作。

該当するソースコード /home/pi/wsgi/led.py

import RPi.GPIO as GPIO
from urllib.parse import parse_qs
import time
 
GPIO.setmode(GPIO.BCM) # GPIO番号で指定
GPIO.setup(21, GPIO.OUT)

def set_led(v):
    if v==1:
        GPIO.output(21, GPIO.HIGH)
    elif v==2:
        for i in range(5):
            GPIO.output(21, GPIO.HIGH)
            time.sleep(0.5)
            GPIO.output(21, GPIO.LOW)
            time.sleep(0.5)
    else:
        GPIO.output(21, GPIO.LOW)
       
def application(env, start_response):
  start_response('200 OK', [('Content-Type', 'text/plain; charset=UTF-8')])
  form = parse_qs(env['QUERY_STRING'])
  print(form)
  if 'v' not in form:
    set_led(0)
    return [b'0']
  else:
    v = int(form['v'][0])
    set_led(v)
    return [str(v).encode()]

該当するソースコード /var/www/html.led.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>LED</title>
  <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
</head>
<body>
  <p><input type="radio" id="led_on" name="led" value="1" onclick="set_led(1)" />LED点灯</p>
  <p><input type="radio" id="led_blink" name="led" value="2" onclick="set_led(2)" />LED点滅</p>
  <p><input type="radio" id="led_off" name="led" value="0" onclick="set_led(0)" />LED消灯</p>
  <script type="text/javascript">
    function set_led(v) {
      $.get("/wsgi/led.py?v=" + v);
    }
    window.onload = function() {
        set_led(0);
        document.getElementById("led_off").checked = true;
    };
  </script>
</body>
</html>

自分で試したこと

その他、以下のようなプログラムを試しましたが、うまくいっていません。

import RPi.GPIO as GPIO
from urllib.parse import parse_qs
import time
 
GPIO.setmode(GPIO.BCM) # GPIO番号で指定
GPIO.setup(21, GPIO.OUT)

led_blink = False

def set_led(v):
    global led_blink
    if v == 1:
        GPIO.output(21, GPIO.HIGH)
        led_blink = False
    elif v == 2:
        led_blink = True
        for i in range(5):
            if led_blink:
                GPIO.output(21, GPIO.HIGH)
                time.sleep(0.5)
                GPIO.output(21, GPIO.LOW)
                time.sleep(0.5)
    else:
        GPIO.output(21, GPIO.LOW)
        led_blink = False
       
def application(env, start_response):
  start_response('200 OK', [('Content-Type', 'text/plain; charset=UTF-8')])
  form = parse_qs(env['QUERY_STRING'])
  if 'v' not in form:
    set_led(0)
    return [b'0']
  else:
    v = int(form['v'][0])
    set_led(v)
    return [str(v).encode()]

以上

0 likes

2Answer

wsgiはまったく詳しくないのですが。。。

以下、コメント追記により取り消し:

そもそも論で、点滅中はapplication(env, start_response)が5秒間ブロックしている(すなわち、set_led(v)が5秒間ブロックしている)んじゃないですかね?

恐らく、単なるPythonアプリケーションであっても、(同じ構造なら)同じ動きになると思います。

1Like

Comments

  1. @uhpa

    Questioner

    imagou様
    ご連絡ありがとうございます。
    参考情報で示した情報をもとに、少しづつ勉強している段階でして、imagou様のご指摘も十分に理解していません。
    もう少し、自身で勉強せねば、ならない、と考えております。
  2. すみません、ブロックという言い方に馴染みがなかったかもしれません。

    要は、application関数(というかset_led関数)が先発・後発でどのように動作しているのか(先発が終わるまで待つのか、平行駆動するのか)が確認できればよいかと。

    (平行駆動しなきゃWEBシステムとして破綻しているのですが、書かれている動作からすると待っているようにも見えてしまいます。ということで初回の回答となった次第。)

    別のLEDがあるとスンナリ解析できそうですが、いかがですか?
  3. @uhpa

    Questioner

    imagou様
    追加のご連絡ありがとうございます。

    ご指摘の点で確認してみます。

簡易ログ出力サンプルです。
/tmp/mylogに時刻付きで出力されますので、こっちのほうが簡単かもしれません(そちらの環境で「期待通りに」動くかは不明ですが)。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging

logging.basicConfig(
    level=logging.DEBUG,
    filename="/tmp/mylog",
    format="%(asctime)s:%(levelname)s:%(message)s"
)
logger = logging.getLogger(__name__)

num = 1
logger.debug("Number is %d", num)

str = "test"
logger.debug("String is %s", str)
0Like

Your answer might help someone💌