我们的组织已部署了Zabbix服务器来监视服务器和工作站的运行状况。 由于技术过程的特殊性,设备被“散布”在几个房间中,并分布在整个企业中。 自然,连同计算机的主要参数(工作/不工作)一样,我想控制服务器中的微气候。 同时,像往常一样,可能性是非常有限的,将“大笔资金”用于复杂的温度监控系统(我还包括带有用于机架式APC UPS的温度传感器的控制板)是一项单独的任务。
在主服务器中,一切都很简单:安装了一块这样的板(很久以前它是由前身和主要设备一起购买的),安装了APC传感器,在Zabbix中安装了代理,一切都可以通过SNMP进行。 无聊:)也没有对远程硬件的监视,也就是说-参见上文。 因此,它被认为是聪明的,可以节省预算,同时可以通过构建简单且廉价的“膝深”解决方案来提升新技能,但该解决方案仍适用于Zabbix的现有监视基础结构。
必要组件:
交付时组件的总成本为10美元。
组装设备并不困难。 网络模块用“三明治”放在主板上,温度传感器焊接到其引脚上。 传感器连接:红色+5 V,黑色-接地,黄色-数据; 在+ 5V和数据之间,焊接一个4.7kΩ上拉电阻。
选择数据引脚时要考虑网络模块使用的引脚(D10-SS; D11-MOSI; D12-MISO; D13-SCK; D2-IRQ)。
抽水:在设备的原型中,我遇到了冲突-温度数据是“两到三”随机发送的。 原因是我将温度传感器连接到了引脚2,正如我后来在Internet上发现的那样,当模块到达数据包时,网络模块将其用于生成中断。 重新排列在4号-它像时钟一样工作。组装硬件后,转到软件。
该设备将在网络上工作并假装为zabbix代理,为此它需要MAC和IP地址。 我们决定如何方便-在编程过程中很难缝制,
从温度传感器的地址生成
MAC并通过DHCP接收IP等。 我采用了最简单的路径并对两个参数进行了硬编码。
与zabbix服务器的通信协议在
文档中进行了
描述 。 我们的设备将响应两个命令
-agent.ping和
env.temp (还有进一步的创造空间,您可以绑定可用于arduino的任何扩展模块-至少湿度传感器,至少照明-随心所欲)。 它将
对所有其他命令
发誓并提供标准答案,这对于zabbix服务器是可以理解的。
对于那些从头开始的人(例如我)-Arduino编程是使用
Arduino IDE完成的,其安装和配置是基本的。 这些组件需要UIPEthernet和OneWire库,它们已通过“草图”菜单安装-并连接到项目-连接库-管理库...
如果您还有其他组件(例如,网络模块不在enc28j60上,而是在另一个芯片上)-您将需要其他库!来自Internet的用于网络模块和温度传感器的代码是典型的,带有一些假设和简化。
将代码填充到控制器中并连接以太网电缆后,我们从控制台进行检查:
$ zabbix_get -s 192.168.4.5 -k agent.ping 1 $ zabbix_get -s 192.168.4.5 -k env.temp 23.12 $ zabbix_get -s 192.168.4.5 -k bla-blah ZBX_NOTSUPPORTED
瑞克:zabbix.com上Windows的zabbix_get的编译版本已过时,并使用了不同的协议(服务器请求中带有标头ZBXD \ x01)。 Linux版本是最新的,并且协议对应于给定的代码。一切都按预期工作。 在zabbix管理面板中,使用选定的IP创建一个新主机,其中有两个键,即Numeric(未签名)agent.ping和Numeric(float)env.temp,可以享受工作。 图表,触发器-一切正常。
该设备通过其本地USB供电。 情况-可选:合适的塑料盒,热收缩膜,蓝色电工胶带。
传感器的分辨率约为0.06(更准确地说是1/16)°C,准确度-浸入融化的雪中时,显示为0.19°C(也许降得更低,但积雪很少并且迅速融化)。 我认为对于价值10美元的设备和上述用途-绰绰有余。
草绘 #include <OneWire.h> #include <UIPEthernet.h> byte mac[] = { 0xDE, 0x05, 0xB6, 0x27, 0x39, 0x19 }; // random MAC byte ip[] = { 192, 168, 4, 5 }; // IP address in local network String readString = String(20); byte addr[8]; OneWire ds(4); // DS18B20 at pin 4 EthernetServer server(10050); // Zabbix port void setup() { Ethernet.begin(mac, ip); server.begin(); ds.search(addr); } void loop() { byte data[2]; float celsius; readString = ""; if (EthernetClient client = server.available()) { while (client.connected()) { if (client.available()) { char c = client.read(); if (c == '\n') // end of query from zabbix server { client.print("ZBXD\x01"); // response header if (readString == "agent.ping") { byte responseBytes [] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '1'}; client.write(responseBytes, 9); } else if (readString == "env.temp") { ds.reset(); ds.select(addr); ds.write(0x44); // start conversion with regular (non-parasite!) power delay(1000); ds.reset(); ds.select(addr); ds.write(0xBE); // read Scratchpad data[0] = ds.read(); data[1] = ds.read(); int16_t raw = (data[1] << 8) | data[0]; celsius = (float)raw / 16.0; byte responseBytes [] = {(byte) String(celsius).length(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; client.write(responseBytes, 8); client.print(celsius); } else { byte responseBytes [] = {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; client.write(responseBytes, 8); client.print("ZBX_NOTSUPPORTED"); } break; } else if (readString.length() < 20) { readString = readString + c; } } } delay(10); client.stop(); } }