Do you still own a home phone? I do! It came with my cable and Internet service as a bundle. This tutorial will show you how to integrate your home phone with OpenHAB.
Get an Orange Pi Zero ($9!!!)
I used an orange pi zero mainly because of the built-in ethernet. Though its bandwidth is shared amongst the USB hub, it’s more than adequate for this purpose.
Install Armbian
Perhaps any other ARM-based OS of your choice!
At the time of this tutorial, I used the headless Armbian_5.35_Orangepizero_Ubuntu_xenial_default_3.4.113
Get a USB Modem
We need to have a way to connect the Pi to the phone jack. A USB dial-up modem should suffice.
-
Plug in
-
Check using lsusb/dmesg
lucky@callerid:~$ lsusb ... Bus 006 Device 003: ID 0572:1340 Conexant Systems (Rockwell), Inc.
lucky@callerid:~$ sudo dmesg | grep USB ... [ 1222.944998] cdc_acm 6-1:1.0: ttyACM0: USB ACM device [ 1222.981669] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters ...
Important: make note of: dc_acm 6-1:1.0: ttyACM0: USB ACM device
Good! Pi recognized the device without any extra drivers needed.
Get a Phone Jack (RJ11) splitter
If you have a spare phone jack in your home, then you won’t need this.
Configure your Orange Pi
- sudo armbian-config
I often change the timezone and locale settings, as well as the hostname of the device.
Optional: Add the MAC ID to your DHCP server to manually set the route.
Installation
- Update then upgrade
- sudo apt-get update
- sudo apt-get upgrade
- This will take a while.
- Take a coffee break.
- Install required packages and tools
- sudo apt-get install libpcap0.8-dev
- sudo apt-get install build-essential
- sudo apt-get install gdebi
- Get and install the package
- wget http://cfhcable.dl.sourceforge.net/project/ncid/ncid/1.7/ncid_1.7-3_armhf.deb
- sudo gdebi ncid_1.7-3_armhf.deb
- Configure
- Edit configuration file
- sudo nano /etc/ncid/nicdd.conf
- set ttyport = /dev/ttyACM0
This is from your dmesg command above
- set ttyport = /dev/ttyACM0
- sudo nano /etc/ncid/nicdd.conf
- Start the service
- sudo service ncidd start
- Edit configuration file
Initial Testing
-
Telnet to your orange pi IP using port 3333…
-
Call the phone number the phone jack is connected to. You should see your own phone number and this output in telnet:
200 Server: ncidd (NCID) 1.7 210 API: 1.6 Feature Set 1 2 3 4 5 252 Call log empty OPT: LineIDS: POTS 300 End of connection startup CIDINFO: *LINE*POTS*RING*1*TIME*23:21:34* CID: *DATE*02062018*TIME*2321*LINE*POTS*NMBR*XXXXXXXXXX*MESG*NONE*NAME*MALLARI LUCKY* CIDINFO: *LINE*POTS*RING*0*TIME*23:21:46*
It works! You should see your phone number instead of the XXXXXXXXXX. As you can see, it shows my name also (this will be the caller’s name).
Notes
- NCID is very lightweight. You can install this alongside your OpenHABian
OpenHAB Integration
-
Configure your item (change IP and PORT)
String callerid_raw "[%s]" { tcp=">[192.168.1.166:3333:'REGEX((.*))']" } DateTime callerid_time "[%s]" String callerid_phone "[%s]" String callerid_name "[%s]" String callerid_message "[%s]" ```
-
Add your rule
/* Items: String callerid_raw DateTime callerid_time String callerid_phone String callerid_name String callerid_message */ import java.text.DateFormat import java.text.SimpleDateFormat import java.util.Date rule "Caller ID" when Item callerid_raw changed then var raw = callerid_raw.state.toString logInfo("CallerID", "..parsing") if (raw.contains("CID:")) { //CID: *DATE*02062018*TIME*2321*LINE*POTS*NMBR*XXXXXXXXXX*MESG*NONE*NAME*SMITH JOHN* var parts = raw.split("\\*") var callerDateTimeString = parts.get(2) + parts.get(4) val callerNumberRaw = parts.get(8) var callerMessage = parts.get(10) var callerName = parts.get(12) if (callerMessage == "NONE") callerMessage = "" val String callerNumber = callerNumberRaw.substring(0, 3) + "-" + callerNumberRaw.substring(3,6) + "-" + callerNumberRaw.substring(6) var DateFormat format = new SimpleDateFormat("MMddyyyyHHmm"); var Date callerDateTime = now try { callerDateTime = format.parse(callerDateTimeString); } catch(Throwable t) { logError("CallerID", "Unable to parse date: " + callerDateTimeString) } val String toHabPanelVoice = "Call from " + callerName + " (" + callerNumber + ") on " + new SimpleDateFormat("hh:mm a").format(callerDateTime) + " {" + callerMessage + "}" sendCommand(hp_s_voicer, toHabPanelVoice) sendCommand(hp_s_activateDashboard, "Caller ID") sendCommand(callerid_time, DateTimeType.valueOf(new SimpleDateFormat(DateTimeType.DATE_PATTERN).format(callerDateTime))) sendCommand(callerid_phone, callerNumber) sendCommand(callerid_name, callerName) sendCommand(callerid_message, callerMessage) } end
Note this:
val String toHabPanelVoice = "Call from " + callerName + " (" + callerNumber + ") on " + new SimpleDateFormat("hh:mm a").format(callerDateTime) + " {" + callerMessage + "}" sendCommand(hp_s_voicer, toHabPanelVoice) sendCommand(hp_s_activateDashboard, "Caller ID")
That’s for my HABPanel. It will:
- Say “call from …”
- Switch to this dashboard:
HABPanel Template Widget
<style>
.callerid {
font-size: 16px;
text-align: center;
}
.callerid h1, h2 {
margin: 0;
position: relative;
width: auto;
}
.callerid h1 {
font-size: 10em;
color: darkkhaki;
animation: blinker 1s linear infinite;
}
.callerid h2 {
font-size: 7em
}
.callerid div {
font-size: 4em
}
@keyframes blinker {
50% { opacity: 0; }
}
</style>
<div class="callerid">
<h1>Phone Call!</h1>
<h2>{{itemValue('callerid_name')}}</h2>
<div><em>{{itemValue('callerid_time') | date: 'M/dd/yy HH:mm a'}}</em></div>
<div>{{itemValue('callerid_phone')}}</div>
<div>{{itemValue('callerid_message')}}</div>
</div>
What’s Next (TO-DO)
I’ll show you how to turn this as a
- Screener (blacklist calls based on phone numbers/marketers)
- Answer calls
- Make phone calls (good for a Panic! button by dialing 911)
- Send a fax