Shell 脚本构建摄像头服务器
几年前,瑞典公司 Axis Communications AB 推出了一个新概念,即推出其摄像头服务器系列。该公司可能意识到其网络摄像头系列(其中一款在 2000 年 9 月的 LJ 中评测过)无法填补老式模拟监控摄像头的所有空白,因此还以独立的、坚固的、无风扇的外壳提供了其控制和数字化电子设备。摄像头服务器提供单路或四路模拟视频输入以及一路直通输出的版本,如今已为各公司提供了一种在近十年内逐步实现监控系统现代化的方法。
当然,这些设备现在都运行 Linux 系统,在相当专业的硬件上。我们接触到这款服务器是因为一位客户的需求无法通过 Axis 自己的摄像头来满足,但我们和客户都非常喜欢其基于 Web 浏览器的界面。因此,我们引用了一家传统监控摄像头供应商的专业级第三方硬件,经测试,该硬件与摄像头服务器配合良好。
与计算机硬件一样,摄像头及其光学器件也是烧钱的东西。根据所需的复杂程度,您可能会花费任何可用的金额。
出于我们的目的,我们需要一款可远程控制的云台变焦 (PTZ) 摄像头,用于户外使用,并具有相当大的放大倍数。您可以找到几百美元的基本室内版本 PTZ 摄像头,以及几千美元的能够耐受户外气候、阳光直射和轻微破坏的变体。
当时我们选择了一个吊装式封闭透明球罩系统——您可能在现代机场看到的那种类型。对于挪威的户外冬季使用,我们需要一个加热外壳以避免结冰。以下是规格
水平移动:360 度连续。
垂直倾斜:+2 至 -92 度。
图像传感器:1/4 英寸 CCD(3.2 x 2.4 毫米)。
变焦:22 倍光学变焦,焦距 4 至 88 毫米。
灵敏度:0.07 勒克斯,快门速度 1/1.5 秒。
快门速度:1/1.5 至 1/30,000 秒。
最小光圈:f/1.6
运行环境:-40 至 +50 摄氏度,持续。
现在,为这个项目使用 PTZ 摄像头的想法之一是定期拍摄几个固定点的图像,并将这些图像上传到 Web 服务器。在这里我们遇到了一个问题。库存软件可以很好地进行定期成像和 FTP。但是,我们无法告诉它在拍摄图像之前转到 PTZ 位置。该功能对于我们的第一个客户来说不是必需的,因此在交付继续进行的同时,我们研究了这个问题。
此设备中的软件可以通过几种方式进行修改。固件映像的所有开源组件的源代码都是可用的——因此管理界面 CGI 缺失,但其余部分大部分可供检查和修改。但是,特定固件版本的源代码不可下载;您必须以书面形式向 Axis IPR 部门索取。他们将以象征性费用向您发送包含源代码的 CD。
我们有更多的客户在筹备中,因此研究继续进行。这项工作最终产生了几个可以挖掘功能的 API。
以下是可用的 API
正常的管理界面(Web 浏览器)。
HTTP API。
脚本。
Shell 脚本。
PHP3 Lite。
用于 Linux/cris 的 GCC SDK。
与大多数嵌入式设备一样,存在一些限制和不便之处。首先也是最重要的,是严重受限的空间。在 4MB 闪存存储器中,只有不到 100kb 的可写文件系统空间可用于第三方修改。所有标准软件都位于只读文件系统上,如果不创建自定义固件映像,则无法替换。
当时没有 SSH 服务器或客户端可用,因此自定义 shell 脚本必须由计时器触发或从 PHP 脚本运行。但是,有一个 telnet 服务器可用于开发用途。如今,Dropbear SSH 已被移植到该架构。
如果可以的话,我们希望在不增加额外服务器的情况下进行自动化,因此我们的努力方向是进行一些内部 shell 脚本编写,由任务调度程序 utask 以设定的间隔触发。顺便说一句,与普通的 cron 相比,这个任务调度程序有一些额外的功能——它可以对外来事件做出反应,例如数字输入低电平到高电平的转换,或者摄像头 #2 上的视频信号丢失。
在嵌入式开发中,公开功能始终是一个问题——应该在易于自定义方面投入多少精力?在这种情况下,已经投入了大量精力——没有两个相同的监控装置。
基于浏览器的界面易于使用、功能齐全,并且专为人类使用而设计。它通常不太适合机器自动化。
HTTP API 是一个简单的请求-响应 API,专为自动化而设计,提供基于浏览器的界面中的大多数选项。它通常只返回状态代码或裸请求对象,例如快照或视频流。这非常适合远程控制,一些第三方供应商销售的软件使用此 API 从一个或几个中央节点控制数十到数百个摄像头。
PHP3 lite 方言是向基于浏览器的界面添加自定义动态页面的最简单选择,它也可以用于通用内部脚本编写。
Shell 脚本通过提供的 sh 兼容 shell 和随附的实用程序,在需要一些本地智能时非常灵活和快速——例如,通过抓拍照片来响应门铃的按下,然后通过继电器打开门。
如果需要一些高级本地智能,可以使用该平台的 GCC SDK。
如前所述,我们为手头的问题选择了 shell 脚本。在相关的固件修订版中,我们有很多值得使用的程序
BusyBox:包括 sash shell 作为 /bin/sh。
mish:minix sh 兼容 shell。
utask:任务调度程序,与 cron 不兼容。
bufferd:图像捕获/缓冲。
sftpclient:简单的 FTP 客户端。
shttpclient:简单的 HTTP 客户端。
smtpclient:简单的邮件程序。
特别值得注意的是不引人注目的 shttpclient。这使我们能够从内部 shell 脚本中使用 HTTP API,这是我们进行 PTZ 控制所需要的。当然,它也可以在许多其他方面使用——向另一个 Web 服务器或视频服务器发出事件信号、通过 HTTP 上传图片以及其他不需要基本身份验证的东西。毕竟,它只是一个简单的 HTTP 客户端,而不是 wget 或 cURL。
我们在将此技术投入生产使用时遇到的问题大多与脚本编写无关。我们遇到了一些间歇性上传图像失败的情况——事实证明,这些问题是由攀爬植物侵占无线桥接器的一根天线引起的。
所有美好的事物都会结束。我现在要离开了,但首先,清单 1 中显示了我们拼凑出来的最终脚本。当然,它不是特别优雅,但很小,而且不难编写,这要归功于最初的嵌入式开发人员的考虑。这是一个值得从中吸取的公平教训,不是吗?
清单 1. 最终脚本
#!/bin/mish PATH=/bin:/sbin:/usr/bin:/usr/sbin # stop button pressed? skip the rest. stopp=`ls /tmp/stopp` ; if [ "x$stopp" = "x" ]; then # clear working directory bufferd -reset -buffername BILDE ; # read configured positions, '~' signifies a unset # position grep -v '~' /etc/sysconfig/presetpos.conf \ >/tmp/presets ; # pos 1-10 reserved for non-public views num=11; while [ $num -lt 21 ]; do # another stop button check - break the loop stopp=`ls /tmp/stopp` ; if [ "x$stopp" = "x" ]; then grep Pos$num /tmp/presets >/tmp/canptz ; canptz=`cat /tmp/canptz` ; if [ "x$canptz" != "x" ]; then # go to position shttpclient "http://127.0.0.1/axis-cgi/\ com/ptz.cgi?camera=1&gotoserverpresetno=$num"; # wait for picture to settle sleep 6 ; # save picture to /tmp/BILDE/ bufferd -start -buffername BILDE -snapshot\ -pre 1 -format snapshot_pos$num.jpg -uri\ 'ftp://127.0.0.1/jpg/1/704x576.jpg' ; bufferd -stop -buffername BILDE ; tmpwait=20 ; while [ $tmpwait -gt 0 ]; do sleep 2; expr $tmpwait - 2 >/tmp/tmpwait ; tmpwait=`cat /tmp/tmpwait` ; if [ $tmpwait -eq 0 ]; then # timeout creating jpeg, kill process and # settle for potentially incomplete picture logger "timeout waiting for bufferd -stop,\ killing image_buffer and continuing." # ps is only available as a builtin # command in /bin/sh /bin/sh -c ps >/tmp/kverk ; grep image_buffer /tmp/kverk >/tmp/kverk2 ; imbuf_pid=`cut -b 0-5 /tmp/kverk2` ; rm /tmp/kverk; rm /tmp/kverk2; kill $imbuf_pid ; fi; if [ -f /tmp/BILDE/status ]; then # status file appeared - picture complete rm /tmp/BILDE/status ; tmpwait=0; fi; done; rm /tmp/tmpwait ; fi; fi; expr $num + 1 >/tmp/A ; num=`cat /tmp/A` ; rm /tmp/A; done; rm /tmp/presets ; rm /tmp/canptz ; # batch ftp all the pictures from this round sftpclient -L -m 10.0.0.1 -k /tmp/BILDE -c \ /var/www/pictures/c2 -u web -w P2SsW1Rd -t \ /var/www/pictures/c2/temp_c2.jpg ; fi;
本文资源: /article/8695。
Erik Inge Bolso 是一位 UNIX 顾问和重剑击剑运动员,居住在挪威的莫尔德,自 1996 年以来一直在运行 Linux。他的另一个爱好可以通过 Google 搜索“balrog genealogy”找到,您可以通过 ljcomment@tvilsom.org 与他联系。