PJSIP Edition – How to use an Obihai 200 series VoIP device as a gateway between Google Voice and FreePBX

TelephoneA year ago we published an article entitled “How to use an Obihai 200 series VoIP device as a gateway between Google Voice and FreePBX” and in that article we noted that we were using chan_sip even though chan_sip is being deprecated. So on the one-year anniversary of that article we thought we’d show you how to do the same thing, but using PJSIP. This article is actually a duplicate of that original article, but with all the parts that used chan_sip now changed to use PJSIP, plus a bit of additional text.

This article is intended for a specific, probably rather narrow group of readers. It is for people who have experience setting up and configuring FreePBX, and who also currently own an Obihai 200 series device (200 or 202), and that are using standard Obihai firmware and use Obihai’s “OBi Dashboard” to configure your device. It is specifically not intended as an inducement for anyone to go out and buy a new Obihai device, because in our opinion Obihai hasn’t been treating its customers very well lately, and we have no reason to think that will change. And it is also not for those who like to run custom firmware, or that think that the “OBi Dashboard” is in some way evil – although if you do, this method will probably work just as well on a locally-configured Obihai. But if you happen to have an Obihai 200 series device lying around, and you are running FreePBX, you can put it to good use. This method might also work on an unlocked 300-series device running certain custom firmware but we have no experience at all with that, so we aren’t saying it will or won’t work in such a case, and we don’t support such usage. This method will not work with older Obihai 100-series devices, though you can still use those for FreePBX extensions or other types of SIP connections.

As always we are telling you how we did this, which is not necessarily how you should do it. Any changes you make to your Obihai or FreePBX configuration are at your own risk, and we assume you know what you’re doing. If you somehow manage to really screw things up, that’s on you, not us. We don’t guarantee that this will work for everyone, we just know it did for us.

Some other technical information: The method we show here uses PJSIP, not the older chan_sip, for the connection to FreePBX. We note that chan_sip is being deprecated in the newest versions of Asterisk but we suspect that it will more than likely continue to work for years to come. Nevertheless, some have chosen to bite the bullet and convert to PJSIP now, so this revision of the article is for those folks. We assume that you have already set up your extensions and trunks to use PJSIP rather than chan_sip, and therefore we won’t go over the basics of PJSIP configuration, except as they relate to this specific use.

We do suggest that if your Obihai device has previously been configured, you follow this procedure to start over with a clean configuration:

  • Completely remove the device from the “OBi Dashboard”, as you would if you planned to transfer ownership to someone else.
  • Then do a hard reset of the Obihai device – dial ***8 from a connected phone and follow the prompts to restore the factory default settings.
  • If there were previously one or more Google Voice accounts configured on the device and you plan to continue using any of those same accounts, log into those Google Voice accounts and remove the Obihai device as a destination. If you don’t do this, then after following this procedure you will see two Obihai device destinations in each Google Voice account, only one of which will be valid, and it will be difficult to tell which one is the correct one. Also, keeping an old invalid Obihai destination in your Google Voice account configuration may stop incoming calls from getting to your Obihai.
  • Then add the device back to the “OBi Dashboard”, as you would if you had just purchased it new.

This is entirely optional, but it does help make sure that you don’t have any settings from an old configuration messing things up.

Also, you need to have the latest firmware. Dial ***1 to find out the local IP address of your device and go to that page and see if it comes up with the Polycom logo – note that if you cannot access the device, you may need to dial ***0 and then 30# and follow the prompts to enable WAN access. Login using “admin” as the username, and use the password shown under “Webpage Admin Password” on the “OBi Dashboard” at Obihai’s site – on that site you may need to click the gear icon next to your device to see the Webpage Admin Password. If it’s still the default password, this might be a good time to change it to something a bit more secure, but if you do be sure to make a note of it, because you will need it later in these instructions.

If your device’s web pages still come up with the old Obihai logo, dial ***6 to see if new firmware is available, and if so let it install. If it does not find new firmware, then go to System Management/Auto Provisioning, and look to see if there is a value entered for the FirmwareURL setting. You may need to change this to point to a more recent firmware version. For example, our device currently shows this in that field:

IF ( $FWV < 3.2.2.5921 ) FWU http://fw.obihai.com/OBi202-3-2-2-5921EX-332148940.fw

That is all one line even if it is split on this page. We are not telling you to copy that verbatim to your device, just that this field is what seems to control what version of the firmware you receive. Normally if that field is set correctly, your device should grab the latest firmware after a reboot, though you may need to dial ***6 to get it started. Do not unplug or even touch the Obihai while it is upgrading firmware or you may brick it! After a successful upgrade the device’s web pages should be branded Polycom rather than Obihai.

One other thing we very strongly suggest is that you set your Obihai device to a fixed IP address on your local network. This can either be done in the Obihai’s device settings, under System Management/WAN Settings, or in your router’s configuration – it doesn’t matter as long as your Obihai is always at the same local IP address. If you don’t do this you will not be able to use parts of this method.

The assumption we make here is as follows: An Obihai 200-series device can support up to four “service providers”, up to three of which can be Google voice accounts, and one of which is in this method a FreePBX extension. There are technical reasons for this limitation but we won’t go into those here. The point is that any given Obihai 200-series device can bridge up to three Google Voice accounts to FreePBX, and we assume those will be designated as Service Provider 1 (SP1), Service Provider 2 (SP2), and Service Provider 3 (SP3) in the Obihai configuration. Your FreePBX extension will be on SP4. In the case of an OBi202, which has two phone ports, you can have a FreePBX extension associated with each phone port. If you are connecting your OBi202 to only one or two Google Voice accounts, then your two extensions can be on SP3 and SP4. But if you are connecting to three Google Voice accounts and still want to let each phone port on an OBi202 be on a different extension, then assign the extension you want associated with Phone Port 1 to SP4, and we’ll tell you later how to configure the extension you want associated with Phone Port 2.

If you do not use SP4 for at least one of your FreePBX extensions then these instructions probably won’t work for you, since we have assumed throughout that SP4, and by association, ITSP Profile D will be used with your FreePBX extension (or at least with one of them if you have an OBi202). You could modify the instructions to take this into account, but chances are you’re going to miss something and it won’t work as intended.

We assume you know how to configure a FreePBX extension, by selecting a “Generic Service Provider” in the “OBi Dashboard” and then pointing it at your FreePBX server. Once again, just be sure to use SP4 for your FreePBX extension, or the configuration examples shown here won’t work without modification. Note that you may need to modify the phone port’s DigitMap and OutboundCallRoute settings to allow calls to other extensions, but that is beyond the scope of this article. You can make SP4 the Primary Line for Phone Port 1, but if you have an OBi202 we recommend that you do NOT make ANY of the service providers the Primary Line for Phone Port 2, at least not yet. OBi200 users don’t need to worry about this; it won’t affect you because you only have a single phone port.

You can configure your Google Voice account(s) in the normal manner using the “OBi Dashboard”, in fact if there’s a way to do it without using the Dashboard we don’t know about it, at least not without using custom third-party firmware which is beyond the scope of this article. Get everything set up and working normally – get your first Google Voice account set up on SP1 and make sure it is working, then if you have additional accounts add them on SP2 and if necessary, SP3. Make sure that you can make and receive calls on your Google Voice account(s) before you go any further. Note that you can use dialing prefixes to make test calls using a particular Service Provider without setting it as your Primary Line – for example **1 followed by the number you are calling will send the call through the account associated with Service Provider 1 in the Obihai configuration, and the **2 and **3 prefixes will do the same with regard to Service Providers 2 and 3.

So now that you have your FreePBX extension working and your Google Voice accounts set up and configured, there are two things that need to happen. One is to redirect all incoming Google Voice calls to a FreePBX PJSIP trunk, which will be used for incoming calls only. And the other is to send all outgoing calls to a Custom trunk, and configure the Obihai to correctly route them to the correct Google Voice accounts. Some users may not need both of these – for example, if your main reason for wanting to route calls through FreePBX is so you can use its blacklist and other call screening features on incoming calls, then you may not need the outbound connectivity. But we’ll show you how to do both.

Preliminary FreePBX Configuration for PJSIP users:

In FreePBX’s settings please check your Asterisk SIP settings, PJSIP tab, and look to see what the Endpoint Identifier Order is set to. The Default order as of this writing is as follows:

  • ip
  • username
  • anonymous
  • header
  • auth_username

But this order will prevent proper operation if you have two or more things registering or sending traffic from the same IP address. So, for example, if you are using an Obihai as both an Asterisk extension (for a phone plugged into the phone port) and as an Asterisk trunk, all incoming traffic will be considered as one or the other if you are using the default Endpoint Identifier Order, because all that traffic is coming from the same IP address. So we recommend changing the order to this:

  • auth_username
  • username
  • ip
  • anonymous
  • header

What you don’t want is for it to match on the IP address first. If you’ve been having problems getting PJSIP to work generally, changing this order from the default to our recommended order may cure several ills. If you are converting from chan_sip, it’s rare that you’d want to first match on the IP address! Note that after you make this change and you reload FreePBX, you must also restart Asterisk for it to take effect (use “core restart gracefully” or “core restart when convenient” from the Asterisk CLI).

Handling incoming Google Voice calls:

☞ These changes must be made using the OBi Dashboard’s Expert Configuration option.

Go to Voice Services/Gateways & TrunkGrps – we’ll be changing the settings for Voice Gateway1 (vg1). You can use any unused Voice Gateway, but the examples here assume the use of vg1. Start by unchecking the checkboxes under “OBiTALK Settings” for these values: Name, AccessNumber, AuthUserID, and AuthPassword. Then click “Submit” at the bottom of the page. If any of the checkboxes in the “Device Default” column for those settings are now checked, uncheck them and click “Submit” again. You need to do this or the page won’t let you enter the new values. This is true anyplace we make changes to any of the settings in the OBi Dashboard – if either of those boxes are checked, they must be unchecked and “Submit” clicked before you can make changes.

Now you can enter the new settings for vg1:
Name: Anything you like to identify it, such as FreePBX trunk
AccessNumber: SP4(192.168.x.x) – replace 192.168.x.x with the fixed IP address of your FreePBX server
AuthUserID: The FreePBX trunk name, we’ll use gvgateway in this example
AuthPassword: The password (or as FreePBX calls it, the Secret) that will be used with the Asterisk trunk. Do not leave this blank!

When you have these the way you want them, click Submit. Note that for the AccessNumber setting we specified SP4, which should be your FreePBX extension. This isn’t actually using SP4, but rather it is telling the device that this voice gateway uses the same technology (SIP) as SP4, so don’t worry that FreePBX will confuse calls on vg1 with calls from your extension.

We are using a password in this configuration because we had problems when we tried not using one, and also for a bit of additional security. In addition, we’ll be limiting the trunk to only accepting calls from the IP address of your Obihai device. For now we’re assuming the Obihai device is on the same local network as the FreePBX server, or at least that it’s at a fixed IP address.

Next, we must configure the Google Voice accounts to send incoming calls to this Voice Gateway.

Go to Voice Services/SP1 Service and find the setting X_InboundCallRoute near the top of the page. In order to configure this properly you need to know the Google Voice number associated with this Google Voice account, so if you don’t know what it is then log into the Google Voice account and find it there. Now change this setting as follows:

X_InboundCallRoute: vg1(XXXXXXXXXX/$1)

Replace XXXXXXXXXX with the ten digit Google Voice number, and click “Submit”. Do not under any circumstances change any other settings on the page! If you do you may screw up the configuration so badly you’ll have to start over with the factory reset again. If you have more than one Google Voice account then do the same thing under SP2 Service and if necessary, SP3 Service, using the Google Voice number associated with that particular Google Voice account in place of the XXXXXXXXXX.

Now we need to increase the maximum number of sessions between the device and the FreePBX server.

Go to Voice Services/SP4 Service and find the “Calling Features” section, and under that the setting for MaxSessions. We suggest increasing this number from the default, to at least 6. We used 10, but the Obihai may not be able to handle that many simultaneous connections. Don’t forget to click “Submit”.

That concludes the changes you need to make on the Obihai to handle incoming calls.

☞ These changes must be made on the FreePBX server.

Next we must turn our attention to FreePBX. The first thing we need to do is edit /etc/asterisk/extensions_custom.conf, so in a ssh session enter this – you can use your text editor of choice, we like nano:

nano /etc/asterisk/extensions_custom.conf

Add the following to the end of the file (note that some lines are wrapped, so you may wish to cut and paste them into a text editor in order to view them correctly):

[custom-from-obihai]
exten => _X!,1,Set(CALLERID(num)=${CUT(EXTEN,/,2)})
exten => _X!,n,Set(CALLERID(ani)=${CALLERID(num)})
exten => _X!,n,Set(CALLERID(name)=${SHELL(curl --silent --digest --user admin:obipassword http://192.168.X.X/callstatus.htm --stderr - | grep -n "<td>Peer Number<td>${CALLERID(num)}" | grep -o -P '(?<=<td>Peer Name<td>).*?(?=<td>)' | tr -d '\n')})
exten => _X!,n,ExecIf($["${CALLERID(name)}"="${CALLERID(num)}"]?Set(CALLERID(name)=))
exten => _X!,n,Set(CDR(did)=${CUT(EXTEN,/,1)})
exten => _X!,n,Goto(from-pstn-e164-us,${CUT(EXTEN,/,1)},1)
exten => h,1,Macro(hangupcall,)

Replace obipassword with the password you use to log into your Obihai device’s web interface when you log in locally (this is admin, unless you have changed it as we suggested earlier in this article). This is probably not the same as the password you use when you log into your Obitalk account, so don’t confuse the two. Also, replace 192.168.X.X with the local IP address of the Obihai device.

This is used to get the Caller ID number on incoming calls, and it also attempts to get the Caller ID name on the rare occasion when Google Voice sends one. Note this only works if, on the Obihai device, the X_InboundCallRoute setting in the Service Provider settings for Google Voice account(s) contains the /$1 appendage, in case you were wondering what that was for. And also, the curl command must be installed and working on the Asterisk server; usually this is installed by default but you can check by typing “which curl” at the Linux command prompt – it should return a path, typically /usr/bin/curl. Note that attempting to get the Caller ID name from the Obihai device does take a small amount of time, because it’s actually querying the device’s web interface, since there’s no other way to get it. But, you probably won’t notice any delay when the Obihai device is on the same local network as the Asterisk server. If you don’t care about trying to get a Caller ID name from the Obihai device, just omit the two lines that contain references to the CALLERID(name) variable.

Next, using the FreePBX web interface, create a new PJSIP Trunk. Under the General tab the only things you need to fill in are the Maximum Channels and the Trunk Name, which must match the AuthUserID you used for Voice Gateway1 on the Obihai – we suggested gvgateway:

Trunk Name: gvgateway
Maximum Channels: 6
Disable Trunk: No

Skip the other settings on that page, other than if you like you can fill in an Outbound CallerID to stop FreePBX from complaining, even though this trunk will not be used for outgoing calls. Next, under the pjsip Settings tab, General tab:

Username: Leave blank (it will change to “Username is trunk name”) as you change the other settings
Secret: The password you used for AuthPassword in the Obihai’s Voice Gateway settings
Authentication: Inbound
Registration: None
SIP Server: 192.168.X.X (replace with the local IP address of the Obihai device)
Context: custom-from-obihai

Leave all the other settings under the pjsip Settings tab, General tab at their defaults unless you have some reason to change them. Then, under the pjsip Settings tab, Advanced tab, leave all settings at the defaults EXCEPT for the following (depending on which version of FreePBX you are running, some of these settings may already be the defaults):

Permanent Auth Rejection: No
Forbidden Retry Interval: 30
Fatal Retry Interval: 30
Max Retries: 10000
Qualify Frequency : 0
Match (Permit): 192.168.X.X
(replace with the local IP address of the Obihai device).

Leave all the other settings under the pjsip Settings tab, Advanced tab at their defaults unless you have some reason to change them. Then, under the pjsip Settings tab, Codecs tab, the only codecs that should be enabled are ulaw and (if you have it installed) opus, with ulaw at the top of the list. Google Voice does use the opus protocol, but we are not sure if the Obihai device will use it, however it doesn’t hurt anything to enable it if you have it available.

As you see there are several places where you need to replace 192.168.X.X with the local IP address of the Obihai device in these instructions. This is why we strongly urged you to assign a fixed IP address to the Obihai.

Don’t forget to click the Submit button before leaving the PJSIP Trunk configuration page, or you’ll get to start over and do it all again!

Finally you need to create your Inbound Route(s). You need one for each of your 10-digit Google voice numbers that are coming in via the Obihai. When creating them, under the “Advanced” tab you may want to set “Force Answer” to Yes – this causes the call to be answered immediately when it comes in, so that it will not go to Google Voice’s voicemail. In rare circumstances this may cause a problem where calls come in and when you answer there is no one there, but the caller continues to hear ringing and then winds up at Google Voice’s voicemail. We have not experienced this issue in recent firmware releases, but if you do then set the “Pause Before Answer” setting to 1, which delays one second before answering the call. Also, if you have configured CallerID Superfecta, you may want to enable that on the Inbound Route, in the “Other” tab, because Google Voice seldom provides Caller ID name information on incoming calls.

In your Inbound Route you can make the destination whatever you like, including but not limited to the FreePBX extension served by the Obihai device, in order to take advantage of FreePBX’s various features.

After you have made all these changes don’t forget to apply the configuration in FreePBX! Now any calls made to one of your Google Voice numbers should come into FreePBX and be routed according to the Inbound Route specifications.

Sending outgoing calls to Google Voice:

☞ These changes must be made using the OBi Dashboard’s Expert Configuration option.

Some users may not care about doing this but for those that do, here’s how it is done.

Go to Service Providers/ITSP Profile D/SIP and look for the X_AccessList setting. This should be filled in with the local IP address of your FreePBX server, so that your Obihai will not accept connections from any other IP address via SP4. Note that we are assuming here that ITSP Profile D is associated with SP4, which will always be the case unless you have gone out of your way to change it.

While you are on this page, make sure that the setting X_UseRefer is enabled – check the box if it isn’t – and that X_SessionRefresh is disabled – uncheck that box if necessary. Then Submit the changes. So to recap, these are the settings to change if necessary:

X_UseRefer: Checked
X_SessionRefresh: Unchecked
X_AccessList:
Set to IP address of FreePBX

Next, go back to Voice Services/SP4 Service and change the X_InboundCallRoute setting. The following is how it might be set for three Google Voice accounts on SP1 through SP3:

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1},{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2},{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3},{>(ext1):ph},{>(ext2):ph2}

This is just an example, and in any case you’d need to replace ext1 and ext2 with the extension numbers of your Phone Ports. But don’t just copy and paste that – instead, you should construct this setting according to your particular configuration. So here is an explanation of each part, and keep in mind that each part starts with a { and ends with a } and that the parts are separated by commas. Use only the parts you need!

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1}

The above will route all calls prefixed with **1 that fit the pattern of 11 digit calls starting with “1”, or international calls starting with 011, to the Google Voice account on SP1. Note that it is the FreePBX trunk that will be applying the **1 prefix, not the person making the call. If you don’t want to allow international calls, then use this instead:

{>(<**11:1>xxxxxxxxxx):sp1}

The next part does the same thing for calls prefixed with **2, routing them to SP2. Of course this assumes you have a second Google Voice account; if not you’d omit this entirely:

{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2}

And as before, if you don’t want to allow international:

{>(<**21:1>xxxxxxxxxx):sp2}

And if you have a third Google Voice account then you should include one of these two parts:

{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3}
or
{>(<**31:1>xxxxxxxxxx):sp3}

The next part deals with incoming routing to extensions. If you have an Obi200 and therefore only one phone port, you’d use this at the end:

{>(ext1):ph}

Replacing ext1 with the actual extension number you are using in FreePBX. However, if you have an OBi202, and you have three Google Voice accounts but you want each phone port to be on a separate extension, so that both extensions have to share a Service Provider connection, then you’d also use this to route the second extension’s calls to phone port 2:

{>(ext2):ph2}

Where ext2 would be the extension number you want associated with phone port 2.

Note that specifying the extension numbers this way adds a bit of security, because any calls that may arrive at your Obihai that are not addressed to a valid extension number or Google Voice number will be rejected. There is, by design, no “default route” for calls that do not match one of the expected patterns.

So for an OBi200 with three Google Voice accounts on SP1 to SP3, and FreePBX extension 123 on SP4, the X_InboundCallRoute setting would be:

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1},{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2},{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3},{>(123):ph}

But if it were an OBi202 with the same configuration but also an extension 124 going to phone port 2:

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1},{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2},{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3},{>(123):ph},{>(124):ph2}

By the way, we realize that some very astute readers may question why we’re replacing either a 0 or a 1 with the same character – the answer is, when we didn’t use any replacement character it didn’t work! It’s as simple as that. This may be a firmware bug, because previously it worked without needing to have at least one replacement character.

While on this page, make note of but don’t change the X_UserAgentPort setting – it will probably be either 5063 or 5083, but in any case you’ll need to know it later in these instructions. Also, check that the X_EnforceRequestUserID setting is not checked – this is very important; if you don’t do this then outgoing calls may not work. And you may also want to verify that MaxSessions is set to something higher than the default. So, these are the changes on this page:

X_InboundCallRoute: See discussion above
X_UserAgentPort: Make note of but don’t change
X_EnforceRequestUserID: Unchecked
MaxSessions:
At least 6, we use 10 but that may be too many.

Don’t forget to submit your changes. Before logging out of the “OBi Dashboard”, it may be a good idea to go back to the main Dashboard page at this point and click on the gear icon for your device, and look under the Phone Port Configuration Summary to make sure that the “Primary Line for Outgoing Calls Route to:” setting is correct for each of your phone ports. Specifically, you probably want it to be set to SP4 for Phone Port 1, and “Not Configured” for Phone Port 2 (for now), assuming that you plan on routing all your outgoing calls through FreePBX. You change this by clicking on the gear icon next to the service provider you wish to choose as the primary, then when the page refreshes and you have dismissed any popups, check the appropriate checkbox next to “Primary Line for Outgoing Calls” to select that Service Provider. But do keep in mind that anything you put in the OutboundCallRoute setting for a phone port may override this setting.

That’s all of the changes you need to make on the Obihai to handle outgoing calls, except for a couple that unfortunately cannot be made from the “OBi Dashboard” at this time.

☞ These changes must be made using the Obihai device’s web interface.

Log into your Obihai device’s web interface and go to Service Providers/ITSP Profile D/General and make sure that the following two settings are enabled:

X_ICEEnable: Checked
X_EarlyICEEnableIn: Checked

Click Submit, wait for the page to reload, and then click the Reboot button in the upper right corner of the page. This fixes a specific issue with outgoing calls. This assumes that ITSP Profile D is associated with SP4, which will always be the case unless you have gone out of your way to change it.

☞ These changes must be made on the FreePBX server.

Go into the FreePBX web configuration and create one new Custom Trunk – note Custom, not SIP or PJSIP – for each of your Google Voice accounts. Here’s how they are configured:

• General tab:

Trunk Name: Whatever you want
Outbound CallerID: The 10 digit Google Voice number for the account
CID Options: Force Trunk CID
Maximum Channels: 2
Disable Trunk: No
(It’s important to check this setting if you have copied the configuration from another trunk!)

• Dialed Number Manipulation Rules tab – Dial patterns:

**1+1NXXNXXXXXX
**11+NXXNXXXXXX
**11areacode+NXXXXXX

If your area does not have 7 digit dialing of local calls then omit the last one; but if it does then replace areacode with the actual 3 digit area code. If you wish to allow international calls, then also add this pattern:

**1+011X.

This is set to use the Google Voice account on Service Provider 1 on the Obihai, but if you replace all instances of **1 with **2 or **3 then it will use the Google Voice accounts associated with SP2 or SP3 respectively. We chose this method because it is the exact same pattern you’d use to select a particular service provider when dialing from a phone connected to the Obihai.

● Custom Settings tab – Custom Dial String:

PJSIP/gvgateway/sip:$OUTNUM$@ip_address_of_obihai:X_UserAgentPort

This is why we said to take note of the X_UserAgentPort setting earlier. So if, for example, your Obihai is at 192.168.1.123 and the X_UserAgentPort was set to 5083, you’d use this:

PJSIP/gvgateway/sip:$OUTNUM$@192.168.1.123:5083

Note that “gvgateway” is the name of the PJSIP trunk we created in the previous section. This must be a valid PJSIP trunk name on your system – PJSIP is different from chan_sip, in that when specifying a dial string in chan_sip you don’t need to include the name of a chan_sip trunk in this way, but under PJSIP you do need to include the name of a PJSIP trunk. We don’t know why; it makes no sense to us, but we just do it the way that works.

That’s it – submit your changes. Repeat the process for any additional Google Voice accounts on that Obihai. Remember that it is the **n prefix that selects the Google Voice account that the call goes out on, so if instead of using multiple trunks you wanted to use a single trunk and make the Google Voice account selection in your Outbound Routes you could probably do that, although we imagine that it would be a lot more complicated to do it that way.

After you’ve created your custom trunks, don’t forget to apply the configuration. Now you can select those trunks in your Outbound Routes, as usual in FreePBX.

OBi202 users only: How to use one Service Provider connection for two FreePBX extensions

As we mentioned earlier, Obi202 devices have two phone ports, and maybe you’d like to have a separate FreePBX extension associated with each phone port. If you are already using SP1 through SP3 for other purposes, such as Google Voice connections, then you are only left with SP4 to use for both extensions. So as we said above, what you want to do in that case is configure SP4 as the extension that will be associated with Phone Port 1 (ph1), and you do that in the normal manner using the “OBi Dashboard”, although you may need to make some additions to the default DigitMap and OutboundCallRoute settings to allow extension to extension calls. Since we don’t know how extensions are numbered on your system, we can’t really explain how to do that, but we are aware that there is a tool called OBiCfg (this is a .zip file that expands to a Windows-compatible program) that may help you configure those settings. If you don’t use Windows, the program will probably run under WINE on Linux or MacOS based systems. Some time back we were able to convert this program to a Mac application, more or less, using a Mac program called Wineskin but that’s not exactly a straightforward process, and we haven’t tried to do it recently.

But the main thing is that you should get your Phone Port 1 working as a FreePBX extension, and make sure that it can make and receive calls. Then, and only then, can you configure Phone Port 2. Here is how, starting with the Obihai configuration.

☞ These changes must be made using the OBi Dashboard’s Expert Configuration option.

Go to Service Providers/ITSP Profile D/General. In your browser, place your cursor inside the text field for the DigitMap setting, and select the entire field and copy it. This assumes that ITSP Profile D is associated with SP4, which will always be the case unless you have gone out of your way to change it, and that SP4 is used for the FreePBX extension associated with Phone Port 1, which you have already configured. You may wish to temporarily paste the copied text into a text editor if you don’t use a clipboard manager, so that you don’t accidentally copy something else over it.

Go to Voice Services/Gateways & TrunkGrps – we’ll be changing the settings for Voice Gateway2 (vg2), since we’ve already used vg1. You can use any unused Voice Gateway, but we assume the use of vg2 in these instructions. We’ll be changing the Name, AccessNumber, DigitMap, AuthUserID, and AuthPassword settings, as follows:

Name: The extension number you wish to use for this extension
AccessNumber: SP4(192.168.x.x) – replace 192.168.x.x with the fixed IP address of your FreePBX server
DigitMap: The DigitMap that you copied from ITSP Profile D
AuthUserID: The extension number you wish to use for this extension again
AuthPassword: The password (or as FreePBX calls it, the Secret) that will be used with this extension. Do not leave this blank!

Then click Submit.

Go to Physical Interfaces/PHONE 1. In your browser, place your cursor inside the text field for the OutboundCallRoute setting, and select the entire field and copy it. Paste it into any plain text editor you have handy – this is just for your convenience so you can see the entire setting. We are going to modify this slightly and the use it as the OutboundCallRoute for Phone Port 2. Without knowing exactly what you have there now, we can’t just give you a replacement to paste in – you need to edit what’s there now. But note that we are not changing this setting in Phone Port 1 at all, so don’t try to edit it in place – copy it to a text editor so you won’t accidentally save it to the wrong Phone Port configuration.

Before we continue, please note the following:

These instructions assume that you want to send all calls from Phone Port 2 to your FreePBX server, and that if the call is ultimately destined for a Google Voice connection then FreePBX will send it back to your Obihai. In other words, you want your FreePBX extension to be your “Primary Line”. If that is NOT the case, and you want the Primary Line for Phone Port 2 to be a Google Voice account, then you can set that up in the “OBi Dashboard” in the normal manner. In this case you will not want to make any of the changes shown below in your DigitMaps or in the OutboundCallRoute, EXCEPT that if you have added a rule that routes calls to other extensions to sp4, you’ll want to change that to point to vg2. So make that change only if appropriate, and then paste the entire text into Phone Port 2’s OutboundCallRoute, click Submit, and then skip down to the paragraph that begins with “We’ve already showed you above how to route incoming calls for a particular extension to Phone Port 2” and continue from there. But if you DO want your FreePBX extension to be your “Primary Line”, which we recommend, then continue on from here.

There are two basic things you need to do in the OutboundCallRoute setting you just copied:

First, replace any references to pli (typically part of the text Mpli) with vg2. You need to do this because pli stands for “Primary Line” but you can’t select a Voice Gateway as a primary line in the “OBi Dashboard”, so this makes that change in the Phone Port configuration. Typically there will be two rules that need to be changed:

{([1-9]x?*(Mpli)):pp} is changed to {([1-9]x?*(Mvg2)):pp} – this is near the beginning of the text.
{(Mpli):pli} is changed to {(Mvg2):vg2} – this is near the end of the text, and note there are two replacements in this rule.

Next, you need to change any existing references to sp4 to point to vg2, EXCEPT for the rule that looks like this: {(<**4:>(Msp4)):sp4}. Don’t change that one, but any other references to sp4 should be changed to vg2, unless you have some specific reason for leaving them set to sp4. When making changes, note that rules are enclosed in {curly braces} and then separated by commas, so be careful not to accidentally delete a curly brace or comma. Just make sure that nothing remains routed to sp4 other than the single rule for the **4 prefix mentioned above; otherwise some calls from Phone Port 2 may appear to be coming from Phone Port 1’s extension when they arrive at FreePBX.

Once you have the OutboundCallRoute text modified as described above, go to Physical Interfaces/PHONE 2 – make sure you are not still in PHONE 1 where you copied the settings from; you must now be in the PHONE 2 configuration – and paste your modified settings into the OutboundCallRoute setting there, and Submit.

There are two other settings on this page that needs to be changed, DigitMap, which is just above the OutboundCallRoute setting, and CallReturnDigitMaps, which is just below it. It would be safest to copy those over from Physical Interfaces/PHONE 1, make the necessary changes, and then paste them in to the equivalent fields in Physical Interfaces/PHONE 2, but typically each of these fields will by default be the same as their equivalents in Phone Port 1 anyway.

What you need to do in both the DigitMap and CallReturnDigitMaps is replace any references to pli with vg2. In the DigitMap setting this will typically need to be changed in two places:

[1-9]x?*(Mpli) is changed to [1-9]x?*(Mvg2) – this is near the beginning of the text.
(Mpli) is changed to (Mvg2) – this is near the end of the text.

And in the CallReturnDigitMaps there is typically only one replacement that needs to be made:

{pli:(xx.)} is changed to {vg2:(xx.)} – this is near the beginning of the text.

Again, when making these changes make sure you don’t accidentally delete a curly brace or comma, and don’t forget to click Submit when you are finished.

Before leaving the “OBi Dashboard”, go back out to the main Dashboard page and click on the gear icon for your device, and look under the Phone Port Configuration Summary to make sure that the “Primary Line for Outgoing Calls Route to:” setting for Phone 2 says “Not Configured”. If, instead, it shows a service provider (SP1, SP2, SP3, or SP4) then look in the section just above, “Configure Voice Service Providers (SP)”, and click the gear icon next to that Service Provider, dismiss the popup, and then on the line “Primary Line for Outgoing Calls”, UNCHECK the checkbox next to Phone 2. This should leave Phone 2 with no configured Primary Line, meaning it should only use the rules in the settings we configured above. It would be great if we could simply set the Primary Line for Phone Port 2 to Voice Gateway 2, but the “OBi Dashboard” doesn’t allow it, which is why we had to change all those instances of pli to vg2.

If, after making these changes and setting up the configuration in FreePBX as described below, you find that you are having problems making some calls, check to see if you have the same issue on Phone Port 1. The reason we said to copy the DigitMap setting from Service Providers/ITSP Profile D/General to Voice Gateway2’s DigitMap was because we assumed that the DigitMap in ITSP Profile D, which should be associated with Phone Port 1 if you have followed these instructions from the beginning, would allow outgoing calls as configured for Service Provider 4 in the “OBi Dashboard”. So if, for example, you allowed 7 digit dialing to a particular area code when you set up SP4, then by copying the ITSP Profile D DigitMap to Voice Gateway2 those same rules should be followed by Phone Port two, PROVIDED you made all the replacements of pli to vg2 and sp4 to vg2 that we documented above.

We’ve already showed you above how to route incoming calls for a particular extension to Phone Port 2, using the X_InboundCallRoute setting under Voice Services/SP4 Service – once again, there needs to be a rule there of the form {>(ext2):ph2} where ext2 is the extension number associated with Phone Port 2.

That’s all you need to do in the Obihai device configuration.

☞ These changes must be made on the FreePBX server.

In FreePBX we need to make a Custom Extension and a new PJSIP trunk. When you create the extension, make sure you specify that it is Custom and not SIP or PJSIP! The details for the Custom Extension are as follows:

Under the General tab, set the User Extension, Display Name and Outbound CID as you normally would – obviously, the User Extension must match the Obihai device settings you used for the Name and AuthUserID for Voice Gateway 2, and especially with the extension number you associated with Phone Port 2 in the X_InboundCallRoute setting under Voice Services/SP4 Service. For all the other tabs, in most cases you can use the same settings that you would if you were creating a PJSIP extension. The major exception to this is in the Advanced tab, Edit Extension section, Dial setting. For that you want to use something like this:

PJSIP/extension_number/sip:extension_number@ip_address_of_obihai:X_UserAgentPort

In both places where you see extension_number, replace it with the number of this extension, and use the actual ip_address_of_obihai. The X_UserAgentPort is the same one we had you make a note of earlier, that was used in the Custom Dial String for the trunk(s) you created for outgoing calls to each of your Google Voice accounts. So if, for example, your extension number is 124, your Obihai is at 192.168.1.123 and the X_UserAgentPort was set to 5083, you’d use this as your Dial setting:

PJSIP/124/sip:124@192.168.1.123:5083

When you finish your custom extension configuration, don’t forget to click Submit. Note that this custom extension is used for calls going TO Phone Port 2 on the Obihai only, although there is one important exception to that – if you set an Emergency CID in the Advanced tab, Extension Options section, it will be used for calls FROM the extension that are routed through an “Emergency” outbound route, provided that the extension number you use in the trunk settings in the next section exactly matches the custom extension’s number.

For calls coming FROM Phone Port 2 we need to create a new PJSIP Trunk – this may sound strange, but it’s the easiest way to handle this. So, create a new PJSIP Trunk. Under the General tab use the following settings:

Trunk Name: MUST exactly match the extension number for the extension, and only the extension number with no additional characters! If FreePBX complains about this, go to the FreePBX Advanced Settings page, System Setup section, and make sure that the “Aggresively Check for Duplicate Extensions” setting is set to “No”.
Outbound CallerID: Set this in the same way you would set a Caller ID for a regular extension, with the Caller ID name and number.
CID Options: Force Trunk CID
Maximum Channels: 3
Disable Trunk: No

Skip the other settings on that page. Next, under the pjsip Settings tab, General tab:

Username: Leave blank (it will change to “Username is trunk name”) as you change the other settings
Secret: The password you used for AuthPassword in the Obihai’s Voice Gateway settings for the extension
Authentication: Inbound
Registration: None
SIP Server: 192.168.X.X (replace with the local IP address of the Obihai device).
SIP Server Port: X_UserAgentPort (replace with the same port number we had you make a note of earlier, that was used in the Custom Dial String for the trunk(s) you created for outgoing calls to each of your Google Voice accounts)
Context: from-internal

Leave all the other settings under the pjsip Settings tab, General tab at their defaults unless you have some reason to change them. Then, under the pjsip Settings tab, Advanced tab, leave all settings at the defaults EXCEPT for the following (depending on which version of FreePBX you are running, some of these settings may already be the defaults):

Permanent Auth Rejection: No
Forbidden Retry Interval: 30
Fatal Retry Interval: 30
Max Retries: 10000
Qualify Frequency : 0
(Optional, only needed if “pjsip show endpoints” shows extension as unavailable)
Match (Permit): 192.168.X.X (replace with the local IP address of the Obihai device)
Trust RPID/PAI: Yes
Send RPID/PAI: Send P-Asserted-Identity header

Leave all the other settings under the pjsip Settings tab, Advanced tab at their defaults unless you have some reason to change them. Then, under the pjsip Settings tab, Codecs tab, the only codecs that should be enabled are ulaw and (if you have it installed) opus, with ulaw at the top of the list. Google Voice does use the opus protocol, but we are not sure if the Obihai device will use it, however it doesn’t hurt anything to enable it if you have it available.

Don’t forget to click the Submit button before leaving the PJSIP Trunk configuration pages, or you’ll get to start over and do it all gain!

Final thoughts

We realize that there are many different ways to do this, and that some work better than others. These are what worked for us. If they work for you, great! PJSIP seems a bit more finicky than chan_sip at this point in time and therefore it was harder to convert these settings to PJSIP than we think it should have been, but at least everything is working now and we aren’t using chan_sip at all anymore, so our system should be fine until the Asterisk folks decide to change up something else.

One that that really gave us fits at first was understanding the difference between registration and authentication in PJSIP trunks. You would think this should have been obvious (and it probably is obvious to real full-time tech guys that work with this stuff all the time), since the concepts are the same as when using chan_sip, but in PJSIP trunk configuration the two settings for Authentication and Registration are shown one right under the other, whereas in chan_sip configuration you need to go to a separate tab in the trunk settings to enter a registration string. Registration is something a device or server does periodically (every few minutes, usually). FreePBX registers with commercial VoIP providers, extensions register with FreePBX, etc.

But, and this is the important part, our understanding is that Voice Gateways on an Obihai device do NOT register. The OBi Device Administration Guide seens to indicate this as well, since when it discusses Voice Gateways it says “that when using a SP trunk to access a (SIP) gateway, the device will … Use the gateway’s AuthUserID and AuthPassword for authentication.” (emphasis added). So, if you fill in a username and password in a Voice Gateway configuration, they use that to authenticate, not to register. Authentication happens on a per-call basis and it is not the same thing as registration. This is why you set the Authentication to Inbound, and the Registration to None on trunks that receive calls from Voice Gateways on an Obihai device. Note that the Voice Gateways only send calls from the Obihai to FreePBX – traffic that flows in the opposite direction uses a different mechanism.

Configuring an Obihai device isn’t the easiest thing to do, and that’s why we stick to using the “OBi Dashboard” – it makes configuration a lot easier. But if you need help understanding dialplans and other internal workings of the Obihai, we suggest you download the OBi Device Administration Guide – it’s a 220 page PDF file. It’s what we used to come up with most of this method, along with a few tricks we’ve picked up in various forums here and there.

One final thought – if you happen to also have an older OBi100 or OBi110 device, keep in mind that it can still be used as a FreePBX extension even though it can no longer connect with Google Voice. But it’s entirely possible to place or receive calls that go through FreePBX, to or from the 200-series device, because those devices still work fine with PJSIP connections, so in a roundabout manner you could still use Google Voice with such devices. It’s also possible to use the Obitalk network as an intermediary instead of FreePBX for such calls, but if you have a FreePBX server we don’t really see much point in doing that, and in any case that’s beyond the scope of this article.

If you have privacy concerns regarding Etcher (now known as balenaEtcher), here are some alternatives

We’ve used Etcher several times, mostly to make a bootable SD card for a Raspberry Pi or to put a bootable image of a Linux distribution onto a USB thumb drive. But we’re rethinking that now because we’ve read some concerns about privacy when using Etcher, or balenaEtcher as it is now called. Here are just three links where the issue is discussed:

What is a good replacement for Etcher (ads and ignores privacy) – from the Raspberry Pi Forums.
Serious Privacy Concerns with Etcher 1.4.4 – from forums.balena.io – in case that page disappears, it’s also archived here.
Etcher 1.4.4 Ignores Privacy Setting #2497 – from Github – also archived here.

Some users have opined that balenaEtcher might violate GDPR regulations in Europe (see for example balenaEtcher and privacy/GDPR #1266 from Github), but balena appears to disagree. We are neither lawyers nor European residents, so we are staying out of that dispute. All we wanted to point out is that if you do have any concerns about using Etcher or balenaEtcher, there are alternatives, depending on which operating system you are using:

Windows: The program to use here is Rufus – their tag line is “Create bootable USB drives the easy way”:


Mac: A program called ApplePi-Baker v2 is a great alternative. It’s designed to allow backing up an SD card, but the “Restore” function allows you to to create a bootable SD card or USB drive in a manner pretty similar to how it’s done in Etcher:


ApplePi-Baker v2 is actually a much more capable program than Etcher. For example, if you are creating a Raspbian Lite image to use as a server on a Raspberry Pi, you may want to enable ssh access. To do that just go to the Additional Functions and Options settings and “Enable SSH”:

One other option on a Mac is to keep using Etcher or balenaEtcher, but use Little Snitch to block all outgoing connections. It will still try to go out to various Internet sites, but Little Snitch should stop it in its tracks. However, Little Snitch is not free software, so unless you’ve already purchased it for other reasons, this might not be be the best option.

Linux: Some users (generally those who love using the command line) swear that using dd is the answer. One example we saw posted was this:

dd if=/path-to-image of=/path-to-sdcard

Sometimes other options are also shown, for example to specify a block size. The problem with that is that is that if you make a mistake while using dd, for example by mixing up the paths, you can destroy your hard drive! This is why some people say that “dd” stands for “Drive Destroyer” – they’re sort of joking, but pointing out a serious problem for inexperienced users trying to use dd! If you are trying to create a bootable SD card for a Raspberry Pi, this article explains how to do it using dd: Installing operating system images on Linux. Unless you are an experienced Linux user, we do not recommend using dd if any other alternative is available, due to the potential for inadvertent destruction of data you want to keep – of course this can also happen with other software, but dd just makes it too easy to destroy your hard drive if you are not paying close attention!

If you are running Ubuntu, there is a better option: Use the Startup Disk Creator utility that’s included with Ubuntu. Other versions of Linux may have the same or a similar utility installed, or available for download in their repository.

This How-To Geek article explains your options: How to Burn an ISO File to a USB Drive in Linux. While the article specifically talks about ISO files and USB drives, the same techniques should work for IMG files (with the .img extension) and SD cards. Note that if the files are compressed you will probably need to expand them first to get the actual .iso or .img file. In some cases you may need to format or re-format the USB drive or SD card first, but there are many tutorials available, as well as videos on YouTube, that show how to do that in Linux.

More options: If none of the above work for you, there are other options, though some require a greater level of technical expertise than those mentioned above. You can easily find several of them at this page on the AlternativeTo site. Many of them are not as user-friendly as the ones shown above.

How to install and run youtube-dl from actual source code, so that you can apply patches as needed

If you use the program youtube-dl, you may have noticed that from time to time things stop working.  Usually it’s because something changes on a site and youtube-dl needs to be patched to deal with it.  But what sometimes happens is that someone will submit a patch and then the youtube-dl developers will ignore that patch for many months before they finally get around to merging it into the program.  The speed at which the youtube-dl developers fix issues with sites can seem glacial at times.

What’s frustrating is that if you browse through the issues section of the youtube-dl support area using an appropriate search term, you may find the fix for your problem, and maybe it’s just been sitting there for quite some time. But, since youtube-dl is distributed as a compiled binary you may think you have no way to apply it.  But that’s not really true – at its core, the entire program is simply a multitude of Python scripts, and it can be run without first being compiled.  And if you use it that way, then you can apply patches as needed to any of the python modules, whether they are patches you have written or patches that you have found in the issues area, or elsewhere on the Internet.

So here is how you can install and use youtube-dl using actual source code.  Please don’t confuse this with other sites that show you how to “install from source” because in most cases what they are showing you how to do is install the binary from the developer’s source site rather than using an old version from your Linux distro’s repository, which is never a good idea since youtube-dl gets updated a lot.  I should mention here that since youtube-dl runs under Python, in theory it will run on any system that has a Python 2.6, 2.7, or 3.2+ interpreter available.  So although it is not Linux-specific, these instructions are aimed primarily at Linux users, and they will probably also work in MacOS. They should work in Windows, too, but we don’t do much in Windows so can’t say what additional steps might be involved.  And, many Linux distributions, as well as MacOS, have Python already included in their base installation, so we’re not going to tell you how to install Python if you don’t already have it.  Just type python --version from a command prompt and if python is already installed, it should tell you which version of Python you have.

So here’s the procedure: First, create a directory under your home directory, maybe call it ytdl, and change to that directory:

cd ~
mkdir ytdl
cd ytdl

There are two versions of the youtube-dl source code that can be obtained.  One is the source code only, and the other is the Full source + docs + binary, which is a much larger download but can be verified using a SHA256 checksum. You can use either one.

If you want the (larger) Full source + docs + binary version, do this: In a web browser go to the youtube-dl Download Page and look for the link that says Full source + docs + binary tarball:

Full source + docs + binary tarball link
That link is updated when new versions are released. Click it and download the resulting file, or right click on it and copy the link, and then in a terminal window use wget to get the file.  The file should be downloaded to or placed in the directory you just created.  For example:

cd ~/ytdl (only necessary if you have changed directories since the previous step)
wget https​://yt-dl.org/downloads/2019.04.17/youtube-dl-2019.04.17.tar.gz (but use the current link from the download page)

Optional, but highly recommended:  Check the SHA256 checksum to make sure it matches the one shown on the download page:

shasum -a 256 youtube-dl-2019.04.17.tar.gz

Then uncompress the file using tar xvzf:

tar xvzf youtube-dl-2019.04.17.tar.gz

The next step is to find the file __main__.py – this is the file you will actually run when using the source code (note that where you see __ in this article, that’s really two underscore characters side by side, even if the gap between them appears nonexistent). If you have followed the directions so far, it will probably be in the ~/ytdl/youtube-dl/youtube_dl directory, unless they change the directory tree in a future version. So try this:

~/ytdl/youtube-dl/youtube_dl/__main__.py --version

That should show you the version number of youtube-dl that you are running.

Now you should be able to use the same string to invoke the source code version of youtube-dl. The format is:
~/ytdl/youtube-dl/youtube_dl/__main__.py [options] [url]

Now scroll down to “Using aliases to avoid excessive typing” and continue from there. Where you see [path to __main__.py], substitute that with /home/username/ytdl/youtube-dl/youtube_dl/__main__.py but replace username with the name of your user directory (also, MacOS users should replace “home” with “Users”).

If you want the (smaller) source code only version, do this: In a web browser go to the youtube-dl GitHub Page and click the green “Clone or Download” button, then right click on the “Download Zip” button in the dropdown that appears and copy the link:

Location of Download Zip button

Then in a terminal window use wget to get the file. The file should be downloaded to or placed in the directory you just created. For example:

cd ~/ytdl (only necessary if you have changed directories since the previous step)
wget https://github.com/ytdl-org/youtube-dl/archive/master.zip

Then uncompress the file using unzip:

unzip master.zip

The next step is to find the file __main__.py – this is the file you will actually run when using the source code (note that where you see __ in this article, that’s really two underscore characters side by side, even if the gap between them appears nonexistent). If you have followed the directions so far, it will probably be in the ~/ytdl/youtube-dl-master/youtube_dl directory, unless they change the directory tree in a future version. So try this:

~/ytdl/youtube-dl-master/youtube_dl/__main__.py --version

That should show you the version number of youtube-dl that you are running.

Now you should be able to use the same string to invoke the source code version of youtube-dl. The format is:
~/ytdl/youtube-dl-master/youtube_dl/__main__.py [options] [url]

Where you see [path to __main__.py] below, substitute that with /home/username/ytdl/youtube-dl-master/youtube_dl/__main__.py but replace username with the name of your user directory (also, MacOS users should replace “home” with “Users”).

Using aliases to avoid excessive typing

Perhaps you don’t want to have to remember that long string, or type it out. In that case, open your .bashrc file in your home directory (assuming you use bash as your shell) and add a line like this:

alias ytdl='[path to __main__.py]'

Remember to make the correct substitution for [path to __main__.py], depending on which version you downloaded. After logging out and back in, you should be able to just use ytdl in place of ~/ytdl/youtube-dl/youtube_dl/__main__.py or ~/ytdl/youtube-dl-master/youtube_dl/__main__.py.

You can also make alaiases that invoke frequently-used options.  For example, if in some cases a file seems to be coming in normally and then all of a sudden you get a series of “Non-monotonous DTS in output stream” errors, you may find that you need to use the --hls-prefer-native option to get a good file. If you find you are doing this a lot, you could add an alias such as this:

alias ytdln='[path to __main__.py] --hls-prefer-native'

The above is all on one line, even if it shows as two or more lines in your display.  Then you would use ytdln to include that option. You can create one or more aliases that include just about any frequently used option(s) in this way.

Please keep in mind that any time you upgrade to a newer version of youtube-dl, you will need to follow this procedure again – you can’t just use youtube -U because that would probably get the binary version. And be careful; if you make any changes and then later on install a new version over the top of them, those changes will be lost. Finally, please note that if you are ever trying to download patches or even entire modules from GitHub, make sure you get the “Raw” versionGitHub "Raw" button(use the button at the top right of the code block) or you will get the html version, which is almost certainly not what you want.

You don’t need to pay an outrageous price to replace the broken glass lens in a NuTone LS80L, LS80LF, LS100L, or LS100LF bathroom fan/light!

One of us was attempting to replace a burned out light bulb in a bathroom exhaust fan/light combo. The problem with this particular model, a NuTone LS100L, is that it contains a booby trap for the unwary – a glass lens that isn’t independently secured within the plastic grille, and therefore can fall out the minute you attempt to release the metal reflector so that you can replace the bulb! And fall out it did, painfully striking a foot on the way down before shattering into many pieces when it hit the bathtub surface.  Gravity sucks sometimes, but then so does poor product design.

So no big deal, we thought, just buy a replacement lens – it should only cost a few bucks; it’s just a piece of glass, right? Except that NuTone (a.k.a. Broan-NuTone), the company that manufactured the fan/light, no longer makes or sells the glass lens, so the only sources are online sellers who apparently think that glass is as valuable as gold, or something like that. The first online seller we came across wanted about $90 – that’s not a typo, ninety bucks for just the glass lens! And we found other sellers charging even more! Look it up for yourself if you like, the part number of the glass lens is S84999000 (some sources leave off the leading “S”) and the fan/light model number is LS100L (sometimes hyphenated as LS-100L, which according to this PDF document is similar to other NuTone models LS80L, LS80LF, and LS100LF, at least with regard to the grille and lens used). Even a translucent plastic replacement (that in our opinion doesn’t look nearly as good as the original glass) costs $58!

Since paying that kind of money for a relatively small piece of glass or plastic didn’t appeal to us, we took a closer look at the grille that the lens fits into, which looks like the image at the right when there’s no glass installed. We started wondering if maybe some kind of LED lighting would fit into the opening where the lens is supposed to go.  After some searching we found a five-inch square LED Panel Light on Amazon (link removed because it now goes to a different size light, but this one may be similar to the one we used), and figured out that two of them would fit quite nicely into the opening in the grille.

This is the result:

Here are two views of a single LED panel light of the type we used. Go to the Amazon page linked above to see larger images:

It should be noted that the one inch thickness shown includes the tabs on the sides, onto which the spring-loaded clips are placed. The actual panels are quite a bit thinner than that. The small white module is what steps the AC voltage down to whatever DC voltage the LED panel requires. When we purchased the LED Panel Lights, the springs were already attached and the power modules were already connected to the LED panels.

Anyone else attempting to duplicate what we did would not necessarily need to buy from the same seller, but be careful – almost identical looking LED Panel Lights are available in many other sizes, but only the ones with the dimensions shown in the graphic above are known to fit correctly.  The main criteria we were concerned about was the size of the unit – we wanted it (in this case, two of them) to fit in the opening enough to completely cover the opening, but without being so large that we’d need to try to enlarge the opening or modify the grille in any way.

The steps we took for installing the LED Panel Lights into the grille were as follows:

  • Removed the old reflector and light bulb socket from the grille.
  • Snipped the wires from the power connector close to the bulb socket, so we had several inches of wire between the power connector and the connection to the power modules of the LED Panel Lights. We then put the power connector cable aside for the moment.
  • Inserted the LED Panel lights into the grille, using the attached spring clips to hold them in place.
  • On the inside of the grille (the side usually not visible when the grille is attached to the fan housing) we attempted to position the LED Panel Lights as squarely in the opening as possible, then applied dabs of 100% silicone sealant to the corners, along the edges, and where the two LED Panel Lights meet (making sure they were tightly together so no silicone seeped through).  When using silicone sealant, don’t overdo it – we used just enough to hold the LED Panel Lights in place after the sealant had cured.  The attached spring clips are what keep the LED Panel Lights in place; the only reason for using the silicone sealant was to keep them from changing position within the opening.
  • While the silicone sealant was still fresh, we carefully flipped the grille over so that the normally visible side was facing up, holding the LED Panel Lights so they did not move while we made the flip.  Then we did fine positioning to make sure that the LED Panel Lights were as square and even in the opening as we could possibly get them.  Once we were happy with the way they were positioned, we walked away and let the silicone sealant cure for at least three or four hours.
  • Once the silicone sealant had cured enough that the LED Panel Lights wouldn’t move around within the grille opening, we connected the wires from the power connector to the wires from the power modules using the supplied wire nuts.  Although the wires from the power modules are pre-stripped, they don’t leave much bare wire exposed, so we stripped a small bit more of the insulation off.  On the power modules we received, the wire colors were brown and blue, which is international (read: Chinese) color coding.  Brown is the hot wire and blue is the neutral, so we connected the two brown wires from the two power modules to the black wire from the power connector cable, and the two blue wires from the modules to the white wire from the power connector cable.  There was also a green (ground) wire coming from the power connector cable that had been connected to the old metal reflector, but since we removed that reflector there was really not anything to connect it to, so we just left it unconnected.
  • After connecting all the wires we tie-wrapped them together and put a glob of silicone sealant around the open ends of the wire nuts, in an attempt to keep moisture out of the connections (this is a bathroom fan/light, after all).  We then allowed that to cure for a couple of hours.

After that the inside of the grille looked like this:

We do want to point out that the two power modules have small vents on them that probably should not be blocked.  If you notice in the picture, there are a couple of small holes on the power modules (not the ventilation slots – it’s the small slightly oblong holes in the corners that are visible in the above image that we are talking about). As (sort of) shown in the small image at the left, we looped a long tie-wrap through those two holes shown in the larger picture above (with the modules back to back) and only partially tightened it, so that it kind of lazily looped around the modules, and we did not cut off the excess “tail” – the effect of this was that it prevented the modules from flipping into a position where one of the module’s vents is down against the top of one of the LED panels – instead both are on their sides and the long “tail” of the tie-wrap keeps them from rotating.  We now wish we’d taken a better quality picture of that, but at the time we did it we weren’t sure we were going to go with that method.

Perhaps you can think of a better way to hold the power modules in the desired place, maybe by mounting them to something that would keep the vents facing sideways, but the point is that it’s probably best if the small vents on the power modules aren’t completely blocked.  One reason we preferred leaving them on their sides is so that if a small amount of moisture did somehow manage to seep in, the vent holes would allow it to weep back out and not trap it inside (though we would certainly hope that all of the room moisture would be drawn out by the fan inside the unit, and anyway these things are supposed to be okay to use in bathrooms).

Once the power plug was connected inside the fan housing, but before pushing the grille back up to the ceiling, we had the opportunity to maneuver the power modules so they wouldn’t block the vents.  We really didn’t want them in the direct path of moist air being sucked out of the shower anyway, so we positioned them above the LED panels.

This was the result after mounting the grille with the new LED Panel Lights:

In case it’s not obvious these LED panels are bright – we’d been a little worried that they might not be as bright as the bulb they were replacing, but no worries there!

The total cost of this conversion was about $28 – far less than the cost of a highly overpriced piece of glass or plastic, and we think the end result actually looked much better than either of those options.  Plus each of those LED panels only uses 9 watts, or 18 watts total for the pair, which is far less that the 100 watt incandescent light that this fixture was designed to hold.

As always, we are just showing you what we did, not suggesting you should do likewise, particularly if you have any reservations about using electrical equipment manufactured in China.  If you attempt to do anything similar to this, you do so entirely at your own risk.  We don’t make any guarantees about anything electrical, because it’s always remotely possible that you could get a defective or poorly made unit that will cause something bad to happen, and also because we have no idea whether our readers have any experience in working with electricity or electrical equipment.  It’s your responsibility to make sure that whatever project you are working on is safe, and if you don’t have a basic knowledge of electricity and electrical safety then you most emphatically should not be doing a conversion like this.  If you have any doubts whatsoever about your ability to safely do something like this, consult a licensed electrician to make the electrical connections for you, or just stick with replacing the lens.  After all, if you don’t want to do what we did for any reason, there’s always that $58 translucent plastic replacement.  On the other hand, if you want to do a project that’s a bit more challenging, maybe you could use flexible LED strip lighting, as explained here.  In that case, you’d still need to replace the lens, but you could probably use a flat piece of frosted glass or plexiglass cut to the correct size, since there would not be a light bulb protruding downward that would need to be covered.

All that said, we were really happy with the way this project turned out.  We not only think the result looks better than the original design, but you can’t beat using less than one-fifth of the required power to get an even brighter light!  They make those LED Panel Lights in several sizes, so we could even see where someone might use something like this to retrofit other models of older bathroom fans with LED lighting, perhaps even units that were not originally supplied with a light.  Anyway, we hope this article saves someone else the expense of buying an overpriced glass lens!

How we got hardware acceleration of graphics to work in Ubuntu 18.04.2 with an Intel Core i7-9700K Coffee Lake processor

Intel Core I7.pngWe recently set up a new system using an Intel Core i7-9700K Coffee Lake processor, and discovered that the Intel® UHD Graphics 630 is not yet supported in Ubuntu, at least not in the 18.04 Long Term Support release. Therefore hardware acceleration of video did not work in Kodi or any other program. We first realized this when none of the VAAPI settings were shown in Kodi’s settings (they are normally found in Settings Player Settings Videos Processing).  Then we installed the vainfo program (using sudo apt install vainfo), and when we ran it we got this output:

libva info: VA-API version 1.1.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_1_1
libva error: /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so init failed
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit

Obviously this is not what you want to see, so we knew we had a problem.  Much additional research led us to the conclusion that the Intel Core i7-9700K processor is so new that it’s not yet supported in Ubuntu 18.04.

After searching many pages and sites, the answer appeared in a post by user yasij in the Kodi forum, although it seems he thought you’d need to start with Ubuntu 18.10 or 19.04 (the latter should have support for this processor built in, but it’s not a Long Term Support release).

What we found was that support for this processor could be added to Ubuntu 18.04.2 – note the point version here, you need at least the 4.18 Linux kernel in that version for this to work. Check your kernel version using uname -a if you aren’t sure.

The method is rather simple, actually. First you run this command to add the necessary repository:

sudo add-apt-repository ppa:mamarley/updates

Then you need to edit the file etc/apt/sources.list.d/mamarley-ubuntu-updates-bionic.list

nano etc/apt/sources.list.d/mamarley-ubuntu-updates-bionic.list
(Or use your preferred text editor).

Look for the line:
deb http://ppa.launchpad.net/mamarley/updates/ubuntu bionic main

and change bionic to cosmic:

deb http://ppa.launchpad.net/mamarley/updates/ubuntu cosmic main

Exit nano (Ctrl-X) and save your changes. Then run:
sudo apt update
sudo apt install i965-va-driver va-driver-all
sudo apt install libasound2 libasound2-plugins

The last two packages were needed to get sound to work in Kodi. We use ALSA audio, so if you use PulseAudio you may not need those, or you may need to upgrade different packages. Additional dependencies may be installed when you install or upgrade these packages.

Then either delete etc/apt/sources.list.d/mamarley-ubuntu-updates-bionic.list or comment out that repository (add # to the start of the line, like this):
# deb http://ppa.launchpad.net/mamarley/updates/ubuntu cosmic main

Then run:
sudo apt update
again so that no additional packages from that repository are inadvertently added.

Reboot the system.

Now when you run vainfo the output should look something like this (with no errors):

libva info: VA-API version 1.4.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_1_3
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.4 (libva 2.1.0)
vainfo: Driver version: Intel i965 driver for Intel(R) Coffee Lake - 2.3.0
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            :	VAEntrypointVLD
      VAProfileMPEG2Simple            :	VAEntrypointEncSlice
      VAProfileMPEG2Main              :	VAEntrypointVLD
      VAProfileMPEG2Main              :	VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline:	VAEntrypointVLD
      VAProfileH264ConstrainedBaseline:	VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline:	VAEntrypointEncSliceLP
      VAProfileH264Main               :	VAEntrypointVLD
      VAProfileH264Main               :	VAEntrypointEncSlice
      VAProfileH264Main               :	VAEntrypointEncSliceLP
      VAProfileH264High               :	VAEntrypointVLD
      VAProfileH264High               :	VAEntrypointEncSlice
      VAProfileH264High               :	VAEntrypointEncSliceLP
      VAProfileH264MultiviewHigh      :	VAEntrypointVLD
      VAProfileH264MultiviewHigh      :	VAEntrypointEncSlice
      VAProfileH264StereoHigh         :	VAEntrypointVLD
      VAProfileH264StereoHigh         :	VAEntrypointEncSlice
      VAProfileVC1Simple              :	VAEntrypointVLD
      VAProfileVC1Main                :	VAEntrypointVLD
      VAProfileVC1Advanced            :	VAEntrypointVLD
      VAProfileNone                   :	VAEntrypointVideoProc
      VAProfileJPEGBaseline           :	VAEntrypointVLD
      VAProfileJPEGBaseline           :	VAEntrypointEncPicture
      VAProfileVP8Version0_3          :	VAEntrypointVLD
      VAProfileVP8Version0_3          :	VAEntrypointEncSlice
      VAProfileHEVCMain               :	VAEntrypointVLD
      VAProfileHEVCMain               :	VAEntrypointEncSlice
      VAProfileHEVCMain10             :	VAEntrypointVLD
      VAProfileHEVCMain10             :	VAEntrypointEncSlice
      VAProfileVP9Profile0            :	VAEntrypointVLD
      VAProfileVP9Profile0            :	VAEntrypointEncSlice
      VAProfileVP9Profile2            :	VAEntrypointVLD

Note that if you run vainfo in a ssh session, you will probably see one error message right at the beginning of the output:

error: can't connect to X server!

This is to be expected in a ssh session, but that error should not appear if you run vainfo from a terminal window on the desktop.

That should be all you need to do — at least it was all we needed to do to get support for this processor into Ubuntu 18.04.2. We hope it works for you, too!  Note that you are mixing packages intended for different versions of Ubuntu, so there’s always a chance that doing this might cause some unintended breakage somewhere, but so far we haven’t encountered any problems.

How to use an Obihai 200 series VoIP device as a gateway between Google Voice and FreePBX

TelephoneNOTE: There is a newer version of this article for those who are using PJSIP rather than chan_sip in FreePBX. If you have already converted to PJSIP, please go directly to PJSIP Edition – How to use an Obihai 200 series VoIP device as a gateway between Google Voice and FreePBX.

This article is intended for a specific, probably rather narrow group of readers. It is for people who have experience setting up and configuring FreePBX, and who also currently own an Obihai 200 series device (200 or 202), and that are using standard Obihai firmware and use Obihai’s “OBi Dashboard” to configure your device. It is specifically not intended as an inducement for anyone to go out and buy a new Obihai device, because in our opinion Obihai hasn’t been treating its customers very well lately, and we have no reason to think that will change. And it is also not for those who like to run custom firmware, or that think that the “OBi Dashboard” is in some way evil – although if you do, this method will probably work just as well on a locally-configured Obihai. But if you happen to have an Obihai 200 series device lying around, and you are running FreePBX, you can put it to good use. This method might also work on an unlocked 300-series device running certain custom firmware but we have no experience at all with that, so we aren’t saying it will or won’t work in such a case, and we don’t support such usage. This method will not work with older Obihai 100-series devices, though you can still use those for FreePBX extensions or other types of SIP connections.

As always we are telling you how we did this, which is not necessarily how you should do it. Any changes you make to your Obihai or FreePBX configuration are at your own risk, and we assume you know what you’re doing. If you somehow manage to really screw things up, that’s on you, not us. We don’t guarantee that this will work for everyone, we just know it did for us.

Some other technical information: The method we show here uses chan_sip, not the newer pjsip, for the connection to FreePBX. The reason is that we are running FreePBX on a Raspberry Pi and as best we can tell, it does not have pjsip installed. We realize that chan_sip is being deprecated in the newest versions of Asterisk but we suspect that it will more than likely continue to work for years to come.

We do suggest that if your Obihai device has previously been configured, you follow this procedure to start over with a clean configuration:

  • Completely remove the device from the “OBi Dashboard”, as you would if you planned to transfer ownership to someone else.
  • Then do a hard reset of the Obihai device – dial ***8 from a connected phone and follow the prompts to restore the factory default settings.
  • If there were previously one or more Google Voice accounts configured on the device and you plan to continue using any of those same accounts, log into those Google Voice accounts and remove the Obihai device as a destination. If you don’t do this, then after following this procedure you will see two Obihai device destinations in each Google Voice account, only one of which will be valid, and it will be difficult to tell which one is the correct one. Also, keeping an old invalid Obihai destination in your Google Voice account configuration may stop incoming calls from getting to your Obihai.
  • Then add the device back to the “OBi Dashboard”, as you would if you had just purchased it new.

This is entirely optional, but it does help make sure that you don’t have any settings from an old configuration messing things up.

Also, you need to have the latest firmware. Dial ***1 to find out the local IP address of your device and go to that page and see if it comes up with the Polycom logo – note that if you cannot access the device, you may need to dial ***0 and then 30# and follow the prompts to enable WAN access. Login using “admin” as the username, and use the password shown under “Webpage Admin Password” on the “OBi Dashboard” at Obihai’s site – on that site you may need to click the gear icon next to your device to see the Webpage Admin Password. If it’s still the default password, this might be a good time to change it to something a bit more secure, but if you do be sure to make a note of it, because you will need it later in these instructions.

If your device’s web pages still come up with the old Obihai logo, dial ***6 to see if new firmware is available, and if so let it install. If it does not find new firmware, then go to System Management/Auto Provisioning, and look to see if there is a value entered for the FirmwareURL setting. You may need to change this to point to a more recent firmware version. For example, our device currently shows this in that field:

IF ( $FWV < 3.2.2.5921 ) FWU http://fw.obihai.com/OBi202-3-2-2-5921EX-332148940.fw

That is all one line even if it is split on this page. We are not telling you to copy that verbatim to your device, just that this field is what seems to control what version of the firmware you receive. Normally if that field is set correctly, your device should grab the latest firmware after a reboot, though you may need to dial ***6 to get it started. Do not unplug or even touch the Obihai while it is upgrading firmware or you may brick it! After a successful upgrade the device’s web pages should be branded Polycom rather than Obihai.

One other thing we very strongly suggest is that you set your Obihai device to a fixed IP address on your local network. This can either be done in the Obihai’s device settings, under System Management/WAN Settings, or in your router’s configuration – it doesn’t matter as long as your Obihai is always at the same local IP address. If you don’t do this you will not be able to use parts of this method.

The assumption we make here is as follows: An Obihai 200-series device can support up to four “service providers”, up to three of which can be Google voice accounts, and one of which is in this method a FreePBX extension. There are technical reasons for this limitation but we won’t go into those here. The point is that any given Obihai 200-series device can bridge up to three Google Voice accounts to FreePBX, and we assume those will be designated as Service Provider 1 (SP1), Service Provider 2 (SP2), and Service Provider 3 (SP3) in the Obihai configuration. Your FreePBX extension will be on SP4. In the case of an OBi202, which has two phone ports, you can have a FreePBX extension associated with each phone port. If you are connecting your OBi202 to only one or two Google Voice accounts, then your two extensions can be on SP3 and SP4. But if you are connecting to three Google Voice accounts and still want to let each phone port on an OBi202 be on a different extension, then assign the extension you want associated with Phone Port 1 to SP4, and we’ll tell you later how to configure the extension you want associated with Phone Port 2.

If you do not use SP4 for at least one of your FreePBX extensions then these instructions probably won’t work for you, since we have assumed throughout that SP4, and by association, ITSP Profile D will be used with your FreePBX extension (or at least with one of them if you have an OBi202). You could modify the instructions to take this into account, but chances are you’re going to miss something and it won’t work as intended.

We assume you know how to configure a FreePBX extension, by selecting a “Generic Service Provider” in the “OBi Dashboard” and then pointing it at your FreePBX server. Once again, just be sure to use SP4 for your FreePBX extension, or the configuration examples shown here won’t work without modification. Note that you may need to modify the phone port’s DigitMap and OutboundCallRoute settings to allow calls to other extensions, but that is beyond the scope of this article. You can make SP4 the Primary Line for Phone Port 1, but if you have an OBi202 we recommend that you do NOT make ANY of the service providers the Primary Line for Phone Port 2, at least not yet. OBi200 users don’t need to worry about this; it won’t affect you because you only have a single phone port.

You can configure your Google Voice account(s) in the normal manner using the “OBi Dashboard”, in fact if there’s a way to do it without using the Dashboard we don’t know about it, at least not without using custom third-party firmware which is beyond the scope of this article. Get everything set up and working normally – get your first Google Voice account set up on SP1 and make sure it is working, then if you have additional accounts add them on SP2 and if necessary, SP3. Make sure that you can make and receive calls on your Google Voice account(s) before you go any further. Note that you can use dialing prefixes to make test calls using a particular Service Provider without setting it as your Primary Line – for example **1 followed by the number you are calling will send the call through the account associated with Service Provider 1 in the Obihai configuration, and the **2 and **3 prefixes will do the same with regard to Service Providers 2 and 3.

So now that you have your FreePBX extension working and your Google Voice accounts set up and configured, there are two things that need to happen. One is to redirect all incoming Google Voice calls to a FreePBX SIP trunk, which will be used for incoming calls only. And the other is to send all outgoing calls to a Custom trunk, and configure the Obihai to correctly route them to the correct Google Voice accounts. Some users may not need both of these – for example, if your main reason for wanting to route calls through FreePBX is so you can use its blacklist and other call screening features on incoming calls, then you may not need the outbound connectivity. But we’ll show you how to do both.

Handling incoming Google Voice calls:

☞ These changes must be made using the OBi Dashboard’s Expert Configuration option.

Go to Voice Services/Gateways & TrunkGrps – we’ll be changing the settings for Voice Gateway1 (vg1). You can use any unused Voice Gateway, but the examples here assume the use of vg1. Start by unchecking the checkboxes under “OBiTALK Settings” for these values: Name, AccessNumber, and AuthUserID. Then click “Submit” at the bottom of the page. If any of the checkboxes in the “Device Default” column for those settings are now checked, uncheck them and click “Submit” again. You need to do this or the page won’t let you enter the new values. This is true anyplace we make changes to any of the settings in the OBi Dashboard – if either of those boxes are checked, they must be unchecked and “Submit” clicked before you can make changes.

Now you can enter the new settings for vg1:
Name: Anything you like to identify it, such as FreePBX trunk
AccessNumber: SP4(192.168.x.x) – replace 192.168.x.x with the fixed IP address of your FreePBX server
AuthUserID: The FreePBX trunk name, we’ll use gvgateway in this example

When you have these the way you want them, click Submit. Note that for the AccessNumber setting we specified SP4, which should be your FreePBX extension. This isn’t actually using SP4, but rather it is telling the device that this voice gateway uses the same technology (SIP) as SP4, so don’t worry that FreePBX will confuse calls on vg1 with calls from your extension.

We are not using a password in this configuration; instead we’ll be limiting the trunk to only accepting calls from the IP address of your Obihai device. This makes configuration a bit easier. But if the Obihai were on a different local network than your FreePBX server then you might need to configure an AuthPassword for additional security, and configure the trunk to look for it. For now we’re assuming the Obihai device is on the same local network as the FreePBX server, or at least that it’s at a fixed IP address.

Next, we must configure the Google Voice accounts to send incoming calls to this Voice Gateway.

Go to Voice Services/SP1 Service and find the setting X_InboundCallRoute near the top of the page. In order to configure this properly you need to know the Google Voice number associated with this Google Voice account, so if you don’t know what it is then log into the Google Voice account and find it there. Now change this setting as follows:

X_InboundCallRoute: vg1(XXXXXXXXXX/$1)

Replace XXXXXXXXXX with the ten digit Google Voice number, and click “Submit”. Do not under any circumstances change any other settings on the page! If you do you may screw up the configuration so badly you’ll have to start over with the factory reset again. If you have more than one Google Voice account then do the same thing under SP2 Service and if necessary, SP3 Service, using the Google Voice number associated with that particular Google Voice account in place of the XXXXXXXXXX.

Now we need to increase the maximum number of sessions between the device and the FreePBX server.

Go to Voice Services/SP4 Service and find the “Calling Features” section, and under that the setting for MaxSessions. We suggest increasing this number from the default, to at least 6. We used 10, but the Obihai may not be able to handle that many simultaneous connections. Don’t forget to click “Submit”.

That concludes the changes you need to make on the Obihai to handle incoming calls.

☞ These changes must be made on the FreePBX server.

Next we must turn our attention to FreePBX. The first thing we need to do is edit /etc/asterisk/extensions_custom.conf, so in a ssh session enter this – you can use your text editor of choice, we like nano:

nano /etc/asterisk/extensions_custom.conf

Add the following to the end of the file (note that some lines are wrapped, so you may wish to cut and paste them into a text editor in order to view them correctly):

[custom-from-obihai]
exten => _X!,1,Set(CALLERID(num)=${CUT(EXTEN,/,2)})
exten => _X!,n,Set(CALLERID(ani)=${CALLERID(num)})
exten => _X!,n,Set(CALLERID(name)=${SHELL(curl --silent --digest --user admin:obipassword http://192.168.X.X/callstatus.htm --stderr - | grep -n "Peer Number
${CALLERID(num)}" | grep -o -P '(?<=
Peer Name
).*?(?=
)' | tr -d '\n')})
exten => _X!,n,ExecIf($["${CALLERID(name)}"="${CALLERID(num)}"]?Set(CALLERID(name)=))
exten => _X!,n,Set(CDR(did)=${CUT(EXTEN,/,1)})
exten => _X!,n,Goto(from-pstn-e164-us,${CUT(EXTEN,/,1)},1)
exten => h,1,Macro(hangupcall,)

Replace obipassword with the password you use to log into your Obihai device’s web interface when you log in locally (this is admin, unless you have changed it as we suggested earlier in this article). This is probably not the same as the password you use when you log into your Obitalk account, so don’t confuse the two. Also, replace 192.168.X.X with the local IP address of the Obihai device.

This is used to get the Caller ID number on incoming calls, and it also attempts to get the Caller ID name on the rare occasion when Google Voice sends one. Note this only works if, on the Obihai device, the X_InboundCallRoute setting in the Service Provider settings for Google Voice account(s) contains the /$1 appendage, in case you were wondering what that was for. And also, the curl command must be installed and working on the Asterisk server; usually this is installed by default but you can check by typing “which curl” at the Linux command prompt – it should return a path, typically /usr/bin/curl. Note that attempting to get the Caller ID name from the Obihai device does take a small amount of time, because it’s actually querying the device’s web interface, since there’s no other way to get it. But, you probably won’t notice any delay when the Obihai device is on the same local network as the Asterisk server. If you don’t care about trying to get a Caller ID name from the Obihai device, just omit the two lines that contain references to the CALLERID(name) variable.

Next, using the FreePBX web interface, create a new PJSIP Trunk. Under the General tab the only things you need to fill in are the Maximum Channels and the Trunk Name, which must match the AuthUserID you used for Voice Gateway1 on the Obihai – we suggested gvgateway:

Trunk Name: gvgateway
Maximum Channels: 6
Disable Trunk: No

Skip the other settings on that page, other than if you like you can fill in an Outbound CallerID to stop FreePBX from complaining, even though this trunk will not be used for outgoing calls. Next, in the sip Settings tab, Outgoing tab:

Trunk Name: gvgateway     (yes you have to fill it in here again)

PEER Details:

type=friend
permit=192.168.X.X/255.255.255.255
nat=no
host=192.168.X.X
dtmfmode=rfc2833
disallow=all
directmedia=no
deny=0.0.0.0/0.0.0.0
context=custom-from-obihai
allow=ulaw

Replace the two instances of 192.168.X.X with the local IP address of the Obihai device. This is why we don’t need to use a password, because access to this trunk is only allowed from the Obihai’s IP address. This is why we strongly urged you to assign a fixed IP address to the Obihai. Also, omit the line nat=no if the Obihai device is not on the same local network as the FreePBX server, or if you experience issues with one-way audio.

Don’t forget to click the Submit button before leaving the Trunk configuration page, or you’ll get to start over and do it all again!

Finally you need to create your Inbound Route(s). You need one for each of your 10-digit Google voice numbers that are coming in via the Obihai. When creating them, under the “Advanced” tab you may want to set “Force Answer” to Yes – this causes the call to be answered immediately when it comes in, so that it will not go to Google Voice’s voicemail. In rare circumstances this may cause a problem where calls come in and when you answer there is no one there, but the caller continues to hear ringing and then winds up at Google Voice’s voicemail. We have not experienced this issue in recent firmware releases, but if you do then set the “Pause Before Answer” setting to 1, which delays one second before answering the call. Also, if you have configured CallerID Superfecta, you may want to enable that on the Inbound Route, in the “Other” tab, because Google Voice seldom provides Caller ID name information on incoming calls.

In your Inbound Route you can make the destination whatever you like, including but not limited to the FreePBX extension served by the Obihai device, in order to take advantage of FreePBX’s various features.

After you have made all these changes don’t forget to apply the configuration in FreePBX! Now any calls made to one of your Google Voice numbers should come into FreePBX and be routed according to the Inbound Route specifications.

Sending outgoing calls to Google Voice:

☞ These changes must be made using the OBi Dashboard’s Expert Configuration option.

Some users may not care about doing this but for those that do, here’s how it is done.

Go to Service Providers/ITSP Profile D/SIP and look for the X_AccessList setting. This should be filled in with the local IP address of your FreePBX server, so that your Obihai will not accept connections from any other IP address via SP4. Note that we are assuming here that ITSP Profile D is associated with SP4, which will always be the case unless you have gone out of your way to change it.

While you are on this page, make sure that the setting X_UseRefer is enabled – check the box if it isn’t – and that X_SessionRefresh is disabled – uncheck that box if necessary. Then Submit the changes. So to recap, these are the settings to change if necessary:

X_UseRefer: Checked
X_SessionRefresh: Unchecked
X_AccessList:
Set to IP address of FreePBX

Next, go back to Voice Services/SP4 Service and change the X_InboundCallRoute setting. The following is how it might be set for three Google Voice accounts on SP1 through SP3:

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1},{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2},{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3},{>(ext1):ph},{>(ext2):ph2}

This is just an example, and in any case you’d need to replace ext1 and ext2 with the extension numbers of your Phone Ports. But don’t just copy and paste that – instead, you should construct this setting according to your particular configuration. So here is an explanation of each part, and keep in mind that each part starts with a { and ends with a } and that the parts are separated by commas. Use only the parts you need!

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1}

The above will route all calls prefixed with **1 that fit the pattern of 11 digit calls starting with “1”, or international calls starting with 011, to the Google Voice account on SP1. Note that it is the FreePBX trunk that will be applying the **1 prefix, not the person making the call. If you don’t want to allow international calls, then use this instead:

{>(<**11:1>xxxxxxxxxx):sp1}

The next part does the same thing for calls prefixed with **2, routing them to SP2. Of course this assumes you have a second Google Voice account; if not you’d omit this entirely:

{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2}

And as before, if you don’t want to allow international:

{>(<**21:1>xxxxxxxxxx):sp2}

And if you have a third Google Voice account then you should include one of these two parts:

{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3}
or
{>(<**31:1>xxxxxxxxxx):sp3}

The next part deals with incoming routing to extensions. If you have an Obi200 and therefore only one phone port, you’d use this at the end:

{>(ext1):ph}

Replacing ext1 with the actual extension number you are using in FreePBX. However, if you have an OBi202, and you have three Google Voice accounts but you want each phone port to be on a separate extension, so that both extensions have to share a Service Provider connection, then you’d also use this to route the second extension’s calls to phone port 2:

{>(ext2):ph2}

Where ext2 would be the extension number you want associated with phone port 2.

Note that specifying the extension numbers this way adds a bit of security, because any calls that may arrive at your Obihai that are not addressed to a valid extension number or Google Voice number will be rejected. There is, by design, no “default route” for calls that do not match one of the expected patterns.

So for an OBi200 with three Google Voice accounts on SP1 to SP3, and FreePBX extension 123 on SP4, the X_InboundCallRoute setting would be:

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1},{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2},{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3},{>(123):ph}

But if it were an OBi202 with the same configuration but also an extension 124 going to phone port 2:

{>(<**10:0>11x.|<**11:1>xxxxxxxxxx):sp1},{>(<**20:0>11x.|<**21:1>xxxxxxxxxx):sp2},{>(<**30:0>11x.|<**31:1>xxxxxxxxxx):sp3},{>(123):ph},{>(124):ph2}

By the way, we realize that some very astute readers may question why we’re replacing either a 0 or a 1 with the same character – the answer is, when we didn’t use any replacement character it didn’t work! It’s as simple as that. This may be a firmware bug, because previously it worked without needing to have at least one replacement character.

While on this page, make note of but don’t change the X_UserAgentPort setting – it will probably be either 5063 or 5083, but in any case you’ll need to know it later in these instructions. Also, check that the X_EnforceRequestUserID setting is not checked – this is very important; if you don’t do this then outgoing calls may not work. And you may also want to verify that MaxSessions is set to something higher than the default. So, these are the changes on this page:

X_InboundCallRoute: See discussion above
X_UserAgentPort: Make note of but don’t change
X_EnforceRequestUserID: Unchecked
MaxSessions:
At least 6, we use 10 but that may be too many.

Don’t forget to submit your changes. Before logging out of the “OBi Dashboard”, it may be a good idea to go back to the main Dashboard page at this point and click on the gear icon for your device, and look under the Phone Port Configuration Summary to make sure that the “Primary Line for Outgoing Calls Route to:” setting is correct for each of your phone ports. Specifically, you probably want it to be set to SP4 for Phone Port 1, and “Not Configured” for Phone Port 2 (for now), assuming that you plan on routing all your outgoing calls through FreePBX. You change this by clicking on the gear icon next to the service provider you wish to choose as the primary, then when the page refreshes and you have dismissed any popups, check the appropriate checkbox next to “Primary Line for Outgoing Calls” to select that Service Provider. But do keep in mind that anything you put in the OutboundCallRoute setting for a phone port may override this setting.

That’s all of the changes you need to make on the Obihai to handle outgoing calls, except for a couple that unfortunately cannot be made from the “OBi Dashboard” at this time.

☞ These changes must be made using the Obihai device’s web interface.

Log into your Obihai device’s web interface and go to Service Providers/ITSP Profile D/General and make sure that the following two settings are enabled:

X_ICEEnable: Checked
X_EarlyICEEnableIn: Checked

Click Submit, wait for the page to reload, and then click the Reboot button in the upper right corner of the page. This fixes a specific issue with outgoing calls. This assumes that ITSP Profile D is associated with SP4, which will always be the case unless you have gone out of your way to change it.

☞ These changes must be made on the FreePBX server.

Go into the FreePBX web configuration and create one new Custom Trunk – note Custom, not SIP – for each of your Google Voice accounts. Here’s how they are configured:

• General tab:

Trunk Name: Whatever you want
Outbound CallerID: The 10 digit Google Voice number for the account
CID Options: Force Trunk CID
Maximum Channels: 2
Disable Trunk: No
     (It’s important to check this setting if you have copied the configuration from another trunk!)

• Dialed Number Manipulation Rules tab – Dial patterns:

**1+1NXXNXXXXXX
**11+NXXNXXXXXX
**11areacode+NXXXXXX

If your area does not have 7 digit dialing of local calls then omit the last one; but if it does then replace areacode with the actual 3 digit area code. If you wish to allow international calls, then also add this pattern:

**1+011X.

This is set to use the Google Voice account on Service Provider 1 on the Obihai, but if you replace all instances of **1 with **2 or **3 then it will use the Google Voice accounts associated with SP2 or SP3 respectively. We chose this method because it is the exact same pattern you’d use to select a particular service provider when dialing from a phone connected to the Obihai.

● Custom Settings tab – Custom Dial String:

sip/$OUTNUM$@ip_address_of_obihai:X_UserAgentPort

This is why we said to take note of the X_UserAgentPort setting earlier. So if, for example, your Obihai is at 192.168.1.123 and the X_UserAgentPort was set to 5083, you’d use this:

sip/$OUTNUM$@192.168.1.123:5083

That’s it – submit your changes. Repeat the process for any additional Google Voice accounts on that Obihai. Remember that it is the **n prefix that selects the Google Voice account that the call goes out on, so if instead of using multiple trunks you wanted to use a single trunk and make the Google Voice account selection in your Outbound Routes you could probably do that, although we imagine that it would be a lot more complicated to do it that way.

After you’ve created your custom trunks, don’t forget to apply the configuration. Now you can select those trunks in your Outbound Routes, as usual in FreePBX.

OBi202 users only: How to use one Service Provider connection for two FreePBX extensions

As we mentioned earlier, Obi202 devices have two phone ports, and maybe you’d like to have a separate FreePBX extension associated with each phone port. If you are already using SP1 through SP3 for other purposes, such as Google Voice connections, then you are only left with SP4 to use for both extensions. So as we said above, what you want to do in that case is configure SP4 as the extension that will be associated with Phone Port 1 (ph1), and you do that in the normal manner using the “OBi Dashboard”, although you may need to make some additions to the default DigitMap and OutboundCallRoute settings to allow extension to extension calls. Since we don’t know how extensions are numbered on your system, we can’t really explain how to do that, but we are aware that there is a tool called OBiCfg (this is a .zip file that expands to a Windows-compatible program) that may help you configure those settings. If you don’t use Windows, the program will probably run under WINE on Linux or MacOS based systems. Some time back we were able to convert this program to a Mac application, more or less, using a Mac program called Wineskin but that’s not exactly a straightforward process, and we haven’t tried to do it recently.

But the main thing is that you should get your Phone Port 1 working as a FreePBX extension, and make sure that it can make and receive calls. Then, and only then, can you configure Phone Port 2. Here is how, starting with the Obihai configuration.

☞ These changes must be made using the OBi Dashboard’s Expert Configuration option.

Go to Service Providers/ITSP Profile D/General. In your browser, place your cursor inside the text field for the DigitMap setting, and select the entire field and copy it. This assumes that ITSP Profile D is associated with SP4, which will always be the case unless you have gone out of your way to change it, and that SP4 is used for the FreePBX extension associated with Phone Port 1, which you have already configured. You may wish to temporarily paste the copied text into a text editor if you don’t use a clipboard manager, so that you don’t accidentally copy something else over it.

Go to Voice Services/Gateways & TrunkGrps – we’ll be changing the settings for Voice Gateway2 (vg2), since we’ve already used vg1. You can use any unused Voice Gateway, but we assume the use of vg2 in these instructions. We’ll be changing the Name, AccessNumber, DigitMap, and AuthUserID settings, as follows:

Name: The extension number you wish to use for this extension
AccessNumber: SP4(192.168.x.x) – replace 192.168.x.x with the fixed IP address of your FreePBX server
DigitMap: The DigitMap that you copied from ITSP Profile D
AuthUserID: The extension number you wish to use for this extension again

Then click Submit.

Go to Physical Interfaces/PHONE 1. In your browser, place your cursor inside the text field for the OutboundCallRoute setting, and select the entire field and copy it. Paste it into any plain text editor you have handy – this is just for your convenience so you can see the entire setting. We are going to modify this slightly and the use it as the OutboundCallRoute for Phone Port 2. Without knowing exactly what you have there now, we can’t just give you a replacement to paste in – you need to edit what’s there now. But note that we are not changing this setting in Phone Port 1 at all, so don’t try to edit it in place – copy it to a text editor so you won’t accidentally save it to the wrong Phone Port configuration.

Before we continue, please note the following:

These instructions assume that you want to send all calls from Phone Port 2 to your FreePBX server, and that if the call is ultimately destined for a Google Voice connection then FreePBX will send it back to your Obihai. In other words, you want your FreePBX extension to be your “Primary Line”. If that is NOT the case, and you want the Primary Line for Phone Port 2 to be a Google Voice account, then you can set that up in the “OBi Dashboard” in the normal manner. In this case you will not want to make any of the changes shown below in your DigitMaps or in the OutboundCallRoute, EXCEPT that if you have added a rule that routes calls to other extensions to sp4, you’ll want to change that to point to vg2. So make that change only if appropriate, and then paste the entire text into Phone Port 2’s OutboundCallRoute, click Submit, and then skip down to the paragraph that begins with “We’ve already showed you above how to route incoming calls for a particular extension to Phone Port 2” and continue from there. But if you DO want your FreePBX extension to be your “Primary Line”, which we recommend, then continue on from here.

There are two basic things you need to do in the OutboundCallRoute setting you just copied:

First, replace any references to pli (typically part of the text Mpli) with vg2. You need to do this because pli stands for “Primary Line” but you can’t select a Voice Gateway as a primary line in the “OBi Dashboard”, so this makes that change in the Phone Port configuration. Typically there will be two rules that need to be changed:

{([1-9]x?*(Mpli)):pp} is changed to {([1-9]x?*(Mvg2)):pp} – this is near the beginning of the text.
{(Mpli):pli} is changed to {(Mvg2):vg2} – this is near the end of the text, and note there are two replacements in this rule.

Next, you need to change any existing references to sp4 to point to vg2, EXCEPT for the rule that looks like this: {(<**4:>(Msp4)):sp4}. Don’t change that one, but any other references to sp4 should be changed to vg2, unless you have some specific reason for leaving them set to sp4. When making changes, note that rules are enclosed in {curly braces} and then separated by commas, so be careful not to accidentally delete a curly brace or comma. Just make sure that nothing remains routed to sp4 other than the single rule for the **4 prefix mentioned above; otherwise some calls from Phone Port 2 may appear to be coming from Phone Port 1’s extension when they arrive at FreePBX.

Once you have the OutboundCallRoute text modified as described above, go to Physical Interfaces/PHONE 2 – make sure you are not still in PHONE 1 where you copied the settings from; you must now be in the PHONE 2 configuration – and paste your modified settings into the OutboundCallRoute setting there, and Submit.

There are two other settings on this page that needs to be changed, DigitMap, which is just above the OutboundCallRoute setting, and CallReturnDigitMaps, which is just below it. It would be safest to copy those over from Physical Interfaces/PHONE 1, make the necessary changes, and then paste them in to the equivalent fields in Physical Interfaces/PHONE 2, but typically each of these fields will by default be the same as their equivalents in Phone Port 1 anyway.

What you need to do in both the DigitMap and CallReturnDigitMaps is replace any references to pli with vg2. In the DigitMap setting this will typically need to be changed in two places:

[1-9]x?*(Mpli) is changed to [1-9]x?*(Mvg2) – this is near the beginning of the text.
(Mpli) is changed to (Mvg2) – this is near the end of the text.

And in the CallReturnDigitMaps there is typically only one replacement that needs to be made:

{pli:(xx.)} is changed to {vg2:(xx.)} – this is near the beginning of the text.

Again, when making these changes make sure you don’t accidentally delete a curly brace or comma, and don’t forget to click Submit when you are finished.

Before leaving the “OBi Dashboard”, go back out to the main Dashboard page and click on the gear icon for your device, and look under the Phone Port Configuration Summary to make sure that the “Primary Line for Outgoing Calls Route to:” setting for Phone 2 says “Not Configured”. If, instead, it shows a service provider (SP1, SP2, SP3, or SP4) then look in the section just above, “Configure Voice Service Providers (SP)”, and click the gear icon next to that Service Provider, dismiss the popup, and then on the line “Primary Line for Outgoing Calls”, UNCHECK the checkbox next to Phone 2. This should leave Phone 2 with no configured Primary Line, meaning it should only use the rules in the settings we configured above. It would be great if we could simply set the Primary Line for Phone Port 2 to Voice Gateway 2, but the “OBi Dashboard” doesn’t allow it, which is why we had to change all those instances of pli to vg2.

If, after making these changes and setting up the configuration in FreePBX as described below, you find that you are having problems making some calls, check to see if you have the same issue on Phone Port 1. The reason we said to copy the DigitMap setting from Service Providers/ITSP Profile D/General to Voice Gateway2’s DigitMap was because we assumed that the DigitMap in ITSP Profile D, which should be associated with Phone Port 1 if you have followed these instructions from the beginning, would allow outgoing calls as configured for Service Provider 4 in the “OBi Dashboard”. So if, for example, you allowed 7 digit dialing to a particular area code when you set up SP4, then by copying the ITSP Profile D DigitMap to Voice Gateway2 those same rules should be followed by Phone Port two, PROVIDED you made all the replacements of pli to vg2 and sp4 to vg2 that we documented above.

We’ve already showed you above how to route incoming calls for a particular extension to Phone Port 2, using the X_InboundCallRoute setting under Voice Services/SP4 Service – once again, there needs to be a rule there of the form {>(ext2):ph2} where ext2 is the extension number associated with Phone Port 2.

That’s all you need to do in the Obihai device configuration.

☞ These changes must be made on the FreePBX server.

In FreePBX we need to make a Custom Extension and a new SIP trunk. When you create the extension, make sure you specify that it is Custom and not SIP! The details for the Custom Extension are as follows:

Under the General tab, set the User Extension, Display Name and Outbound CID as you normally would – obviously, the User Extension must match the Obihai device settings you used for the Name and AuthUserID for Voice Gateway 2, and especially with the extension number you associated with Phone Port 2 in the X_InboundCallRoute setting under Voice Services/SP4 Service. For all the other tabs, in most cases you can use the same settings that you would if you were creating a SIP extension. The major exception to this is in the Advanced tab, Edit Extension section, Dial setting. For that you want to use something like this:

sip/extension_number@ip_address_of_obihai:X_UserAgentPort

Replace extension_number with the number of this extension, and use the actual ip_address_of_obihai. The X_UserAgentPort is the same one we had you make a note of earlier, that was used in the Custom Dial String for the trunk(s) you created for outgoing calls to each of your Google Voice accounts. So if, for example, your extension number is 124, your Obihai is at 192.168.1.123 and the X_UserAgentPort was set to 5083, you’d use this as your Dial setting:

sip/124@192.168.1.123:5083

When you finish your custom extension configuration, don’t forget to click Submit. Note that this custom extension is used for calls going TO Phone Port 2 on the Obihai only, although there is one important exception to that – if you set an Emergency CID in the Advanced tab, Extension Options section, it will be used for calls FROM the extension that are routed through an “Emergency” outbound route, provided that the extension number you use in the trunk settings in the next section exactly matches the custom extension’s number.

For calls coming FROM Phone Port 2 we need to create a new SIP Trunk – this may sound strange, but it’s the easiest way to handle this. So, create a new SIP (chan_sip) Trunk. Under the General tab use the following settings, but note that the Trunk Name can be whatever you want, for example:

Trunk Name: Extension_124_from_Obihai
Maximum Channels: 3
Disable Trunk: No

Skip the other settings on that page, other than if you like you can fill in the Outbound CallerID to stop FreePBX from complaining. Next, in the sip Settings tab, Outgoing tab, use the extension number as the Trunk name (this is what must exactly match the custom extension’s number for the Emergency CID setting to be honored), and then fill in the PEER Details as shown below:

Trunk Name: The extension number, such as 124

PEER Details:

deny=0.0.0.0/0.0.0.0
callerid=Caller ID name and number (see below)
context=from-internal
directmedia=no
dtmfmode=rfc2833
host=192.168.X.X
port=X_UserAgentPort
nat=no
permit=192.168.X.X/255.255.255.255
qualify=yes
qualifyfreq=60
sendrpid=pai
transport=udp
trustrpid=yes
type=friend

Replace the information in the callerid= item with the correct user name and extension number, in the same way you would set a Caller ID for a regular extension, and replace the two instances of 192.168.X.X with the local IP address of the Obihai device. Once again, for the port= item replace X_UserAgentPort with the same port number we had you make a note of earlier, that was used in the Custom Dial String for the trunk(s) you created for outgoing calls to each of your Google Voice accounts. Omit the line nat=no if the Obihai device is not on the same local network as the FreePBX server, or if you experience issues with one-way audio.

Note that you can adjust the PEER Details settings as necessary. If you are trying to figure out what settings to use, you can always look in the file /etc/asterisk/sip_additional.conf and look at the settings for an actual SIP extension in FreePBX that is similar to this one, perhaps the settings for the extension associated with Phone Port 1, and use similar settings in the PEER Details here. However, the host= and port= settings must contain the IP address and X_UserAgentPort number of the Obihai device. We found that you don’t need to use every single setting that FreePBX would use when creating a SIP extension – the subset shown above worked well for us.

In case you are wondering, for us FreePBX didn’t complain about having a Custom Extension and a SIP Trunk Name set to the same extension number. If it does complain about it for you, go to the FreePBX Advanced Settings page, System Setup section, and make sure that the “Aggresively Check for Duplicate Extensions” setting is set to “No”.

Final thoughts

We realize that there are many different ways to do this, and that some work better than others. These are what worked for us. If they work for you, great! One thing we do notice is that we do not seem to experience the spontaneous rebooting of the Obihai device that some users of other methods have reported. We don’t know whether we’ve just been lucky, or whether the latest firmware fixed that problem, or whether there really is something different about our method, but we thought we’d put it out there as another possible way to do this that may work for some where other methods have failed.

Configuring an Obihai device isn’t the easiest thing to do, and that’s why we stick to using the “OBi Dashboard” – it makes configuration a lot easier. But if you need help understanding dialplans and other internal workings of the Obihai, we suggest you download the OBi Device Administration Guide – it’s a 220 page PDF file. It’s what we used to come up with most of this method, along with a few tricks we’ve picked up in various forums here and there.

One final thought – if you happen to also have an older OBi100 or OBi110 device, keep in mind that it can still be used as a FreePBX extension even though it can no longer connect with Google Voice. But it’s entirely possible to place or receive calls that go through FreePBX, to or from the 200-series device, because those devices still work fine with SIP connections, so in a roundabout manner you could still use Google Voice with such devices. It’s also possible to use the Obitalk network as an intermediary instead of FreePBX for such calls, but if you have a FreePBX server we don’t really see much point in doing that, and in any case that’s beyond the scope of this article.

Extending the remote control capabilities of LIRC

If you have installed the LIRC package on your computer so that it can receive signals from an infrared remote control (as we showed how to do in Ubuntu 18.04 in our previous article, Make LIRC work in Ubuntu 18.04, so that you can use your infrared remote in Kodi), you may have thought that you could only utilize it inside programs that have remote control support built-in, such as Kodi.  But did you know that you can also use your remote to execute any command that can be executed from a Linux command prompt, or even run a shell script to execute multiple commands?

In order to do that you need to do at least two things.  First, you need to run the irexec program (which is installed as part of the LIRC package), and second, you need to create a .lircrc file in your user directory.  In addition, you may wish to create shell scripts to do whatever you want.

An example may make things easier to understand.  Let’s take the case of starting or restarting Kodi from the desktop.  Let’s say you have just started up your system and it is sitting at the desktop waiting for you to start a program, and you want to start Kodi.  Sure, you could use your mouse to select Kodi and start it, but it’s more convenient to just be able to push a button on the remote to do it.  Or maybe you have been using Kodi and it has simply frozen up on you – wouldn’t it be nice to be able to push a button, kill the frozen instance of Kodi, and then restart Kodi?

Windows Media Center Edition compatible remote controlMost Windows Media Center Edition compatible remotes have four colored buttons, colored red, green, yellow, and blue, that don’t do anything inside Kodi by default. But, LIRC still recognizes them, and they are perfect for use in such an application.

The first thing you would need is a script to start Kodi.  Here’s a bash script that we use with Kodi 17.  Note that in Kodi 18 (at least in beta versions) some changes will need to be made, and these are noted in comment lines. Also note the comment about changing the value of yourusername in the “export USER=” line:

#!/bin/bash
# For Kodi V18 change AE_SINK=ALSA to KODI_AE_SINK=ALSA and
# all instances of kodi.bin to kodi-x11

# In the line below replace yourusername with your actual
# user name in Ubuntu (this will probably be the same as
# the name of your user directory)
export USER=yourusername

# Now try to kill existing Kodi if it is running
if ps -ef|grep -v grep|grep -i kodi.bin
then
ps aux|grep -i $USER|grep -v grep|grep -i kodi.bin|awk '{print $2}'|xargs kill
sleep 3
fi

# If it's still running, force kill it using kill -9
if ps -ef|grep -v grep|grep -i kodi.bin
then
ps aux|grep -i $USER|grep -v grep|grep -i kodi.bin|awk '{print $2}'|xargs kill -9
sleep 3
fi

# If it's STILL running it won't die, so exit
if ps -ef|grep -v grep|grep -i kodi.bin
then
exit
fi

# Delete old Kodi crashlogs (optional)
/bin/rm -f ~/kodi_crashlog-????????_??????.log

# Start Kodi using ALSA sound system
AE_SINK=ALSA nice -20 kodi --standalone &
exit

We saved this script as startkodi.sh and made it executable:

chmod +x startkodi.sh

Please note that we start Kodi with some specific options that you may or may not wish to use. To break them down:

AE_SINK=ALSA (this will change to KODI_AE_SINK=ALSA in Kodi 18): This usually forces Kodi to use the ALSA sound system rather than PulseAudio, which can give better performance if you are using passthrough audio in a multichannel system (5.1 or 7.1 audio). We say usually because on at least one system it was necessary to take more aggressive steps to kill PulseAudio before this would work (see the section headed “Disabling daemon autospawn” on this wiki page if you have this problem). You will know if it is working because you’ll need to reset your audio output under System Settings | System | Audio to use the ALSA output (and the PulseAudio options will disappear). If you are not using passthrough audio (using the “Allow passthrough” setting, and selecting a Passthrough audio device), then there is probably no reason to use this.

nice -20: This gives Kodi more CPU time than other processes that may be running at the same time, and therefore helps avoid jerkiness and dropped frames during playback.

kodi - -standalone: The recommended way to run Kodi from a shell script. (Please note there is a hidden character between the two – (hyphen) characters in this line, to force WordPress to display it correctly, so if you copy and paste this it won’t work if you don’t remove that hidden character.  Unfortunately, this is the case anyplace you see two adjacent hyphens in this article, except when they are within a code block.)

&: The ampersand at the end allows the script to exit immediately, without shutting down Kodi. It effectively makes Kodi a background task.

So that is the script we use to start Kodi, and of course we could run that from a terminal window (which you may want to do in order to check for errors), but that would not be very convenient. So, we use the .lircrc file (in the user’s home directory) to start the script when a button is pressed. We’ll use the green button in this example. Start by editing the file .lircrc (if it doesn’t already exist, this should create it):

nano ~/.lircrc

And just paste in these lines:

begin
 prog = irexec
 button = KEY_GREEN
 config = ~/startkodi.sh &
 repeat = 0
end

Then you can use Ctrl-X to exit nano (be sure to save the file).

The only other thing you need to do is make sure that the irexec program runs at startup. To do that, from the Ubuntu desktop bring up Startup Applications, and when it comes up click the Add button and enter these values:

Name: irexec
Command: irexec -d
Comment: Whatever you want, we used “Infrared Remote Control”

Add irexec to startup programs
Click the Add button to save it.

Then REBOOT THE SYSTEM.

Once the system has rebooted, you should be able to press the green button and it should run the startkodi.sh script and start Kodi. If it doesn’t, it’s probably because your remote is using different labels for the buttons, and we’ll cover how to determine that in a moment.  In case you are wondering, the -d option used with irexec is what makes it run as a background task.

Now maybe you’d like to be able to push the red button to stop Kodi in case it is hung, but without restarting it.  All you need to do is copy the startkodi.sh script to another script (call it stopkodi.sh), then edit that script to remove the line that starts Kodi, and then edit the .lircrc configuration to add another section:

begin
 prog = irexec
 button = KEY_RED
 config = ~/stopkodi.sh &
 repeat = 0
end

We can also run system commands directly from the .lircrc file. Let’s say we wanted to use the blue button to reboot the system, in case things really get messed up. We could add this to .lircrc:

begin
 prog = irexec
 button = KEY_BLUE
 config = sudo reboot
 repeat = 0
end

You would think this would work, but it won’t because when it tries to run sudo it will prompt for your password, and the script can’t deal with that. In order to avoid that, you’ll need to edit the /etc/sudoers file:

sudo nano /etc/sudoers

Move the cursor to the end of the file and on a new line add this:

yourusername ALL = NOPASSWD: /sbin/reboot

Replace yourusername with your your actual user name in Ubuntu. Use Ctrl-X to exit nano, and save the file. This allows running “sudo reboot” without needing to enter a password.

Remember that you will need to REBOOT THE SYSTEM before any changes take effect!

Now, if you are lucky these .lircrc configurations will work as shown. But if you have a different type of remote, you may need to use different buttons, or maybe the buttons aren’t returning the values that .lircrc is expecting to see. To determine that, from a Linux command prompt run this:

irw

Then while watching the terminal window or ssh session, press the buttons you are trying to use on the remote. As an example, here is what we see when we press the green button:

$ irw
000000037ff07ba3 00 KEY_GREEN mceusb
000000037ff07ba3 01 KEY_GREEN mceusb

Press Ctrl-C to exit irw. The thing you are looking for here is the button name, in this case it is KEY_GREEN as shown in the .lircrc section that starts Kodi above, but if your remote returns something other than that, that’s what you’ll need to use in the .lircrc file.  By the way, it is not unusual for a remote to send a button press two or three times in a row, just in case the infrared receiver misses it the first time.  This is not a cause for concern.

When you use irw as shown above, remember that lirc is still running, so don’t press any buttons that would take any action you don’t want to have happen, such as rebooting the system or launching Kodi or something else.

ADDING ADDITIONAL BUTTONS FROM THE SAME OR A DIFFERENT REMOTE

When you use irw, there’s a slight chance you might notice that your remote has one or more buttons that don’t generate any output at all, and maybe you’d like to make them recognized. Or, maybe you’d like to use a second remote (perhaps one that came with a device that you no longer use) to control some additional functions. These things are possible (usually) but the procedure is slightly complicated. One thing to keep in mind is that infrared receivers are only responsive to a certain part of the spectrum of infrared light, and some remotes may generate light pulses outside that range, in which case a particular remote may not work with a particular infrared receiver. But it’s worth a try.

Here’s the basic procedure for getting LIRC to recognize additional buttons:

Open the file /etc/lirc/lircd.conf in a text editor, or just do cat /etc/lirc/lircd.conf from a Linux command prompt, and note the contents – more than likely it will contain an “include” statement such as

include "/usr/share/lirc/remotes/mceusb/lircd.conf.mceusb"

Open THAT file in a text editor and note how it is constructed. You will probably see definitions for one or more remotes, in sections between “begin remote” and “end remote” tags. In each such section you will see a list of codes, in sections between “begin codes” and “end codes”, and in such sections you will see two columns. The first is a list of names that have already been used for existing remote buttons, and that you therefore should not use when adding new buttons.

However, you cannot just go using any button names you like for your new buttons. You can only use the button names that are shown when you run this command from a Linux command prompt:

irrecord - -list-namespace

(Please note there is a hidden character between the two – (hyphen) characters in the above line, to force WordPress to display the line correctly, so if you copy and paste the above it won’t work if you don’t remove that hidden character.)

So to try to make this clear, when naming a new button you can only use names that appear in the list you get when you run irrecord - -list-namespace but you should NOT use names that appear in the /etc/lirc/lircd.conf file, or in any file that is mentioned in an include statement within that file, because you run the risk of specifying the same button name for two different buttons.

You may have to read that a couple of times for it to sink in, but it’s important. You will probably want to find a way to keep both lists visible during the next steps. You could open them in two different Text Editor windows, or two different terminal windows, or two different ssh sessions from another computer – it really doesn’t matter as long as you can refer to both lists, and know which is which.

Now you are ready to try to map new buttons. During this process, lircd cannot be running, so do this:

sudo killall lircd

Next, run this command:

sudo irrecord -d /dev/lirc0 ~/newremote.txt

The character at the end of lirc0 is a zero, not a letter O. You can use any filename you want rather than “newremote.txt”, just make sure it’s a filename you aren’t already using. When using irrecord, don’t try to add buttons from more than one remote in a single run, and if you make a mistake just Ctrl-C out, delete the “newremote.txt” file, and start over. Also, note the above line assumes that /dev/lirc0 is the correct path for LIRC’s connection to your infrared receiver, which is almost always the case.

The irrecord program will walk you through the entire procedure for adding new buttons — just follow the instructions it gives precisely. It will first have you perform some tasks so it can determine basic timing information about your remote.  If irrecord can’t seem to detect your remote, it may be that the remote isn’t compatible with your infrared receiver, or it may be that the batteries are dead in the remote! Don’t give up on a remote without at least trying new batteries.

After the preliminary tasks are completed, irrecord will ask you to enter the name of a button. This is when you will refer to the two lists — remember, you want to use a name that DOES appear in the irrecord - -list-namespace list, but that does NOT currently appear in /etc/lirc/lircd.conf or in any file referenced by an include statement therein (such as /usr/share/lirc/remotes/mceusb/lircd.conf.mceusb in our example above).  Just to be clear, there is no requirement that the names you use in this procedure be in any way related to the names of the buttons on the remote, since you will be defining what the button press actually does in the .lircrc file.  It may be convenient to use a related name (if it’s not already used in another remote’s codes list) to help you remember which button is associated with which name, but if you can’t find an unused name that comes close to the name of the button on your remote,  it’s perfectly okay to pick any unused name from the irrecord - -list-namespace list and use that, though in that case you may want to make notes about which names are associated with which buttons.

After you enter the name, it will ask you to hold down the button on the remote. After a few moments it should ask you to enter the name for your next button – that is your confirmation that the button was accepted by your infrared receiver. You can keep on adding new buttons from the same remote, or exit by pressing only the Enter key when asked for the name of the next button.

Once you have exited irrecord, you must open the file it created (~/newremote.txt, or whatever name you used) in a text editor, and change the value on the name line (right below the line that reads “begin remote”) to something that is all lowercase letters with NO SPACES – underscore characters are okay, though.  So, something like

 name new_remote

would be fine.  The name must not duplicate the name in any of your existing remote definitions.  Also, we always remove all the commented-out lines produced by irrecord (lines that begin with a # character), since they are not needed.

After you have made those changes, copy the section starting with “begin remote” and ending with “end remote” to the clipboard, and then open the file containing your other remote definitions and carefully paste your new remote definitions to the end of that file (leave at least one blank line after the existing contents of the file before pasting).  By “the file containing your other remote definitions” we mean either /etc/lirc/lircd.conf or the file that is mentioned in an include statement within /etc/lirc/lircd.conf, such as /usr/share/lirc/remotes/mceusb/lircd.conf.mceusb in our above example (we used the latter).  The basic idea is you want to put your new remote definitions and codes at the end of the same file that contains all the other remote definitions and codes. BE CAREFUL when doing this because if you somehow screw up this file, your remote may not work at all!  It probably isn’t the worst idea to make a backup of the file prior to making any changes.

If you don’t want to mess with your existing remote definitions file, you could probably add a new include line within /etc/lirc/lircd.conf and point that to a new file that you have created that contains your new remote definitions.  That is supposed to work, according to the LIRC documentation, but we haven’t actually tested doing it that way (please note that the LIRC documentation link takes you to the documentation for the latest version of LIRC, and therefore some parts may not be applicable if you are using an older LIRC version).

Note that if you were trying to add buttons from your main remote that LIRC has not previously recognized for some reason, you will probably want to add just those new codes directly to the existing codes list for that remote, rather than copying the entire new block of remote definitions.

You will probably want to save a backup of your new remote definitions someplace, so you don’t have to go through this process again the next time you upgrade the system!  This comment comes from experience — during our most recent Ubuntu upgrade, we backed up the entire home directory and some specific configurations from the /etc directory, but we totally forgot about the remote definitions that we had put into the /usr/share/lirc/remotes/mceusb/lircd.conf.mceusb file, so we had to do redo this process.

Once you have added your new remote definitions and codes to the file containing your existing remote definitions and codes and saved it, you should REBOOT THE SYSTEM so that lircd will restart and read in the new codes.  After the system is rebooted, you can once again run irw and now when you press one of the buttons you added, it should show the name that you assigned to the button.  And if that works, you can then use that button name in the .lircrc file to launch shell scripts or system commands, or do just about anything you could do from a Linux command prompt.

Addendum:  Mind the Gap!  No, we haven’t been riding the London underground, but we have discovered that on some systems, but not others for some weird reason, if you add remote definitions that contain a “gap” value in the headers — which almost all added definitions will — it may cause LIRC to stop working altogether if for whatever reason irexec doesn’t like the gap value.  So if you have a gap value that is a bit on the high side (near or above 100000) you may need to reduce the gap value to get things working again.  For example in one case the gap value should have been 108382, but we wound up having to reduce it to 80000 on just one system for it to work, even though the higher value works fine on several other systems, and even though some of the other remote definitions had higher gap values.  The real issue is that if you get bitten by this, your remote won’t work at all until you change the gap value to something that irexec approves of — it will just silently fail to recognize your remote! This may even be a problem when you are copying remote definitions from one system to another — the gap value that works just fine on one system will cause the failure of your remote control to work at all on a different system.