Digium電話の本当に便利なアプリケーション

画像



あいさつ、habrasociety。



1年ちょっと前に、Digium電話用のアプリケーションを開発しました 。 計画が広範であったという事実にもかかわらず、私たちは次のバリエーションのみで解決しました。







これらのアプリケーションは、コミュニティをAPIやサンプルに慣れさせるために作成されたものであり、さらに楽しくするためのものです。 ソフトウェアは、それを呼び出すことができる場合、実際のビジネスに役立つユニークなアプリケーションを搭載していません。



今日、このトピックに戻って、ユーザーが同じピックアップグループにいる場合に電話画面に通話を表示し、それを傍受できるようにする、もっと興味深いアプリケーションを共有することにしました。



詳細-> Habrakat





電話機自体がHTTPを介してアスタリスクにアクセスできないため、クライアント/サーバー構造が選択されました。 呼び出し時にアスタリスクからのCURLリクエストを「キャッチ」し、電話でjavascriptを「キャッチ」するPythonのサーバーは、一定の周期で新しいレコードの可用性についてポーリングします。



server.py
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer import urlparse import json import shelve import datetime import sys import os TIME_FORMAT = '%d.%m.%Y %H:%M:%S.%f' DB_NAME = "db.db" class HttpProcessor(BaseHTTPRequestHandler): def do_GET(self): if "/get" in self.path: fields = self.get_fields() if not fields: print "There are no parameters" return callgroup = fields.get("callgroup") pickupgroup = fields.get("pickupgroup") if callgroup is None or pickupgroup is None: print "There are no pickupgroup or no callgroup" self.send_error(404) return None db = shelve.open( DB_NAME) data = [] for key in db.keys(): if "callgroup" in db[key] and "pickupgroup" in db[key] and str(db[key]["callgroup"]) == str(callgroup) and str(db[key]["pickupgroup"]) == str(pickupgroup): entry = db[key] data.append(entry) # Make simple dict for json self.send_json(data) db.close() def do_POST(self): data = self.get_json_data() if "uid" not in data: print "There are no a number" return uid = str(data["uid"]) print data if "/put" in self.path: db = shelve.open( DB_NAME) db[uid] = data db.close() data = {"status": 200, "message": "OK"} self.send_json(data) elif "/del" in self.path: db = shelve.open( DB_NAME) if uid in db: del db[uid] data = {"status": 200, "message": "OK"} self.send_json(data) def send_json(self, data): self.send_response(200) self.send_header('Content-Type', 'application/json') self.end_headers() self.wfile.write(json.dumps(data)) def get_json_data(self): length = int(self.headers.getheader('content-length')) field_data = self.rfile.read(length) try: data = json.loads(field_data) except: print "JSON error:" + field_data self.send_error(404) return None return data def get_fields(self): fields_data = self.path.split("?") if len(fields_data) < 2: return GET = {} args = fields_data[1].split('&') for arg in args: t = arg.split('=') if len(t) > 1: k, v = arg.split('=') GET[k] = v return GET if __name__ == "__main__": if os.path.exists( DB_NAME): os.remove( DB_NAME) host = "192.168.1.254" port = 8000 serv = HTTPServer((host, port), HttpProcessor) print "Server running at {}:{}".format(host, port) serv.serve_forever()
      
      









このファイルに実行権限(chmod + x)を付与し、実行して自動実行に追加することを忘れないでください。



電話へのアプリケーションのインストール





ご存じのように、または聞いたことがあると思いますが、Digium電話はWebインターフェイスを使用するか、独自のDPMAプロビジョニングを使用して設定できます。 (Digium Phone Moduleアスタリスク)。

最も簡単なセットアップ(Web経由)がある場合は、システムツールの電話メニューに移動して[アプリ開発を有効にする]をクリックし、 phone_ip-address / app_devで電話にログインする必要があります(デフォルト:ユーザー:管理者、パスワード:789)大きな緑色の[アプリの追加]ボタンをクリックします。







アプリケーション自体をダウンロードするための実際のファイルは次のとおりです。pbxware.ru



コード自体
 var incomingGroupCall = {} var screen = require('screen'); //util for debugging var util = require('util'); var app = require('app'); //we needs to get all info about app app.init(); screen.clear(); //Get config of app(we needs settings) var config = app.getConfig(); var callgroup = config.settings.callgroup; //Get callgroup var pickupgroup = config.settings.pickupgroup; //Get pickupgroup var server = config.settings.server; //server uri, like http://{host}:{port} var app_name = config.settings.id; //App name from json file var phonePrefix = config.settings.prefix; //App name from json file var language = config.settings.language || "ru"; var uids = []; // This list contains all uids server give us at runtime var phonesCount = 0; // This variable needs to watch uids missing from uids list var timer; var currentListPos = 0; var listWidget = new List(0, 0, window.w, window.h); var lang = digium.readFile("app", language + ".json"); language = JSON.parse(lang); incomingGroupCall.show = function () { util.debug("Call show"); if (this.visible) { window.add(listWidget); } this.update(); if (timer) { clearInterval(timer); } timer = setInterval(this.update, 1100); }; incomingGroupCall.showGui = function(message, params) { util.debug("Show gui"); var lastSelected = listWidget.selected; listWidget.clear(); listWidget.set(0,0, message); var i=1; if(!params){ return; } params.forEach(function(entry) { var msg = entry.from + " --> " + entry.to; if(i<=9){ msg = "[" + i + "] " + msg; } else if(i === 10) { msg = "[0] " + msg; } else if(i === 11) { msg = "[*] " + msg; } else if(i === 12) { msg = "[#] " + msg; } listWidget.set(i, 0, msg); listWidget.set(i, 1, entry.to); //container to get value in key handler i++; }); listWidget.select(lastSelected); } incomingGroupCall.update = function() { var request = new NetRequest(); request.open("GET", server + "/get?callgroup="+callgroup+"&pickupgroup="+pickupgroup); request.onreadystatechange = function() { //(readyState === 4) indicates a completed request if (4 === request.readyState) { if (200 === request.status) { try { var data = JSON.parse(request.responseText); if (!data || data.length === 0) { if (!digium.app.inForeground) { return; } incomingGroupCall.showGui(language["NO_CALLS"]); return; } //Remove ended calls var currentUids = data.map( function(item) { return item.uid; }); var needsToRefresh = false; var newEntryAvailable = false; uids.forEach(function(uid) { if(currentUids.indexOf(uid) === -1) { uids.splice(uids.indexOf(uid), 1); needsToRefresh = true; } }); // Add new phones to list data.forEach(function(entry) { if (uids.indexOf(entry.uid) === -1) { needsToRefresh = true; newEntryAvailable = true; uids.push(entry.uid); } }); util.debug("New entry:" + newEntryAvailable); if (!digium.app.inForeground && newEntryAvailable) { digium.foreground(); } if(needsToRefresh) { incomingGroupCall.showGui(language["INCOMING_CALLS"], data); } } catch (e) { util.debug('request error: ' + JSON.stringify(e)); incomingGroupCall.showGui(language["SERVER_UNAVAILABLE"]); } } else { util.debug('request error1: ' + request.status); incomingGroupCall.showGui(language["SERVER_UNAVAILABLE"]); } } }.bind(this); request.setTimeout(1000); request.send(); }; //initialize variables incomingGroupCall.init = function () { this.widgets = {}; //stay open when the app is backgrounded digium.app.exitAfterBackground = false; this.visible = digium.app.inForeground; incomingGroupCall.listeners(); // setInterval(digium.restart, 180000); }; incomingGroupCall.listeners = function () { //show the full window when the app is foregrounded digium.event.observe({ 'eventName' : 'digium.app.foreground', 'callback' : function () { util.debug("app.foregrounded"); window.clear(); this.visible = digium.app.inForeground; this.setButtons(); this.show(); }.bind(this) }); //show the idle window when the idleScreen is shown digium.event.observe({ 'eventName' : 'digium.app.background', 'callback' : function () { util.debug("app.background"); this.visible = digium.app.inForeground; window.clearSoftkeys(); this.show(); }.bind(this) }); }; incomingGroupCall.setButtons = function () { window.onkeyselect = function() { var phone = listWidget.get(listWidget.selected, 1); util.debug("Selected " + phone); digium.phone.dial({ "number": phonePrefix+phone }) } window.onkey = function(e) { //Digits keyboard handler try { var key = e.key; if(e.key == "0") { key = 10; } else if (e.key == "*") { key = 11; } else if (e.key == "#") { key = 12; } var phone = listWidget.get(key, 1); if (phone) { digium.phone.dial({ "number": phonePrefix+phone }) } } catch(e) { util.debug("Error in trying to dial"); } util.debug(JSON.stringify(e)); } window.setSoftkey(4, language['EXIT'], function() { digium.app.exitAfterBackground = true; digium.background(); }.bind(this)); window.setSoftkey(3, language['HIDE'], function() { digium.background(); }.bind(this)); } incomingGroupCall.init(); incomingGroupCall.show();
      
      







新しいアプリケーションの設定では、次のオプションを指定する必要があります。



コールグループ:1

ピックアップグループ:1

サーバー: 192.168.1.254 :8000(または、pythonスクリプトが実行されているその他のIP)

プレフィックス:* 8(通話を傍受するためのプレフィックス)

言語:ru(en / ruサポート)



電話設定のスクリーンショット






DPMAを使用する場合、この手順を使用してアプリケーションを電話にダウンロードする必要があります



アプリケーションを起動します。 開いたままにするか、背景に折りたたむことができます。







アスタリスクダイヤルプランの変更





そのため、電話でアプリケーションを記録し、サーバーでリレーも開始しました。 アスタリスクダイヤルプランに変更を加えて、必要なcallgroupおよびPickupGroupパラメータを使用してコールが内線に到着したことを報告するようにします。



たとえば、作業用のダイヤルプランを使用できます。



exten => _7XX、1、NoOp($ {CALLERID(num)}から$ {EXTEN}への呼び出し)

同じ=> n、設定(CallGroup = $ {SIPPEER($ {EXTEN}、callgroup)})

同じ=> n、NoOp(Callgroup = $ {CallGroup})

同じ=> n、設定(PickupGroup = $ {SIPPEER($ {EXTEN}、pickupgroup)})

同じ=> n、NoOp(PickupGroup = $ {PickupGroup})

same => n、System(curl -i -H "Accept:application / json" -H "Content-Type:application / json" -X POST -d '{"uid": "$ {UNIQUEID}"、 "callgroup ":" $ {CallGroup} "、" pickupgroup ":" $ {PickupGroup} "、" from ":" $ {CALLERID(num)} "、" to ":" $ {EXTEN} "} ' 192.168.1.254 : 8000 / put)

同じ=> n、ダイヤル(SIP / $ {EXTEN}、60、Tt)

同じ=> n、設定(CallGroup = $ {SIPPEER($ {EXTEN}、callgroup)})

同じ=> n、ハングアップ()



exten => h、1、NoOp(アプリの終わり)

same => n、System(curl -i -H "Accept:application / json" -H "Content-Type:application / json" -X POST -d '{"uid": "$ {UNIQUEID}"、 "callgroup ":" $ {CallGroup} "、" pickupgroup ":" $ {PickupGroup} "、" from :: $ {CALLERID(num)} "、" to ":" $ {TARGETNO} "} ' 192.168.1.254 : 8000 / del)

同じ=> n、ハングアップ()



実行中のアプリケーション









着信コールがあると、アプリケーションが電話スクリーンにポップアップし、このコールグループのコールが表示され、それを傍受することができます。 他のアラームはありません(メロディーやライト表示など)



「上」ボタンと「下」ボタンを使用して番号を移動し、「OK」ボタンをクリックして通話を傍受することができます。強調表示された番号は傍受されるか、番号と*、#を使用します。



アプリケーションを起動し、最小化し、呼び出しを待ちます)。 新しい呼び出しにより、アプリケーションがデプロイされます。 再び折りたたむことができます。






All Articles