Я написал веб-приложение, которое взаимодействует с последовательным устройством на / dev / ttyS02.
Проблема в моем текущем решении для обмена сообщениями и очередей. Пожалуйста, прочитайте ниже.
Вот мост связи между приложением и pyserial:
Мое веб-приложение вставляет запись запроса через PHP в таблицу d_requests в MySQL.
Обработанный столбец вставленной записи имеет значение 0.
Идентификатор вставленной записи сохраняется в переменной $ id, и приложение PHP вводит
состояние цикла, где он будет постоянно проверять, если столбец d_requests [обработано] = 1, используя
$ id в качестве справочной информации.
У меня есть служба демона python, которая каждую секунду проверяет записи в
Таблица d_requests, где обработанный столбец = 0.
Это считается новым запросом. (см. Исходный код - служба python)
Служба python затем использует информацию записи для подключения к порту через
pyserial.
Запрошенное действие выполнено. Обработанный столбец записи затем обновляется до 1
и несколько других полей также обновляются.
Это помечает запись как обработанную.
Блок управления PHP затем выходит из цикла (точка 1.) и возвращает результат в виде json
в приложение JS. Где оно представлено пользователю.
Некоторые заметки
- Последовательное устройство способно обрабатывать 1 запрос каждые 250 мс.
- Служба демона python контролирует таблицу d_requests для записей, где обработано
столбец = 0 каждые 1 секунду.
- Единственное соединение, которое мое веб-приложение имеет со службой демона python, - это MySQL
БД путем вставки записей запросов в таблицу d_requests.
- Я использую блочный код PHP для поиска запроса, используя каждую секунду вставленный идентификатор для проверки
если обработанный столбец обновлен до 1.
Мои проблемы
Одна точка отказа
Когда служба демона не работает, последовательные запросы не могут выполняться
Чрезвычайное использование ресурсов
Я ожидаю около 4-5 запросов в секунду к последовательному устройству. Используя текущую реализацию
для обработки сообщений БД будет работать сверхурочно, а загрузка ЦП будет высокой, так как приложение PHP и демон / служба python будут подключаться и выполнять запросы к БД, и будут задержки с обработкой запросов.
Вывод:
Есть ли лучший способ улучшить мое текущее решение для обмена сообщениями и очередей?
Я думаю, что веб-сервис pyserial будет отлично работать в этом случае, когда, например, последовательный порт. подключен к веб-сокету, например. host: <7000> и я могу просто отправить ему запрос через PHP и дождаться ответа от веб-службы. К сожалению, я не знаю, как это сделать.
Есть идеи?
Спасибо
Исходный код
служба 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)