php - 如何创建 pyserial 网络服务?

标签 php python linux ubuntu pyserial

我编写了一个与/dev/ttyS02 上的串行设备交互的 Web 应用程序。 问题是我当前的消息传递和排队解决方案。请阅读下文。

Heres the communication bridge between the application and pyserial:

  • 我的 Web 应用程序通过 PHP 将请求记录插入到 MySQL 中的 d_requests 表中。 插入记录的已处理列设置为 0。 插入记录的 ID 保存在 $id 变量中,PHP 应用程序输入 循环状态,它将不断检查 d_requests[processed] column = 1 使用 $id 作为查找引用。

  • 我有一个 python 守护进程服务,它每秒检查一次 d_requests 表,其中已处理的列 = 0。 这被认为是一个新的请求。(引用源码-python服务)

  • 然后 python 服务使用记录的信息通过以下方式连接到端口 pyserial.

  • 执行请求的操作。然后记录的已处理列更新为 1 以及其他一些字段也会更新。 这会将记录标记为已处理。

  • 然后 PHP 控制 block 退出循环(第 1 点)并将结果作为 json 返回 到 JS 应用程序。它在何处呈现给用户。

一些注意事项

  • 串行设备能够每 250 毫秒处理 1 个请求。
  • python 守护进程服务监控 d_requests 表以查找已处理的记录 每 1 秒列 = 0。
  • 我的 Web 应用程序与 Python 守护进程服务的唯一通信是 MySQL
    DB 通过在 d_requests 表中插入请求记录。
  • 我使用 PHP block 代码每秒使用插入的 ID 来查找请求以检查 如果已处理的列已更新为 1。

我的疑虑

单点故障

当守护服务没有运行时,串行请求无法发生

极端资源使用

我预计串行设备每秒大约有 4-5 个请求。使用当前的实现 为了处理消息,数据库将超时工作并且 CPU 使用率会很高,因为 PHP 应用程序和 python 守护程序/服务将连接并在数据库上执行查询,并且请求的处理会出现延迟。

Conclusion : Is there a better way to improve my current messaging and queuing solution? I think a pyserial web service will work great in this case, where the serial port for eg. is attached to a web socket eg. host:<7000> and I can just send a request via PHP to it and wait for the response back from the web service. Unfortunately I dont know how to do this.

有什么想法吗?

谢谢

源代码

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)

最佳答案

Is there a better way to improve my current messaging and queuing solution?

你打赌!它们被称为消息队列,它们很棒。

我最喜欢的是Gearman ,由为我们带来 memcached 的同一个团队编写。它有 PHPPython绑定(bind)。它实际上不是一个消息队列,而是一个 RPC 服务。无论如何,它会让您从一个环境中调用方法并在另一个环境中处理它们。

在这种情况下,您希望用 Python 编写串行接口(interface)代码,并让它公开它可以作为 Gearman 函数执行的所有操作。它将作为守护进程打开。您的 PHP 代码可以通过 Gearman 调用这些函数。

关于php - 如何创建 pyserial 网络服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5266347/

相关文章:

php - ZF2 - 如何在 columns() 中使用 SQL_CALC_FOUND_ROWS

PHP exec 在长时间执行后没有得到标准输出

php - CodeIgniter 数据库 session 错误

python - Visual Studio Code Python 笔记本输出扩展?

C - 尝试在 linux 中构建一个简单的 shell 并在循环中使用 strtok、realloc 时遇到问题

javascript - 如何把P放在1的位置,A放在0的位置

python - 用于删除空格的正则表达式

python - 连接拒绝 PythonAnywhere 上的 Twitter API

linux - 如何隐藏顶部 "idle"(CPU和RAM)进程?

java - 我怎样才能让 Log4j2 登录到我的日志文件,我已经尝试了我能想到的一切,这可能是 linux 中的配置问题吗?