Controlling Physical Devices via Approval Processes in Force.com
My kids leave the lights on at home. All the time. It's so bad, I decided to tackle the problem at its source, by introducing an approval step into the 'switch light on' process via Force.com. See how I hooked a Raspberry Pi and a desk lamp to Force.com to reduce my power bills...
My kids leave the lights on at home. All the time. It’s so bad, I decided to tackle the problem at its source, by introducing an approval step into the ‘switch light on’ process via Force.com. Actually, I’m joking; Kevin O’Hara and Reid Carlberg‘s antics inspired me to try hooking my Raspberry Pi to the platform. I recently bought a PowerSwitch Tail II, so I was looking for a project where I could control some simple appliance; this is what I came up with.
Here’s how that all works…
Starting with the tactile button switch; it’s wired to pin 24 of my Raspberry Pi. A simple Python app running on the Pi uses the OAuth 2.0 Resource Owner Password Credentials Grant (also known as the username-password flow) to authenticate to Force.com and obtain an access token. The app samples the state of the button every hundredth of a second. If the state of the button (up/down) is different from the last sample, the app sends an HTTP POST to an Apex REST method with the access token in an HTTP header and the state of the button as its payload.
The Apex REST method queries for the appropriate Light__c custom object record (the code assumes there’s just one right now, but an identifier for the light could be added to the URL) and, if the state of the light is Off, modifies the state to Request On, updates the record, and fires the approval process. If the state of the light is On, it simply modifies the state to Off and updates the record. I’ll let my kids turn the light OFF whenever they like! The approval process includes an action to change the state from Request On to On, assuming I give my approval!
A trigger on Light__c detects the state transition to On or Off and, since it cannot make a callout directly, invokes a @future method. That method sends an HTTP POST with the desired state of the light to a second Python app running on the Pi. I used Flask, a lightweight Python web framework, for this app; the effectiveness of Flask is demonstrated by the fact that the web app required less than 20 lines of code. This blog post guided me in my choice of Flask, and its installation on the Pi. I also had to assign the Pi a static IP address, and configure my router to forward incoming traffic on port 5000 to the Pi, so I could access the Pi from the cloud.
The app completes the chain of events by changing the state of pin 25 of the Raspberry Pi according to the incoming POST, pin 25 driving the PowerSwitch, which makes a satisfying ‘clack’ as its relay actuates.
So – how useful is this? Not very, given that it’s easy to subvert by just removing the PowerSwitch and plugging the lamp into the outlet; not to mention the fact that the POST to control the lamp is not secured in any way, but it demonstrates that we can control external processes with building blocks like Force.com Approvals. Instead of a button, there might be an incoming SOAP message from some legacy system. Instead of the light, there might be an outgoing message sent to some ERP system.
And, you know what, hitting ‘Approve’ and seeing the lamp light was a LOT of fun.
What are you going to make with Force.com?