التفاعل مع خادم Asterisk من تطبيق java من خلال واجهة Asterisk Managment (AMI)
إذا كنت تبدأ البحث في هذا المجال ، فقد يبدو التفاعل مع هذا الخادم مربكًا إلى حد ما ، كما بدا لي من قبل.
لكي لا ابحث عن الأجزاء الضرورية من المعلومات في المنتديات بأسلوب الإجابة على الأسئلة ، أرفق برنامج تعليمي صغير حول التفاعل مع خادم Asterisk من java.
هام: أفترض أنه بمجرد وصولك إلى مرحلة كتابة التعليمات البرمجية ، يكون لديك بالفعل خادم Asterisk فعال يمكنك الوصول إليه.1) ماذا تختار لجعلها مريحة للعمل؟بالتأكيد - واجهة إدارة النجمة (AMI): تحتوي هذه الواجهة على مجموعة كاملة من الوظائف التي تتيح لك إجراء مكالمة ، والاستماع إلى الأحداث في الوقت الفعلي من الخادم ، وتلقي حالة الاتصال ومقاطعتها إذا لزم الأمر.
2) ما مكتبة للاتصال؟هذا واحد:
<dependency> <groupId>org.asteriskjava</groupId> <artifactId>asterisk-java</artifactId> <version>2.0.4</version> </dependency>
3) ما التكوينات تحتاج إلى عرضها على الخادم؟extensions.conf - التكوين الذي يصف diaplan. سوف تكون باستمرار الاتصال به. إذا كان بلغة أكثر قابلية للفهم ، فهو يحتوي على نصوص لما سيفعله الخادم عندما يتلقى مكالمة إلى رقم محدد. أولاً ، يتم البحث في سياق معين في diaplan - إنه مكتوب بين قوسين معقوفين ، وبعد ذلك يتم البحث عن رقم تحت علامة هذا السياق الذي تتصل به.
manager.conf - التكوين مع المستخدم وكلمة المرور لخادم النجمة الخاص بك
يجب أن يكون محتوى هذا التكوين تقريبًا كما يلي:
[user_name] secret = password read = all write = all deny=0.0.0.0/0.0.0.0 permit=0.0.0.0/255.255.255.0
- اسم المستخدم - اسم المستخدم
- سر - كلمة المرور لذلك
- رفض - عناوين IP التي تم رفض الوصول تحت هذا المستخدم
- تصريح - الوصول إلى ما هو مسموح به. تأكد من تحديد عنوان IP الذي تتصل به في التصريح ، نظرًا لأن النجم يمكنه صد طلبك.
sip.conf - جميع جذوعها مسجلة هنا. الجذع هو الهاتف الذي سنتصل منه بالعميل.
4) من أين تبدأ كتابة التعليمات البرمجية؟هناك خياران: إما أن تحتاج إلى القيام ببعض الإجراءات على خادم Asterisk ، أو الاستماع إلى الأحداث على الخادم. ويشمل تسلسل لدينا على حد سواء.
وصفنا خطة العمل:
- افتح الاتصال بالخادم
- وصفنا سيناريو العمل ؛
- نستمع إلى الأحداث.
- أغلق الاتصال.
وفقًا لذلك ، تتم تهيئة الاتصال أثناء إنشاء كائن DefaultAsteriskServer:
import org.asteriskjava.live.AsteriskServer; import org.asteriskjava.live.DefaultAsteriskServer;
AsteriskServer asteriskServer = new DefaultAsteriskServer(HOSTNAME, USERNAME, PASSWORD); asteriskServer.initialize();
بعد فتح الاتصال ، نحتاج إلى الاتصال بالمستخدم. سوف نسمي هذا سيناريو العمل. سيكون وصف السيناريو في فصل منفصل:
public class ScenarioCall extends OriginateAction { private final Logger log = LoggerFactory.getLogger(ScenarioCall.class); private String TRUNK; private final String PHONE_FOR_RINGING; private final String EXTEN_FOR_APP; private final String CONTEXT_FOR_APP; public ScenarioCall(String trunk, String phoneForRinging, String extension, String context) { this.TRUNK = trunk; this.PHONE_FOR_RINGING = phoneForRinging; this.EXTEN_FOR_APP = extension; this.CONTEXT_FOR_APP = context; this.init(); } private void init() {
ماذا نحتاج أن نفهم في هذا السيناريو؟ أولاً ، يتم إنشاء اتصال جذع. الجذع هو الرقم الذي سوف تتصل منه بالمشترك. بعد ذلك ، يتم إنشاء اتصال بين الجذع والمشترك ، وبعد ذلك الاتصال بين المشترك والذي تحتاجه هو الآخر.
إنه بهذا الترتيب.
this.setContext(CONTEXT_FOR_APP)
القيمة المنقولة: هي السياق الذي سنبحث فيه عن رقم الهاتف الذي تريد ربط المشترك به (من extensions.conf).
this.setExten(EXTEN_FOR_APP)
القيمة المنقولة: البرنامج النصي الذي سيتم تنفيذه بعد الاتصال بالمشترك (من extensions.conf).
this.setCallerId(callId)
القيمة المنقولة: رقم المشترك لدينا
this.setChannel(channelAsterisk)
القيمة المنقولة: قناة اتصال قائمة ، عادة ما تبدو كما يلي: trunk_name / phone_user.
أن ننظر فيها ل trunk_name؟ هناك تكوين sip.conf على خادم العلامة النجمية - يتم تسجيل جميع الأمتعة هناك.
إنشاء مكالمة:
if (asteriskServer .getManagerConnection().getState().equals(ManagerConnectionState.CONNECTED) || asteriskServer .getManagerConnection().getState().equals(ManagerConnectionState.CONNECTING) || asteriskServer .getManagerConnection().getState().equals(ManagerConnectionState.INITIAL)) { try { ScenarioCall scenarioCall = new ScenarioCall(trank, phone, extension, context); CallBack callBackForScenarioCall = new CallBack(); asteriskServer.originateAsync(scenarioCall, callBackForScenarioCall); } catch (ManagerCommunicationException e) {
أنشأنا مكالمة ، ولكن كيف لتتبع ذلك بشكل حيوي؟
يتم إجراء شيئين لهذا: يتم تمرير مثيل لفئة CallBack في طريقة originateAsync
ويتم تعليق المستمع على الخادم ، والذي سيدمج كل ما يحدث لنا.
هناك حاجة إلى مستمع لأن فئة CallBack لن تُعلمك بنهاية المكالمة عندما يكون المستخدم قد تحدث بالفعل ، ولن يخطرك بأنه لا يزال بإمكان المستخدم النقل في مكان آخر.
public class CallBack implements OriginateCallback { private ChannelState resultCall = ChannelState.PRERING; @Override public void onDialing(AsteriskChannel asteriskChannel) {
كيفية تعليق المستمع على النجمة؟للقيام بذلك ، قم بإنشاء فئة تطبيق AsteriskServerListener ، PropertyChangeListener.
بالنسبة للاتصال الذي تم إنشاؤه ، من خلال مثيل لفئة AsteriskConnection ، نقوم بتنفيذ:
this.asteriskConnection.addAsteriskServerListener(this.callBackEventListener);
this.callBackEventListener - مثيل لفئة المستمع الخاصة بنا ، المولودة من:
** * Asterisk * PropertyChangeListener , . * AsteriskServerListener , AsteriskConnection. */ public class CallBackEventListener implements AsteriskServerListener, PropertyChangeListener { public void onNewAsteriskChannel(AsteriskChannel channel) { channel.addPropertyChangeListener(this); } public void onNewMeetMeUser(MeetMeUser user) { user.addPropertyChangeListener(this); } public void onNewQueueEntry(AsteriskQueueEntry user) { user.addPropertyChangeListener(this); } public void onNewAgent(AsteriskAgent asteriskAgent) { asteriskAgent.addPropertyChangeListener(this); } public void propertyChange(PropertyChangeEvent propertyChangeEvent) { findEventEndCall(propertyChangeEvent); } private void findEventEndCall(PropertyChangeEvent event) { if (event.getSource() instanceof AsteriskChannel) { AsteriskChannel callBackChannel = (AsteriskChannel) event.getSource(); String callId = getStringWithOnlyDigits(callBackChannel.getCallerId().toString()); callId = ValidValues.getValidCallId(callId); if (callBackChannel.getState().toString().equals("HUNGUP") && event.getOldValue().toString().contains("RINGING")) {
أنصحك في البداية بالتعهد ، ماذا يأتي إلى propertyChange وإلقاء نظرة على PropertyChangeEvent ، سيكون بمثابة جحيم كومة من كل شيء يحدث على الخادم. لا تصفية المعلومات على الإطلاق. لذلك ، الاستنتاج: شنق المستمع بأقل قدر ممكن. ليس لكل مكالمة ، لأنه يمكن القيام به حتى في فئة OriginateCallback ، بقدر ما وجدت. هذا لا طائل منه. انظر إلى ما تأتي به كائنات PropertyChangeEvent ، انظر إلى نوع الحقول هناك والحقول التي تحتاجها. التالي - مرحبا بكم في عالم معالجة المعلومات.
قليلا عن التحقق من صحة البيانات.
في OriginateAction.setChannel - يتم تمرير trunk_name / phone_user
phone_user - إذا كانت روسية ، فيجب أن تبدأ برقم ثمانية ، إذا كان الرقم الدولي زائدًا.
في OriginateAction.setCallerId - يتم إرسال رقم هاتف العميل ،
ثم في CallBackEventListener سوف يأتي في callBackChannel.getCallerId ().
سوف أعتبر مثل هذا:
String callId = getStringWithOnlyDigits(callBackChannel.getCallerId().toString());
في النهاية ، لا تنسى:
asteriskServer.shutdown();
إذا كنت بحاجة إلى مقاطعة أي مكالمة ، فإما في فئة CallBackEventListener
لقناة الاتصال الحالية التي نقوم بها:
callBackChannel.hangup();
تحولت مثل هذا البرنامج التعليمي البسيط. للوهلة الأولى ، بالطبع ، الأمر بسيط للغاية ، لكن صدقوني ، يستغرق الكثير من الوقت والأعصاب للعثور على المعلومات ، وتأجيل جميع الأساليب وترك العمل.
حظا سعيدا مع خوادم النجمة الخاصة بك!
مزيد من القراءة:
1)
النجمة جافا تعليمي2)
واجهة إدارة العلامة النجمية (AMI)