2011-03-10 75 views
0

我写了一个web应用程序,它与/ dev/ttyS02上的串行设备进行交互。 问题是我目前的消息传递和排队解决方案。请阅读下面。如何创建pyserial网络服务?

继承人的应用和pyserial沟通的桥梁:

  • 我的web应用程序通过插入一个PHP请求记录到MySQL中的d_requests表。 插入记录的处理列设置为0. 插入记录的ID保存在$ id变量中,并且PHP应用程序输入 循环状态,在该状态下,它将持续检查d_requests [processed]列= 1是否使用 $ id作为查找参考。

  • 我有一个python守护进程服务,每隔一秒检查 d_requests表中处理的列= 0的记录。 这被认为是一个新的请求。 (参照源代码 - 蟒服务)

  • 然后蟒服务使用该记录的信息经由 pyserial连接到的端口。

  • 执行请求的操作。记录的处理列然后更新为1 并且其他一些字段也会更新。 这标志着处理过的记录。

  • 然后PHP控制块退出循环(Point 1.),并将结果作为json 返回给JS应用程序。向用户展示它。

音符

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

我的顾虑

失败

的单点当守护程序服务没有运行串行要求不能发生

至尊资源使用

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

结论: 有没有更好的方法来改进我当前的消息传递和排队解决方案? 我认为一个pyserial web服务将在这种情况下工作,例如,串行端口。连接到网络插座,例如。主机:< 7000>我可以通过PHP发送一个请求到它并等待Web服务的响应。不幸的是我不知道该怎么做。

任何想法?

谢谢

的源代码

蟒蛇服务

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) 
+0

你有没有试过看node.js,它有一个非常快速的事件驱动循环系统,可以处理很多像这样的东西。 – RobertPitt 2011-03-11 00:13:41

回答

1

有没有改善我目前信和排队的解决方案更好的办法?

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

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

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

+0

感谢Charles的回应。我会考虑Gearman。 @RobertPitt不确定node.js是否可以用于我的目的,因为我仍然需要与python(pyserial)&php进行通信。 – QCar 2011-03-11 06:52:03

0

研究类似的需求。发现到目前为止有帮助的“ser2net”和“termnetd”守护进程。