I have been using two of these Ethernet Relay Boards (ERBs) with our HA system for the past few months. They're reasonably priced, and seem to be well-made. Best of all, they're very fast/responsive and have proven to be 100% reliable so far. I've been impressed, so I thought I'd spread the word. They appear to be available from several different Asia-based eBay sellers; I'm in no way affiliated with any of them. Just a satisfied customer.
You'll need a separate 12V DC power supply with a standard 2.1mm x 5.5mm barrel plug on it (like this one), and an Ethernet cable to connect the ERB to your network (no Wi-Fi).
The ERB presents a rudimentary on-board, web-based UI which allows you to query, control and configure the hardware via any web browser. Or you can use any other software that can send basic http commands over your network, and read the response. I'm currently using AppleScript (more on that below).
There is little to no documentation available, and none at all was provided with the board itself. The package contained only a naked circuit board in an anti-static bag.
However, one of the other eBay sellers (can't seem to find the link now) had some very basic instructions on his/her eBay listing, and from that I was able to gain access via Safari. From there, I managed to cobble together an AppleScript that provides full control and query functionality. Obviously, the same could have been done using Python or virtually any scripting/coding language. But I chose AppleScript since I need to control one ERB using Remote Buddy, and the other using Indigo. Remote Buddy doesn't speak Python, and I'm too lazy to write the handlers twice. Fortunately, Indigo is multilingual!
NOTE TO MATT & JAY: Don't you dare drop that AppleScript support!

Currently, I'm using one ERB to control a haked Hunter Ceiling Fan remote that I also bought on eBay. This allows us to control our living room ceiling fan and light (including the reverse function!) using our Harmony Elite remote (via Remote Buddy).
I'm using a 2nd ERB in a modified/updated version of our Vehicle Remote Start feature with Indigo. This one turned out to be a VERY long and somewhat humorous saga. Another post about that later...
Things you'll need to know:
DHCP is not supported, so you must assign a static IP address suitable for your network. Factory defaults are:
IP address: 192.168.1.167
Netmask: 255.255.255.0
Default Gateway: 192.168.1.1
HTTP Port: 80
TCP Port: 1234
User name: "admin"
Password: "12345678"
Below is a set of simple AppleScript handlers I put together for my own testing and documentation. Feel free to copy and use as you see fit. All the usual caveats, disclaimers, and warnings apply. Use at your own risk.
Feel free to post any questions/comments.
Enjoy!
- Code: Select all
(*
Ethernet Relay Board (ERB) Control Script
v1.0 - July 12, 2016
This script contains handlers for controlling the 8-Channel Ethernet Relay board purchased via eBay last week:
http://www.ebay.com/itm/182011913244
This ethernet-accessible relay board has 8 individual single-pole, double-throw relays with contacts rated for 10A at 227VAC, 12A AT 125VAC
It is controlled via a simple web-based interface, but no documentation of any kind was provided. After hunting around on eBay, I found
a few other sellers offering the same board for sale. Most had at least enough information to access the board via the web-based interface.
DHCP is not supported. The default networking parameters are (all are configurable via the web-based interface):
• HTTP port: 80
• TCP port: 1234
• Static IP address: 192.168.1.166
• Username: "admin"
• Password: "12345678"
• Subnet Mask: 255.255.255.0
• Default Gateway: 192.168.1.1
• Primary DNS Server: 194.25.2.129
• Secondary DNS Server: 194.25.2.130
Each relay can be assigned it's own pulse delay value from 1 to 65536 seconds on the "Switch Configuration" page. Each relay is initially assigned
a pulse delay of 1 second.
On the "Switch Control" page in addition to the basic "on" and "off" commands, each relay can be sent a pulse command (misspelled as "pluse")
which will cause it to turn on (energize the coil) for the number of seconds assigned to it, before automatically turning back off.
After looking over the page source for the "Switch Control" page, I discovered that simple HTTP POST requests could be used to send individual
"on", "off", and "pulse" commands to each relay. Additionally, there are commands to turn all 8 relays on or off, but no command to
pulse all 8. I was unable to figure out how to directly query the board for the state of a given relay. As such, I'm doing it the old fashioned
way -- by reading the entire "Switch Control" page (such as it is), then parsing the HTML results to determine the individual relay states. Even so,
these handlers are reasonably fast -- more than fast enough for any real-world control scenario.
The board is very responsive, and functioned without a single glitch or failed command during several hours of testing/debugging of this script.
***
UPDATE 01/25/2017: Two of these ERBs have been in use (one of them multiple times per day, every day) for several months, with no problems or errors.
***
*)
property relayBoardIP : "192.168.1.167"
property relayBoardUser : "admin"
property relayBoardPW : "12345678"
property relayBoardTimeOut : 2
property relayBoardURL : "http://" & relayBoardUser & ":" & relayBoardPW & "@" & relayBoardIP & "/relay_en.cgi"
set r to 8
set s to true
-- Test commands:
-- my setRelayState(r, s)
-- my toggleRelayState(r)
-- set newState to my getRelayState(r)
-- my setRelayStates({true, false, missing value, 1, "true", 0, false, true})
--my setRelayStatesOff()
--my pulseRelayState(r, 0.5)
--my pulseRelayStateNoWait(r, 1.61)
--set stateList to my getRelayStates()
-- realy board handlers ----------------------------------------------------------------------------------------------------------------------------------------
on setRelayState(relayNumber, relayState)
-- set the energized state of the specified relay (the first relay is 1) to the specified state (true is energized)
local theResult, relayCommand
try
set relayNumber to relayNumber as integer
set relayState to relayState as boolean
on error
return ""
end try
if relayNumber > 0 and relayNumber < 10 then
set relayCommand to "off"
if relayState is true then set relayCommand to "on"
try
set theResult to doShellScript({"curl --connect-timeout", relayBoardTimeOut, "--data", "saida" & (relayNumber as text) & relayCommand & "=" & relayCommand, relayBoardURL})
end try
end if
return ""
end setRelayState
on getRelayState(relayNumber)
-- get the energized state of the specified relay (the first relay is 1, true is energized)
local retVal
-- default return value in case of comm failure
set retVal to missing value
set relayNumber to relayNumber as integer
if relayNumber > 0 and relayNumber < 9 then
try
set theResult1 to doShellScript({"curl --connect-timeout", relayBoardTimeOut, relayBoardURL})
set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {"img src=\"", ".jpg"}}
set bs to the text items of theResult1
set retVal to ((text item (relayNumber * 2) of theResult1) is "lighton")
set AppleScript's text item delimiters to TID
on error errMsg number errNum
set fullErrMsg to (errMsg & " (" & errNum as text) & ")." -- for degugging purposes
end try
end if
return retVal
end getRelayState
on toggleRelayState(relayNumber)
-- toggle the energized state of the specified relay (the first relay is 1)
local currentState
set relayNumber to relayNumber as integer
if relayNumber > 0 and relayNumber < 9 then
set currentState to my getRelayState(relayNumber)
if currentState is not missing value then
my setRelayState(relayNumber, not currentState)
end if
end if
end toggleRelayState
on setRelayStates(newStates)
-- set the states of the specified relays (the first relay is 1) to the specified states (true is energized)
-- newStates is assumed to be a list of booleans (or values that can be coerced to booleans)
-- each value in the list is used to set the state of the corresponding relay, in order. That is, the first value in the list determines
-- the state of relay 1, the second value determines the state of relay 2, etc. If there are fewer than 8 values in the list,
-- the remaining relays' states will be unaltered. If there are more than 8 values in the list, the extras are ignored.
-- if 'missing value' is encountered or if a value cannot be coerced to a boolean, the corresponding relay's state is left unaltered.
local fullErrMsg
local stateCount
try
set newStates to newStates as list
on error errMsg number errNum
set fullErrMsg to (errMsg & " (" & errNum as text) & ")." -- for debugging purposes
return
end try
if newStates is {} then return
set stateCount to the count of newStates
if stateCount > 8 then set stateCount to 8
repeat with i from 1 to stateCount
set thisState to item i of newStates
if thisState is not missing value then
try
my setRelayState(i, thisState as boolean)
on error errMsg number errNum
set fullErrMsg to (errMsg & " (" & errNum as text) & ")." -- for debugging purposes
end try
end if
end repeat
end setRelayStates
on setRelayStatesOn()
-- set the states of all 8 relays to on (energized) simultaneously
my setRelayState(9, true)
end setRelayStatesOn
on setRelayStatesOff()
-- set the states of all 8 relays to off (not energized) simultaneously
my setRelayState(9, false)
end setRelayStatesOff
on getRelayStates()
-- return a list of 8 boolean values corresponding to the current states of relays 1-8
local retVal
-- default return value in case of comm failure
set retVal to missing value
try
set theResult1 to doShellScript({"curl --connect-timeout", relayBoardTimeOut, relayBoardURL})
set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {"img src=\"", ".jpg"}}
set bs to the text items of theResult1
set retList to {}
repeat with i from 1 to 8
set the end of retList to ((text item (i * 2) of theResult1) is "lighton")
end repeat
set AppleScript's text item delimiters to TID
return retList
on error errMsg number errNum
set fullErrMsg to (errMsg & " (" & errNum as text) & ")." -- for degugging purposes
end try
return retVal
end getRelayStates
on pulseRelayState(relayNumber, delaySeconds)
-- pulse the energized state of the specified relay (the first relay is 1). "Pulse" means to energize the relay, then after a delay, de-energize it
-- delaySeconds can be any floating point value greater than zero. If delaySeconds is missing value or <= 0, the command is ignored.
-- this handler executes the delay in software (not dependent on the relay board's pulse delay settings), and returns only after completion
local fullErrMsg
try
if delaySeconds is missing value or (delaySeconds as number) ≤ 0.0 then
return
end if
set theResult to doShellScript({"curl --connect-timeout", relayBoardTimeOut, "--data", "saida" & (relayNumber as text) & "on=on", relayBoardURL, ";sleep", ((delaySeconds as number) as text), ";", "curl --connect-timeout", relayBoardTimeOut, "--data", "saida" & (relayNumber as text) & "off=off", relayBoardURL})
on error errMsg number errNum
set fullErrMsg to (errMsg & " (" & errNum as text) & ")." -- for debugging purposes only
end try
end pulseRelayState
on pulseRelayStateNoWait(relayNumber)
-- pulse the energized state of the specified relay (the first relay is 1) and return immediately; do not wait for the completion of the pulse cycle
-- "Pulse" means to energize the relay, then after a delay, de-energize it; the ERB's on-board pulse function is used, and the pulse delay will
-- be as configured for the specified relay.
local fullErrMsg
try
-- use the relay board's built-in pulse command, causing the specified relay to pulse for the number of seconds set on the "Switch Configuration" page (min = 1 sec)
set relayCommand to "pluse" -- the word "pulse" is misspelled in the firmware
set theResult to doShellScript({"curl --connect-timeout", relayBoardTimeOut, "--data", "saida" & (relayNumber as text) & relayCommand & "=" & relayCommand, relayBoardURL})
on error errMsg number errNum
set fullErrMsg to (errMsg & " (" & errNum as text) & ")." -- for debugging purposes only
end try
end pulseRelayStateNoWait
on doShellScript(parmList)
local retVal, theCommand, TID, errMsg, errNum, testMode
try
set retVal to ""
set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, " "}
set theCommand to parmList as text
set AppleScript's text item delimiters to TID
set retVal to do shell script theCommand
on error errMsg number errNum
set retVal to (errMsg & " (" & errNum as text) & ")."
end try
return retVal
end doShellScript