イベント/トリガーを定期的にチェックするためのよりエレガントな方法はありますか?

szantaii

私はパッシブ赤外線センサーを持っていて、動きに基づいてディスプレイのオンとオフを切り替えたいと思っていました。たとえば、5分間動きがない場合は、電力を節約するためにディスプレイをオフにする必要があります。ただし、動きがある場合は、ディスプレイをオフにしたり、オンに戻したりしないでください。(スクリーンセーバーがこれに適していない理由を聞かないでください。私が作成しているデバイスにはキーボードやマウスがありません。スタンドアロンディスプレイのみになります。)

私のアイデアは、プロデューサーとコンシューマーの2つのスレッドを作成することでした。プロデューサースレッド(PIRセンサー)はメッセージをキューに入れ、コンシューマー(ディスプレイを制御する)が読み取ります。このようにして、ある信号から別の信号を送信できます。

以下に完全に機能するコードがあります(説明付き)。これで前述の内容が完成します。私の質問は、これをよりエレガントな方法で達成する方法はあるのでしょうか?私のアプローチについてどう思いますか、大丈夫ですか、ハックですか?

#!/usr/bin/env python

import Queue
from threading import Thread
import RPi.GPIO as gpio
import time
import os
import sys

class PIRSensor:

    # PIR sensor's states
    current_state = 0
    previous_state = 0

    def __init__(self, pir_pin, timeout):
        # PIR GPIO pin
        self.pir_pin = pir_pin
        # Timeout between motion detections
        self.timeout = timeout

    def setup(self):
        gpio.setmode(gpio.BCM)
        gpio.setup(self.pir_pin, gpio.IN)
        # Wait for the PIR sensor to settle
        # (loop until PIR output is 0)
        while gpio.input(self.pir_pin) == 1:
            self.current_state = 0

    def report_motion(self, queue):
        try:
            self.setup()

            while True:
                self.current_state = gpio.input(self.pir_pin)

                if self.current_state == 1 and self.previous_state == 0:
                    # PIR sensor is triggered
                    queue.put(True)
                    # Record previous state
                    self.previous_state = 1
                elif self.current_state == 1 and self.previous_state == 1:
                    # Feed the queue since there is still motion
                    queue.put(True)
                elif self.current_state == 0 and self.previous_state == 1:
                    # PIR sensor has returned to ready state
                    self.previous_state = 0

                time.sleep(self.timeout)
        except KeyboardInterrupt:
            raise

class DisplayControl:

    # Display's status
    display_on = True

    def __init__(self, timeout):
        self.timeout = timeout

    def turn_off(self):
        # Turn off the display
        if self.display_on:
            os.system("/opt/vc/bin/tvservice -o > /dev/null 2>&1")
            self.display_on = False

    def turn_on(self):
        # Turn on the display
        if not self.display_on:
            os.system("{ /opt/vc/bin/tvservice -p && chvt 9 && chvt 7 ; } > /dev/null 2>&1")
            self.display_on = True

    def check_motion(self, queue):
        try:
            while True:
                try:
                    motion = queue.get(True, self.timeout)

                    if motion:
                        self.turn_on()
                except Queue.Empty:
                        self.turn_off()
        except KeyboardInterrupt:
            raise

if __name__ == "__main__":
    try:
        pir_sensor = PIRSensor(7, 0.25)
        display_control = DisplayControl(300)
        queue = Queue.Queue()

        producer = Thread(target=pir_sensor.report_motion, args=(queue,))
        consumer = Thread(target=display_control.check_motion, args=(queue,))

        producer.daemon = True
        consumer.daemon = True

        producer.start()
        consumer.start()

        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        display_control.turn_on()
        # Reset GPIO settings
        gpio.cleanup()
        sys.exit(0)

プロデューサースレッドreport_motionは、PIRSensorクラスインスタンスの関数()を実行します。PIRSensorクラスは、パッシブ赤外線センサーの状態を1秒間に4回読み取り、動きを感知するとメッセージをキューに入れます。

コンシューマースレッドcheck_motionは、DisplayControlクラスインスタンスの)の関数を実行します。所定のタイムアウトでブロッキングモードで前述のキューを読み取ります。次のことが発生する可能性があります。

  • ディスプレイがオンで、一定時間キューにメッセージがない場合、つまりタイムアウトが期限切れになると、コンシューマスレッドはディスプレイの電源をオフにします。
  • ディスプレイがオフでメッセージが表示されると、スレッドはディスプレイの電源をオンにします。
ヨルゲン

それは良い解決策だと思います。その理由は、異なるクラスの関心を分離したためです。1つのクラスがPIRセンサーを処理します。1つはディスプレイを処理します。あなたは今日、それらをキューで接着します。それが1つのアプローチです。

これを行うことにより、さまざまなクラスを簡単にテストできます。

これを拡張するには(読んで拡張可能にする)、コントローラーを導入することができます。コントローラは(キューからなど)イベントを取得し、イベントに基づいて動作します(たとえば、ディスプレイコントローラにディスプレイをオフにするように指示します)。コントローラーはセンサーについて知っており、ディスプレイについて知っています。ただし、センサーはディスプレイについて認識してはなりません。その逆も同様です。(これはMVCと非常によく似ており、この場合、データはモデル(センサー)であり、ディスプレイはビューであり、コントローラーはその間にあります。

このアプローチにより、設計はテスト可能、拡張可能、保守可能になります。そして、それによってあなたはハックではなく、実際のコードを書いています。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

フォームのデフォルト値をチェックするためのよりエレガントな方法はありますか?

分類Dev

HTMLチェックボックスがオフになったときにJavaScriptでイベントをトリガーする方法はありますか?

分類Dev

freemarkerで変数をチェックするよりエレガントな方法はありますか?

分類Dev

CUDAでmallocおよびfreeするためのより良い/よりクリーンな/よりエレガントな方法はありますか?

分類Dev

マップからリストを埋めるためのよりエレガントなソリューションはありますか?

分類Dev

コードブロックを再利用するためのよりエレガントな方法はありますか?

分類Dev

部分文字列を作成するためのよりエレガントな方法はありますか?

分類Dev

typescriptに値オブジェクトを含めるエレガントな方法はありますか?

分類Dev

このLCM関数を書くためのよりクリーンでエレガントなHaskellの方法はありますか?

分類Dev

golangの他のゴルーチンを一時停止および再開するためのエレガントな方法はありますか?

分類Dev

Pythonで辞書ループ例外を処理するためのより良いまたはよりエレガントな方法はありますか?

分類Dev

このタイプの順列のためのよりエレガントな方法はありますか?

分類Dev

アナグラムをチェックするためのよりエレガントな方法は何ですか?

分類Dev

オブジェクトのタイプがタイプのリストに属しているかどうかをチェックするエレガントな方法はありますか?

分類Dev

エラーを克服するためのよりエレガントな方法は何ですか:オブジェクト指定子を期待しています。JXA経由でメッセージ経由でSMSを送信する場合、引数にはオブジェクト指定子がありません

分類Dev

これらの条件を書くためのよりエレガントな方法はありますか?

分類Dev

これを書くためのより短く/エレガント/効率的な方法はありますか?

分類Dev

Python:部分文字列がリストにあるかどうかをチェックするためのエレガントなソリューション?

分類Dev

コレクションをグループ化するための単一行削減のこのハッキーな実装を回避するためのよりエレガントな方法はありますか?

分類Dev

React Nativeでさまざまなコンポーネントを条件付きでレンダリングするためのより良いまたはよりエレガントな方法はありますか?

分類Dev

このビルダーをコーディングするためのよりエレガントな方法はありますか?

分類Dev

サーバーからフェッチされたmd5ファイルを使用してansibleでmd5とファイルの整合性をチェックするエレガントな方法はありますか?

分類Dev

Swiftでこの遅延読み込みパターンを作成するためのよりエレガントな方法はありますか?

分類Dev

pyqt5チェックされているチェックボックスに応じて、ボタンの機能を変更するよりエレガントな方法はありますか?

分類Dev

実行時にジョブ番号にアクセスするためのよりエレガントな方法はありますか?

分類Dev

AutoItでInternetExpolorバージョンを入手するためのよりエレガントな方法はありますか?

分類Dev

スクリプトにデータを送信するためのよりエレガントなボタン

分類Dev

ヌルチェックを処理するためのよりクリーンな方法はありますか?変数のテストは存在しますか?

分類Dev

nilをチェックし、同時に変数に割り当てるエレガントな方法はありますか?

Related 関連記事

  1. 1

    フォームのデフォルト値をチェックするためのよりエレガントな方法はありますか?

  2. 2

    HTMLチェックボックスがオフになったときにJavaScriptでイベントをトリガーする方法はありますか?

  3. 3

    freemarkerで変数をチェックするよりエレガントな方法はありますか?

  4. 4

    CUDAでmallocおよびfreeするためのより良い/よりクリーンな/よりエレガントな方法はありますか?

  5. 5

    マップからリストを埋めるためのよりエレガントなソリューションはありますか?

  6. 6

    コードブロックを再利用するためのよりエレガントな方法はありますか?

  7. 7

    部分文字列を作成するためのよりエレガントな方法はありますか?

  8. 8

    typescriptに値オブジェクトを含めるエレガントな方法はありますか?

  9. 9

    このLCM関数を書くためのよりクリーンでエレガントなHaskellの方法はありますか?

  10. 10

    golangの他のゴルーチンを一時停止および再開するためのエレガントな方法はありますか?

  11. 11

    Pythonで辞書ループ例外を処理するためのより良いまたはよりエレガントな方法はありますか?

  12. 12

    このタイプの順列のためのよりエレガントな方法はありますか?

  13. 13

    アナグラムをチェックするためのよりエレガントな方法は何ですか?

  14. 14

    オブジェクトのタイプがタイプのリストに属しているかどうかをチェックするエレガントな方法はありますか?

  15. 15

    エラーを克服するためのよりエレガントな方法は何ですか:オブジェクト指定子を期待しています。JXA経由でメッセージ経由でSMSを送信する場合、引数にはオブジェクト指定子がありません

  16. 16

    これらの条件を書くためのよりエレガントな方法はありますか?

  17. 17

    これを書くためのより短く/エレガント/効率的な方法はありますか?

  18. 18

    Python:部分文字列がリストにあるかどうかをチェックするためのエレガントなソリューション?

  19. 19

    コレクションをグループ化するための単一行削減のこのハッキーな実装を回避するためのよりエレガントな方法はありますか?

  20. 20

    React Nativeでさまざまなコンポーネントを条件付きでレンダリングするためのより良いまたはよりエレガントな方法はありますか?

  21. 21

    このビルダーをコーディングするためのよりエレガントな方法はありますか?

  22. 22

    サーバーからフェッチされたmd5ファイルを使用してansibleでmd5とファイルの整合性をチェックするエレガントな方法はありますか?

  23. 23

    Swiftでこの遅延読み込みパターンを作成するためのよりエレガントな方法はありますか?

  24. 24

    pyqt5チェックされているチェックボックスに応じて、ボタンの機能を変更するよりエレガントな方法はありますか?

  25. 25

    実行時にジョブ番号にアクセスするためのよりエレガントな方法はありますか?

  26. 26

    AutoItでInternetExpolorバージョンを入手するためのよりエレガントな方法はありますか?

  27. 27

    スクリプトにデータを送信するためのよりエレガントなボタン

  28. 28

    ヌルチェックを処理するためのよりクリーンな方法はありますか?変数のテストは存在しますか?

  29. 29

    nilをチェックし、同時に変数に割り当てるエレガントな方法はありますか?

ホットタグ

アーカイブ