📜 ⬆️ ⬇️

Office PBX - The Devil in the details

About a year ago I had to face a new task for myself - automation of PBX control. At first glance, there is nothing difficult in it: you need to connect to the controlling port of the PBX via a TCP or Serial interface, send a command and analyze the response. As it turned out in the process, this simplicity was deceptive.

In my article I want to talk about the difficulties that I had to face in the process. It is unlikely that this article will be of interest to a wide circle of readers, but perhaps specialists in the field of telephony will find in it something useful for themselves. As an illustrative material, I will use examples of Alcatel S12 and M200 PBX commands supported by the project at present.

1. Glossary


For starters, you should decide on the terminology.

1.1 Tasks


A task is a set of actions performed atomically. From the point of view of the equipment management subsystem, the task consists of a set of services . Each service controls subscriber's access to a particular service (for example, you can select access services to long-distance and international communications).
')
When performing a task, individual services can be turned on or off. In addition, for a number of services, the values ​​of configuration parameters (for example, such as the alarm time or PIN value) can be set. Boolean values ​​that determine the status of connecting or disconnecting a service are also considered as parameters.

From the point of view of equipment, the process of connecting or disconnecting a service is reduced to the execution of one or more commands . The process of executing commands on the equipment will be called activation .

1.2 Specifications


Specifications control the work of a specialized ORM , designed to integrate an application with the Order Management subsystem, which controls the execution of tasks. I will not delve into this topic, since it is not related to issues of specificity of interaction with PBX. To understand the subsequent presentation, it is enough to know that this layer provides read and write access to the named variables containing the values ​​loaded from the database.

In addition to accessing scalar values, access to tuple collections is provided. For example, by opening a collection represented by the name 'tk' (Tech. Card), you can access records containing data from technical cards, such as 'tk.phone' - the subscriber’s phone or 'tk.ats_type' - the type of PBX. In turn, these records may contain links to other collections. Nesting of collections is not limited.

Of all the above, it is perhaps not very clear why the term specification is used? The fact is that during the development of this layer, SID concepts such as the Specification and Policy were actively used, which, from my point of view, greatly simplified the development. In general, I strongly recommend that you familiarize yourself with the materials of the TM Forum , and to all who have such an opportunity.

1.3 Scripts


I already described this subsystem earlier . Initially, the script performed two tasks: it described the order of command execution as part of the work order and hid in itself platform-specific features. The script accessed the variables provided by the specifications and formed the commands, depending on the type of PBX. Here's what it looked like:

Fragment of the script of the first version
... [002082] platform:M-200; if (tk.attach.service = 'SET_HOLD') { [020820] < text:settune %s enb_flash=on; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; [020821] is_rollback:1; { [001020] < device_id:tk.ats_id; [020822] < text:settune %s enb_flash=off; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; } } [003082] platform:S-12; if (tk.attach.service = 'SET_HOLD') { [030820] < text:MODIFY-SUBSCR:DN=K'%s,RECALL=ADD&ECTRF.; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; [030821] is_rollback:1; { [001020] < device_id:tk.ats_id; [030822] < text:MODIFY-SUBSCR:DN=K'%s,RECALL=REMOVE&ECTRF.; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; } } ... 

From the above fragment, you can see that by analyzing the variable tk.attach.service, we determine which command should be executed. Then, depending on the platform, by substituting the phone number from the variable tk.phone into the corresponding command pattern, a command is generated for execution on the hardware.

Since there were quite a few different commands, the script was large (over 1000 lines) and obscure. As a result, when developing the second version, it was decided to abandon the formation of separate commands in the script (transferring it to a lower level), transferring service codes instead of ready commands. This decision is very beneficial effect on the size of the script. Here’s what the whole version of the second script looks like:

Script of the second version
 [002000] { [200001] var_list:retry_cnt = retry_cnt + 1, state = 1; [200002] if (subtype = -1) { [200003] foreach (devices) { [200004] < device_id:devices.ats_id; device_ip:devices.ats_ip; device_password:devices.ats_password; device_port:devices.ats_tcp_port; device_protocol:devices.ats_type; [200005] < device_id:devices.ats_id; [200006] < text:ROLLBACK; [200007] var_list:retry_cnt = 0; } } [200008] if (subtype = 1) { [200009] foreach (tk) { [200010] if (tk.phone = '') { [200011] var_list:tk.phone = tk.phone_old; } [200012] < device_id:tk.ats_id; device_protocol:tk.ats_type; device_ip:tk.ats_ip; device_port:tk.ats_tcp_port; device_password:tk.ats_password; [200013] var_list:action = 0, is_dou_activated = 0; [200014] target:tk.ats_type; foreach (tk.detach) { [200015] < device_id:tk.ats_id; [200016] var_list:activate_command = 1; [200017] platform:S-12; if (tk.detach.service = 'C_INTRAAREAL' | tk.detach.service = 'C_INTERCITY' | tk.detach.service = 'C_INTERNATIONAL') { [200018] if (is_dou_activated = 1) { [200019] var_list:activate_command = 0; } [200020] var_list:is_dou_activated = 1; } [200025] if (activate_command = 1) { [200026] < text:%s; var_list:tk.detach.service; [200027] var_list:retry_cnt = 0; } } [200028] var_list:action = 1, is_dou_activated = 0, is_cat_activated = 0; [200029] target:tk.ats_type; foreach (tk.attach) { [200030] < device_id:tk.ats_id; [200031] var_list:activate_command = 1; [200032] platform:S-12; if (tk.attach.service = 'C_INTRAAREAL' | tk.attach.service = 'C_INTERCITY' | tk.attach.service = 'C_INTERNATIONAL') { [200033] if (is_dou_activated = 1) { [200034] var_list:activate_command = 0; } [200035] var_list:is_dou_activated = 1; } [200021] if (tk.attach.service = 'CATEG_AON_0' | tk.attach.service = 'CATEG_AON_1' | tk.attach.service = 'CATEG_AON_2' | tk.attach.service = 'CATEG_AON_3' | tk.attach.service = 'CATEG_AON_4' | tk.attach.service = 'CATEG_AON_6' | tk.attach.service = 'CATEG_AON_7' | & tk.attach.service = 'CATEG_AON_8' | tk.attach.service = 'CATEG_AON_9') { [200022] if (is_cat_activated = 1) { [200023] var_list:activate_command = 0; } [200024] var_list:is_cat_activated = 1; } [200036] if (activate_command = 1) { [200037] < text:%s; var_list:tk.attach.service; [200038] var_list:retry_cnt = 0; } } } } } 

I will explain the logic of its execution in the subsequent sections, for the time being I will only say that now the script controls only the sequence of connecting and disconnecting services within the scope of the task. We can still execute different code, depending on the type of equipment used, but now it is used only if the dependence on the platform matters in the performance of the task as a whole, and not individual commands.

1.4 Adapter


An adapter is a plug-in ( plugin ) that implements the logic of working with a specific type of equipment. In the first version, the adapter received ready-made commands from the script and its role was to transfer these commands to the PBX using a TCP or Serial connection and process the received response. In the current (second) version, the logic of forming a set of commands, when connecting or disconnecting a service, is transferred to the adapter. The explanation of the reasons for which this was done is the subject of this article.

1.5 Synchronization


Synchronization we will call the process of obtaining current subscriber settings from equipment. The problem of discrepancies in the data on the state of settings of subscribers on the PBX in relation to the database is fundamental for this class of tasks. This problem is relevant not only for telephony. In the previous activation project related to the management of cisco equipment, he was no less acute. We can say that this article talks about how, using synchronization, to make the activation process more "smart".

2. Task Level


Obviously, to control various types of PBXs, completely different command systems are used, for example, the command is used to disable outgoing communications in PBX M-200:

 settune XXXXXXX cmn_outcome=off 

and in the Alcatel S12:

 MODIFY-SUBSCR:DN=K'XXXXXXX,OCB=REMOVE&TOTALBAR. 

But such differences in command syntax are far from the only difficulty. We will understand this issue in more detail.

2.1 Mapping services to teams


The first thing we face is that the possibilities for activating various services provided by different PBXs are also different. Of course, there is some common set of services supported by most types of PBXs, such as outgoing call control, setting an alarm, dialing control, etc.

At the same time, a significant part of teams that are interesting from a business point of view may not be implemented on a particular type of PBX (and the larger the set of PBX types supported, the more such teams). This means that the service that is part of the task can not always be performed at the PBX where activation is performed. An attempt to activate such a service may be considered as an error, or it may simply be ignored. It is important that a mechanism should be implemented for displaying services used as part of service tasks implemented on supported PBX types.

One job service can be displayed on several different services supported by PBXs. For example, M-200 supports the following commands to enable a PIN:

 settune XXXXXXX dvo_pincode=on settune XXXXXXX dvo_pincodetwo=on 

The first includes the use of a PIN for long-distance and international calls, and the second for all outgoing calls. In our case, one of the requirements of the Customer was that both of these services, at the task level, be mapped into one common 'PINCODE' service. What kind of service will be performed is determined by the value of additional variables. For Alcatel S12, only one PIN enable command is implemented:

 MODIFY-SUBSCR:DN=K'XXXXXXX,PASSWORD=ADD&"YYYY",SUBCTRL=ADD&OCBVAR. 

Besides the fact that there is no division of this service into two types, it can be noted that this command not only includes the use of a PIN code, but also sets its value. Of course, M-200 allows you to run, for example, the following command:

 settune XXXXXXX dvo_pincode=on pincode=YYYY 

But, in the process of introducing the first version of the activation module into commercial operation, it turned out that these commands are more convenient to activate separately. In addition, it turned out that, in order for the PIN code to work, it is necessary to activate one more command. Thus, for the M-200, the PIN installation command should result in the activation of three commands in the specified order:

 settune XXXXXXX enb_pincode=on settune XXXXXXX dvo_pincode=on settune XXXXXXX pincode=YYYY 

Moreover, the enb_pincode command, which controls the use of a PIN code, can be executed separately (thus adding another display option for the 'PINCODE' service). In this case, the PIN code can be set by the subscriber himself. This leads to a rather non-trivial problem, which I will discuss below in the section "Problems associated with synchronization."

2.2 Restriction of outgoing communication


PBXs of different types can vary not only the set of supported services, but also how these services are implemented. So for the M-200, access to intrazonal, long-distance, and international communications can be controlled separately:

 settune XXXXXXX cmn_82xxx=on settune XXXXXXX cmn_8xxx=on settune XXXXXXX cmn_10xxx=on 

For the Alcatel S12, similar commands look like this:

 MODIFY-SUBSCR:DN=K'XXXXXXX,OCB=MODIFY&PERM&5. MODIFY-SUBSCR:DN=K'XXXXXXX,OCB=MODIFY&PERM&4. MODIFY-SUBSCR:DN=K'XXXXXXX,OCB=REMOVE. 

You may notice that these commands control the state of just one setting (when you turn on long-distance communication, the restrictions are simply removed). This leads to the following problem:


This means that if we need to enable intra-zone and long-distance communications on the Alcatel S12, we should activate only the command to switch on long-distance communications. If the command to enable intra-zone communication is subsequently activated, long-distance communication for the subscriber will be disabled! Simultaneous activation of intrazonal and international communication, with disconnected long-distance communication, is impossible (unlike M-200).

This is a good example of functionality implemented at the level of an activation script. Let's see how this can be implemented:

 [200028] var_list:action = 1, is_dou_activated = 0, is_cat_activated = 0; [200029] target:tk.ats_type; foreach (tk.attach) { [200031] var_list:activate_command = 1; [200032] platform:S-12; if (tk.attach.service = 'C_INTRAAREAL' | tk.attach.service = 'C_INTERCITY' | tk.attach.service = 'C_INTERNATIONAL') { [200033] if (is_dou_activated = 1) { [200034] var_list:activate_command = 0; } [200035] var_list:is_dou_activated = 1; } [200036] if (activate_command = 1) { [200037] < text:%s; var_list:tk.attach.service; [200038] var_list:retry_cnt = 0; } } 

Variables save us. By activating the first command that controls outgoing communication from the tk.attach collection, we set the is_dou_activated flag, which prohibits the activation of subsequent commands. Moreover, this code only works for Alcatel S12.

The only thing we need for this approach to work is for the teams to come in the correct order: first, the inclusion of international calls (if any), then the long-distance and intra-zone calls. Fortunately, specs allow sorting of samples.
Collections by any criterion. You only need to add priority fields to the service table when connecting and disconnecting.

3. Problems associated with synchronization


As I said above, the possibility of obtaining actual settings from the equipment is one of the main requirements for performing at least some kind of correct activation. Let's see why this is so?

3.1 "Intellectual" activation


The very first additional requirement that we received from the Customer, when introducing the first version of the product, was that it was not necessary to reactivate the settings previously activated on the equipment. This is really important for two reasons:

  1. Activation of commands on the equipment is not a quick process. The average execution time for a single command on the Alcatel S12 is ~ 10 seconds (the M-200 is much faster (~ 1 second) because it returns a much smaller amount of data). Add to this the fact that the connection with the PBX is not very stable and we can lose it within those 10 seconds. If at each re-execution of the task (and we must fulfill all the commands that make up the task, to ensure the atomicity of its execution) we will re-activate all the commands from the very beginning, then, in the worst case, we will activate these commands again and again and never get to the end of the mission
  2. In some cases (on Alcatel S12), re-activating a command may result in an error. In this case, we can not peek at the state of settings in the database, because, perhaps, the activation for this subscriber is carried out for the first time. In this case, the only correct solution is to get the status of the settings directly from the equipment, before executing the activation command.

All this means that before activating any command, we must receive the current values ​​of settings affecting the execution of this command from the PBX. In that case, if the settings are already in the required state, we can not execute the activated command and move on (if the activated command cannot be executed due to conflicting settings, we can also not execute the command, but immediately trigger an exception). This approach works great for the M-200 because:

  1. All subscriber settings are returned in response to the execution of a single gettune command.
  2. Activation on the M-200 is relatively quick and the connection is stable. We can afford to perform one additional command at the beginning of each activation.

For the Alcatel S12, everything is not so bright. To read the settings, you will have to execute various commands and all of them will be executed slowly. Thus, it is impossible to do without storing the state of settings in the database. When activating, we will be able to get the settings values ​​from the database and, only if they are not there, form the necessary commands to get the missing values ​​from the equipment.

Of course, this is not the ideal solution, because with manual execution of commands, bypassing the activation subsystem, the data in the database will be out of sync, but this is the lesser of the evils that we can afford. In addition, upon completion of the command activation, the actual values ​​of the settings will become known to us (since the command has successfully changed them) and we will be able to update the unsynchronized data in the database.

There is also a problem with the M-200. In some cases, the tune- server used to interact with the PBX, which I will discuss below, starts to work incorrectly. He answers Ok to all settune commands, although the data on the PBX does not change! Calling gettune, in this case, results in an error.

This means that for the M-200, we must call gettune not only before, but also after activation and, in the event of an error, must initiate a rerun of the task. As soon as the tune-server starts working correctly, we will be able to activate those commands, the activation of which actually failed during the previous execution of the task. What has been successfully activated will not be re-activated.

3.2 Dependent Services


As I mentioned above, on the PBX M-200, the inclusion of the 'PINCODE' service (depending on the values ​​of the specification variables) can lead to the activation of one of the three command sequences:

 settune XXXXXXX enb_pincode=on 

 settune XXXXXXX enb_pincode=on settune XXXXXXX dvo_pincode=on settune XXXXXXX pincode=YYYY 

 settune XXXXXXX enb_pincode=on settune XXXXXXX dvo_pincodetwo=on settune XXXXXXX pincode=YYYY 

Setting enb_pincode is enabled in all three cases. It is easy to imagine a possible error arising from the naive implementation of the activation of these commands:

  1. The service is activated, which includes the enb_pincode setting, which allows the subscriber to set a PIN code independently
  2. The service activating the PIN-code for outgoing communication (within which enb_pincode is activated again)
  3. The subscriber refuses the service enb_pincode

As a result of this sequence of actions, the enb_pincode setting is disabled and the PIN code set in the second step stops working! What can be done to prevent this from happening?

The decision, in general, is obvious. We must record all activated services in the database and conduct additional checks when the trip commands are activated. If the setting to be disabled is still used by some other non-disabled service, the disable command should be ignored.

Yes, the subscriber will be able to use the enb_pincode service, which he actually refused, but the PIN codes set will work without any complaints from the subscriber. There are not many such dependencies in the M200 command system, but they are all associated with important services (such as setting an alarm clock or turning on redirection). Accounting for these dependencies is important in terms of correct activation.

3.3 Implementing Rollback


Not any task can be completed successfully. Activation of the command may fail, due to incorrect data (the subscriber’s number is not served by this PBX, incorrect time when setting the alarm, etc.), or when activated services conflict (this often happens on Alcatel S12). Such errors will be called unrecoverable.

Since the task must be executed atomically, in the event of an unrecoverable error, we will have to “roll back” all the commands that were successfully activated earlier, within the same task. The first thing that comes to mind is to remember all the commands that you managed to fulfill and, when an error occurred, execute the commands that they reverse. The implementation of this approach can be seen in the old version of the script:

 ... [002391] platform:M-200; if (tk.detach.service = 'PINCODE' & tk.detach.act_mode = 0 & tk.detach.act_level = 2) { [023910] < text:settune %s dvo_pincode=off; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; [001610] < text:settune %s pincode=; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; [022010] < text:settune %s enb_pincode=off; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; [023911] is_rollback:1; if (tk.detach.value != '') { [001020] < device_id:tk.ats_id; [023912] < text:settune %s dvo_pincode=on; var_list:tk.phone; [001041] > is_error:1; regexp:(.+); var_list:error; [001603] < text:settune %s pincode=%s; var_list:tk.phone, tk.detach.value; [001041] > is_error:1; regexp:(.+); var_list:error; } } ... 

Here, immediately after the successful disconnection of the 'PINCODE' service, the return commands are saved, to activate the service, in the rollback command stack. In addition to excessive verbosity, this approach has several other disadvantages.

  1. Proper implementation of this approach is very time consuming. The fact is that in order to execute the reverse commands, the values ​​of the variables are required at the time of activation of the direct command, but some of these variables are in the collections viewed by the foreach operator. This means that when forming the inverse command, you need to save the "snapshots" of the state of these collections (and the subcollections enclosed in them) and use them instead of the original specifications when you roll back. In addition, commands such as resetting a PIN code require a PIN value for a reverse command in order for it to be restored, and we have to add this value to the specification, although the direct command does not use it
  2. Running a rollback command after an activation error occurs may result in an error on the Alcatel S12. For example, in case of an incorrect setting of any of the parameters, the PBX requests the correct value and expects to receive it, and not the rollback command. Receiving a command in this context results in an error, as a result of which the rollback command is not executed. In the section “Validation of parameters” I will examine this question in more detail.
  3. This approach does not work! In fact, we have nowhere to get the correct values ​​of the parameters, not only for the PIN code setting command, but also for the enb_pincode and dvo_pincode commands. If we turned them off during the assignment, this does not mean that they were not turned off before the activation of the assignment. In this case, the inclusion of these settings, in the rollback process, will be an error

Thus, the only place from which we can get the correct values ​​of the settings at the time of activation is the equipment or database, provided that the data in it is synchronized with the state of the PBX.

In order to close this question, it remains to mention one more thing. The fact is that the activation task can activate commands on several PBXs (for example, when a subscriber is transferred from one PBX to another).

Access settings to the PBX are stored in the tk collection and it may turn out that having successfully completed the commands on one PBX, we received an error when executing the command on another. In the open record of the tk collection, at this moment, there are no parameters for access to the PBX, which should be rolled back. The easiest way to deal with this problem is after initiating a rollback, to cause a restart to activate the task. In this case, all collections will be reopened and the “service” 'ROLLBACK' will be executed for all PBXs involved in activation:

 ... [200002] if (subtype = -1) { [200003] foreach (tk) { [200015] < device_id:tk.ats_id; [200006] < text:ROLLBACK; ... } } ... 


3.4 Renewable Activation


In addition to the unrecoverable errors discussed in the previous section, errors are possible, after the occurrence of which the activation can be continued. For example, if a TCP connection with a PBX was broken during the activation process, rollback is not required. In this case, activation is sufficient to repeat, skipping the execution of commands activated earlier. Here is the hierarchy of exceptions raised in the activation process:

image

Exceptions implying the need for renewed activation are inherited from RetryRequiredException. A rollbackRequiredException additionally triggers a rollback activation. Unplanned errors are triggered by a RuntimeAeException, shutting down the activation service with the appropriate diagnostics. Renewal of activation due to loss of connection with PBX (TcpConnectionLostException) can occur in two fundamentally different cases:

  1. Loss of connection with PBX during activation
  2. Impossibility of primary connection to PBX

In the first case, intervention by the administrator is not required. Since the PBX, in principle, is available, having repeated the activation several times (with a delay of several minutes), we will sooner or later complete the task.

In the second case, an error, for example, may be caused by the fact that the parameters of access to the PBX are set incorrectly. In this case, several connection attempts should be made, after which an error message should be generated. This logic is implemented by the script:

 [002000] { [200001] var_list:retry_cnt = retry_cnt + 1, state = 1; ... [200008] if (subtype = 1) { [200009] foreach (tk) { ... [200014] target:tk.ats_type; foreach (tk.detach) { [200015] < device_id:tk.ats_id; ... [200025] if (activate_command = 1) { [200026] < text:%s; var_list:tk.detach.service; [200027] var_list:retry_cnt = 0; } } ... } 

At the very beginning of the script, we increase the attempt counter (if the variable is not defined by the specification, it is automatically created with a zero value), and after successful execution of any command, reset it to 0. Exceeding the counter value by the maximum number of connection attempts is tracked by the specification and forms an exception, appropriate diagnosis.

4. Validation of parameters


The important point is the need to validate the values ​​of parameters that are inserted into the command. As I said above, passing an incorrect value to a parameter can make it impossible to automatically execute subsequent commands (for example, rollback commands):

 10.0.5.130:4001> MODIFY-SUBSCR:DN=K'8553377684,ALMCALL=ACTIVATE&06&00&00. 10.0.5.130:4001> SEQ=1306.130403 9002 10.0.5.130:4001> COM=4294 10.0.5.130:4001> JOB SUBMITTED 10.0.5.130:4001> 10.0.5.130:4001> 10.0.5.130:4001> ARGUMENT SEMANTIC ERROR : ALMCALL ARG 0004 10.0.5.130:4001> ERROR CODE = 0008 10.0.5.130:4001> < 10.0.5.130:4001< MODIFY-SUBSCR:DN=K'8553377684,ALMCALL=ACTIVATE&06&00&00. 10.0.5.130:4001> MODIFY-SUBSCR:DN=K'8553377684,SUBCTRL=REMOVE&CWTG. 10.0.5.130:4001> PARAMETER NOT EXISTENT ; MODIFY-S 10.0.5.130:4001> < 

Of course, you can analyze the patterns of such errors and automatically generate additional commands that put the PBX in the waiting state of the next team, but this will significantly complicate the algorithm of interaction with the PBX. It is much easier to avoid such errors. Make it pretty easy. For example, to validate the number of times the alarm went off, the zero value of which resulted in an error in this example, it suffices to use the following regular expression:

 ^([1-9])$ 

Of course, it is best to perform this check back in Order Management, preventing the creation of tasks with incorrect parameter values. But, regardless of whether such testing is implemented or not, it makes sense to check the values ​​of the parameters immediately before sending the command to the PBX. This will help to avoid unnecessary mistakes and simplify the logic of interaction with PBX.

5. Access to PBX


Features access to the PBX should also be considered in the design. A common point for both Alcatel S12 and M-200 (using tune) is that a control session is not created for each connection to the PBX. In fact, every time we connect to the same “session” (this is a certain simplification, but, for the activation subsystem, it looks like this). From this fact there are two important consequences:

  1. . . , Alcatel S12 . 'PASSWORD' . , , , , . , , , 'INVALID PASSWORD'. , , , ,
  2. . , - . , , , , ( ). , ,

It should also take into account a number of features Alcatel S12. Thus, non-printable characters (0x05, 0x17) may be present in its output, and when entering commands, line feed and carriage return characters are not used. The command string sent to the Alcatel S12 must end with a '.' or ';' (the password transmitted during authorization must also be terminated by a ';'). The high bit in each byte transmitted to the PBX can be used for parity (this is configured on the PBX). These settings do not apply to the text transmitted from the PBX.

Currently, a Telnet-like TCP connection is used to connect to both the Alcatel S12 and the M-200, but this solution is not the only one possible. Below are briefly discussed other options for connecting to these PBXs.

5.1 Serial vs TCP


As I said earlier, at the time the project started I didn’t have any experience with Alcatel S12. The fact that with this type of PBX (in any case, in the configuration used by the Customer) will have to work on the Serial-connection, from the very beginning, was considered as one of the most significant risks of the project. This may seem strange, but at the same time I was right and wrong.

Of course, using such libraries as RXTX or jSSC (which I learned from an article on Habré), connecting to the Serial port from Java SE (used in the project) is not a problem in itself, but here you need to take two things into account:

  1. , Serial-. , USB-Serial ( ) . , , . , Serial- «»
  2. RS-232 , . , ( , ), !

The solution was found in the process of communicating with the Customer, who had more experience in interaction with the PBX. Of course, telephonists also wanted to manage all PBXs from one place, and they had been successfully doing this for a long time, using MOXA communication equipment , which allows them to “push” a Serial connection through an Intranet. Unfortunately, when trying to connect to the virtual port created by MOXA on the client side, there were problems .

We spent quite a lot of time trying to solve this problem until we found out that some MOXA models allow you to use a TCP connection. This approach has been used. A Serial-port monitor and a sniffer helped us a lot .

5.2 Tune vs TCP


There were fewer problems connecting to the M-200, since it initially supported a TCP connection. Initially it was planned to use direct access to the “subscriber card”. I will not clutter the article with dumps of TCP sessions, I will only say that the subscriber settings in M-200 are stored in a bitmap. The PBX control protocol allows (using TCP) to read this bitmap entirely and write it back after making the necessary changes.

We managed to decrypt some of the subscriber card fields (we could not find the documentation), but eventually it was decided to use the tune server as a more documented method for managing the PBX. In addition, the work in the mode of entering text commands was more convenient.

Conclusion


In this article I tried to describe (and somehow classify) the difficulties that arose in a real activation project. Despite the pronounced focus on the equipment of traditional telephony, the material can be useful when working on the automation control of any equipment (for example, switches cisco). I hope that this article will be useful to someone.

Source: https://habr.com/ru/post/186900/


All Articles