构建网络气象站
去年秋天,我和我的家人从中爱荷华州中部搬到了科罗拉多州埃斯蒂斯帕克这个小山地度假小镇。埃斯蒂斯帕克是一个美丽的城镇,位于落基山国家公园的东入口。每年夏天有超过三百万的游客参观这个公园。
当我们搬到这里时,我带来了我刚起步的咨询业务 Daylight Software,并建立了一些网页来招揽一些业务。在灵光一闪的启发下,我决定购买或建造气象站设备,并在网上提供天气数据。来自全国各地——以及全球各地——的访客将看到我的网页,Daylight Software 将被确立为 Linux 咨询强企。好吧,也许这不会导致全球统治,但这肯定是一件好事。我认为这是一项社区服务,因为除了当地一家银行的时间和温度标志外,没有其他公共天气报告服务可用。
经过一番调查,我确定我的硬件开发技能不足以设计和建造天气传感器。我四处寻购,最终从宾夕法尼亚州媒体市的 American Weather Enterprises (http://www.americanweather.com/) 购买了一套德州仪器“天气报告”WRL-25 系统。
WRL-25 就像许多气象站一样,它包括一个 RS-232 连接,并附带 DOS/Windows 软件,用于下载和查看收集的数据。它具有用于测量风速、风向、温度、湿度、大气压和降雨量的传感器。使用普通电视天线桅杆和配件,我将气象站传感器安装在房屋的屋顶上,将传感器电缆穿过阁楼空间并一直延伸到我地下室的办公室。我将美观的显示单元安装在办公室的架子上。
在与天气显示器隔着房间的地方是我的电脑阵列,包括我的 Linux 工作站。我正在 AMD 486DX-4 120MHz ISA 服务器上运行 Red Hat 4.0 Colgate 版本、2.0.18 内核。我制作了一根电缆,并将天气显示器连接到服务器中的 Boca AT-66 串口卡。然后我编写了一些 Perl 脚本来构建 HTML 和 GIF 文件并将它们上传到我的 ISP,并管理气象站发出的数据读数。
传感器安装在两段十英尺长的钢制电视天线桅杆上,在美国可以从 Radio Shack 等商店购买到。大约四英尺埋在地下,桅杆的其余部分垂直于我们单层房屋的山墙端。桅杆通过电视桅杆支架固定在房屋的屋顶线处。大约六英尺的桅杆突出于屋顶线之上。
传感器随附夹具和硬件,用于将它们连接到桅杆。(见图 1。)我按照安装说明,将风向/风速传感器模块指向北方安装在桅杆顶部。温度和湿度传感器位于一个“宝塔”外壳中,以保护它们免受阳光直射,宝塔安装在屋顶线以上约三英尺处。雨量收集器安装在屋顶线上;我使用木匠水平仪正确地安装了它。
来自传感器模块的多芯电缆进入接线盒底部,在那里它们插入来自 100 英尺电缆的匹配连接器,这些电缆连接到天气显示单元。(见图 2。)所有多余的电缆都盘绕起来并牢固地固定在屋檐下。进入接线盒的电缆略微下垂,以鼓励雨水滴落而不是流入接线盒。
100 英尺的电缆穿过阁楼,然后穿过屋檐顶部的孔伸出。这个孔后来用填缝剂填充,以防止松鼠和其他害虫进入。从阁楼,我在内墙顶板上钻了一个孔,并将电缆穿到地下室。一个用于有线电视安装的精美木制开关面板用于遮盖电缆穿过墙壁进入我的办公室/计算机区域的孔。电缆连接到 WRL-25 显示单元的背面。
我最终在阁楼的吹入式玻璃纤维绝缘材料中爬行的次数比我愿意记住的还要多。如果您这样做,请小心——佩戴防尘口罩或呼吸器以及长袖和长裤。阁楼很热。我认为这是安装中最困难的部分。
我必须在显示单元上设置当前时间并更改一些选项设置。除此之外,WRL-25 的传感器和其他功能都经过校准并准备运行。
显示单元的背面有一个 9 针串口尾纤。WRL-25 随附一根混合搭配的 4 端 25 针和 9 针串口电缆,用于适应任何可用的连接器。我没有使用那根特定的电缆。我的 Boca Io-AT-66 六端口串口卡使用 RJ-45 插座进行连接。因此,我用一段十英尺长的废弃八芯双绞线制作了一根电缆,该电缆的一端已经压接了一个 RJ-45 连接器。Io-AT-66 文档中包含了引脚分配和接线信息。
WRL-25 可以被编程为定期通过串行线路发送状态报告。这可以用于直接在串行打印机上打印。我将我的设备编程为每 5 分钟发送一次读数。我还更改了一个可选设置,以允许降雨率报告并在每天结束时打印每日最大/最小报告。我将串行线路数据速率设置为 9600bps。
该单元还可以通过串行连接使用单字符命令进行定向。我很少使用此功能。单元随附的 PC 软件可以用于设置各种选项和设置,显示面板上的按钮也可以。因此,可以使用更复杂的编程来按需查询单元或更改各种功能。我选择使用简单的日志记录功能来收集我的数据。
我通过使用以下命令在我的设置上运行了一个快速测试
cat < /dev/ttyS19
此命令获取 /dev/ttyS19 串行线路上出现的任何输入,并将其回显到屏幕。按下 WRL-25 上的手动报告按钮会在屏幕上生成一行报告。我很高兴!
从串行线路下来的报告看起来像这样
17:05 08/09/97 WSW 00MPH 460F 069F 057F 085% 23.42F 00.00"D 01.39"M 00.00"R
前两个字段是时间和日期。当前时间和日期在 WRL-25 显示单元上维护。我没有注意到时间设置有任何大的漂移。
第二个和第三个字段是风向(WSW—西南偏西)和风速(00 MPH—英里/小时)。
字段 5 到 7 是华氏温度读数。字段 5 未连接到任何传感器,因此应忽略。字段 6 是室内温度,字段 7 是室外温度。
字段 8 是相对湿度,在本例中为 85%。字段 9 是以英寸汞柱为单位的大气压,后跟一个字符,表示下降 (F)、上升 (R) 或稳定 (S)。
最后三个字段是每日降雨量和每月降雨量,单位均为英寸,以及每小时降雨率,单位为英寸。
在每天结束时,报告两行每日最低和最高读数
Max 08/08/97 WSW 24MPH 460F 074F 081F 100% 23.42" 00.00"D 01.39"M 00.00"R Min 08/08/97 SW 00MPH 460F 068F 044F 021% 23.28" 00.00"D 01.39"M 00.00"R
这些行的格式与其他报告相同,只是第一个字段将这些记录标记为最大/最小报告。每日最小/最大值的读数是独立的。在上面的示例中,当天的最高温度为 81 华氏度,最高湿度读数为 100%。这些读数不是在同一时间发生的,并且是不相关的,只是两者都是该特定统计数据的最大值。
我第一次尝试编写数据收集脚本是一个简单的 cat 命令
cat /dev/ttyS19 >> data1
它奏效了——主要是偶然。下次我的机器重启时,它根本不起作用了。当我启动它时,气象站控制台开始吐出各种各样的长报告。经过一番挠头,很明显,常规字符回显正在反馈命令字符——这根本不是我想要的。
我当前的脚本名为 weatherd.pl,如 列表 1 所示,其中删除了空行。第 8 行将变量 $TTY 设置为第一个命令行参数。第 10 行将终端重置为适当的速度、奇偶校验和非回显。我使用 stty 命令将终端设置成我想要的方式,然后将设置保存到一个文件中。此 stty 命令从该文件读取并根据保存的配置设置终端。
数据保存在一个文件中,文件名是当前日期。每天的数据都进入一个文件(第 14-16 行)。第 16 行的 print 语句帮助我确信事情运行正常。从第 27 行开始,对于从 tty 接收的每一行数据,我们检查它是否是最小值或最大值,以及它是否仍然是今天的数据。最小值和最大值数据进入单独的文件。
要启动 weatherd.pl,我在我的 /etc/inittab 文件中添加了以下单行
ws:2345:respawn:/home/weather/bin/weatherd.pl /dev/ttyS19
此行启动 weatherd.pl,如果由于任何原因它应该终止,则重新生成它。
现在我有了从气象站输入的数据,这些数据被 weatherd.pl 拾取并放入一个文件中,文件名使用日期。
下一步是将数据格式化为 HTML 文件,以便在 Web 上显示。我编写了一个 Perl 脚本 (列表 2),它从当前数据文件中获取最后一行,并结合模板 HTML 文件,填写天气信息。它还计算校正后的大气压和露点。(露点计算是由科罗拉多气候中心的 John Kleist 提供给我的,johnk@loki.atmos.colostate.edu。)最后,它查看昨天的最大/最小文件,并将这些值放入输出 HTML 中。
我还编写了一个脚本 plotdays.pl (列表 3),它绘制了过去几天的 一些有趣的统计数据。
最后,我有一个名为 loop.pl 的主程序,我编写它是为了可靠地连接到我的 ISP,建立我的 PPP 连接,传输电子邮件,设置系统时间并上传天气数据。
首先,我们必须看看如何自动化 FTP 连接。FTP 通常用于交互式网络文件传输。要使用常规 FTP,您需要在远程计算机上拥有一个帐户。在这种情况下,我使用我在 Front Range Internet (frii.net) 的 ISP shell 帐户。用户可以通过在其 $HOME 目录中使用名为 .netrc 的文件来设置自动 FTP 会话。我向我的系统添加了一个名为“weather”的用户,专门用于拥有天气数据文件和脚本。在 /home/weather/.netrc 文件中,我有以下几行
machine ftp.frii.net login: password: macdef init cd public_html put /home/weather/WWW/wscurrent.html wscurrent.html put /home/weather/WWW/wsplot.html wsplot.html put /home/weather/WWW/temp.gif temp.gif put /home/weather/WWW/pressure.gif pressure.gif put /home/weather/WWW/raind.gif raind.gif put /home/weather/WWW/winds.gif winds.gif quit
此文件中的语句定义并执行一个名为 init 的宏。我所要做的就是启动 FTP,此脚本会尝试运行宏,将我的 HTML 和 GIF 文件上传到我 ISP 帐户上的适当位置。
列表 1 和列表 3 都从一个名为 doup 的简短脚本调用,列表 4,它也执行实际的 FTP 调用。
最后但并非最不重要,loop.pl (列表 5) 由 root 用户持续执行。loop.pl 唯一棘手的部分是,如果命令由于与 ISP 的连接丢失而卡住,则必须恢复。我编写了一个替换常规 Perl “system” 函数的函数,它允许我为每个命令指定超时。如果该命令超过分配的时间,则它及其所有子进程都会被杀死。Loop.pl 还有其他工作要做,例如下载和上传我的电子邮件以及使用 ntpdate 设置系统时间。在这些辅助作业发生时,我有一个子进程同时运行 doup 脚本。如果辅助作业先完成,它们会给 doup 更多时间完成。在良好的连接下,在一个分钟内完成所有事情没有问题。
我有两个不同的拨号脚本,因为计算机在拨打我的 ISP 时可以尝试两个可能的电话号码。如果主号码失败,它会尝试第二个号码。如果两者都失败,它会休眠 60 秒然后重试。loop.pl 中 sleep 语句的目标是使连接大约每 15 分钟发生一次。否则,代码中的注释几乎涵盖了所有细节。
我主要担心的问题之一是闪电。幸运的是,我们的站点位于树木繁茂的区域,在某种程度上可以防止直接雷击。尽管如此,如果远程天气传感器与显示单元和我的 Linux 机器电气隔离,我会感觉更好。某种形式的光隔离可能会起作用。
此外,我可能必须开发一种自动设置天气显示单元时钟的方法。
否则,系统似乎运行良好。通过从 inittab 运行 weatherd.pl,以及在我的启动 rc 文件中运行 loop.pl,天气站监控在重启后继续进行,无需人工干预。断电或服务器故障会中断服务,但这两种情况都不常见。
我的气象站网页(见图 3)可以在 http://www.frii.net/~daylight/wscurrent.html 找到。请顺道来看看。如果您有机会,请来埃斯蒂斯帕克看看,这是一个多么美丽的地方。
本文中提到的所有列表都可以通过匿名下载文件 ftp.linuxjournal.com/pub/lj/listings/issue56/2538.tgz 获得。