Etherio allows software to interact with hardware using the SNMP protocol. It is possible to detect power outages or push-button presses, switch on the fan or measure temperatures, etc. in PHP, node.js, Java, Erlang, Bash and many other environments.
- Digital input returns the current level (possibly debounced), counts level transitions, and sends traps.
- Digital output can be set to certain levels and produce single or periodic impulses of a given length.
- Analog input returns measured value depending on adapter installed. Adapters available for voltage, current, temperature etc.
All configuration is also done using SNMP under energyfive OID .22.214.171.124.4.1.50687 Read and write community is "public". The default IP address is 192.168.5.5, netmask 255.255.255.0. For example, to change the IP address, using net-snmp:
SNMPv2-SMI::enterprises.506126.96.36.199 = IpAddress: 192.168.5.7
It's convenient to use human-readable names instead of numeric OID. To do so, we need to specify the mib file, which contains such a dictionary. For NET-SNMP under Windows, the snmp installation mib file can be downloaded to %netsnnp_install_dir%/share/snmp/mibs. Then the -m parameter should be added to command. Now we can use IP.0 instead of numeric OID.
SNMPv2-SMI::ip.0 = IpAddress: 192.168.5.7
For net-snmp in common, see their tutorial.
If you have forgotten the IP address, device configuration can be reset to default by holding the reset button for 5 seconds.
SNMP allows you to GET and SET multiple values with a single request. If one of several SET variables is invalid, the whole SET request will be discarded.
To set IP, netmask and gateway use:
SNMPv2-SMI::ip.0 = IpAddress: 192.168.5.7
SNMPv2-SMI::netmask.0 = IpAddress: 255.255.255.0
SNMPv2-SMI::gateway.0 = IpAddress: 192.168.5.1
To show current network settings, use snmpget:
ENERGYFIVE-MIB::ip.0 = IpAddress: 192.168.5.5
ENERGYFIVE-MIB::netmask.0 = IpAddress: 255.255.255.0
ENERGYFIVE-MIB::gateway.0 = IpAddress: 0.0.0.0
Etherio can send traps (described below). To set IP, where SNMP traps will be sent:
ENERGYFIVE-MIB::trapListener.0 = IpAddress: 192.168.20.1
If the trap listener is outside your network, gateway should be set as well:
Digital input returns the current input level, counts level transitions, and sends traps. Input can be optionally inverted, debounced, and configured to ignore too-quick transitions.
The number of digital inputs available for device can be read from digitalInputsNumber.0.
Digital inputs (as well as other ports) are presented as a SNMP table. To get digital input 3 level:
ENERGYFIVE-MIB::diLevel.3 = INTEGER: false(2)
1 = high level, 2 = low level
Often we are interested not in the level itself, but the transition from level to level. diCaptureEdge tells Etherio which transition to capture:
- rising edge = 1
- falling edge = 2
- both rising and falling edges = 3
- track nothing = 0
Captured edges are counted in diEdgeCount and may be additionally sent via SNMP trap (see diTrapOnEdge). To capture only falling edges on port 5:
Every captured edge (specified by diCaptureEdge) increments diEdgeCount. If diCaptureEdge = 1, diEdgeCount increases by 1 every rising edge. But if diCaptureEdge = 3, it increases by 1 on rising and then again by 1 on falling edge. The counter increases until 4294967295 and then overflows into 0. Not only is read of diEdgeCount possible, but also write; it can be useful to reset the counter.
To get edge counters for inputs 2 and 5:
ENERGYFIVE-MIB::diEdgeCount.2 = Counter32: 3
ENERGYFIVE-MIB::diEdgeCount.5 = Counter32: 35240
Sending trap on edge
If diTrapOnEdge for port is true (1), SNMP trap will be sent on every captured edge (as defined in diCaptureEdge). Trap is sent to IP, specified by trapListener, port 162. If trapListener is in another network, the gateway should be specified.
Traps are described in edgeNotification (188.8.131.52.4.1.506184.108.40.206). Each port has two individual trap OIDs: one for rising edge, one for falling. This allows you to implement simple logic using just snmptrapd.Here is an example of a notification about door state via Telegram. %%NUMBER%% and %%API_KEY%% should be replaced with the actual bot number and API key, obtained during bot creation. It's free and fast.
traphandle .220.127.116.11.4.1.50618.104.22.168.1.0.1 curl.exe -s -X POST https://api.telegram.org/bot<strong>%%NUMBER%%:%%API_KEY%%</strong>/sendMessage -d chat_id="@etherio" -d text="Box 1: Door closed"
traphandle .22.214.171.124.4.1.506126.96.36.199.1.0.2 curl.exe -s -X POST https://api.telegram.org/bot<strong>%%NUMBER%%:%%API_KEY%%</strong>/sendMessage -d chat_id="@etherio" -d text="Box 1: Door opened"
The format of OID is 188.8.131.52.4.1.506184.108.40.206.P.0.E, where P is port number (from 1 to digitalInputsNumber), and E is edge direction (1 - rising, 2 - falling).
A possible application of digital input is push-button. We may expect a button press to produce a single-level transition to capture, but in fact there is always some bouncing before the level changes finally and digital input is fast enough to capture some odd edges. To capture only the actual button press, every digital input is equipped with debounce logic, so impulses shorter than diDebouncePeriod ms are ignored: they are not visible on diLevel, not counted, and do not cause traps. diDebouncePeriod can be tuned experimentally; however, for most cases, switching to 40 ms is a good start. Of course it may be 0, so we'll have to see for every transition. To enable 40 ms debouncing on port 3:
Ignoring repeated keypressesWhen a human presses a button and the system doesn't produce immediate feedback, the user tends to press the button again and again. diMinDelayBetweenEdges lets the system to ignore odd presses. After the transition is captured, the input will ignore subsequent transitions during diMinDelayBetweenEdges. It looks like diDebouncePeriod, but diDebouncePeriod suppresses a fast electric bounce, while diMinDelayBetweenEdges suppresses a slow intentional bounce by the user.
Expressed in 1/10 seconds: For example, 20 means that only a single transition per 2 seconds will be captured:
Of course it's a good idea to provide the user with feedback, indicating that the button press is processing.
Transitions, filtered by diDebouncePeriod and diMinDelayBetweenEdges, are not captured and do not cause a trap.
Sometimes it's intuitive to treat levels in some way (for example, a high level is the presence of something, while a low level is the absence), but circuitry supplies a reversed signal. diInvert allows you to invert it back to make configuration more natural. If enabled, inversion happens in the very first turn, and all further processing is done with an inverted signal.
- 1 - inversion enabled
- 2 - inversion disabled
Digital input scheme shows all digital input processing steps, their order, and SNMP properties involved:
Each digital output allows you to set levels permanently or as a pulse – single or periodic. The number of digital outputs available on device can be read from digitalOutputsNumber.0.
doLevel allows you to set the output level. 1 = high, 2 = low:
Etherio can do pulses on digital out. It's done by setting the desired pulse length in ms to doPulse. A positive length makes for a high-level pulse, while a negative length makes for a low-level pulse.
After setting doPulse, doLevel is set to 1 (high level). Each millisecond doPulse decreases by 1, and when it reaches 0, doLevel sets to 2 (low). A negative doPulse has the opposite logic: doLevel sets to 2 (low), doPulse increases till 0, and then doLevel sets to 1 (high). doPulse is available for reading. It allows you to check the number of ms remaining.
It's ok to “start” high pulse when doLevel is already high. The logic remains as described before, so in fact it means “set low level after doPulse ms”.
doPulse in progress doesn't block doLevel from write.
doLevel is not persistent; to define level on device boot-up, doBootUpLevel should be set.
Pulses can be periodic. It's done with doPeriod, doDuty and doPeriodsLeft. For example, SET doPeriod=1000, doDuty=500, doPeriodsLeft=3 will make 3 half-second pulses, one per second.
When doPeriod and doPeriodsLeft both become non-zero, doPulse is set equal to doDuty and pulse begins. When doPulse ends, it is set again to (doPeriod-doDuty) with the opposite sign, starting the second part of period. When second doPulse ends, doPeriodsLeft decreases by one and everything repeats until doPeriodsLeft is not 0. If doPeriodsLeft = -1, pulses will be repeated forever until setting doPeriodsLeft to zero with another request.
Order is important here. (TL;DR: set doDuty first). Variables are set from left to right one by one. Let's say we are setting doPeriod=1000, doPeriodsLeft=3, doDuty=500. Setting doPeriod and doPeriodsLeft non-zero is sufficient to start the first pulse. In such cases, the old value of doDuty will be taken, not the one we are going to set third. So again, just set doDuty first.
Configuration of outputs on boot
doPeriod, doPeriodsLeft and doDuty are reset on the Etherio reboot. To start periodic pulses after device boot, there are doBootUpPeriod, doBootUpDuty and doBootUpPeriodsLeft properties for each output. Their values are copied to doPeriod, doDuty and doPeriodsLeft on boot.
If doInvert is true (1=true; 2=false), output level is inverted. Inversion is done last.
Analog input allows you to perform measurements. There are adapters for different measurements: voltage, current, temperature, etc. Etherio detects the type of connected adapter automatically. The number of analog inputs available can be read from analogInputsNumber.0.
The measured value is in aiValue; units of measurement is in aiUnits.
aiType contains the type of adapter attached (Voltage, Current, etc.); aiDescription contains the extra description. aiRawValue contains raw value from ADC.