{"id":277921,"date":"2016-04-08T12:40:04","date_gmt":"2016-04-08T08:40:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=277921"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=277921","title":{"rendered":"\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f Digium \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043e\u0432"},"content":{"rendered":"<p>       <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/287\/d22\/cf7\/287d22cf7608437bea71fd37a6c54f6b.png\" alt=\"image\"\/><\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e, \u0445\u0430\u0431\u0440\u0430\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e. <\/p>\n<p>  \u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u043c\u044b <a href=\"https:\/\/habrahabr.ru\/post\/230927\/\">\u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438<\/a> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f Digium \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043e\u0432. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u043b\u0430\u043d\u044b \u0431\u044b\u043b\u0438 \u043e\u0431\u0448\u0438\u0440\u043d\u044b\u043c\u0438, \u043c\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u0446\u0438\u044f\u0445:<\/p>\n<ul>\n<li> \u041f\u043e\u0433\u043e\u0434\u0430 \u0441 \u0441\u0430\u0439\u0442\u0430 \u0433\u0438\u0441\u043c\u0435\u0442\u0435\u043e<\/li>\n<li> \u041a\u0443\u0440\u0441 \u0432\u0430\u043b\u044e\u0442 \u0441 \u0441\u0430\u0439\u0442\u0430 \u0446\u0435\u043d\u0442\u0440\u043e\u0431\u0430\u043d\u043a\u0430<\/li>\n<li> RSS \u043b\u0435\u043d\u0442\u0430 \u0441 \u043d\u043e\u0432\u043e\u0441\u0442\u043d\u044b\u0445 \u043f\u043e\u0440\u0442\u0430\u043b\u043e\u0432<\/li>\n<\/ul>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u0441 API \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438, \u0434\u0430\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 just for fun. C\u043e\u0444\u0442, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0435\u0433\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c, \u043d\u0435 \u043d\u0435\u0441\u0435\u0442 \u0441\u0435\u0431\u0435 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0431\u0438\u0437\u043d\u0435\u0441\u0443. <\/p>\n<p>  \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u0439 \u0442\u0435\u043c\u0435, \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u043c, \u043d\u0430 \u043d\u0430\u0448 \u0432\u0437\u0433\u043b\u044f\u0434 \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u0439 \u043f\u0438\u043a\u0430\u043f \u0433\u0440\u0443\u043f\u043f\u0435 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c.<\/p>\n<p>  \u0417\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u2014 &gt; \u0445\u0430\u0431\u0440\u0430\u043a\u0430\u0442 <br \/>  <a name=\"habracut\"><\/a><\/p>\n<p>  \u0412\u0432\u0438\u0434\u0443 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u0441\u0430\u043c \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0430\u0441\u0442\u0435\u0440\u0438\u0441\u043a\u0443 \u043f\u043e HTTP, \u0431\u044b\u043b\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u043b\u0438\u0435\u043d\u0442-\u0441\u0435\u0440\u0432\u0435\u0440. \u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043f\u0438\u0442\u043e\u043d\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u00ab\u043b\u043e\u0432\u0438\u0442\u00bb \u043e\u0442 \u0430\u0441\u0442\u0435\u0440\u0438\u0441\u043a\u0430 CURL \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u0438 \u0437\u0432\u043e\u043d\u043a\u0435, \u0438 javascript \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">server.py<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\">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 =  &quot;db.db&quot;   class HttpProcessor(BaseHTTPRequestHandler):      def do_GET(self):          if &quot;\/get&quot; in self.path:              fields = self.get_fields()              if not fields:                  print &quot;There are no parameters&quot;                  return              callgroup = fields.get(&quot;callgroup&quot;)              pickupgroup = fields.get(&quot;pickupgroup&quot;)              if callgroup is None or pickupgroup is None:                  print &quot;There are no pickupgroup or no callgroup&quot;                  self.send_error(404)                  return None              db = shelve.open( DB_NAME)              data = []              for key in db.keys():                  if &quot;callgroup&quot; in db[key] and &quot;pickupgroup&quot; in db[key] and str(db[key][&quot;callgroup&quot;]) == str(callgroup) and str(db[key][&quot;pickupgroup&quot;]) == 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 &quot;uid&quot; not in data:              print &quot;There are no a number&quot;              return          uid = str(data[&quot;uid&quot;])          print data          if &quot;\/put&quot; in self.path:              db = shelve.open( DB_NAME)              db[uid] = data              db.close()              data = {&quot;status&quot;: 200, &quot;message&quot;: &quot;OK&quot;}              self.send_json(data)          elif &quot;\/del&quot; in self.path:              db = shelve.open( DB_NAME)              if uid in db:                  del db[uid]              data = {&quot;status&quot;: 200, &quot;message&quot;: &quot;OK&quot;}              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 &quot;JSON error:&quot; + field_data              self.send_error(404)              return None          return data        def get_fields(self):          fields_data = self.path.split(&quot;?&quot;)          if len(fields_data) &lt; 2:              return          GET = {}          args = fields_data[1].split('&')          for arg in args:              t = arg.split('=')              if len(t) &gt; 1:                  k, v = arg.split('=')                  GET[k] = v          return GET    if __name__ == &quot;__main__&quot;:      if os.path.exists( DB_NAME):          os.remove( DB_NAME)      host = &quot;192.168.1.254&quot;      port = 8000      serv = HTTPServer((host, port), HttpProcessor)      print &quot;Server running at {}:{}&quot;.format(host, port)      serv.serve_forever()  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0434\u0430\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 (chmod +x), \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u0443\u0441\u043a.<\/p>\n<h3>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d<\/h3>\n<p>  \u041a\u0430\u043a \u0432\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u043d\u0430\u0435\u0442\u0435, \u0438\u043b\u0438 \u0441\u043b\u044b\u0448\u0430\u043b\u0438, Digium \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043b\u0438\u0431\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u043a\u043e\u0435\u0433\u043e \u043f\u0440\u043e\u043f\u0440\u0438\u0435\u0442\u0430\u0440\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0438\u0436\u0435\u043d\u0438\u043d\u0433\u0430 DPMA. (Digium Phone Module Asterisk). <br \/>  \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 (\u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431), \u0442\u043e \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043c\u0435\u043d\u044e \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 System tools \u0438 \u043d\u0430\u0436\u0430\u0442\u044c Enable App Development, \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u043b\u043e\u0433\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <a href=\"http:\/\/phone_ip-address\/app_dev\">phone_ip-address\/app_dev<\/a> (\u043f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443: \u042e\u0437\u0435\u0440: admin, \u041f\u0430\u0440\u043e\u043b\u044c: 789) \u0438 \u0442\u0430\u043c \u043d\u0430\u0436\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0437\u0435\u043b\u0435\u043d\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 Add App.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/0ad\/d32\/6b8\/0add326b89b74ea4b54ce8f117deb973.png\"\/><\/p>\n<p>  \u0412\u043e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0444\u0430\u0439\u043b \u043d\u0430 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: <a href=\"http:\/\/www.pbxware.ru\/upload\/medialibrary\/50e\/app_2.0.zip\">pbxware.ru<\/a><\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0430\u043c \u043a\u043e\u0434<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">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 || &quot;ru&quot;;  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(&quot;app&quot;, language + &quot;.json&quot;); language = JSON.parse(lang);  incomingGroupCall.show = function () { \tutil.debug(&quot;Call show&quot;); \tif (this.visible) { \t\twindow.add(listWidget);\t\t \t} \tthis.update(); \tif (timer) { \t\tclearInterval(timer); \t} \ttimer = setInterval(this.update, 1100); };  incomingGroupCall.showGui = function(message, params) { \tutil.debug(&quot;Show gui&quot;); \tvar lastSelected = listWidget.selected; \tlistWidget.clear(); \tlistWidget.set(0,0, message); \tvar i=1; \tif(!params){ \t\treturn; \t} \tparams.forEach(function(entry) { \t\tvar msg = entry.from + &quot; --&gt; &quot; + entry.to; \t\tif(i&lt;=9){ \t\t\tmsg = &quot;[&quot; + i + &quot;]  &quot; + msg; \t\t} else if(i === 10) { \t\t\tmsg = &quot;[0]  &quot; + msg; \t\t} else if(i === 11) { \t\t\tmsg = &quot;[*]  &quot; + msg; \t\t} else if(i === 12) { \t\t\tmsg = &quot;[#]  &quot; + msg; \t\t} \t\tlistWidget.set(i, 0, msg); \t\tlistWidget.set(i, 1, entry.to); \/\/container to get value in key handler \t\ti++; \t}); \tlistWidget.select(lastSelected); }   incomingGroupCall.update = function() { \tvar request = new NetRequest(); \trequest.open(&quot;GET&quot;, server + &quot;\/get?callgroup=&quot;+callgroup+&quot;&pickupgroup=&quot;+pickupgroup); \trequest.onreadystatechange = function() { \t\t\/\/(readyState === 4) indicates a completed request\t\t \t\tif (4 === request.readyState) { \t\t\tif (200 === request.status) {\t\t\t\t \t\t\t\ttry {\t\t\t\t \t\t\t\t\tvar data = JSON.parse(request.responseText); \t\t\t\t\tif (!data || data.length === 0) { \t\t\t\t\t\tif (!digium.app.inForeground) { \t\t\t\t\t\t\treturn; \t\t\t\t\t\t} \t\t\t\t\t\tincomingGroupCall.showGui(language[&quot;NO_CALLS&quot;]); \t\t\t\t\t\treturn; \t\t\t\t\t} \t\t\t\t\t\/\/Remove ended calls \t\t\t\t\tvar currentUids = data.map( function(item) {  \t\t\t\t\t\treturn item.uid;  \t\t\t\t\t}); \t\t\t\t\tvar needsToRefresh = false; \t\t\t\t\tvar newEntryAvailable = false; \t\t\t\t\tuids.forEach(function(uid) { \t\t\t\t\t\tif(currentUids.indexOf(uid) === -1) { \t\t\t\t\t\t\tuids.splice(uids.indexOf(uid), 1); \t\t\t\t\t\t\tneedsToRefresh = true; \t\t\t\t\t\t} \t\t\t\t\t});\t\t\t\t\t \t\t\t\t\t\/\/ Add new phones to list\t\t\t\t \t\t\t\t\tdata.forEach(function(entry) { \t\t\t\t\t\tif (uids.indexOf(entry.uid) === -1) { \t\t\t\t\t\t\tneedsToRefresh = true; \t\t\t\t\t\t\tnewEntryAvailable = true; \t\t\t\t\t\t\tuids.push(entry.uid); \t\t\t\t\t\t} \t\t\t\t\t}); \t\t\t\t\tutil.debug(&quot;New entry:&quot; + newEntryAvailable); \t\t\t\t\tif (!digium.app.inForeground && newEntryAvailable) { \t\t\t\t\t\tdigium.foreground(); \t\t\t\t\t} \t\t\t\t\tif(needsToRefresh) { \t\t\t\t\t\tincomingGroupCall.showGui(language[&quot;INCOMING_CALLS&quot;], data); \t\t\t\t\t} \t\t\t\t\t \t\t\t\t} catch (e) { \t\t\t\t\tutil.debug('request error: ' + JSON.stringify(e)); \t\t\t\t\tincomingGroupCall.showGui(language[&quot;SERVER_UNAVAILABLE&quot;]); \t\t\t\t} \t\t\t} else { \t\t\t\tutil.debug('request error1: ' + request.status);\t\t\t\t \t\t\t\tincomingGroupCall.showGui(language[&quot;SERVER_UNAVAILABLE&quot;]); \t\t\t} \t\t}\t\t\t \t}.bind(this); \trequest.setTimeout(1000); \trequest.send(); };  \/\/initialize variables incomingGroupCall.init = function () { \tthis.widgets = {};  \t\/\/stay open when the app is backgrounded \tdigium.app.exitAfterBackground = false;  \tthis.visible = digium.app.inForeground; \tincomingGroupCall.listeners();  \t\/\/ setInterval(digium.restart, 180000); };   incomingGroupCall.listeners = function () { \t\/\/show the full window when the app is foregrounded \tdigium.event.observe({ \t\t'eventName'\t\t: 'digium.app.foreground', \t\t'callback'\t\t: function () { \t\t\tutil.debug(&quot;app.foregrounded&quot;); \t\t\twindow.clear(); \t\t\tthis.visible = digium.app.inForeground; \t\t\tthis.setButtons(); \t\t\tthis.show(); \t\t}.bind(this) \t});  \t\/\/show the idle window when the idleScreen is shown \tdigium.event.observe({ \t\t'eventName'\t\t: 'digium.app.background', \t\t'callback'\t\t: function () { \t\t\tutil.debug(&quot;app.background&quot;); \t\t\tthis.visible = digium.app.inForeground; \t\t\twindow.clearSoftkeys(); \t\t\tthis.show(); \t\t}.bind(this) \t}); };  incomingGroupCall.setButtons = function () { \twindow.onkeyselect = function() { \t\tvar phone = listWidget.get(listWidget.selected, 1); \t\tutil.debug(&quot;Selected &quot; + phone); \t\tdigium.phone.dial({ \t\t\t&quot;number&quot;: phonePrefix+phone \t\t}) \t} \twindow.onkey = function(e) { \t\t\/\/Digits keyboard handler \t\ttry { \t\t\tvar key = e.key; \t\t\tif(e.key == &quot;0&quot;) { \t\t\t\tkey = 10; \t\t\t} else if (e.key == &quot;*&quot;) { \t\t\t\tkey = 11; \t\t\t} else if (e.key == &quot;#&quot;) { \t\t\t\tkey = 12; \t\t\t} \t\t\tvar phone = listWidget.get(key, 1); \t\t\tif (phone) { \t\t\t\tdigium.phone.dial({ \t\t\t\t\t&quot;number&quot;: phonePrefix+phone \t\t\t\t}) \t\t\t} \t\t} catch(e) { \t\t\tutil.debug(&quot;Error in trying to dial&quot;); \t\t} \t\tutil.debug(JSON.stringify(e)); \t} \twindow.setSoftkey(4, language['EXIT'], function() { \t\tdigium.app.exitAfterBackground = true; \t\tdigium.background(); \t}.bind(this)); \twindow.setSoftkey(3, language['HIDE'], function() { \t\tdigium.background(); \t}.bind(this)); }  incomingGroupCall.init(); incomingGroupCall.show(); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0446\u0438\u0438:<\/p>\n<p>  callgroup: 1<br \/>  pickupgroup: 1<br \/>  server: <a href=\"http:\/\/192.168.1.254\">192.168.1.254<\/a>:8000 (\u043d\u0443 \u0438\u043b\u0438 \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 IP, \u0433\u0434\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043f\u0438\u0442\u043e\u043d\u043e\u0432\u0441\u043a\u0438\u0439 \u0441\u043a\u0440\u0438\u043f\u0442) <br \/>  prefix: *8 (\u043f\u0440\u0435\u0444\u0438\u043a \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 \u0437\u0432\u043e\u043d\u043a\u0430)<br \/>  language: ru (\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f en \/ ru) <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430<\/b><\/p>\n<div class=\"spoiler_text\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/27a\/7a8\/e8c\/27a7a8e8cfa44edc92638ab29c88fc72.png\"\/>  <\/div>\n<\/div>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 DPMA, \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u043e\u0439 <a href=\"https:\/\/wiki.asterisk.org\/wiki\/display\/DIGIUM\/Custom+Phone+Applications+with+Asterisk\">\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438<\/a><\/p>\n<p>  \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041c\u043e\u0436\u0435\u0442\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c, \u043b\u0438\u0431\u043e \u0441\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432 \u0444\u043e\u043d.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/423\/cd4\/9a3\/423cd49a3afb4b829926f2abec0021d7.png\"\/> <\/p>\n<h3> \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0434\u0438\u0430\u043b\u043f\u043b\u0430\u043d\u0430 Asterisk <\/h3>\n<p>  \u0418\u0442\u0430\u043a, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u044b \u0437\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d, \u0440\u0435\u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0442\u043e\u0440 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0442\u043e\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0432\u043d\u0435\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0434\u0438\u0430\u043b\u043f\u043b\u0430\u043d \u0430\u0441\u0442\u0435\u0440\u0438\u0441\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0441\u043e\u043e\u0431\u0449\u0430\u043b, \u0447\u0442\u043e \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043e\u0447\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u0440\u0438\u0448\u0435\u043b \u0437\u0432\u043e\u043d\u043e\u043a \u0441 \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u043d\u0430\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 callgroup \u0438 PickupGroup. <\/p>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0434\u0438\u0430\u043b\u043f\u043b\u0430\u043d<\/p>\n<p>  exten =&gt; _7XX,1,NoOp(Call from ${CALLERID(num)} to ${EXTEN})<br \/>  same =&gt; n,NoOp(Callgroup = ${CallGroup})<br \/>  same =&gt; n,Set(PickupGroup=${SIPPEER(${EXTEN},pickupgroup)})<br \/>  same =&gt; n,NoOp(PickupGroup = ${PickupGroup})<br \/>  same =&gt; n,System(curl -i -H \u00abAccept: application\/json\u00bb -H \u00abContent-Type: application\/json\u00bb -X POST -d &#8216;{\u00abuid\u00bb:&quot;${UNIQUEID}&quot;, \u00abcallgroup\u00bb:&quot;${CallGroup}&quot;, \u00abpickupgroup\u00bb:&quot;${PickupGroup}&quot;, \u00abfrom\u00bb:&quot;${CALLERID(num)}&quot;, \u00abto\u00bb:&quot;${EXTEN}&quot;}&#8217; <a href=\"http:\/\/192.168.1.254\">192.168.1.254<\/a>:8000\/put)<br \/>  same =&gt; n,Dial(SIP\/${EXTEN},60,TtXxWw)<\/p>\n<h3>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438<\/h3>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/7fc\/475\/ad9\/7fc475ad93d14fd58a6ec7a61228fa62.png\"\/> <\/p>\n<p>  \u041f\u0440\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u043c \u0437\u0432\u043e\u043d\u043a\u0435 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0437\u0432\u043e\u043d\u043a\u0438 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043b\u043b-\u0433\u0440\u0443\u043f\u043f\u0435 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c. \u041d\u0438\u043a\u0430\u043a\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u0442 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043c\u0435\u043b\u043e\u0434\u0438\u0438 \u0438\u043b\u0438 \u0441\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u0438)<\/p>\n<p>  \u041f\u043e \u043d\u043e\u043c\u0435\u0440\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043e\u043a \u00ab\u0432\u0432\u0435\u0440\u0445\u00bb \u0438 \u00ab\u0432\u043d\u0438\u0437\u00bb, \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u0432\u044b\u0437\u043e\u0432 \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041e\u041a\u00bb, \u0442\u043e\u0433\u0434\u0430 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u0441\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440, \u043b\u0438\u0431\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0446\u0438\u0444\u0440 \u0438 *, #. <\/p>\n<p>  \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0448\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0448\u044c \u0435\u0433\u043e \u0438 \u0436\u0434\u0435\u0448\u044c, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0437\u0432\u043e\u043d\u044f\u0442). \u041f\u0440\u0438 \u043d\u043e\u0432\u043e\u043c \u0437\u0432\u043e\u043d\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0435\u0442\u0441\u044f. \u041c\u043e\u0436\u043d\u043e \u043e\u043f\u044f\u0442\u044c \u0441\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0435\u0433\u043e.               <\/p>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/281146\/\"> https:\/\/habrahabr.ru\/post\/281146\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>       <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/287\/d22\/cf7\/287d22cf7608437bea71fd37a6c54f6b.png\" alt=\"image\"\/><\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e, \u0445\u0430\u0431\u0440\u0430\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e. <\/p>\n<p>  \u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u043c\u044b <a href=\"https:\/\/habrahabr.ru\/post\/230927\/\">\u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438<\/a> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f Digium \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043e\u0432. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u043b\u0430\u043d\u044b \u0431\u044b\u043b\u0438 \u043e\u0431\u0448\u0438\u0440\u043d\u044b\u043c\u0438, \u043c\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u0446\u0438\u044f\u0445:<\/p>\n<ul>\n<li> \u041f\u043e\u0433\u043e\u0434\u0430 \u0441 \u0441\u0430\u0439\u0442\u0430 \u0433\u0438\u0441\u043c\u0435\u0442\u0435\u043e<\/li>\n<li> \u041a\u0443\u0440\u0441 \u0432\u0430\u043b\u044e\u0442 \u0441 \u0441\u0430\u0439\u0442\u0430 \u0446\u0435\u043d\u0442\u0440\u043e\u0431\u0430\u043d\u043a\u0430<\/li>\n<li> RSS \u043b\u0435\u043d\u0442\u0430 \u0441 \u043d\u043e\u0432\u043e\u0441\u0442\u043d\u044b\u0445 \u043f\u043e\u0440\u0442\u0430\u043b\u043e\u0432<\/li>\n<\/ul>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u0441 API \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438, \u0434\u0430\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 just for fun. C\u043e\u0444\u0442, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0435\u0433\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c, \u043d\u0435 \u043d\u0435\u0441\u0435\u0442 \u0441\u0435\u0431\u0435 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0431\u0438\u0437\u043d\u0435\u0441\u0443. <\/p>\n<p>  \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u0439 \u0442\u0435\u043c\u0435, \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u043c, \u043d\u0430 \u043d\u0430\u0448 \u0432\u0437\u0433\u043b\u044f\u0434 \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u0439 \u043f\u0438\u043a\u0430\u043f \u0433\u0440\u0443\u043f\u043f\u0435 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c.<\/p>\n<p>  \u0417\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u2014 &gt; \u0445\u0430\u0431\u0440\u0430\u043a\u0430\u0442   <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-277921","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/277921","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=277921"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/277921\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=277921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=277921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=277921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}