微控制器输出到Python CGI脚本
我买了一个温度传感器记录器套件:http://quozl.netrek.org/ts/。它和提供的C代码一起工作得很好,但我更喜欢用python,因为它简单易用。所以我写了一个python脚本,用来显示微控制器的输出。我只连接了一个温度传感器到这个套件上。我想把温度显示在网页上,但我搞不明白怎么做。我觉得这可能和微控制器输出的内容有关,因为它有一个\r\n的结束符,而Linux的网页服务器不能正确识别这个。我的书上说:“根据你使用的网页服务器,你可能需要进行一些配置更改,以便理解如何提供CGI文件。”我正在使用Debian和Apache2,基本的CGI脚本运行得很好。
这是我用来在控制台显示传感器数据的代码(这个运行得很好):
import serial
ser = serial.Serial('/dev/ttyS0', 2400)
while 1:
result = ser.readline()
if result:
print result
这是我测试的cgi脚本,它可以正常工作:
#!/usr/bin/python
print "Content-type: text/html\n"
print "<title>CGI Text</title>\n"
print "<h1>cgi works!</h1>"
这是我开始编写的用于显示温度的cgi脚本(不工作 - 500内部服务器错误):
#!/usr/bin/python
import sys, serial
sys.stderr = sys.stdout
ser = serial.Serial('/dev/ttyS0', 2400)
print "Content-type: text/html\n"
print """
<title>Real Time Temperature</title>
<h1>Real Time Temperature:</h1>
"""
#result = ser.readline()
#if result:
print ser.readline()
如果我在控制台运行python rtt.cgi,它会输出正确的html和温度。我知道这不会是实时的,用户每次想查看温度时都需要刷新页面,但这些以后再说。从我的Apache2错误日志来看,它显示: 脚本的头部格式错误。错误的头部= 文件 "/usr/lib/cgi-bin/rtt.c: rtt.cgi
3 个回答
迈克尔,
看起来问题确实是权限方面的,不过你不应该试着让你的脚本拥有 /dev/ttyS0 的权限。你可能需要做的是启动一个新的进程,首先要做的就是把你的用户组改成 /dev/ttyS0 设备的用户组。在我的电脑上是 'dialout',你可能会不一样。
你需要导入 os 这个包,查看文档中的进程参数,在那一页你会找到一些可以让你改变拥有权的函数。你还需要使用 os 包中的进程管理相关的函数,这些函数可以启动进程,但你需要选择一个可以返回新进程数据的函数。使用 subprocess 包可能会更好。
你需要启动另一个进程的原因是,CGI 脚本需要在 Apache 进程下运行,而这个新进程需要访问串口。
如果我在接下来的几天有时间,我会试着为你整理一些东西,但你可以先试试,不用等我。
还有一件事,所有的 HTTP 头部都需要以两个 CRLF 序列结束。所以你的头部需要是:
print "Content-type: text/html\r\n\r\n"
如果你不这样做,浏览器可能不知道头部什么时候结束,实体数据什么时候开始。可以看看 RFC-2616。
~卡尔
再来一次:
# Added to allow cgi-bin to execute cgi, python and perl scripts
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
AddHandler cgi-script .cgi .py .pl
<Directory /var/www>
Options +Execcgi
AddHandler cgi-script .cgi .py .pl
</Directory>
我猜你的CGI脚本运行的环境可能无法完成从串口读取数据的操作。
顺便说一下,Python的标准库提供了比你现在使用的方法更好的方式来编写CGI脚本;即使是基本的字符串处理,也有更好的方法来把结果(假设你的代码有权限去读取这些数据)插入到HTML中。
我至少建议你使用类似下面的方式:
#!/usr/bin/python
import sys, serial
sys.stderr = sys.stdout
ser = serial.Serial('/dev/ttyS0', 2400)
html = """Content-type: text/html
<html><head><title>Real Time Temperature</title></head><body>
<h1>Real Time Temperature:</h1>
<p>%s</p>
</body></html>
""" % ser.readline() # should be cgi.escape(ser.readline())!
ser.close()
sys.exit(0)
注意我们是通过%字符串操作符把ser.readline()
的结果插入到字符串中的。(顺便提一下,你的HTML缺少了<html>
、<head>
、<body>
和<p>
(段落)标签)。
不过这还有一些问题。例如,我们至少应该导入cgi
模块,把外部数据用它包裹起来,以确保HTML实体能够正确替换任何保留字符等等。
我建议你进一步阅读:[Python文档]:http://docs.python.org/library/cgi.html