Patton SmartNode BRI ISDN as an Asterisk gateway.

I’ve looked at and tried a few configuration files out there, and used Patton’s web wizard. None are particularly clear about who registers with who, etc. I also had problems with “The other person has hung up” recorded message from BT, when the other party hung up the call (cured by “allow early disconnect” in the SmartNode SIP profile).

Anyway, here is a configuration file for a Smartnode 4554 dual-BRI. There is no registration or SIP authentication. It is meant for a back-to-back Asterisk <-> Smartnode setup.

Before I get started, here is the trunk configuration, from FreePBX. It is using chan_sip, not chan_pjsip. In my builds, I disable pjsip (for the time being), and move chan_sip back to the former default of UDP port 5060. This is because I use a lot of mixed equipment and the troubleshooting has been extensive, and still, some minor issues persist between PJSIP on Asterisk/FPBX and the various brands of desk phones, cordless phones, gateways, and SIP trunk providers that I use.

One thing to note: I had to turn off “Send Progress” in my ‘RingAll’ Ring Group in FreePBX. The caller did not hear a ringback tone when calling in, if the destination was this ring group.

As usual, you do not need to enter anything at all on the ‘incoming’ settings in FreePBX. Yes this is counter-intuitive, and yes this system makes both incoming and outgoing calls via the gateway, but this is just how FreePBX manages the trunk setup. I never have, and never do put anything in the ‘incoming’ settings part of the chan_sip trunk setup in FreePBX, whether I am using a SIP trunk from an ITSP (Gamma, Voiceflex), a Cisco 2811 with an E1 PRI module, or this Patton Smartnode BRI gateway.

In these configuration examples, FreePBX is on The Smartnode Sn4554 is on

OK, so once again, this is the FreePBX chan_sip trunk configuration. Just put the following in the Outgoing ‘Peer Details’ box (change the host= to be the IP address that you use for the Smartnode).


Next we have the SmartNode configuration. Copy and paste this into notepad, save it, then use the import facility in the web front-end to import it. Do note the “interface WAN -> ipaddress” stuff. You can change it to “dhcp” if you like, or alter the IP address before you do the import.

#                                                                #
# SN4554/2BIS/EUI                                                #
# R5.9 2012-09-05 SIP                                            #
# 2016-12-30T14:17:37                                            #
# SN/00A0BA0528A1                                                #
# Generated configuration file                                   #
#                                                                #

cli version 3.20
clock local default-offset +00:00
webserver port 80 language en


  ic voice 0

  clock-source 1 bri 0 1

profile ppp default

profile tone-set default

profile voip default
  codec 1 g711alaw64k rx-length 20 tx-length 20
  codec 2 g711ulaw64k rx-length 20 tx-length 20
  fax transmission 1 relay t38-udp
  fax transmission 2 bypass g711alaw64k rx-length 20 tx-length 20
  fax transmission 3 bypass g711ulaw64k rx-length 20 tx-length 20
  modem transmission 1 bypass g711alaw64k rx-length 20 tx-length 20
  modem transmission 2 bypass g711ulaw64k rx-length 20 tx-length 20

profile pstn default

profile sip default
  no autonomous-transitioning

profile aaa default
  method 1 local
  method 2 none

context ip router

  interface WAN

context cs switch
  national-prefix 0
  international-prefix 00

  routing-table called-e164 RT_ISDN_TO_SIP
    route .T dest-interface IF_SIP

  interface isdn IF_ISDN_00
    route call dest-table RT_ISDN_TO_SIP
    call-reroute emit
    diversion emit

  interface isdn IF_ISDN_01
    route call dest-table RT_ISDN_TO_SIP
    call-reroute emit
    diversion emit

  interface sip IF_SIP
    bind context sip-gateway GW_SIP
    route call dest-service SRV_HG

  service hunt-group SRV_HG
    drop-cause normal-unspecified
    drop-cause no-circuit-channel-available
    drop-cause network-out-of-order
    drop-cause temporary-failure
    drop-cause switching-equipment-congestion
    drop-cause access-info-discarded
    drop-cause circuit-channel-not-available
    drop-cause resources-unavailable
    route call 1 dest-interface IF_ISDN_00
    route call 2 dest-interface IF_ISDN_01

context cs switch
  no shutdown

location-service SER_LOC
  domain 1

context sip-gateway GW_SIP

  interface IF_GWSIP
    bind interface WAN context router port 5060

context sip-gateway GW_SIP
  bind location-service SER_LOC
  no shutdown

port ethernet 0 0
  bind interface WAN router
  no shutdown

port bri 0 0
  clock auto
  encapsulation q921

    protocol pp
    uni-side auto
    encapsulation q931

      protocol dss1
      uni-side user
      bchan-number-order ascending
      encapsulation cc-isdn
      bind interface IF_ISDN_00 switch

port bri 0 0
  no shutdown

port bri 0 1
  clock auto
  encapsulation q921

    protocol pp
    uni-side auto
    encapsulation q931

      protocol dss1
      uni-side user
      bchan-number-order ascending
      encapsulation cc-isdn
      bind interface IF_ISDN_01 switch

port bri 0 1
  no shutdown



beginnings of arduino dual i2c slave for mi-light remote RGB+CCT dual white

This is as far as I got, then I had to refocus my life for a bit.

it acts as two independent i2c slaves on the same address (two separate buses). The idea is to take the place of the two capacitive touch-sensors in the MiLight remote, and pretend to be them, and get the microcontroller on the little RF header board in the remote to send out the commands we want. This should overcome the need to understand the new RGB+DualWhite (RGB+CCT) MiLight protocol with its as yet unbroken encryption.

This code is terrible and it will only spit out the same packet, but it’s a start. I was able to unpredictably get the bulb to change from off to on or flashing or blue.

I used a Feather M0, the ARM one, which can run two i2c buses at the same time via its sercom thing.

I think I left some of the code commented out for the second i2c bus, before I went to sleep.. i was just experimenting. you can uncomment it, it was working.

// Wire Slave Sender
// by Nicholas Zambetti <>

// Demonstrates use of the Wire library
// Sends data as an I2C/TWI slave device
// Refer to the "Wire Master Reader" example for use with this

// Created 29 March 2006

// This example code is in the public domain.
#include <Wire.h>
#include "wiring_private.h" // pinPeripheral() function

TwoWire myWire(&sercom1, 13, 11); // first pin is SDA, second pin is SCL

int reqNo_ch1 = 0;
int reqNo_ch2 = 0;
int on = 0;

char val1;
char val2;
char ch1read;
char ch2read;
char ch1write;
char ch2write;

byte data1[5];
byte data2[5];
byte cmdon[] = {0x02, 0x00, 0x01, 0x00, 0x00};
byte cmdoff[] = {0x02, 0x00, 0x02, 0x00, 0x00};
byte btnReleased[] = {0x02, 0x00, 0x00, 0x00, 0x00};

void setup() {
Wire.begin(0x53); // join first i2c bus with address 0x53
Wire.onRequest(requestEvent1); // register event for i2c bus 1
Wire.onReceive(receiveEvent1); // register receive event (for Writes from master) for i2c bus 1
myWire.begin(0x53); // join second i2c bus with address 0x53
pinPeripheral(11, PIO_SERCOM);
pinPeripheral(13, PIO_SERCOM); // Assign pins 13 & 11 to SERCOM functionality
myWire.onRequest(requestEvent2); // register event for i2c bus 2
myWire.onReceive(receiveEvent2); // register receive event (for Writes from master) for i2c bus 2
// while (!Serial);
Serial.begin(115200); // start serial for output


void loop() {
if (ch1read == 1) {
if (on == 1) Serial.print("R1 on ");
if (on == 0) Serial.print("R1 off ");
ch1read = 0;
if (ch1write == 1) {
PrintHex83(data1, 5);
ch1write = 0;

if (ch2read == 1) {
ch2read = 0;
if (ch2write == 1) {
PrintHex83(data2, 5);
ch2write = 0;

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent1() {
ch1read = 1;
if (reqNo_ch1 >1) {
if (on == 0) {
Wire.write(cmdon, 5); // respond with "on"
on = 1;
//reqNo_ch1 = ;
else {
Wire.write(cmdoff, 5); // respond with "off"
on = 0;
//reqNo_ch1 = 0;
else {
Wire.write(btnReleased, 5); // respond with "button released"
reqNo_ch1 = 5;

void receiveEvent1(int howMany)
ch1write = 1;
int x = 1;
while (Wire.available())
data1[x] =; // receive byte as a character

void requestEvent2() {
ch2read = 1;
// if (reqNo_ch2 >1) {
// if (on == 0) {
// myWire.write(cmdon, 5); // respond with "on"
// on = 1;
// reqNo_ch2 = 0;
// }
// else {
// myWire.write(cmdoff, 5); // respond with "off"
// on = 0;
// }
// reqNo_ch2--;
// }
// else {
myWire.write(btnReleased, 5); // respond with "button released"
// reqNo_ch2 = 5;
// }

void receiveEvent2(int howMany)
ch2write = 1;
int x=1;
while (myWire.available())
data2[x] =; // receive byte as a character

extern "C" {
void SERCOM1_Handler(void) {

void PrintHex83(uint8_t *data, uint8_t length) // prints 8-bit data in hex
char tmp[length*2+1];
byte first ;
int j=0;
for (uint8_t i=0; i<length; i++)
first = (data[i] >> 4) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first ;

first = (data[i] & 0x0F) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first;
tmp[length*2] = 0;

Excel comparing dates greater/less than when one includes a time

Want to check if the job done (Cell C2) was on or before the deadline day (C1)

C1: 23/07/2015 (cell contains date only)
C2: 23/07/2015 01:00 (cell contains date and time)

instead of =IF(C2<=C1,”Done on time”,”Not done on time”)

Instead use:
=IF(C2<C1+1,”Done on time”,”Not done on time”)

Seems to work for me.

Have changed it from <=, to just less-than (<), but incremented the deadline by a day.


These are scam websites. They will send you some $10 Chinese shoes/boots, from China. Not the $200 – $500 shoes that you order.

All of these websites were created in the past couple of months and registered through a German registrar.


These are scam websites. They will send you some $10 Chinese shoes/boots, from China. Not the $200 – $500 shoes that you order.

All of these websites were created in the past couple of months and registered through a German registrar.

Cisco SPA BLF Call Pickup not working with Asterisk 13

(update: I think I realised that this only applies to PJSIP. With chan_sip it works the same as the rest of the Internet would tell you).

6 hrs later, I discovered that Cisco SPA5xx with firmware 7.6.1, and Asterisk 13, require the ‘system type’ in the attendant console settings, setting to Broadsoft. It doesn’t work when set to Asterisk (Directed Call Pickup doesn’t work). This has been a long night.

I also had to set the function as below:


without the ext= it still doesn’t work.

It needs both, sub= and ext=, and system type = broadsoft

So, broadsoft as system type, directed pickup code **# or whatever, disable lines 2 – 7 or whatever, set type to private, and use above extended function.

This applies whether you have an attendant console are just using the spare line keys.

My SIP attack IP blocklist

Thanks to fail2ban (with correct new “security” log and regex enabled on asterisk 1.8+ (they don’t try to register any more!)), I collect IP addresses of people attempting to hack/fraud SIP systems. I then block the closest, widest IP subnet. I don’t care if I’m blocking a continent at a time. As and when my handful of external users report problems (overlap of bad/good IP addresses), I will correct, but for now my block list at the router looks like this. Fail2ban blocks using iptables on the Asterisk box itself, but I then kill connections and add to my Mikrotik address-list on the router, after whois’ing the IP and looking if the provider has a wider netblock – then I go for that, otherwise I go for what looks like a good fit the for culprit. Thankfully we also pay for fraud insurance. Ideally, the external handsets would have VPN clients inbuilt, but alas this is not the case. I have configured small mikrotiks to travel with the handset but this seems like a cumbersome offering.

To begin with, this list was called “PlusServer”, because the majority of attacks were coming from PlusServer AG. Next in line was This killed off the most severe attacks, but since then I’ve had everything from Denmark to Palastine (twice) and Russia. Anyway here’s the list, from my Mikrotik address-list.

0 SipAttack
1 SipAttack
2 SipAttack
3 SipAttack
4 SipAttack
5 SipAttack
6 SipAttack
7 SipAttack
8 SipAttack
9 SipAttack
10 SipAttack
11 SipAttack
12 SipAttack
13 SipAttack
14 SipAttack
15 SipAttack
16 SipAttack
17 SipAttack
18 SipAttack
19 SipAttack
20 SipAttack
21 SipAttack
22 SipAttack
23 SipAttack
24 SipAttack
25 SipAttack
26 SipAttack
27 SipAttack
28 SipAttack
29 SipAttack
30 SipAttack
31 SipAttack
32 SipAttack
33 SipAttack
34 SipAttack
35 SipAttack
36 SipAttack
37 SipAttack
38 SipAttack
39 SipAttack
40 SipAttack
41 SipAttack
42 SipAttack
43 SipAttack
44 SipAttack
45 SipAttack
46 SipAttack
47 SipAttack
48 SipAttack
49 SipAttack
50 SipAttack
51 SipAttack
52 SipAttack
53 SipAttack
54 SipAttack
55 SipAttack
56 SipAttack
57 SipAttack
58 SipAttack
59 SipAttack
60 SipAttack
61 SipAttack
62 SipAttack
63 SipAttack
64 SipAttack
65 SipAttack
66 SipAttack
67 SipAttack
68 SipAttack
69 SipAttack
70 SipAttack
71 SipAttack
72 SipAttack
73 SipAttack
74 SipAttack
75 SipAttack
76 SipAttack
77 SipAttack

Remove windows 10 appx packages, but retain store

$Packages = “Microsoft.SkypeApp_3.2.1.0_x86__kzf8qxf38zg5c” , `
“Microsoft.People_1.10241.0.0_x64__8wekyb3d8bbwe” , `
“Microsoft.BingFinance_4.4.200.0_x86__8wekyb3d8bbwe” , `
“Microsoft.WindowsCalculator_10.1507.15010.0_x64__8wekyb3d8bbwe” , `
“Microsoft.BingNews_4.4.200.0_x86__8wekyb3d8bbwe” , `
“Microsoft.BingSports_4.4.200.0_x86__8wekyb3d8bbwe” , `
“Microsoft.Getstarted_2.2.7.0_x64__8wekyb3d8bbwe” , `
“Microsoft.WindowsMaps_4.1506.50715.0_x64__8wekyb3d8bbwe” , `
“Microsoft.BingWeather_4.4.200.0_x86__8wekyb3d8bbwe” , `
“Microsoft.WindowsSoundRecorder_10.1507.7010.0_x64__8wekyb3d8bbwe” , `
“Microsoft.WindowsAlarms_10.1507.17010.0_x64__8wekyb3d8bbwe” , `
“Microsoft.XboxApp_7.7.29027.0_x64__8wekyb3d8bbwe” , `
“Microsoft.Windows.Photos_15.803.16240.0_x64__8wekyb3d8bbwe” , `
“Microsoft.ZuneVideo_3.6.12101.0_x64__8wekyb3d8bbwe” , `
“Microsoft.ZuneMusic_3.6.12101.0_x64__8wekyb3d8bbwe” , `
“Microsoft.MicrosoftSolitaireCollection_3.3.8040.0_x64__8wekyb3d8bbwe” , `
“Microsoft.WindowsCamera_5.42.3008.0_x64__8wekyb3d8bbwe” , `
“Microsoft.MicrosoftOfficeHub_17.6106.23501.0_x64__8wekyb3d8bbwe” , `
“Microsoft.windowscommunicationsapps_17.6106.42001.0_x64__8wekyb3d8bbwe” , `

ForEach ($package in $Packages)
remove-AppxProvisionedPackage -online -packagename $package
remove-AppxPackage -package $package

owncloud restrict download of entire root as zip

in /var/www/owncloud/lib/private/files.php

In this case, the workspace/store is called Savills. We also want to cover when the other download button is chosen from the root itself (


Look for the code starting with “try”, and modify like below. Dirty but does the job for now.

try {
if ($name ===’’) {
header(“HTTP/1.0 403 Forbidden”);
die(“Please choose a smaller selection to download. Use your back button to return.”);
if (($name ===’’) && (count($files) == “1”)) {
header(“HTTP/1.0 403 Forbidden”);
die(“Tried to download whole of root, as Not allowed.”);