程序源代码请点击文章标题进入完整阅读模式获取
这段时间一直在"筹建"以前提到过的智能化家庭系统(IHES)。前不久购买并配置了500G的RAID 1存储阵列服务器,为了保证数据安全,同时又购买了Santak MT-500pro智能型UPS。
这里说智能型可能不是很专业,其实就是说该UPS提供了相关的接口允许从服务器上读取出UPS的相关状态信息。比如:
不过,其实最需要关心的就是希望能够在发生断电情况下ups能即时告知。以便服务器机组能在UPS逆变供电实效前自动关机。毕竟不可能让我24小时监控家中服务器状况。
以上可以算是背景介绍了,现在面临的问题是,这个品牌的UPS虽然在官方提供了相关的监控和管理软件Winpower。不过使用后,存在许多不足:
- 程序采用java (1.14) 开发,甚至连与ups通讯的部分也完全采用java
- 该程序实现上十分低效,监控目模块间通讯需要采用java rmi
- 没有命令行接口,可制订性差
当然这些问题不是所有人都会抱怨的,不过目前考虑到家里的中央服务器还采用P3 CPU, 512mb内存,以及没有安装X Server环境。纯命令行下WinPower完全无法工作。同时采用java的实现虽然从厂家角度降低了porting成本,不过绝对是一个低效的实现。我测试过仅仅开启了Winpower中的监控模块,java进程就消耗了近20Mb的资源。同时还不考虑低效的实现(我逆向工程过其class文件,实现很糟糕)。仅仅为了监控ups信息而做出如此的资源消耗实在不值得。
另一方面,如果选用APC品牌的UPS,linux下则有现成的Apcupsd。当然东西都买下了,后悔也没用。于是,我实现一个满足我需求的ups监控程序。这里提供一个原形程序的代码以及整个整个制作过程的叙述。支持的型号是Santak MT-500pro。不过我相信通过源代码以及按照我的制作思路,其他型号也很容易做出对应的程序。原形程序是纯命令行的,很容易用bash shell写一个断电后一定时间内控制服务器自动关机的daemon脚本。
下面是制作介绍部分,没兴趣看得话代码在文章末尾给出了,请自行编译使用。Windows版本的也可以很容易修改而成。
MT-500pro的相关信息:
毕竟不是给人家做广告,这里什么技术参数就不给了。
该UPS采用串口(COM)提供自身的状态信息。串口的通讯采用2400bps速率,目前已知的状态信息有如下2种形式:
- "#220.0 004 12.00 50.0\r"
- "(231.4 231.0 231.4 011 50.1 13.9 25.0 00001001\r"
这里先暂时不介绍相关的通讯协议。在上面的状态信息中,第一条应当为该UPS的标准参数(即正常情况下理论值)。这几个数据每次都是固定不变的。其含义依次为:
而第二项则为当前UPS的实际数据,这也是我需要关心的内容。其可能含义依次为:
这里需要对状态标志做下介绍,因为我在逆向分析时无法重现所有可能情况,这里只给出我知道的几个标志位:
| +--- UPS输出关闭位
+--------- 外部供电失效位
虽然只知道2个标志位含义,不过我想应该足够了,最高位表示当前交流供电是否异常,如果为1就表示断电了。UPS输出关闭位有效则表示当前UPS没有工作。
知道这些格式信息后,下面的问题就是如何知道相关的请求代码,即通讯协议。
监听串口通讯:
我曾想过通过把Winpower逆向工程来研究通讯协议,毕竟java 1.5以前的class文件可以很容易被反汇编(应该说是反代码)。不过后来放弃了,这里就不多说了...
目前采用的办法是监听串口的通讯。这里介绍一个相对使用什么本机COM1与COM2对接等方法简单多得手段。在Windows平台下可以采用一款叫做HHD Free Serial Port Monitor的免费软件。或者Sysinternal上也提供了相关工具。他们都通过hook IOCTRL函数来截获COM的通讯内容。
使用这类工具,开启Winpower后,相关的通讯协议也一目了然。其实根本不能算协议,十分的简单:
Request: 2009-2-7 20:00:19.95264 (+0.9013 seconds)
46 0D F.
Answer: 2009-2-7 20:00:19.01264 (+0.0601 seconds)
23 32 32 30 2E 30 20 30 30 34 20 31 32 2E 30 30 #220.0 004 12.00
20 35 30 2E 30 0D 50.0.
Request: 2009-2-7 20:00:20.97364 (+0.8913 seconds)
51 31 0D Q1.
Answer: 2009-2-7 20:00:20.03364 (+0.0601 seconds)
28 32 32 35 2E 39 20 32 32 35 2E 39 20 30 30 30 (225.9 225.9 000
2E 30 20 30 30 30 20 30 30 2E 30 20 31 33 2E 38 .0 000 00.0 13.8
20 32 35 2E 30 20 30 30 30 30 31 30 31 31 0D 25.0 00001011.
因此,上面提到的2组信息分别对应的请求数据为:
"F\r"
"Q1\r"
Linux下的轻量级监控程序:
有了上面的分析结果后,很容易的就能自己编写一个监控程序。为了各位方便,我提供一个简单的原形程序。用法如下:
如果忽略了port name,则默认采用/dev/ttyS0。 程序会先输出第一项UPS信息,然后以1秒为间隔打印出第二项状态信息,如:
#220.0 004 12.00 50.0
(233.9 234.3 233.9 011 50.1 13.9 25.0 00001001
(234.3 233.9 234.3 011 50.1 13.8 25.0 00001001
(234.3 234.3 233.9 011 50.1 13.9 25.0 00001001
(234.3 234.3 234.3 011 50.1 13.9 25.0 00001001