I’m trying to create a simple generic handler for a range of legacy devices (if something similar already exists, I’d appreciate a link). Actuators were pretty simple, but sensors have me stumped and seeking help. Please excuse the newbie questions.
The basic idea is that a simple script running on an always-on computer at the location acts as a bridge between ST and the legacy devices. This computer might be a small board (Raspberry Pi, Beaglebone, Odroid, CHIP), a server that primarily performs other functions (fileserver, webserver, PBX), or a normal workstation.
Most of these devices lack IP connectivity. Examples include an X10 USB interface (CM15A), a weather station with a serial port, or a relay driven directly by a port on the computer, e.g. an RPi GPIO pin or PC parallel port pin.
Some devices speak IP, but have no official API, e.g. an alarm panel with a web page that displays current status of all zones. A simple script would poll the page every second, compare current and previous results, and report any changes to ST.
Ideally, several scripting languages would be supported (python, perl, PHP, pick-your-poison); these are usually pre-installed on most Mac and Linux systems and are freely available and easily installed on Windows. The developer would choose whichever is most familiar.
Actuators were no trouble: the device type handler makes an HTTP request, which runs a CGI script (at the location) that issues the required command.
But I don’t understand how to make sensors work. There are several examples using poll(), but such schemes are incompatible with applications that need a response within one or two seconds. There are also examples using additional hardware in the path. I’d like to avoid that approach not only because of cost, reliability and complexity issues, but also so that presently unoccupied locations can start utilizing ST.
I was able to write a ‘web services’ SmartApp that accepts updates from a remote sensor and responds by issuing commands to remote actuators. However, that’s not a viable solution, because all the business logic would have to be in that app. What’s needed is a way for the remote sensor to fire events (so other apps can use it as a normal device). That ought to be simple, but it has me stymied:
The IDE allows me to enable OAuth in a device type handler, and it displays a corresponding Client ID and Secret. However, attempting to use said Client ID results in an error “Client <Client ID> is not associated with a SmartApp.” That is of course true, but I don’t understand why it should be an error. The ID seems valid in some sense, because changing one character results in a ‘500’ error instead. How does one use OAuth in a device handler?
Then, I tried calling sendEvent() from a web services SmartApp, but have been unable to cause any action. The documentation shows two signatures:
void sendEvent(Map properties) and
void sendEvent(Device device, Map properties). I would assume that if an app is connected with exactly one device, the first form would use that device. But if I try e.g.
sendEvent(name: “contact”, value: newstate), although no error is flagged and execution continues with the next statement, the event never fires. Trying e.g.
sendEvent(contact1, [name: “contact”, value: newstate]) results in a ‘no matching signature’ error. The only two-parameter examples I found for sendEvent use a device network ID for the first argument. Although deviceNetworkId is not documented as a property of Device, it does seem to exist and e.g.
sendEvent(contact1.deviceNetworkId, [name: “contact”, value: newstate]) seems to be a valid call, but results in an internal null pointer exception. What am I doing wrong here? Or, is there a simple example of an incoming request triggering an event?
Thanks for taking the time to read this rambling post, and for any guidance you can offer.