/ dev/ttyS02でシリアルデバイスと対話するWebアプリケーションを作成しました。問題は、私の現在のメッセージングおよびキューイングソリューションです。以下をお読みください。
アプリケーションとpyserial間の通信ブリッジは次のとおりです。
私のWebアプリケーションは、PHPを介してMySQLのd_requestsテーブルにリクエストレコードを挿入します。挿入されたレコードの処理済み列は0に設定されます。挿入されたレコードのIDは$id変数に保存され、PHPアプリケーションはループ状態に入り、$idをルックアップ参照として使用してd_requests[processed]列=1かどうかを継続的にチェックします。 。
処理された列が0であるd_requestsテーブルのレコードを毎秒チェックするPythonデーモンサービスがあります。これは新しいリクエストと見なされます。(ソースコード-pythonサービスを参照してください)
次に、Pythonサービスはレコードの情報を使用して、pyserialを介してポートに接続します。
要求されたアクションが実行されます。次に、レコードの処理済み列が1に更新され、他のいくつかのフィールドも更新されます。これにより、レコードが処理済みとしてマークされます。
次に、PHP制御ブロックはループを終了し(ポイント1)、結果をjsonとしてJSアプリケーションに返します。ここでユーザーに提示されます。
いくつかの注意点
- シリアルデバイスは、250ミリ秒ごとに1つの要求を処理できます。
- Pythonデーモンサービスは、d_requestsテーブルを監視して、処理された列が1秒ごとに0であるレコードを探します。
- 私のWebアプリケーションがPythonデーモンサービスと通信するのは
、d_requestsテーブルにリクエストレコードを挿入することによるMySQLDBだけです。 - PHPブロックコードを使用して、挿入されたIDを毎秒使用してリクエストを検索し、処理された列が1に更新されているかどうかを確認します。
私の懸念
単一障害点
デーモンサービスが実行されていない場合、シリアルリクエストは実行できません
極端なリソース使用量
シリアルデバイスへの1秒あたりのリクエスト数は約4〜5と予想されます。メッセージを処理するために現在の実装を使用すると、PHPアプリケーションとPythonデーモン/サービスが接続してDBでクエリを実行し、リクエストの処理に遅延が発生するため、DBは時間外に動作し、CPU使用率が高くなります。
結論:現在のメッセージングおよびキューイングソリューションを改善するためのより良い方法はありますか?この場合、pyserial Webサービスはうまく機能すると思います。たとえば、シリアルポートは次のようになります。Webソケットに接続されています。host:<7000>と、PHPを介してリクエストを送信し、Webサービスからの応答を待つことができます。残念ながら、これを行う方法がわかりません。
何か案は?
ありがとうございました
ソースコード
Pythonサービス
import sys, time
from daemon import Daemon
import MySQLdb
#Database parameters
config = {"host":"localhost","username":"root","password":"cake","database":"mydb"}
#Check if MySQLdb library is present
try:
conn = MySQLdb.connect(config['host'],config['username'],config['password'],config['database'])
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[o], e.args[1])
sys.exit(1);
#Check if pyserial library is present
try:
import serial
except ImportError:
print "Error,pySerial module not installed"
sys.exit(1);
#Create DB cursor
#cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
#Declare global variables here
class MyDaemon(Daemon):
def run(self):
while True:
time.sleep(2)
cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
data = ''
try:
cursor.execute ("""SELECT * FROM d_requests where processed = 0""")
rows=cursor.fetchall()
print "Waiting for requests..."
except MySQLdb.Error as detail:
print "MySQL Error,",detail
if len(rows) == 0:
cursor.close()
print "No request found..."
continue
for row in rows:
try:
print "Processing request..."
ser = serial.Serial(port=row['port'],
baudrate = row['baud'],
bytesize = row['bytesize'], #8
parity = row['parity'], #serial.PARITY_NONE or N or C
stopbits = row['stopbits'], #1
timeout = row['wait_for_reply'], #0.5
xonxoff = row['sw_flowcontrol'], #0
rtscts = row['hw_flowcontrol']) #0
#Send command to device
ser.write(row['request_string'] + "\r")
#Read device response
data = ser.read(100)#TBD:This value needs to be changeable,not always 100 bytes
ser.close()
print "RESULT : " + data
except (serial.SerialException, AttributeError, NameError) as detail:
data = "Error, could not open port"
print data
except serial.SerialTimeoutException as detail:
data = "Error, port connection timeout" #Error ,detail
print data
except:
data = "Error,Unexpected error"
print data
finally:
#ser.close()
try:
cursor.execute("""UPDATE d_requests SET processed = %s, result_string = %s WHERE id = %s""",(1,data,row['id']))
except MySQLdb.Error as detail:
print "MySQL Error,",detail
#cursor.commit() for innoDB table engines
cursor.close()
if __name__ == "__main__":
daemon = MyDaemon('/tmp/daemon-example.pid')
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
elif 'foreground' == sys.argv[1]: #this runs the daemon in the foreground
daemon.run()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
else:
print "usage: %s start|stop|restart" % sys.argv[0]
sys.exit(2)