When the phone rings in my small office, Frizzix tells me instantaneously
who’s calling, and I can decide whether to take the call or not. (I usually do,
because few people phone me.) It’s a nice utility is no longer maintained, but I can neither automate
it nor can I easily save the call logs, and doing that from the FritzBox Web
interface is a nuisance. And when I’m not at home, I’m blissfully unaware that
somebody called, but curious nonetheless. I was curious whether I could be
notified of calls in “real-time”.
Enter openHAB.
My initial experiments with openHAB have been fruitful, and with a bit of help in understanding some of the more intricate combinations, I’m progressing in automating the Intranet of Things at Casa Mens.
openHAB has a FritzBox binding (there’s also an Asterisk counterpart) which I can use to trigger switches on incoming calls. This binding updates an openHAB item when it detects a call on the FritzBox, useful for, say, automatically muting the Sonos when the phone rings. This item definition looks like this:
Call Incoming_Call_No
"Caller No. [%2$s]"
(Phone)
{ fritzbox="inbound" }
That item definition suffices for openHAB to detect an incoming log, which it shows in its log:
17:22:00.095 INFO runtime.busevents[:26] - Incoming_Call_No state updated to 05556302547##1234567
17:22:49.607 INFO runtime.busevents[:26] - Incoming_Call_No state updated to ##
If I place that item on an openHAB sitemap I can see the Caller-ID (CID) on the UI (which I don’t want), but what else can I do with that trigger?
When I first discussed my experiments in home automation I wrote about using MQTT extensively, and for me that has been a very good decision. So the question was: can I get openHAB to
- detect an incoming call with the FritzBox binding
- invoke a rule with that CID number
- perform an external lookup on the number to obtain a matching name from my address book
- store the result in a database
- publish the result to an MQTT topic
and the answer is a resounding YES!
The rule
When the incoming call triggers the Call
switch, openHAB invokes this rule I
patiently assembled with a lot of trial and error, and error, and help from the
knowledgeable chaps on the mailing-list.
import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.java.math.*
import org.joda.time.*
import org.openhab.library.tel.types.CallType
rule "Incoming Phone Call"
when
Item Incoming_Call_No changed
then
var CallType c = Incoming_Call_No.state
var String caller = "" + c.origNum
var String callee = "" + c.destNum
var String command
if (caller != "" && callee != "") {
var String cid
command = "/usr/local/bin/phone.py '" + caller + "'"
cid = executeCommandLine(command, 2000)
mqFritz.postUpdate(cid)
}
end
The rule gets the calling number (which may be empty if a caller suppresses it) and executes an external command. (I’d be weary of having openHAB do that on a very busy “trigger”, but it’s not an issue in this case; I don’t get many phone calls… ;-) This little program does a reverse lookup on my address book database, and it returns a string with the number and a name in parentheses.
$ /usr/local/bin/phone.py 05556302547
05556302547 (Jane Jolie)
(Note the binding supplies an empty caller on anonymous calls, and both values are empty when the call ends.)
The rule then posts an update to another openHAB item, this time a String item
String mqFritz
(mqtt)
{mqtt=">[hippo:home/fritz/incoming:state:*:DEFAULT]"}
This item is bound to an MQTT publish string which causes openHAB to publish the value to my MQTT broker. From there, believe it or not, the Caller-ID is pushed to my mobile phone. (How that works is a longish story :-)
17:22:00.095 INFO runtime.busevents[:26] - Incoming_Call_No state updated to 05556302547##1234567
17:22:00.262 INFO runtime.busevents[:26] - mqFritz state updated to 05556302547 (Jane Jolie)
17:22:49.607 INFO runtime.busevents[:26] - Incoming_Call_No state updated to ##
Persistence
There is one thing missing from my five-point checklist above: I wanted the result persisted to a database, trivial to accomplish in my small Python program, but that’s no fun!
As mentioned in my last post I can configure openHAB to persist any state updates and changes to different storages, including a built-in db4o database, rrd files, etc. I chose to use a MySQL database to keep track of a few values including callers.
Persistence is configured on a per/item basis in a .persist
file:
Items {
SunRiseTime : strategy = everyDay, restoreOnStartup
mqFritz: strategy = everyUpdate
}
Resulting from this configuration, I find the following tables in the database:
mysql> SELECT * FROM Items;
+--------+----------------------+
| ItemId | ItemName |
+--------+----------------------+
| 11 | SunRiseTime |
| 13 | mqFritz |
+--------+----------------------+
mysql> SELECT * FROM Items13;
+---------------------+---------------------------------+
| Time | Value |
+---------------------+---------------------------------+
| 2014-02-15 17:22:00 | 05556302547 (Jane Jolie) |
+---------------------+---------------------------------+
I wouldn’t put frequently-changing states in MySQL, rather relying on, say, rrd for things like that, but for my use-case this is perfect.
Presence
The WAF for this is pretty good, but the Señora doesn’t appreciate the notifications whilst en casa. It ought to be easy to add an openHAB switch item which disables notifications to MQTT (and hence onto her mobile device) when she’s at home. And we can automate that presence detection with the binding for OwnTracks (formerly MQTTitude).
I’ve said it before, and I’ll say it again: openHAB and MQTT are a great combination. As Ben succinctly writes:
Using MQTT you can effectively decouple all notifications from within openHAB. This means you no longer need to load the Mail, Twitter, Prowl, NMA, or XBMC action bundles, and you can replace all your notification rules with very simple one-line statements
Good stuff.