2012-01-23 8 views
1

私が取り組んでいるコードでは、GUIアプリケーション内で(音楽を再生する)機能を起動するために、シリアルポートイベント(コンタクトスイッチとピン5と8を接続する)を使用する必要があります。私は、シリアルポートを監視するためのループを作成し、これをpygtk GUIとは別のスレッド内で実行させます。スレッドループを閉じる

私はこれをコマンドラインからテストします。 GUIが閉じられると、監視スレッドはすぐに終了しません。イベントがトリガされるまで(コンタクトスイッチが押された)、それは再び閉じられます。

プログラムを正しく閉じるためにユーザーがスイッチを押す必要はありません!

コードの簡易版は、次のとおりです。

#!/usr/bin/python2 

import sys 
import subprocess 
import pygtk 
pygtk.require('2.0') 
import gtk 
import threading 
import gobject 
from serial import Serial 
from fcntl import ioctl 
from termios import (
    TIOCMIWAIT, 
    TIOCM_RNG, 
    TIOCM_DSR, 
    TIOCM_CD, 
    TIOCM_CTS 
) 

ser = Serial('/dev/ttyS0') 
wait_signals = (TIOCM_RNG | 
       TIOCM_DSR | 
       TIOCM_CD | 
       TIOCM_CTS) 

def startplaying(): 
    #for testing 
    print('Start playing the track!') 

gobject.threads_init() 

class SerialWatch(threading.Thread): 

    def __init__(self): 
     super(SerialWatch, self).__init__() 
     self._stop = threading.Event() 

    def run(self): 
     if __name__ == '__main__': 
      while not self._stop.isSet(): 
       ioctl(ser.fd, TIOCMIWAIT, wait_signals) 
       startplaying() 

    def stop(self): 
     self._stop.set() 

    def stopped(self): 
     return self._stop.isSet() 

class MusicManager(): 

    def delete_event(self, widget, event, data=None): 
     return False 

    def destroy(self, widget, data=None): 
     gtk.main_quit() 

    def __init__(self): 
     self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) 
     self.window.connect("delete_event", self.delete_event) 
     self.window.connect("destroy", self.destroy) 
     self.window.show_all()  

    def main(self): 
     gtk.main() 

sw = SerialWatch() 
sw.start() 

print __name__ 
if __name__ == "__main__": 
    music_manager = MusicManager() 
    music_manager.main() 

sw.stop() 

私は経験豊富なプログラマーではないですし、これで任意の助けをいただければ幸いです。私はsmichakが示唆したように、ポーリングを使用したくなかった

:この記事を見つけて、私は私が望んでいたように動作するように物事を得た方法に興味があるかもしれません誰のために

+0

ここで私が以前投稿した答えは間違っていました。問題は、あなたのスレッドがioctl上でブロックして、シリアルライン上のステータス変更を待つことです。 TIOCMGETを使用してシリアルポートのステータスビットを読み込み、ioctlからすぐに戻り、100msの間スリープしてから、再度確認することができます。そうすれば、スレッドが無期限にブロックされないようにスレッドを停止することができます。 – smichak

+0

これを見る時間を取ってくれてありがとう。私はあなたの提案を試し、それがどうなるか見てみましょう。 – corky

答えて

1

。しかし、TIOCMIWAITループを実行するためにスレッドを使用しようとする試みは、GUIループを妨害して失敗しました。

私が行ったことは、TIOCMIWAITループでシリアルポートを監視し、このスクリプトをメインのGUIプログラムからサブプロセスとして実行するために、別のPythonスクリプトを書くことです。このようにして、GUIを開いたときにスクリプトが起動され、GUIが閉じられたときにスクリプトが強制終了されます。シリアルポートで接続すると、スクリプトはdbusを使用してGUIと通信し、必要な機能を実行します。