Archive for the ‘Asterisk’ Category

Redundancy Design for AstLogger

Posted: September 24, 2016 in Asterisk, TSAPI

AstLogger Redundancy Design

New version of AstLogger can be configured with redundancy support. Three server roles are designed, they are “active”, “backup” and “parallel”. I use the following diagram to illustrate the different combination of redundancy implementation.

RedundancyDesign.png

Active Hot-Standby Recording

Two AstLogger servers are required for this setup. The two AstLogger instances connect to different AES to avoid single point of failure. Also the two AstLogger instances use different pool of phantom devices. The “active” AstLogger always trigger recording when it is alive. The “backup” AstLogger only trigger recording when it detects the “active” AstLogger is failure. Only one voice file is generated for each call by this implementation.

Active Active Recording

Two AstLogger servers are required for this setup. The two AstLogger instances connect to different AES to avoid single point of failure. Also the two AstLogger instances use different pool of phantom devices. The “active” AstLogger always trigger recording when it is alve. The “parallel” AstLogger always start the recording right after the “active” AstLogger. Two voice files are generated for each call by this implementation.

1.4.10 Beta 1

You can download 1.4.10 beta 1 for testing of this new feature. A new parameter called “al_serverrole” is introduced for this purpose, the value can be “active”, “backup” and “parallel”.

AstLogger 1.4.8 Released

Posted: June 23, 2016 in Asterisk, News, TSAPI

23 Jun 2016, AstLogger 1.4.8 just released. This version 

1. Supports call log centralization by integration with CallAban.
2. The logic for application data logging is modified. Only the modified data item will be saved to database.
3. Fixed a bug that AstLogger will not startup successfully before AES startup.
4. Fixed a bug that AstLogger will not startup successfully before Asterisk startup.
5. Supports pauserecording and unpauserecording function by the REST interface.

AstCTI 1.1.0 Released

Posted: December 23, 2015 in Asterisk, News

23 Dec 2015, AstCTI 1.1.0 just released. This version only supports start or stop monitoring agent extensions and delivers the channel events by ActiveX and WebSocket interfaces. I plan to implement a my queue using ARI so all incoming calls will go into my queue, then all calls can be controlled by my supported interfaces such as ActiveX, REST and  WebSocket. I guess it will take a very long time to implement.

The Asterisk CTI implementation has some progress. I have developed a CTI server called AstCTI which connects to Asterisk using ARI and accepts client connections by interfaces such as WebSocket, OCX and REST. I just developed the OCX interface, currently the OCX interface only supports Connect, Disconnect, StartMonitor and StopMonitor methods. Also, it has an OCX event interface called OnJSONEvent for JSON events which are delivered from Asterisk.

The AstCTI is a Windows Service program, it uses tcpgate console for program configuration and message tracing

AstCTI

I also developed a VC program for testing. The telephony icon on the VC program is the OCX that I mentioned above.

AstClientVC

Next I will develop the WebSocket interface and study the call control functions such as MakeCall, Hangup, Transfer and Conference, etc.

AstLogger 1.4.7 Released

Posted: November 11, 2015 in Asterisk, News, TSAPI

11 Nov 2015, AstLogger 1.4.7 just released. A new module called AstLogger Archive Daemon is introduced, it supports the following features:

  1. Archiving of recording files for AstLogger.
  2. Deletion of recording files when harddisk utilization reached a predefined level
  3. Deletion of recording files when files are created before a retention period

The AstLoggerWeb is modified to search archive path when the recording file is delete from the working path. This version also fixed a bug on the websocket mask bit and mask key handling.

I am going to implement my Asterisk CTI class using the Asterisk REST Interface (ARI). The CTI class has different class objects, for example, a reactor object for websocket event notification, a websocket event handler object for receiving of Asterisk telephony events, a thread with a circular buffer to handle the telephony events, also a thread pool to deliver each telephony event to the calling application.

To get telephony events notification from Asterisk, we need to subscribe endpoint eventsource first. For testing #1, I have setup two extensions 1000 and 1002 in FreePBX, I subscribed evens for the two extensions using my class. I dialed 1002 from 1000, answered the call then hangup the call. I found a lot of events were generated from Asterisk and it seems there is no way to filter the number events from Asterisk. So I wrote a function to filter some unwanted events and remained the following events that are useful in my class

  • ChannelCreated
  • ChannelConnectedLine
  • ChannelDestroyed
  • ChannelStateChange
  • ChannelHold
  • ChannelUnhold
  • ChannelTalkingStarted
  • ChannelTalkingFinished
  • ChannelEnteredBridge
  • ChannelLeftBridge

After the filtering applied, the following events in blue are for extension 1000, while the events in red are for extension 1002.

{ “type”: “ChannelCreated”, “timestamp”: “2015-11-02T22:28:38.776+0800”, “channel”: { “id”: “1446474518.30”, “name”: “PJSIP/1000-00000006”, “state”: “Ring”, “caller”: { “name”: “device”, “number”: “1000” }, “connected”: { “name”: “”, “number”: “” }, “accountcode”: “”, “dialplan”: { “context”: “from-internal”, “exten”: “1002”, “priority”: 1 }, “creationtime”: “2015-11-02T22:28:38.774+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelConnectedLine”, “timestamp”: “2015-11-02T22:28:38.862+0800”, “channel”: { “id”: “1446474518.30”, “name”: “PJSIP/1000-00000006”, “state”: “Ring”, “caller”: { “name”: “Kai”, “number”: “1000” }, “connected”: { “name”: “Ping”, “number”: “” }, “accountcode”: “”, “dialplan”: { “context”: “macro-dial-one”, “exten”: “s”, “priority”: 40 }, “creationtime”: “2015-11-02T22:28:38.774+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelCreated”, “timestamp”: “2015-11-02T22:28:38.864+0800”, “channel”: { “id”: “1446474518.32”, “name”: “PJSIP/1002-00000007”, “state”: “Down”, “caller”: { “name”: “device”, “number”: “1002” }, “connected”: { “name”: “”, “number”: “” }, “accountcode”: “”, “dialplan”: { “context”: “from-internal”, “exten”: “s”, “priority”: 1 }, “creationtime”: “2015-11-02T22:28:38.864+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelConnectedLine”, “timestamp”: “2015-11-02T22:28:38.862+0800”, “channel”: { “id”: “1446474518.30”, “name”: “PJSIP/1000-00000006”, “state”: “Ring”, “caller”: { “name”: “Kai”, “number”: “1000” }, “connected”: { “name”: “Ping”, “number”: “1002” }, “accountcode”: “”, “dialplan”: { “context”: “macro-dial-one”, “exten”: “s”, “priority”: 41 }, “creationtime”: “2015-11-02T22:28:38.774+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelConnectedLine”, “timestamp”: “2015-11-02T22:28:38.865+0800”, “channel”: { “id”: “1446474518.32”, “name”: “PJSIP/1002-00000007”, “state”: “Down”, “caller”: { “name”: “device”, “number”: “1002” }, “connected”: { “name”: “Kai”, “number”: “1000” }, “accountcode”: “”, “dialplan”: { “context”: “from-internal”, “exten”: “1002”, “priority”: 1 }, “creationtime”: “2015-11-02T22:28:38.864+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelStateChange”, “timestamp”: “2015-11-02T22:28:39.027+0800”, “channel”: { “id”: “1446474518.32”, “name”: “PJSIP/1002-00000007”, “state”: “Ringing”, “caller”: { “name”: “device”, “number”: “1002” }, “connected”: { “name”: “Kai”, “number”: “1000” }, “accountcode”: “”, “dialplan”: { “context”: “from-internal”, “exten”: “1002”, “priority”: 1 }, “creationtime”: “2015-11-02T22:28:38.864+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelStateChange”, “timestamp”: “2015-11-02T22:28:45.637+0800”, “channel”: { “id”: “1446474518.32”, “name”: “PJSIP/1002-00000007”, “state”: “Up”, “caller”: { “name”: “device”, “number”: “1002” }, “connected”: { “name”: “Kai”, “number”: “1000” }, “accountcode”: “”, “dialplan”: { “context”: “from-internal”, “exten”: “1002”, “priority”: 1 }, “creationtime”: “2015-11-02T22:28:38.864+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelStateChange”, “timestamp”: “2015-11-02T22:28:45.637+0800”, “channel”: { “id”: “1446474518.30”, “name”: “PJSIP/1000-00000006”, “state”: “Up”, “caller”: { “name”: “Kai”, “number”: “1000” }, “connected”: { “name”: “Ping”, “number”: “1002” }, “accountcode”: “”, “dialplan”: { “context”: “macro-dial-one”, “exten”: “s”, “priority”: 44 }, “creationtime”: “2015-11-02T22:28:38.774+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelDestroyed”, “timestamp”: “2015-11-02T22:28:50.080+0800”, “cause”: 16, “cause_txt”: “Normal Clearing”, “channel”: { “id”: “1446474518.30”, “name”: “PJSIP/1000-00000006”, “state”: “Up”, “caller”: { “name”: “Kai”, “number”: “1000” }, “connected”: { “name”: “Ping”, “number”: “1002” }, “accountcode”: “”, “dialplan”: { “context”: “from-internal”, “exten”: “h”, “priority”: 1 }, “creationtime”: “2015-11-02T22:28:38.774+0800”, “language”: “en” }, “application”: “goanswer” }

{ “type”: “ChannelDestroyed”, “timestamp”: “2015-11-02T22:28:50.082+0800”, “cause”: 16, “cause_txt”: “Normal Clearing”, “channel”: { “id”: “1446474518.32”, “name”: “PJSIP/1002-00000007”, “state”: “Up”, “caller”: { “name”: “device”, “number”: “1002” }, “connected”: { “name”: “Kai”, “number”: “1000” }, “accountcode”: “”, “dialplan”: { “context”: “from-internal”, “exten”: “”, “priority”: 1 }, “creationtime”: “2015-11-02T22:28:38.864+0800”, “language”: “en” }, “application”: “goanswer” }

For testing #2, I used three extensions, they are 1000, 1002 and 1006. I initiated a call from 1000 to 1002, answered the call by 1002, then initiated another from 1000 to 1006, answered the call by 1006, the last step transferred the call by 1000, leaving 1002 and 1006 in a call, then ended the call by 1002 finally. The text file is here.

For testing #3, I used three extensions, they are 1000, 1002 and 1006. I initiated a call from 1000 to 1002, answered the call by 1002, then initiated another from 1000 to 1006, answered the call by 1006, the last step conference the call by 1000, and finally hangup the call by 1002. The text file is here.

Next step I will add call control functions such as Originate, Hold, Retrieve, Transfer and Conference, etc. After the implementation of the CTI class, I will port my tools such as ScreenPop, ivrSVR to support Asterisk. Good luck to me.

AstLogger 1.4.5 Released

Posted: June 6, 2015 in Asterisk, News, TSAPI

5 Jun 2015, AstLogger 1.4.5 just release. This version supports REST and WebSocket interfaces. Moreover, it supports playback and control playback of voice records using Avaya phones when Asterisk 12 or above is used.

Next version of AstLogger will support CentOS and archiving of voice files to a backup location such as NAS.