<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.innovaphone.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ckl</id>
	<title>innovaphone wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.innovaphone.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ckl"/>
	<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Special:Contributions/Ckl"/>
	<updated>2026-06-13T11:20:44Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Plus_Overview&amp;diff=79852</id>
		<title>Courseware:IT Plus Overview</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Plus_Overview&amp;diff=79852"/>
		<updated>2026-05-19T08:29:33Z</updated>

		<summary type="html">&lt;p&gt;Ckl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;innovaphone Plus&#039;&#039; is a series of courses, each covering advanced aspects of the configuration of innovaphone devices in separate topics.  Each topic can be worked through on individually or in any order.  Further topics will be added over time.  Each topic is based on the latest firmware at the time of creation.  All topics based on the same firmware version (e.g. 14r2) are included in the same course of the series.  &lt;br /&gt;
&lt;br /&gt;
Access to &#039;&#039;innovaphone Plus&#039;&#039; requires a valid innovaphone &#039;&#039;Plus&#039;&#039; corporate subscription. See [https://www.innovaphone.com/en/partner/training/innovaphone-plus-training.html innovaphone Plus Training] for details.&lt;br /&gt;
&lt;br /&gt;
The rest of this article gives you an overview of the topics covered and in which course they can be found. &lt;br /&gt;
__NOEDITSECTION__ &lt;br /&gt;
{{#invoke-url: https://class.innovaphone.com/moodle2/itplus-overview.php?wiki=true}}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference13r2:Concept_Talking_to_the_v13_Application_Platform_using_PHP&amp;diff=77298</id>
		<title>Reference13r2:Concept Talking to the v13 Application Platform using PHP</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference13r2:Concept_Talking_to_the_v13_Application_Platform_using_PHP&amp;diff=77298"/>
		<updated>2025-07-09T10:49:09Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* PBX / App Platform */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a slight rewrite of the [[Reference13r1:Concept Talking to the v13 Application Platform using PHP | older article]] in the Reference13r1 namespace.  While there is nothing technically wrong with the old article, some of the authentication methods described there are no longer recommended for use with scripts.  In particular, it is not recommended that a script authenticate as a PBX user.  Instead, it should always authenticate against a PBX &#039;&#039;App&#039;&#039; type object.  If the script needs to access other App services, it should use the &#039;&#039;Services&#039;&#039; API described in https://sdk.innovaphone.com/13r2/doc/appwebsocket/Services.htm.&lt;br /&gt;
&lt;br /&gt;
==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* innovaphone platform running the 13r2 (or later) &#039;&#039;App Platform &#039;&#039;&lt;br /&gt;
* PBX running 13r2 (or later) firmware &lt;br /&gt;
* PHP script accessing the &#039;&#039;App Services&#039;&#039; available on the &#039;&#039;App Platform&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
===Problem Details===&lt;br /&gt;
The v13 App Platform runs several &#039;&#039;App Services&#039;&#039; that provide services used by &#039;&#039;Apps&#039;&#039; running in the context of the &#039;&#039;myApps&#039;&#039; client.  Apps (written in JavaScript) are loaded from the App Platform and launched by the myApps client.  They communicate with the App Services using a JSON-based WebSocket protocol.  &#039;&#039;Apps&#039;&#039; can also be loaded from the PBX (so called &#039;&#039;PBX Apps&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;vanilla&#039;&#039; way to go when it comes to 3rd party integration is to write a &#039;&#039;custom App Service&#039;&#039; and install it on the &#039;&#039;App Platform&#039;&#039;.  The creation of such &#039;&#039;App Services&#039;&#039; is facilitated by the [https://sdk.innovaphone.com/13r2/doc/sdk.htm &#039;&#039;v13 SDK&#039;&#039;]. &lt;br /&gt;
&lt;br /&gt;
Note: The mechanisms described here are available in the 13r2 SDK, so all links to the SDK are given for the 13r2 version.  To access other versions of the SDK as they become available, go to [https://sdk.innovaphone.com SDK root] and follow the links to the version of interest.&lt;br /&gt;
&lt;br /&gt;
[[Image:app-platform-php-appplatform-simplified.png]]&lt;br /&gt;
&lt;br /&gt;
However, in some scenarios you may want to talk to the PBX or existing App Services directly from your own application (i.e. not via an App running in the myApps client).  This article describes how to do this.  General considerations are given that apply to all programming languages, and some sample code is given in PHP.&lt;br /&gt;
&lt;br /&gt;
[[Image:app-platform-php-appplatform-simplified-3rd-party.png]]&lt;br /&gt;
&lt;br /&gt;
====  Authentication ====&lt;br /&gt;
To talk to the PBX or another &#039;&#039;App Service&#039;&#039;, your application (written in PHP or any other language that can talk to a WebSocket) needs to be logged in to the PBX.  While an &#039;&#039;App&#039;&#039; does not need to worry about this, as the &#039;&#039;myApps&#039;&#039; client (which is the context in which all &#039;&#039;Apps&#039;&#039; run) would take care of this, an App Service needs to implement the protocol itself.&lt;br /&gt;
&lt;br /&gt;
The process is as follows:&lt;br /&gt;
* An &#039;&#039;App&#039;&#039; type object must be created on the PBX for your application.&lt;br /&gt;
* The &#039;&#039;App&#039;&#039; object defines the authentication credentials (&#039;&#039;Name&#039;&#039; and &#039;&#039;Password&#039;&#039;) as well as the access rights of your application (i.e., the APIs in the &#039;&#039;App&#039;&#039; tab, the licenses in the &#039;&#039;License&#039;&#039; tab, and the Apps in the &#039;&#039;Apps&#039;&#039; tab)&lt;br /&gt;
* The application must log in to the PBX using the credentials configured for the &#039;&#039;App&#039;&#039; type object that corresponds to the application. In other words, it logs in as the App, not as a specific user&lt;br /&gt;
* The application can then use the allowed PBX APIs (according to the definitions in the &#039;&#039;Grant access to APIs&#039;&#039; section in the &#039;&#039;App&#039;&#039; tab of the &#039;&#039;App&#039;&#039; object).&lt;br /&gt;
* The application can authenticate to other allowed App services (as defined in the &#039;&#039;Apps&#039;&#039; tab of the &#039;&#039;App&#039;&#039; object) using the PBX &#039;&#039;Services&#039;&#039; API. It can then request services from these App Services&lt;br /&gt;
&lt;br /&gt;
==== WebSocket ====&lt;br /&gt;
&#039;&#039;App Services&#039;&#039; (as well as the aforementioned PBX APIs) communicate using messages sent through WebSockets. The content of those messages has JSON syntax.  &lt;br /&gt;
&lt;br /&gt;
Although WebSockets are based on the HTTP protocol (for example, they usually use ports 80/443), they behave fundamentally different than HTTP connections in that they are &#039;&#039;asynchronous&#039;&#039;.  With HTTP, all requests are synchronous, that is, each request is responded to by an answer.  Also, only the HTTP client can send requests, not the server. With WebSocket however, both sides can (once they have agreed to upgrade the HTTP connection to a WebSocket connection) send messages at any time.  Such messages may trigger 0, 1 or more response messages, depending on the application protocol.  The protocol itself does not define a relation between a message and its response messages.  As there is no such thing as a synchronous &#039;&#039;request/response&#039;&#039; cycle with WebSocket, an asynchronous programming model is required to take full advantage of the WebSocket approach.&lt;br /&gt;
&lt;br /&gt;
==== JSON ====&lt;br /&gt;
JSON stands for &#039;&#039;J&#039;&#039;ava&#039;&#039;S&#039;&#039;cript&#039;&#039;O&#039;&#039;bject&#039;&#039;N&#039;&#039;otation.  It is a subset of the syntax JavaScript uses to denote (complex) data constants.  Here is an example: &amp;lt;code &amp;gt;{&amp;quot;mystring&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;myint&amp;quot;:42}&amp;lt;/code&amp;gt;. As such, it allows to store the value of an object as a string and also to set the value of an object from a string (a process known as &#039;&#039;serialization/unserialization&#039;&#039; in many programming languages).  JSON allows us to put the value of an object in to a WebSocket message and also of course to retrieve such value from a WebSocket message. Compared to XML (which more or less allows the same), it is much more compact.&lt;br /&gt;
&lt;br /&gt;
Although JSON is related to JavaScript, most programming languages can deal with it.  For example, PHP has the &amp;lt;code&amp;gt;json_encode()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;json_decode()&amp;lt;/code&amp;gt; functions, C# has the &amp;lt;code&amp;gt; DataContractJsonSerializer&amp;lt;/code&amp;gt; class.  &lt;br /&gt;
&lt;br /&gt;
Here is a full example of the JSON message that might be used to authenticate towards the PBX&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;mt&amp;quot;: &amp;quot;AppLogin&amp;quot;,&lt;br /&gt;
    &amp;quot;digest&amp;quot;: &amp;quot;955da4b8351557c54c25b99fa8aad9e8b4ba7a4090ac5c2664e7ef7a301e6586&amp;quot;,&lt;br /&gt;
    &amp;quot;domain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;sip&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;guid&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;dn&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;app&amp;quot;: &amp;quot;myapplication&amp;quot;,&lt;br /&gt;
    &amp;quot;info&amp;quot;: {}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When working with &#039;&#039;App Services&#039;&#039;, there are three message members which are somehow special for all such services.  &lt;br /&gt;
; mt (string) : the &#039;&#039;m&#039;&#039;essage &#039;&#039;t&#039;&#039;ype. Each message must have an &amp;lt;code&amp;gt;mt&amp;lt;/code&amp;gt; member which denotes the message type&lt;br /&gt;
; api (string, optional) : some App services (and in particular the PBX) support different defined sets of messages (referred to as &#039;&#039;api&#039;&#039;). In this case, the &#039;&#039;mt&#039;&#039; message member is not sufficient to specify the type of message. Instead, the API identifier must be given in the &#039;&#039;api&#039;&#039; message member.  The [https://sdk.innovaphone.com/13r2/doc/appwebsocket/RCC.htm RCC api] provided by the PBX would be an example where all messages sent to or received from the PBX  for this API must have an &#039;&#039;api&#039;&#039; message member with the (string) value &amp;lt;code&amp;gt;&amp;quot;RCC&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
; src (string, optional) : this member may be sent along with messages sent to an &#039;&#039;App Service&#039;&#039;.  If the message triggers responses, the &#039;&#039;App Service&#039;&#039; will copy the &amp;lt;code&amp;gt;src&amp;lt;/code&amp;gt; member in to the responses.  This allows the client to associate responses to the message that initiated them.&lt;br /&gt;
All other members (if any) are defined by the application protocol.&lt;br /&gt;
&lt;br /&gt;
==== Definition of Application Protocols ====&lt;br /&gt;
Message types, their members and the message flow are part of the documentation in the [https://sdk.innovaphone.com/13r2 software development kit (SDK)] that comes with the &#039;&#039;App Platform&#039;&#039;.  In this article, we only touch them for educational purposes.&lt;br /&gt;
&lt;br /&gt;
=== PHP Sample Code ===&lt;br /&gt;
These scripts use a configuration from a file called &#039;&#039;my-pbx-data.php&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To provide proper data for your environment to the scripts, create the file &#039;&#039;my-pbx-data.php&#039;&#039; as follows:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
$pbxdns = &amp;quot;your-pbx-dns-or-ip&amp;quot;;&lt;br /&gt;
$pbxapp = &amp;quot;your-app-object-name&amp;quot;;&lt;br /&gt;
$pbxpw = &amp;quot;your-pbx-app-password&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our little example (available in &amp;lt;code&amp;gt;application.php&amp;lt;/code&amp;gt;) will connect to 2 &#039;&#039;App Services&#039;&#039; on the &#039;&#039;App Platform&#039;&#039;, &#039;&#039;Devices&#039;&#039; and &#039;&#039;Users&#039;&#039; to retrieve some configuration data.  To authenticate towards the App service instances, a dedicated PBX &#039;&#039;App&#039;&#039; object in the PBX with appropriate rights is used.&lt;br /&gt;
&lt;br /&gt;
===== PBX configuration =====&lt;br /&gt;
You will need a PBX which has been set up using the standard &#039;&#039;Install&#039;&#039; procedure (http://$pbxdns /install.htm).&lt;br /&gt;
&lt;br /&gt;
On that PBX, you additionally need to create an &#039;&#039;App&#039;&#039; type object &lt;br /&gt;
* whose &#039;&#039;Name&#039;&#039; property is equal to the value of &#039;&#039;$pbxapp&#039;&#039;&lt;br /&gt;
* whose &#039;&#039;Password&#039;&#039; is equal to the value of &#039;&#039;$pbxpw&#039;&#039;&lt;br /&gt;
* that has ticked &#039;&#039;Services&#039;&#039; in the &#039;&#039;Grant access to APIs&#039;&#039; section of the &#039;&#039;App&#039;&#039; tab&lt;br /&gt;
* that has ticked &#039;&#039;devices-api&#039;&#039; and &#039;&#039;users-admin&#039;&#039; in the &#039;&#039;Apps&#039;&#039; tab&lt;br /&gt;
&lt;br /&gt;
===== Login =====&lt;br /&gt;
Logging-in to the PBX requires the following steps:&lt;br /&gt;
* request a challenge from the PBX using the &#039;&#039;AppChallenge&#039;&#039; message&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;sent-&amp;gt;PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;AppChallenge&amp;quot;}&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
* receive the challenge from the PBX&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;received&amp;lt;-PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;AppChallengeResult&amp;quot;,&amp;quot;challenge&amp;quot;:&amp;quot;8b7d8a1a3a281efd&amp;quot;}&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
* compute the digest based on the App data, the secret and the challenge&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;sent-&amp;gt;PBXWS &lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;mt&amp;quot;: &amp;quot;AppLogin&amp;quot;,&lt;br /&gt;
    &amp;quot;digest&amp;quot;: &amp;quot;1a07f3c20d2a4f6b117c64d845b9bed7b884b49b82868f0e2b73200553c40e2d&amp;quot;,&lt;br /&gt;
    &amp;quot;domain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;sip&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;guid&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;dn&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;app&amp;quot;: &amp;quot;myapplication&amp;quot;,&lt;br /&gt;
    &amp;quot;info&amp;quot;: {}&lt;br /&gt;
}&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
* receive the confirmation from the PBX&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;received&amp;lt;-PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;AppLoginResult&amp;quot;,&amp;quot;ok&amp;quot;:true}&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This handshake is implemented in the &#039;&#039;AppPlatform\AppLoginAutomaton&#039;&#039; class available in classes\websocket.class.php.  The thing that needs to be added is the WebSocket connection to the PBX (an &#039;&#039;AppPlatform\WSClient&#039;&#039; object required as constructor argument for the &#039;&#039;AppPlatform\AppLoginAutomaton&#039;&#039; class). We do this using a derived class named &#039;&#039;PbxAppLoginAutomaton&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class PbxAppLoginAutomaton extends AppLoginAutomaton {&lt;br /&gt;
&lt;br /&gt;
    function __construct($pbx, AppServiceCredentials $cred, $useWS = false) {&lt;br /&gt;
        $this-&amp;gt;pbxUrl = (strpos($pbx, &amp;quot;s://&amp;quot;) !== false) ? $pbx :&lt;br /&gt;
                $this-&amp;gt;pbxUrl = ($useWS ? &amp;quot;ws&amp;quot; : &amp;quot;wss&amp;quot;) . &amp;quot;://$pbx/PBX0/APPS/websocket&amp;quot;;&lt;br /&gt;
        // create websocket towards the well known PBX URI&lt;br /&gt;
        $this-&amp;gt;pbxWS  = new WSClient(&amp;quot;PBXWS&amp;quot;, $this-&amp;gt;pbxUrl);&lt;br /&gt;
        parent::__construct($this-&amp;gt;pbxWS, $cred);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This class takes the URL to the PBX and the credentials (wrapped in an object of class &#039;&#039;AppPlatform\AppServiceCredentials&#039;&#039;) as constructor arguments:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$app = new PbxAppLoginAutomaton($pbxdns, new AppPlatform\AppServiceCredentials($pbxapp, $pbxpw));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our new class ultimately is a derivative of the &#039;&#039;AppPlattform\FinitStateAutomaton&#039;&#039; class, so we can run the automaton like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$app-&amp;gt;run();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The automaton will do the authentication towards the PBX as shown above and then terminate (which causes the &#039;&#039;run()&#039;&#039; member function to return).&lt;br /&gt;
&lt;br /&gt;
The code then verifies that the log-in to the PBX succeeded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
if (!$app-&amp;gt;getIsLoggedIn()) {&lt;br /&gt;
    die(&amp;quot;login to the PBX failed - check credentials&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eh voilà, we are connected to the PBX.  &lt;br /&gt;
&lt;br /&gt;
That was the easy part :-)&lt;br /&gt;
&lt;br /&gt;
Note that the code for the &#039;&#039;PbxAppLoginAutomaton&#039;&#039; can be found in the classes/websocket.class.php file.&lt;br /&gt;
&lt;br /&gt;
===== Determination of available services =====&lt;br /&gt;
Now that we are successfully connected to the PBX, we can determine the services that are available to our application.  This is done using the &#039;&#039;Services&#039;&#039; API available in the PBX (which is described in the SDK&#039;s [https://sdk.innovaphone.com/13r3/doc/appwebsocket/Services.htm &#039;&#039;Services&#039;&#039; page]).&lt;br /&gt;
&lt;br /&gt;
Only a few steps are required:&lt;br /&gt;
* subscribe to the available services information&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;sent-&amp;gt;PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;SubscribeServices&amp;quot;,&amp;quot;api&amp;quot;:&amp;quot;Services&amp;quot;}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
: note the additional &amp;lt;code&amp;gt;api&amp;lt;/code&amp;gt; member &lt;br /&gt;
* receive the respones&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;received&amp;lt;-PBXWS {&amp;quot;api&amp;quot;:&amp;quot;Services&amp;quot;,&amp;quot;mt&amp;quot;:&amp;quot;SubscribeServicesResult&amp;quot;}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
: note that there is no further information in this message.  The actual list of services will be received later on&lt;br /&gt;
* unsubscribe from the list of services as we do not need dynamic updates&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;sent-&amp;gt;PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;UnsubscribeServices&amp;quot;,&amp;quot;api&amp;quot;:&amp;quot;Services&amp;quot;}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* receive the actual list of services available to us&lt;br /&gt;
: &amp;lt;code&amp;gt;received&amp;lt; - PBXWS &amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;api&amp;quot;: &amp;quot;Services&amp;quot;,&lt;br /&gt;
    &amp;quot;mt&amp;quot;: &amp;quot;ServicesInfo&amp;quot;,&lt;br /&gt;
    &amp;quot;services&amp;quot;: [{&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;devices-api&amp;quot;,&lt;br /&gt;
            &amp;quot;title&amp;quot;: &amp;quot;DevicesApi&amp;quot;,&lt;br /&gt;
            &amp;quot;url&amp;quot;: &amp;quot;https://192.168.178.71/sample.dom/devices/innovaphone-devices-api&amp;quot;,&lt;br /&gt;
            &amp;quot;info&amp;quot;: {&lt;br /&gt;
                &amp;quot;apis&amp;quot;: {&lt;br /&gt;
                    &amp;quot;com.innovaphone.devices&amp;quot;: {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }, {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;users-admin&amp;quot;,&lt;br /&gt;
            &amp;quot;title&amp;quot;: &amp;quot;Users Admin&amp;quot;,&lt;br /&gt;
            &amp;quot;url&amp;quot;: &amp;quot;https://192.168.178.71/sample.dom/usersapp/innovaphone-usersadmin&amp;quot;&lt;br /&gt;
        }]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
: note that the actual list of services depends on the configuration of the &#039;&#039;Apps&#039;&#039; tab in the &#039;&#039;App&#039;&#039; object for our application&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Life was easy so far as we have derived the &#039;&#039;PbxAppLoginAutomaton&#039;&#039; utility class which simply did what we wanted so far, except for the initialization in its constructor.  Now we want to implement further conversation with the PBX, which requires some more fundamental understanding of the finite state automaton classes.&lt;br /&gt;
&lt;br /&gt;
===== The finite state automaton classes =====&lt;br /&gt;
Generally, to talk to the PBX or any App service, you can of course use just any WebSocket library directly.  We are using (and recommending) a derivative of the [https://github.com/Textalk/websocket-php Textalk] websocket classes.  We simplified the code a bit and also added support for receiving WebSocket messages asynchronously. You will find this code in &amp;lt;code&amp;gt;classes/textalk.class.php&amp;lt;/code&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
However, solely using the textalk classes leaves you with quite a bit of work to do.  As discussed above, there are some challenges:&lt;br /&gt;
* websocket is async by nature&lt;br /&gt;
: you will need some support for receiving messages asynchronously at least. Aside from the support for asynchronous receipt of messages added to the Textalk classes, the sample code has some classes which allow you to easily create &#039;&#039;event driven&#039;&#039; code which processes messages whenever they come in and not when you expect them to come in&lt;br /&gt;
* PBX login requires some fiddling with encryption schemes &lt;br /&gt;
&lt;br /&gt;
The sample code includes some classes to create &#039;&#039;finite state automatons&#039;&#039;.  Also it has some classes derived from this, which actually implement the protocols required to log-in to the PBX and the &#039;&#039;App Services&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Those extensions can be found in &amp;lt;code&amp;gt;classes/websocket.class.php&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== The asynchronous programming model =====&lt;br /&gt;
PHP is not really nicely prepared for asynchronous programming.  To deal with that, we have created a utility class called &#039;&#039;FinitStateAutomaton&#039;&#039;.  This class handles the communication to a single &#039;&#039;App Service&#039;&#039;.  This is why it has a WebSocket connection as argument to the constructor (our WebSocket implementation is actually called &#039;&#039;WSClient&#039;&#039;).   The class will use this WebSocket to talk to the &#039;&#039;App Service&#039;&#039;.  As we have seen above, the &#039;&#039;PbxAppLoginAutomaton&#039;&#039; utility class creates such an &#039;&#039;WSClient&#039;&#039; object and passes it to the &#039;&#039;AppLoginAutomaton&#039;&#039; (which extends the &#039;&#039;FinitStateAutomaton&#039;&#039; class).&lt;br /&gt;
&lt;br /&gt;
However, if you try to instantiate such a class (like &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;$mya = new FinitStateAutomaton($mywebsocket)&amp;lt;/syntaxhighlight&amp;gt; you will see that this is not possible, as the class is &#039;&#039;abstract&#039;&#039;.  This means that there are some  member functions missing which must be implemented by a derived class.  These functions are those which know how to handle messages received from the &#039;&#039;App Service&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Let us look at how the &#039;&#039;AppLoginAutomaton &#039;&#039; class does this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class AppLoginAutomaton extends FinitStateAutomaton {&lt;br /&gt;
    public function ReceiveInitialStart(Message $msg) {&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;log(&amp;quot;requesting challenge&amp;quot;);&lt;br /&gt;
        $this-&amp;gt;sendMessage(new Message(&amp;quot;AppChallenge&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
It defines an override for the abstract &#039;&#039;ReceiveInitialStart&#039;&#039; member function.  This function, as all functions whose name begins with &#039;&#039;Receive&#039;&#039; is called when an event is fed into the automaton.  Usually, this event is a message (of type &#039;&#039;AppPlatform\Message&#039;&#039;) received from an app service.  In this special case however, it is a pseudo event generated by the system indicating that the automaton should start (hence the name &#039;&#039;ReceiveInitial&#039;&#039;&#039;Start&#039;&#039;&#039;&#039;&#039;).  So it implements the first action the automaton performs.&lt;br /&gt;
&lt;br /&gt;
In our case, as discussed above, it sends an &#039;&#039;AppChallenge&#039;&#039; message to the PBX.  Recall that such an automaton is always instantiated with a single &#039;&#039;WSClient&#039;&#039; argument, which is the WebSocket connection used to talk to the App service (or the PBX which behaves like an App service).  In other words, a single instance of a &#039;&#039;FinitStateAutomaton&#039;&#039; always talks to a single App service only.  This is why we can simply say &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
        $this-&amp;gt;sendMessage(new Message(&amp;quot;AppChallenge&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
without specifying a destination and resulting in an AppChallenge message&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
sent-&amp;gt;PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;AppChallenge&amp;quot;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sent to the PBX.&lt;br /&gt;
&lt;br /&gt;
Eventually, the PBX will respond with an &#039;&#039;AppChallengeResult&#039;&#039; message.  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
received&amp;lt;-PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;AppChallengeResult&amp;quot;,&amp;quot;challenge&amp;quot;:&amp;quot;95ed003a24c3fc89&amp;quot;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
When this happens, the system will call the &#039;&#039;ReceiveInitial&#039;&#039;&#039;AppChallengeResult&#039;&#039;&#039;&#039;&#039; member function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveInitialAppChallengeResult(Message $msg) {&lt;br /&gt;
        $infoObj          = new \stdClass();&lt;br /&gt;
        $infoHashString   = json_encode($infoObj, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);&lt;br /&gt;
        $hashcode         = hash(&#039;sha256&#039;, $sha              = &amp;quot;{$this-&amp;gt;cred-&amp;gt;app}:::::{$infoHashString}:{$msg-&amp;gt;challenge}:{$this-&amp;gt;cred-&amp;gt;pw}&amp;quot;);&lt;br /&gt;
        // $this-&amp;gt;log(&amp;quot;computed challenge $sha&amp;quot;, &amp;quot;debug&amp;quot;);  // do not output in any other category than &amp;quot;debug&amp;quot; coz it includes the password&lt;br /&gt;
        $this-&amp;gt;sessionKey = hash(&#039;sha256&#039;, &amp;quot;innovaphoneAppSessionKey:{$msg-&amp;gt;challenge}:{$this-&amp;gt;cred-&amp;gt;pw}&amp;quot;);&lt;br /&gt;
        $this-&amp;gt;sendMessage($this-&amp;gt;loginData  = new Message(&amp;quot;AppLogin&amp;quot;, &amp;quot;digest&amp;quot;, $hashcode, &amp;quot;domain&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;sip&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;guid&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;dn&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;app&amp;quot;, $this-&amp;gt;cred-&amp;gt;app, &amp;quot;info&amp;quot;, $infoObj));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It does some cryptographic magic to compute a digest from the available information and then sends an &#039;&#039;AppLogin&#039;&#039; message to the PBX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
        $this-&amp;gt;sendMessage($this-&amp;gt;loginData  = new Message(&amp;quot;AppLogin&amp;quot;, &amp;quot;digest&amp;quot;, $hashcode, &amp;quot;domain&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;sip&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;guid&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;dn&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;app&amp;quot;, $this-&amp;gt;cred-&amp;gt;app, &amp;quot;info&amp;quot;, $infoObj));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
resulting in a message such as &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
sent - &amp;gt;PBXWS {&lt;br /&gt;
    &amp;quot;mt&amp;quot;: &amp;quot;AppLogin&amp;quot;,&lt;br /&gt;
    &amp;quot;digest&amp;quot;: &amp;quot;955da4b8351557c54c25b99fa8aad9e8b4ba7a4090ac5c2664e7ef7a301e6586&amp;quot;,&lt;br /&gt;
    &amp;quot;domain&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;sip&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;guid&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;dn&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;app&amp;quot;: &amp;quot;myapplication&amp;quot;,&lt;br /&gt;
    &amp;quot;info&amp;quot;: {}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
being sent to the PBX.&lt;br /&gt;
&lt;br /&gt;
The PBX would verify the correctness of the provided digest and then return an &#039;&#039;AppLoginResult&#039;&#039; message.  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
received&amp;lt;-PBXWS {&amp;quot;mt&amp;quot;:&amp;quot;AppLoginResult&amp;quot;,&amp;quot;ok&amp;quot;:true}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Due to the reception of such a message, the &#039;&#039;ReceiveInitialAppLoginResult&#039;&#039; member function is called.  It does a bit of internal housekeeping and then does two interesting things:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveInitialAppLoginResult(Message $msg) {&lt;br /&gt;
&lt;br /&gt;
        $response-&amp;gt;setMt(&amp;quot;AppLoginSuccess&amp;quot;);&lt;br /&gt;
        $this-&amp;gt;postEvent($response);&lt;br /&gt;
&lt;br /&gt;
        return &amp;quot;Dead&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This code creates a &#039;&#039;$response&#039;&#039; message and sets the &#039;&#039;mt&#039;&#039; member to &amp;lt;code&amp;gt;AppLoginSuccess&amp;lt;/code&amp;gt;.  It returns the string &amp;quot;Dead&amp;quot; then.&lt;br /&gt;
&lt;br /&gt;
The event function (&#039;&#039;ReceiveInitialAppChallengeResult&#039;&#039;) we looked at so far did not have any explicit return statement. In PHP terms that means that it returns a &#039;&#039;null&#039;&#039; value.  When an event returns a string however, it indicates that the automaton shall move to a new state. &lt;br /&gt;
&lt;br /&gt;
In our case, the new state is named &amp;quot;Dead&amp;quot; and it has a special meaning.  An automaton in state &amp;quot;Dead&amp;quot; is considered to be terminated.  The system will not listen for incoming messages on the automaton&#039;s WSClient socket any further. &lt;br /&gt;
&lt;br /&gt;
Note that the initial state of any automaton is named &amp;lt;code&amp;gt;Initial&amp;lt;/code&amp;gt;.  This is why event member functions are named &#039;&#039;Receive&#039;&#039;&#039;Initial&#039;&#039;&#039;Start&#039;&#039; for example.  If a member function returns a new state name other than &amp;lt;code&amp;gt;Dead&amp;lt;/code&amp;gt;, the member functions called upon subsequent incoming messages will be named &#039;&#039;Receive&#039;&#039;&#039;NewStateName&#039;&#039;&#039;Event&#039;&#039;.  Also, the first thing the system will do is call the &#039;&#039;Receive&#039;&#039;&#039;NewStateName&#039;&#039;&#039;Start&#039;&#039; member function.&lt;br /&gt;
&lt;br /&gt;
===== Working with multiple automatons ===== &lt;br /&gt;
Obviously, applications may want to talk to multiple destinations, e.g. to the PBX for authentication and to one or more other App services.  As a single &#039;&#039;FiniteStateAutomaton&#039;&#039; always talks to a single &#039;&#039;WSClient&#039;&#039; connection, we need to instantiate multiple automatons to be able to talk to multiple destinations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$a1 = new Type1Automaton();&lt;br /&gt;
$a2 = new Type2Automaton();&lt;br /&gt;
$transitioner = new AppPlatform\Transitioner($a1, $a2);&lt;br /&gt;
$transitioner-&amp;gt;run();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AppPlatform\Transitioner&#039;&#039; is a helper class that takes a number of automatons (either listed as multiple arguments or wrapped in an array and given as single argument) as constructor arguments. When its &#039;&#039;run&#039;&#039; member function is called, it will in turn call all of the automatons &#039;&#039;ReceiveInitialStart&#039;&#039; member functions and then listen for messages coming in on any of the automatons &#039;&#039;WSClient&#039;&#039; connections. &lt;br /&gt;
&lt;br /&gt;
By the way, the &#039;&#039;FinitStateAutomaton&#039;&#039;&#039;s own &#039;&#039;run&#039;&#039; member function is trivial:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * utility function for the simple case you want to run a single (i.e. this) automaton only&lt;br /&gt;
     */&lt;br /&gt;
    public function run($sockettimeout = 5) {&lt;br /&gt;
        $auto = new Transitioner($this);&lt;br /&gt;
        $auto-&amp;gt;run($sockettimeout);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The remaining question is how different automaton instances communicate to each other.  This is done using the &#039;&#039;FinitStateAutomaton&#039;&#039;&#039;s &#039;&#039;postMessage&#039;&#039; member function as in &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
        $this-&amp;gt;postEvent($response);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
shown above in the &#039;&#039;ReceiveInitialAppLoginResult&#039;&#039; event function.  When &#039;&#039;postEvent&#039;&#039; is called, the system would call the corresponding event functions in all currently active automatons. Note that these member functions are called synchronously, that is, they are already executed when the &#039;&#039;postEvent&#039;&#039; function returns. &lt;br /&gt;
&lt;br /&gt;
===== Tandems =====&lt;br /&gt;
The &#039;&#039;postEvent&#039;&#039; mechanisms allows two or more automatons to work in tandem.  To see how that works, we can have a look at the &#039;&#039;Pbx2AppAuthenticator&#039;&#039; class. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * class that authenticates to an App service with help from the PBX &lt;br /&gt;
 */&lt;br /&gt;
class Pbx2AppAuthenticator extends \AppPlatform\FinitStateAutomaton {&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This class takes a &#039;&#039;ServiceConnector&#039;&#039; as constructor argument (for example one delivered from the &#039;&#039;PbxAppLoginAutomaton&#039;&#039;) and creates a WebSocket connection (actually a &#039;&#039;WSClient&#039;&#039; object) towards the App service described by the &#039;&#039;ServiceConnector&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function __construct(ServiceConnector $svc) {&lt;br /&gt;
        $this-&amp;gt;svc = $svc;&lt;br /&gt;
        parent::__construct($svc-&amp;gt;connect(), $svc-&amp;gt;name);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The first thing it then does is to send an &#039;&#039;AppChallenge&#039;&#039; message to the service:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveInitialStart(Message   $msg) {&lt;br /&gt;
        $this-&amp;gt;sendMessage(new Message (&amp;quot;AppChallenge&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
When the service returns the challenge, the class needs help from the &#039;&#039;PbxAppLoginAutomaton&#039;&#039; class (which talks to the PBX as we have seen before). To get help, it posts a &#039;&#039;GotChallenge&#039;&#039; message which includes the challenge received from the service and the name of that service.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveInitialAppChallengeResult(Message   $msg) {&lt;br /&gt;
        $this-&amp;gt;postEvent(new Message (&amp;quot;GotChallenge&amp;quot;, &amp;quot;from&amp;quot;, $this-&amp;gt;svc-&amp;gt;name, &amp;quot;challenge&amp;quot;, $msg-&amp;gt;challenge));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the &#039;&#039;PbxAppLoginAutomaton&#039;&#039; class (which has already been used to authenticate towards the PBX) is activated again (resulting in a call of its &#039;&#039;ReceiveInitialStart&#039;&#039; event function) it will determine that it already obtained a service list from the PBX (see above) and will therefore move into the new state named &#039;&#039;SvcAuthenticate&#039;&#039;. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveInitialStart(Message   $msg) {&lt;br /&gt;
        if (empty($this-&amp;gt;services)) {&lt;br /&gt;
            // initial login to the PBX&lt;br /&gt;
            return parent::ReceiveInitialStart($msg);&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
            // PBX assisted login towards App services&lt;br /&gt;
            return &amp;quot;SvcAuthenticate&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
When the &#039;&#039;GotChallenge&#039;&#039; event is posted, the &#039;&#039;ReceiveSvcAuthenticateGotChallenge&#039;&#039; event function is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveSvcAuthenticateGotChallenge(Message  $msg) {&lt;br /&gt;
        $this-&amp;gt;log(&amp;quot;got challenge info from $msg-&amp;gt;from&amp;quot;);&lt;br /&gt;
        $this-&amp;gt;sendMessage(new Message (&amp;quot;GetServiceLogin&amp;quot;, &amp;quot;api&amp;quot;, &amp;quot;Services&amp;quot;, &amp;quot;app&amp;quot;, $msg-&amp;gt;from, &amp;quot;challenge&amp;quot;, $msg-&amp;gt;challenge, &amp;quot;src&amp;quot;, $msg-&amp;gt;from));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and sends a &#039;&#039;GetServiceLogin&#039;&#039; message to the PBX which includes the service name and the challenge. It also includes a &#039;&#039;src&#039;&#039; property set to the name of the App.  This will instruct the PBX to include the same property when the response is sent, so that the returned information can be associated with the proper service later on.&lt;br /&gt;
&lt;br /&gt;
The PBX will eventually respond with a &#039;&#039;GetServiceLoginResult&#039;&#039; message. This needs to be passed to the &#039;&#039;Pbx2AppAuthenticator&#039;&#039; class instance which will send it to the service.  This is done using the &#039;&#039;postEvent&#039;&#039; mechanism again:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveSvcAuthenticateGetServiceLoginResult(Message  $msg) {&lt;br /&gt;
        $this-&amp;gt;postEvent(new Message (&amp;quot;GotChallengeResult&amp;quot;, &amp;quot;for&amp;quot;, $msg-&amp;gt;src, &amp;quot;msg&amp;quot;, $msg));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &#039;&#039;Pbx2AppAuthenticator&#039;&#039; class instance which is interested in exactly this &#039;&#039;GetServiceLoginResult&#039;&#039; response has a &#039;&#039;ReceiveInitialGotChallengeResult&#039;&#039; event function which is called due to this &#039;&#039;postEvent&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveInitialGotChallengeResult(Message  $msg) {&lt;br /&gt;
        if ($msg-&amp;gt;for == $this-&amp;gt;svc-&amp;gt;name) {&lt;br /&gt;
            $this-&amp;gt;sendMessage(new Message (&amp;quot;AppLogin&amp;quot;,&lt;br /&gt;
                                                       &amp;quot;app&amp;quot;, $msg-&amp;gt;msg-&amp;gt;app,&lt;br /&gt;
                                                       &amp;quot;domain&amp;quot;, $msg-&amp;gt;msg-&amp;gt;domain,&lt;br /&gt;
                                                       &amp;quot;sip&amp;quot;, $msg-&amp;gt;msg-&amp;gt;sip,&lt;br /&gt;
                                                       &amp;quot;guid&amp;quot;, $msg-&amp;gt;msg-&amp;gt;guid,&lt;br /&gt;
                                                       &amp;quot;dn&amp;quot;, $msg-&amp;gt;msg-&amp;gt;dn,&lt;br /&gt;
                                                       &amp;quot;digest&amp;quot;, $msg-&amp;gt;msg-&amp;gt;digest,&lt;br /&gt;
                                                       &amp;quot;pbxObj&amp;quot;, $msg-&amp;gt;msg-&amp;gt;pbxObj,&lt;br /&gt;
                                                       &amp;quot;info&amp;quot;, $msg-&amp;gt;msg-&amp;gt;info));&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The function verifies that it has been called for the challenge result it is actually interested in and then passes it to its service.  The service will return an &#039;&#039;AppLoginResult&#039;&#039; message which is processed by the &#039;&#039;ReceiveInitialAppLoginResult&#039;&#039; function:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveInitialAppLoginResult(Message  $msg) {&lt;br /&gt;
        if (empty($msg-&amp;gt;ok) || $msg-&amp;gt;ok != 1) {&lt;br /&gt;
            $this-&amp;gt;log(&amp;quot;FAILED to log in to $msg-&amp;gt;app ($this-&amp;gt;svc-&amp;gt;name&amp;quot;, &amp;quot;error&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
            $this-&amp;gt;log(&amp;quot;logged in to $msg-&amp;gt;app ({$this-&amp;gt;svc-&amp;gt;name})&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
            $this-&amp;gt;svc-&amp;gt;authenticated = true;&lt;br /&gt;
        }&lt;br /&gt;
        return &amp;quot;User&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The event function checks if the login was successfull (it should have been) and then moves into the new &amp;quot;User&amp;quot; state.  This will trigger the &#039;&#039;ReceiveUserStart&#039;&#039; to be called which simply moves to the &#039;&#039;Dead&#039;&#039; state (that is, it terminates the automaton).  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * this simply ends the automaton.  Override it if you derive a class from this&lt;br /&gt;
     * @param Message  $msg&lt;br /&gt;
     * @return string &lt;br /&gt;
     */&lt;br /&gt;
    public function ReceiveUserStart(Message  $msg) {&lt;br /&gt;
        // &lt;br /&gt;
        return &amp;quot;Dead&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So why is this?  This is just convenience.  In a real application, we obviously would want to continue talking to the service but the &#039;&#039;Pbx2AppAuthenticator&#039;&#039; class doesn&#039;t know how to.  So we would certainly create a new class of our own which extends the &#039;&#039;Pbx2AppAuthenticator&#039;&#039; class and overrides the &#039;&#039; event function. A very simple example can be seen in the &#039;&#039;application.php&#039;&#039; script:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class UsersLister extends AppPlatform\Pbx2AppAuthenticator {&lt;br /&gt;
    public function ReceiveUserStart(\AppPlatform\Message $msg) {&lt;br /&gt;
        $this-&amp;gt;sendMessage(new AppPlatform\Message(&amp;quot;UserData&amp;quot;,&lt;br /&gt;
                                                   &amp;quot;maxID&amp;quot;, 9999, &amp;quot;offset&amp;quot;, 0, &amp;quot;filter&amp;quot;, &amp;quot;%&amp;quot;, &amp;quot;update&amp;quot;, false, &amp;quot;col&amp;quot;, &amp;quot;id&amp;quot;, &amp;quot;asc&amp;quot;, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function ReceiveUserUserDataInfo(\AppPlatform\Message $msg) {&lt;br /&gt;
        $this-&amp;gt;log(&amp;quot;from {$this-&amp;gt;svc-&amp;gt;name}: user: id $msg-&amp;gt;id, name $msg-&amp;gt;username&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
        return &amp;quot;Dead&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This sample class simply sends a &#039;&#039;UserData&#039;&#039; message to the &#039;&#039;users-admin&#039;&#039; service and prints out the user information from the resulting &#039;&#039;UserDataInfo&#039;&#039; response.&lt;br /&gt;
&lt;br /&gt;
So this was an example of how automatons can work in tandem.  However, the mechanism can also be used to work with more than two automatons.  In the sample code, an instance of the &#039;&#039;Pbx2AppAuthenticator&#039;&#039; class (more precisely, a derived class such as the &#039;&#039;UsersLister&#039;&#039; class above) is created for each of the services listed by the PBX as available to our App.  They are pushed into an array of &#039;&#039;FinitStateAutomaton&#039;&#039;s in addition to the instance of the &#039;&#039;PbxAppLoginAutomaton&#039;&#039; class used to talk to the PBX:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// connect to services we need&lt;br /&gt;
$authenticators = [$app];&lt;br /&gt;
&lt;br /&gt;
// scan list of available app services for those we are interested ion&lt;br /&gt;
foreach ($app-&amp;gt;getServices() as $svc) {&lt;br /&gt;
    /* consider if we need this */&lt;br /&gt;
    switch ($svc-&amp;gt;type) {&lt;br /&gt;
        case &amp;quot;innovaphone-devices-api&amp;quot;:&lt;br /&gt;
            $authenticators[] = new DevicesLister($svc);&lt;br /&gt;
            break;&lt;br /&gt;
        case &amp;quot;innovaphone-usersadmin&amp;quot;:&lt;br /&gt;
            $authenticators[] = new UsersLister($svc);&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The resulting list of tasks is then run using the &#039;&#039;Transitioner&#039;&#039; helper class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// tell class talking to PBX how many authentications we need to do&lt;br /&gt;
$app-&amp;gt;setNumberOfAuthentications(count($authenticators) - 1);&lt;br /&gt;
&lt;br /&gt;
$tr = new AppPlatform\Transitioner($authenticators);&lt;br /&gt;
$tr-&amp;gt;run();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More sample code ===&lt;br /&gt;
==== Using the PbxAdminApi ====&lt;br /&gt;
This is a simple piece of code that uses the [https://sdk.innovaphone.com/13r3/doc/appwebsocket/PbxAdminApi.htm PbxAdminApi] to create a duplicate of the App object we were using in the first sample code (&#039;&#039;application.php&#039;&#039;).  It is available in &#039;&#039;pbxadminapi.php&#039;&#039;.  Before you can use the sample, you must make sure that the &#039;&#039;Admin&#039;&#039; check-mark is ticked in the &#039;&#039;App&#039;&#039; tab of your App object.&lt;br /&gt;
&lt;br /&gt;
It first uses the &#039;&#039;PbxAppLoginAutomaton&#039;&#039; to log in to the PBX.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Login to PBX&lt;br /&gt;
$app = new AppPlatform\PbxAppLoginAutomaton($pbxdns, new AppPlatform\AppServiceCredentials($pbxapp, $pbxpw));&lt;br /&gt;
$app-&amp;gt;run();&lt;br /&gt;
if (!$app-&amp;gt;getIsLoggedIn()) {&lt;br /&gt;
    die(&amp;quot;login to the PBX failed - check credentials&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It then uses a new derivative of the &#039;&#039;FiniteStateAutomaton&#039;&#039; class to create the cloned object, passing the WSClient object used by the  &#039;&#039;PbxAppLoginAutomaton&#039;&#039; class to its constructor:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * class to create a new PBX App object just like the one we use for this application&lt;br /&gt;
 */&lt;br /&gt;
class AppObjectCreator extends AppPlatform\FinitStateAutomaton {&lt;br /&gt;
&lt;br /&gt;
    public function ReceiveInitialStart(AppPlatform\Message $msg) {&lt;br /&gt;
        // &lt;br /&gt;
        {&lt;br /&gt;
            return &amp;quot;CopyObject&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * &lt;br /&gt;
     * @global string $pbxapp h323-name of source App object&lt;br /&gt;
     * @param AppPlatform\Message $msg&lt;br /&gt;
     */&lt;br /&gt;
    public function ReceiveCopyObjectStart(AppPlatform\Message $msg) {&lt;br /&gt;
        global $pbxapp;&lt;br /&gt;
        $this-&amp;gt;sendMessage(new AppPlatform\Message(&lt;br /&gt;
                        &amp;quot;GetObject&amp;quot;,&lt;br /&gt;
                        &amp;quot;api&amp;quot;, &amp;quot;PbxAdminApi&amp;quot;,&lt;br /&gt;
                        &amp;quot;h323&amp;quot;, $pbxapp));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function ReceiveCopyObjectGetObjectResult(AppPlatform\Message $msg) {&lt;br /&gt;
        // patch $msg so it can be used for object creation&lt;br /&gt;
        $msg-&amp;gt;setMt(&amp;quot;UpdateObject&amp;quot;);&lt;br /&gt;
        // a new one shall be created, no update of the exiting one&lt;br /&gt;
        unset($msg-&amp;gt;guid);&lt;br /&gt;
        // assert unique identifiers&lt;br /&gt;
        $msg-&amp;gt;h323 .= &amp;quot;-clone&amp;quot;;&lt;br /&gt;
        $msg-&amp;gt;cn   .= &amp;quot; (clone)&amp;quot;;&lt;br /&gt;
        // we don&#039;t want any &amp;quot;Devices&amp;quot; entries&lt;br /&gt;
        unset($msg-&amp;gt;devices);&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;sendMessage($msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function ReceiveCopyObjectUpdateObjectResult(AppPlatform\Message $msg) {&lt;br /&gt;
        if (isset($msg-&amp;gt;guid)) {&lt;br /&gt;
            $this-&amp;gt;log(&amp;quot;App object clone created with Guid $msg-&amp;gt;guid&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $this-&amp;gt;log(&amp;quot;App object clone could not be created: $msg-&amp;gt;error&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        return &amp;quot;Dead&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
$me = new AppObjectCreator($app-&amp;gt;getWs());&lt;br /&gt;
$me-&amp;gt;run();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using the RCC API ====&lt;br /&gt;
To run this sample code, you must make sure&lt;br /&gt;
* there is a waiting queue with &#039;&#039;Name&#039;&#039; (h323/sip) &amp;lt;code&amp;gt;sink&amp;lt;/code&amp;gt;&lt;br /&gt;
: * it has an &#039;&#039;Alert Timeout&#039;&#039; set to a reasonable number (some seconds, e.g. 3)&lt;br /&gt;
: * it has the &#039;&#039;1st Announcement URL&#039;&#039; set to &amp;lt;code&amp;gt;MOH&amp;lt;/code&amp;gt;&lt;br /&gt;
* there must be a user object&lt;br /&gt;
: * it has our application (&#039;&#039;myapplication&#039;&#039;) check-mark ticked in its &#039;&#039;Apps&#039;&#039; tab&lt;br /&gt;
: * it has a phone registered or a softphone provisioned&lt;br /&gt;
* the App object for our application (&#039;&#039;myapplication&#039;&#039;) must have the &#039;&#039;RCC&#039;&#039; check-mark ticked in its &#039;&#039;App&#039;&#039; tab &lt;br /&gt;
&lt;br /&gt;
This sample code demonstrates use of the [http://sdk.innovaphone.com/13r2/doc/appwebsocket/RCC.htm RCC] API.  It monitors some PBX user objects and shows all related calls.  If a peer named &#039;&#039;sink&#039;&#039; is called, the call is forcefully terminated by our script. It is available in the &#039;&#039;rccapi.php&#039;&#039; sample code file. &lt;br /&gt;
&lt;br /&gt;
The code uses a derivative of the &#039;&#039;FinitStateAutomaton&#039;&#039; class called &#039;&#039;RemoteControlUser&#039;&#039;.  The first thing it does is to send an &#039;&#039;Initialize&#039;&#039; message to the PBX which initializes the use of the &#039;&#039;RCC&#039;&#039; api.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class RemoteControlUser extends AppPlatform\FinitStateAutomaton {&lt;br /&gt;
&lt;br /&gt;
    private $myusers = [];&lt;br /&gt;
    private $mycalls = [];&lt;br /&gt;
&lt;br /&gt;
    public function ReceiveInitialStart(AppPlatform\Message $msg) {&lt;br /&gt;
        // move to Monitoring state&lt;br /&gt;
        return &amp;quot;Monitoring&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function ReceiveMonitoringStart(AppPlatform\Message $msg) {&lt;br /&gt;
        // Initialize RCC Api&lt;br /&gt;
        $this-&amp;gt;sendMessage(new AppPlatform\Message(&lt;br /&gt;
                        &amp;quot;Initialize&amp;quot;,&lt;br /&gt;
                        &amp;quot;api&amp;quot;, &amp;quot;RCC&amp;quot;&lt;br /&gt;
        ));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PBX will send a number of &#039;&#039;UserInfo&#039;&#039; messages in response to the &#039;&#039;Initialize&#039;&#039; message.  One message will be sent for each user that has our application check-mark ticked in its &#039;&#039;Apps&#039;&#039; tab. Those users then are said to be monitored by the application using the RCC API.&lt;br /&gt;
&lt;br /&gt;
For each new monitored user that is announced this way, the user information is stored in a class-local array. Also, an &#039;&#039;UserInitialize&#039;&#039; message is sent. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveMonitoringUserInfo(AppPlatform\Message $msg) {&lt;br /&gt;
        // remember UserInfo and do UserInitialize on the user&lt;br /&gt;
        if (isset($this-&amp;gt;myusers[$msg-&amp;gt;h323])) {&lt;br /&gt;
            $this-&amp;gt;log(&amp;quot;user &#039;$msg-&amp;gt;h323&#039; updated&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
            $this-&amp;gt;log(&amp;quot;new user &#039;$msg-&amp;gt;h323&#039;&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
            $this-&amp;gt;myusers[$msg-&amp;gt;h323] = new stdClass();&lt;br /&gt;
            $this-&amp;gt;sendMessage(new AppPlatform\Message(&lt;br /&gt;
                            &amp;quot;UserInitialize&amp;quot;,&lt;br /&gt;
                            &amp;quot;api&amp;quot;, &amp;quot;RCC&amp;quot;,&lt;br /&gt;
                            &amp;quot;cn&amp;quot;, $msg-&amp;gt;cn,&lt;br /&gt;
                            &amp;quot;src&amp;quot;, $msg-&amp;gt;h323 // use &amp;quot;src&amp;quot; to be able to associate response&lt;br /&gt;
            ));&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;myusers[$msg-&amp;gt;h323]-&amp;gt;info = $msg;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;UserInitializeResponse&#039;&#039; message will include a client-local identifier for the initialized user called &#039;&#039;user&#039;&#039;.  We remember it in our class-local array of users:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveMonitoringUserInitializeResult(AppPlatform\Message $msg) {&lt;br /&gt;
        // remember local user id returned from UserInitialize (associated by &amp;quot;src&amp;quot;)&lt;br /&gt;
        $this-&amp;gt;myusers[$msg-&amp;gt;src]-&amp;gt;user = $msg-&amp;gt;user;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user object is monitored (that is, when there was a successful &#039;&#039;UserInitializeResponse&#039;&#039; message), the PBX will start to send additional &#039;&#039;CallInfo&#039;&#039; messages  for each call related to the user and for all call-state changes.&lt;br /&gt;
&lt;br /&gt;
We look at those messages and determine if the remote party (the &#039;&#039;peer&#039;&#039;) is called &#039;&#039;sink&#039;&#039;. If so, we remember this call.  If such remembered call later announces to be connected (a &#039;&#039;CallInfo&#039;&#039; message with &#039;&#039;msg&#039;&#039; member &#039;&#039;r-conn&#039;&#039; is received, we terminate the call by sending an appropriate &#039;&#039;UserEnd&#039;&#039; message. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function ReceiveMonitoringCallInfo(AppPlatform\Message $msg) {&lt;br /&gt;
        // a call state update&lt;br /&gt;
        $this-&amp;gt;log(&amp;quot;user $msg-&amp;gt;user call $msg-&amp;gt;call event $msg-&amp;gt;msg&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
        // see if the call is towards the waiting queue &amp;quot;sink&amp;quot; &lt;br /&gt;
        if (isset($msg-&amp;gt;peer) &amp;amp;&amp;amp; isset($msg-&amp;gt;peer-&amp;gt;h323) &amp;amp;&amp;amp; $msg-&amp;gt;peer-&amp;gt;h323 == &amp;quot;sink&amp;quot;) {&lt;br /&gt;
            $this-&amp;gt;log(&amp;quot;user $msg-&amp;gt;user call $msg-&amp;gt;call with peer h323=sink (notified with $msg-&amp;gt;msg)&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
            // remember this call for monitoring&lt;br /&gt;
            $this-&amp;gt;mycalls[$msg-&amp;gt;call] = $msg;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // check if we monitor this call and if we are connected&lt;br /&gt;
        if (isset($this-&amp;gt;mycalls[$msg-&amp;gt;call])) {&lt;br /&gt;
            switch ($msg-&amp;gt;msg) {&lt;br /&gt;
                case &amp;quot;r-conn&amp;quot; :&lt;br /&gt;
                    $this-&amp;gt;log(&amp;quot;call $msg-&amp;gt;call connected ($msg-&amp;gt;msg) - disconnecting&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
                    $this-&amp;gt;sendMessage(new AppPlatform\Message(&lt;br /&gt;
                                    &amp;quot;UserClear&amp;quot;,&lt;br /&gt;
                                    &amp;quot;api&amp;quot;, &amp;quot;RCC&amp;quot;,&lt;br /&gt;
                                    &amp;quot;call&amp;quot;, $msg-&amp;gt;call,&lt;br /&gt;
                                    &amp;quot;cause&amp;quot;, 88, // &amp;quot;Incompatible destination&amp;quot; see https://wiki.innovaphone.com/index.php?title=Reference:ISDN_Cause_Codes&lt;br /&gt;
                    ));&lt;br /&gt;
                    break;&lt;br /&gt;
                case &amp;quot;del&amp;quot; : &lt;br /&gt;
                    $this-&amp;gt;log(&amp;quot;call $msg-&amp;gt;call ended ($msg-&amp;gt;msg) - terminating&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
                    return &amp;quot;Dead&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is one other interesting mechanism which is used in this script:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    public function timeout() {&lt;br /&gt;
        $this-&amp;gt;log(&amp;quot;timeout&amp;quot;, &amp;quot;runtime&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the system waits for incoming events, there is (by default) a timeout of 5 seconds.  If there are no incoming events during this time, an error message is issued and all the automatons are terminated.   However, if an automaton implements an override for the &#039;&#039;timeout&#039;&#039; function and it does not return true, the timeout will be ignored.  This is why our script waits a long time for the end of the call, occasionally spitting out a log message.&lt;br /&gt;
&lt;br /&gt;
===System Requirements===&lt;br /&gt;
To run the sample code, you need&lt;br /&gt;
* a platform that is able to run v13r2 PBX firmware (e.g. an IP411, but any other will do too)&lt;br /&gt;
* a platform that can run the v13r2 app platform (the same IP411 would do), so if you choose to use a gateway, you will need an SSD&lt;br /&gt;
* a web server running PHP 8.x or up (the code has not been tested with PHP 5.6 or 7, but it may run with no problems)&lt;br /&gt;
* your favourite PHP IDE&lt;br /&gt;
&lt;br /&gt;
You can download the PBX firmware from [https://store.innovaphone.com/release/download.htm store.innovaphone.com].&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The PBX and App Platform is installed using the &#039;&#039;Install&#039;&#039;.  &lt;br /&gt;
==== PBX / &#039;&#039;App Platform&#039;&#039; ====&lt;br /&gt;
* if you choose to use a gateway platform, install an SSD&lt;br /&gt;
* upgrade your box (or IPVA) to the latest v13r2 (or later)&lt;br /&gt;
* you will need two extra IP address. One for the &#039;&#039;App Platform&#039;&#039;, one for the PBX&lt;br /&gt;
* perform a factory reset&lt;br /&gt;
* access the box and you will see the installer (if not, use &amp;lt;code&amp;gt;htps://&amp;lt;ip-of-our-pbx&amp;gt;/install.htm&amp;lt;/code&amp;gt;)&lt;br /&gt;
* complete the installer using IP addresses instead of DNS names, so that it installs a PBX and a fresh &#039;&#039;App Platform&#039;&#039; (you can of course also use DNS names during the Install if you have them operational for the PBX and App platform IP addresses. For running the sample code, it does not matter)&lt;br /&gt;
* be sure to note the &#039;&#039;Admin Password&#039;&#039; shown in the installer&lt;br /&gt;
* the installer will ask for the name of an &#039;&#039;admin account&#039;&#039;.  Be sure to note name and password. &lt;br /&gt;
* for convenience, consider to not turn on &#039;&#039;two factor authentication&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== PHP Script ==== &lt;br /&gt;
* unpack the sample sources in to your web server&#039;s content directories&lt;br /&gt;
* make sure PHP scripts can be executed in the &#039;&#039;.../sample/sources&#039;&#039; directory&lt;br /&gt;
* configure the PBX according to the hints given with the individual sample code above&lt;br /&gt;
* open the file &#039;&#039;application.php&#039;&#039; in your browser&lt;br /&gt;
&lt;br /&gt;
===Known Problems===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Missing php_openssl extension====&lt;br /&gt;
In case following error appears, make sure to enable php_openssl in your php environment configuration:&lt;br /&gt;
 Fatal error: Uncaught Error: Call to undefined function AppPlatform\openssl_random_pseudo_bytes()&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
The sample code can be downloaded [http://wiki.innovaphone.com/index.php?title=Howto:Wiki_Sources#websocketphp8 here ]&lt;br /&gt;
&amp;lt;!-- == Related Articles == --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto|{{PAGENAME}}]]&lt;br /&gt;
[[Category:Concept|{{PAGENAME}}]]&lt;br /&gt;
[[Category:Sample|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference7:HTTP_Request_Message_Format&amp;diff=76923</id>
		<title>Reference7:HTTP Request Message Format</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference7:HTTP_Request_Message_Format&amp;diff=76923"/>
		<updated>2025-06-17T13:55:46Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* POST */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;innovaphone devices will send data to external HTTP servers in various situations.  This article describes these situations and the request formats used. &lt;br /&gt;
&lt;br /&gt;
== Log Messages ==&lt;br /&gt;
[[Reference7:Configuration/General/Logging|Configuration/General/Logging]]&lt;br /&gt;
&lt;br /&gt;
=== GET ===&lt;br /&gt;
When &#039;&#039;&#039;Method External(GET)&#039;&#039;&#039; is selected, the HTTP server will receive a GET request with the following form data parameters (a.k.a. &#039;&#039;query args&#039;&#039;):&lt;br /&gt;
{|&lt;br /&gt;
| Parameter || Example || Description&lt;br /&gt;
|-&lt;br /&gt;
| event || syslog || The &#039;&#039;&#039;event&#039;&#039;&#039; parameter will always have the value &#039;&#039;&#039;syslog&#039;&#039;&#039;.  This allows the receiving script to distinguish it from CDR data.&lt;br /&gt;
|-&lt;br /&gt;
| time || 1214319593 || The time the log messages was created. Coded as number of seconds since January 1st, 1970.  If &#039;&#039;&#039;time&#039;&#039;&#039; is 0, the internal clock has not (yet) been set.  &lt;br /&gt;
|-&lt;br /&gt;
| date ||  20080624-145953 || The same value as &#039;&#039;&#039;time&#039;&#039;&#039;, except that is is coded in a human readable format.&lt;br /&gt;
|-&lt;br /&gt;
| msg || LOG_HTTP 3 TCP-Up   172.16.10.14:7793    172.16.0.17:471 || The message itself&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the receiving HTTP server is running a scripting engine such as PHP, the individual fields will be received as request query parameters.  In PHP they can be accessed via &#039;&#039;&#039;$_GET&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 _GET: Array&lt;br /&gt;
 (&lt;br /&gt;
    [event] =&amp;gt; syslog&lt;br /&gt;
    [time] =&amp;gt; 0&lt;br /&gt;
    [date] =&amp;gt; 19700101-000000&lt;br /&gt;
    [from] =&amp;gt; IP24-1d-00-8d&lt;br /&gt;
    [msg] =&amp;gt; LDIR_SOCK 4 TCP-Out  0.0.0.0:0            0.0.0.0:389&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
=== POST ===&lt;br /&gt;
When &#039;&#039;&#039;Method External(POST)&#039;&#039;&#039; is selected, the HTTP server will receive a POST request.  The request body (i.e. the &#039;&#039;post data&#039;&#039;) is &#039;&#039;not&#039;&#039; coded as a form-data.  Instead, the arguments are put into the request body exactly as the query string when using GET (e.g. &amp;lt;code&amp;gt;?event=syslog&amp;amp;...&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== CDRs ==&lt;br /&gt;
&lt;br /&gt;
== Alarms/Events ==&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference7:HTTP_Request_Message_Format&amp;diff=76922</id>
		<title>Reference7:HTTP Request Message Format</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference7:HTTP_Request_Message_Format&amp;diff=76922"/>
		<updated>2025-06-17T13:55:09Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* POST */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;innovaphone devices will send data to external HTTP servers in various situations.  This article describes these situations and the request formats used. &lt;br /&gt;
&lt;br /&gt;
== Log Messages ==&lt;br /&gt;
[[Reference7:Configuration/General/Logging|Configuration/General/Logging]]&lt;br /&gt;
&lt;br /&gt;
=== GET ===&lt;br /&gt;
When &#039;&#039;&#039;Method External(GET)&#039;&#039;&#039; is selected, the HTTP server will receive a GET request with the following form data parameters (a.k.a. &#039;&#039;query args&#039;&#039;):&lt;br /&gt;
{|&lt;br /&gt;
| Parameter || Example || Description&lt;br /&gt;
|-&lt;br /&gt;
| event || syslog || The &#039;&#039;&#039;event&#039;&#039;&#039; parameter will always have the value &#039;&#039;&#039;syslog&#039;&#039;&#039;.  This allows the receiving script to distinguish it from CDR data.&lt;br /&gt;
|-&lt;br /&gt;
| time || 1214319593 || The time the log messages was created. Coded as number of seconds since January 1st, 1970.  If &#039;&#039;&#039;time&#039;&#039;&#039; is 0, the internal clock has not (yet) been set.  &lt;br /&gt;
|-&lt;br /&gt;
| date ||  20080624-145953 || The same value as &#039;&#039;&#039;time&#039;&#039;&#039;, except that is is coded in a human readable format.&lt;br /&gt;
|-&lt;br /&gt;
| msg || LOG_HTTP 3 TCP-Up   172.16.10.14:7793    172.16.0.17:471 || The message itself&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the receiving HTTP server is running a scripting engine such as PHP, the individual fields will be received as request query parameters.  In PHP they can be accessed via &#039;&#039;&#039;$_GET&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 _GET: Array&lt;br /&gt;
 (&lt;br /&gt;
    [event] =&amp;gt; syslog&lt;br /&gt;
    [time] =&amp;gt; 0&lt;br /&gt;
    [date] =&amp;gt; 19700101-000000&lt;br /&gt;
    [from] =&amp;gt; IP24-1d-00-8d&lt;br /&gt;
    [msg] =&amp;gt; LDIR_SOCK 4 TCP-Out  0.0.0.0:0            0.0.0.0:389&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
=== POST ===&lt;br /&gt;
When &#039;&#039;&#039;Method External(POST)&#039;&#039;&#039; is selected, the HTTP server will receive a POST request.  The request body (i.e. the &#039;&#039;post data&#039;&#039;) is &#039;&#039;not&#039;&#039; coded as a form-data.  Instead, the arguments are put into the request body exactly as the query string when using GET (e.g. &amp;lt;nowiki&amp;gt;&amp;lt;code&amp;gt;?event=syslog&amp;amp;...&amp;lt;/code&amp;gt;&amp;lt;/nowiki&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CDRs ==&lt;br /&gt;
&lt;br /&gt;
== Alarms/Events ==&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_Agenda&amp;diff=76558</id>
		<title>Courseware:IT Advanced - Agenda</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_Agenda&amp;diff=76558"/>
		<updated>2025-05-05T19:20:22Z</updated>

		<summary type="html">&lt;p&gt;Ckl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Agenda | 151}}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_11_How_to_setup_the_Application_Platform_after_a_factory_reset&amp;diff=76493</id>
		<title>Courseware:IT Advanced - 11 How to setup the Application Platform after a factory reset</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_11_How_to_setup_the_Application_Platform_after_a_factory_reset&amp;diff=76493"/>
		<updated>2025-04-30T09:18:00Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Courseware:IT Advanced - 11 How to setup the Application Platform after a factory reset&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | How to setup the Application Platform after a factory reset | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_11_How_to_setup_the_Application_Platform_after_a_factory_reset&amp;diff=76492</id>
		<title>Courseware:IT Advanced - 11 How to setup the Application Platform after a factory reset</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_11_How_to_setup_the_Application_Platform_after_a_factory_reset&amp;diff=76492"/>
		<updated>2025-04-30T09:17:51Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V15 Templates / Advanced | How to setup the Application Platform after a factory reset | 151 }} {{PAGENAME}}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | How to setup the Application Platform after a factory reset | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_10_Password_relations&amp;diff=76491</id>
		<title>Courseware:IT Advanced - 10 Password relations</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_10_Password_relations&amp;diff=76491"/>
		<updated>2025-04-30T08:48:14Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Courseware:IT Advanced - 10 Password relations&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Password relations | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_10_Password_relations&amp;diff=76490</id>
		<title>Courseware:IT Advanced - 10 Password relations</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_10_Password_relations&amp;diff=76490"/>
		<updated>2025-04-30T08:47:52Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V15 Templates / Advanced | Password relations | 151 }} {{PAGENAME}}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Password relations | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_09_Custom_certificates&amp;diff=76489</id>
		<title>Courseware:IT Advanced - 09 Custom certificates</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_09_Custom_certificates&amp;diff=76489"/>
		<updated>2025-04-30T08:22:56Z</updated>

		<summary type="html">&lt;p&gt;Ckl: updated to 15r1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Custom certificates | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_08_Using_a_custom_DNS_on_your_mobile_phone&amp;diff=76488</id>
		<title>Courseware:IT Advanced - 08 Using a custom DNS on your mobile phone</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_08_Using_a_custom_DNS_on_your_mobile_phone&amp;diff=76488"/>
		<updated>2025-04-30T08:22:03Z</updated>

		<summary type="html">&lt;p&gt;Ckl: updated to 15r1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Using a custom DNS on your mobile phone | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_07_Public_access_to_PBX_resources_(practice)&amp;diff=76487</id>
		<title>Courseware:IT Advanced - 07 Public access to PBX resources (practice)</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_07_Public_access_to_PBX_resources_(practice)&amp;diff=76487"/>
		<updated>2025-04-30T08:21:30Z</updated>

		<summary type="html">&lt;p&gt;Ckl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Public access to PBX resources (practice)| 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_06_Public_Access_to_PBX_Resources_(theory)_-_optional&amp;diff=76486</id>
		<title>Courseware:IT Advanced - 06 Public Access to PBX Resources (theory) - optional</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_06_Public_Access_to_PBX_Resources_(theory)_-_optional&amp;diff=76486"/>
		<updated>2025-04-30T08:20:36Z</updated>

		<summary type="html">&lt;p&gt;Ckl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Public Access to PBX Resources (theory) - optional | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_05_Setting_up_the_Apps&amp;diff=76485</id>
		<title>Courseware:IT Advanced - 05 Setting up the Apps</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_05_Setting_up_the_Apps&amp;diff=76485"/>
		<updated>2025-04-30T08:20:03Z</updated>

		<summary type="html">&lt;p&gt;Ckl: updated to 15r1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Setting up the Apps | 151 }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_04_Setting_up_the_Application_Platform&amp;diff=76484</id>
		<title>Courseware:IT Advanced - 04 Setting up the Application Platform</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_04_Setting_up_the_Application_Platform&amp;diff=76484"/>
		<updated>2025-04-30T08:19:26Z</updated>

		<summary type="html">&lt;p&gt;Ckl: updated to 15r1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | Setting up the Application Platform | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_03_The_Application_Platform&amp;diff=76483</id>
		<title>Courseware:IT Advanced - 03 The Application Platform</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_03_The_Application_Platform&amp;diff=76483"/>
		<updated>2025-04-30T08:18:18Z</updated>

		<summary type="html">&lt;p&gt;Ckl: updated to 15r1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | The Application Platform | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_01_innovaphone_overall_Product_Design&amp;diff=76482</id>
		<title>Courseware:IT Advanced - 01 innovaphone overall Product Design</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_01_innovaphone_overall_Product_Design&amp;diff=76482"/>
		<updated>2025-04-30T08:17:11Z</updated>

		<summary type="html">&lt;p&gt;Ckl: updated to 15r1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | innovaphone overall Product Design | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_02_PBX_-_initial_Configuration&amp;diff=76481</id>
		<title>Courseware:IT Advanced - 02 PBX - initial Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_02_PBX_-_initial_Configuration&amp;diff=76481"/>
		<updated>2025-04-30T08:16:25Z</updated>

		<summary type="html">&lt;p&gt;Ckl: updated to 15r1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V15 Templates / Advanced | PBX - initial Configuration | 151 }}&lt;br /&gt;
[[Category:IT_Advanced|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference13r3:IP4/NAT/General&amp;diff=76476</id>
		<title>Reference13r3:IP4/NAT/General</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference13r3:IP4/NAT/General&amp;diff=76476"/>
		<updated>2025-04-29T07:58:42Z</updated>

		<summary type="html">&lt;p&gt;Ckl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
If the device is used as a router, it is able to connect IP terminals from the network with a non-public address to the public Internet. For this, &#039;&#039;&#039;NAT&#039;&#039;&#039; (Network Address Translation) is necessary. Additional configuration is required on the different IP interfaces (e.g. ETH, PPP, etc.) to define on which interfaces the public and on which interfaces the private network is accessed.&lt;br /&gt;
&lt;br /&gt;
;Enable NAT: If this checkmark is set, NAT is enabled. Without this checkmark being set all other NAT settings are without effect.&lt;br /&gt;
&lt;br /&gt;
;Default forward destination: If all incoming data packets from the public network are to be forwarded to a particular private IP address, the destination IP address must be entered here.&lt;br /&gt;
&lt;br /&gt;
;Disable DNS Forwarding: No DNS requests are answered by this host, if this option is enabled.&lt;br /&gt;
&lt;br /&gt;
===Add new map===&lt;br /&gt;
;Port-specific forwarding: To be able to address several internal destinations, different port numbers are assigned to IP addresses of the internal network here.&lt;br /&gt;
&lt;br /&gt;
===STUN/TURN server===&lt;br /&gt;
;Enable STUN: If this checkmark is set, a STUN server is started on the box. The STUN server works like a regular STUN server from external. From internal binding requests create a NAT mapping and the binding response contains the public address of the mapping.&lt;br /&gt;
&lt;br /&gt;
;Non standard port: The port that shall be used for the STUN server. If empty the well known port 3478 is used.&lt;br /&gt;
&lt;br /&gt;
;STUN Changed Address: If the &#039;&#039;Enable STUN&#039;&#039; checkmark is ticked, an IP address:port must be configured, which will be used as source address for replies, when the client is asking for a &#039;&#039;changed address&#039;&#039;. This is used for the classic STUN NAT detection mechanism. Basically any address/port can be used here. It could be that a IP provider does not forward packets with a wrong address, so it is safer to use an address, which is valid in the network of the device. It is also better to use an address, which is not used for something else, because it could be that the local router uses these packets to update its ARP table.  You can use 3480 as port.   Note that NAT detection will not work properly if no &#039;&#039;STUN Changed Address&#039;&#039; is configured&lt;br /&gt;
&lt;br /&gt;
;TURN: Up to four TURN accounts can be configured. If a TURN account is configured a TURN server is enabled for this account.&lt;br /&gt;
&lt;br /&gt;
;TURN Public Address: A TURN server can be operated in a private network behind a firewall. In this case port forwarding must be configured on the firewall for the complete RTP port range to the TURN server. On the TURN server the used public address of the firewall has to be configured, so that this can be provided to the remote RTP peer to send the RTP data to.&lt;br /&gt;
&lt;br /&gt;
;Cluster: TURN servers can be operated in a cluster behind a single firewall. Each TURN server within the cluster should be assigned a separate RTP port range. On the firewall port forwarding to the different TURN servers has to be forwarded for the RTP port ranges. To distribute the incoming requests standard TCP or UDP load balancing to the different TURN servers has to be configured.&lt;br /&gt;
:If in this setup the other RTP peer use the same TURN cluster, the RTP is forwarded between the two session using the public firewall address, this requires the firewall to support hairpinning. To avoid this, on each TURN server all the TURN servers of the cluster can be configured, with their RTP port ranges (first, last) and their local (internal) addresses. If the RTP peer is identified as belonging to the same cluster, the local address is then used for the RTP.&lt;br /&gt;
&lt;br /&gt;
== Known Issues ==&lt;br /&gt;
&lt;br /&gt;
Note: In v12r1 and higher version it&#039;s no longer necessary to enable NAT for the STUN/TURN services be enabled. If NAT is disabled make sure the UDP-NAT port range values are also deleted / not set.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
&lt;br /&gt;
* [[Howto:How to configure NAT in V6]]&lt;br /&gt;
* [[Howto:Avoid DNS Amplification Attacks]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference15r1:Services/Reverse-Proxy&amp;diff=76442</id>
		<title>Reference15r1:Services/Reverse-Proxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference15r1:Services/Reverse-Proxy&amp;diff=76442"/>
		<updated>2025-04-17T07:00:01Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* SMTP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|Reverse Proxy]]&lt;br /&gt;
[[Category:Concept Reverse Proxy]]&lt;br /&gt;
The reverse proxy is used to forward H.323, SIP, LDAP, HTTP and SMTP requests it receives to other hosts, based on system information like gatekeeper name host name, path or domain.&lt;br /&gt;
This way it can be controlled which services may be accessed thru the reverse proxy.&lt;br /&gt;
A reverse proxy may be located at the boundary of an private and a public network, or inside the private network, if the respective ports are forwarded to it by the NAT Router/Firewall.&lt;br /&gt;
It can be even configured on the same device as the PBX itself. In this case the other services on the device should use non-standard ports, so that the reverse proxy can receive the requests on the standard port and forward them locally to the non-standard ports.&lt;br /&gt;
&lt;br /&gt;
== General Parameters ==&lt;br /&gt;
&lt;br /&gt;
;No IPv4: Turn off IPv4 for the reverse proxy function&lt;br /&gt;
;No IPv6: Turn off IPv6 for the reverse proxy function&lt;br /&gt;
;H.323/TCP, H.323/TLS: Ports for incoming H.323 TCP or TLS Connections. Use 1720 and 1300 for the standard ports.&lt;br /&gt;
;SIP/TCP, SIP/TLS: Ports for incoming SIP TCP or TLS Connections. Use 5060 and 5061 for the standard ports.&lt;br /&gt;
;LDAP, LDAPs: Ports for incoming LDAP TCP or TLS Connections. Use 389 and 636 for the Standard ports.&lt;br /&gt;
;HTTP, HTTPS:  Ports for incoming HTTP TCP or TLS Connections. Use 80 and 443 for the Standard ports.&lt;br /&gt;
;SMTP, SMTPS: Ports for incoming SMTP TCP or TLS Connections. Use 25 and 587 for the Standard ports.&lt;br /&gt;
;Log Forwarded Requests: activate protocol dependent logging for successfully forwarded / accepted requests&lt;br /&gt;
;Log Rejected Requests: activate protocol dependent logging for rejected / non-accepted requests&lt;br /&gt;
;Blacklist Expiration: Time in minutes after which an entry put in the blacklist automatically, will be removed from the blacklist.&lt;br /&gt;
;Suspicious Requests/min: Threshold to put an address into the blacklist&lt;br /&gt;
;Public NAT router address: Required for SIP if RP is behind NAT. External SIP clients will receive this value in Route header of SIP messages. You can configure DNS name or IP address and port here.&amp;lt;br&amp;gt;If not configured, RP writes it&#039;s own local IP address and port into Route header of SIP messages. This works only if RP has a public local IP address.&lt;br /&gt;
&lt;br /&gt;
== Hosts ==&lt;br /&gt;
&lt;br /&gt;
List of configured hosts. Click on the host Name to edit or delete. Use new to add new host&lt;br /&gt;
&lt;br /&gt;
;Out&lt;br /&gt;
:Destination IP-Address (IPv4 or IPv6) for this rule, following by the plain text port&lt;br /&gt;
:Destination DNS name: must start with &#039;&#039;&#039;@&#039;&#039;&#039; and is limited to 15 chars. For longer names, you can use a DNS suffix (see below).&lt;br /&gt;
;TLS&lt;br /&gt;
:Port for encrypted traffic&lt;br /&gt;
;Check Certificate&lt;br /&gt;
:If the Check Certificate checkmark is set, for the internal connection TLS is used only if the received certificate matches the user name within the protocol. This way a host receiving a request through the Reverse Proxy using TLS can assume that the connection was authenticated using a valid certificate, which matches the user.&lt;br /&gt;
;App Login&lt;br /&gt;
:Experimental feature to allow access only if a myPBX session has been previously authenticated. Not supported for myApps.&lt;br /&gt;
;Default&lt;br /&gt;
:This rule will be used if only the Domain without a path or file in the URI was requested.  The empty path is then replaced by the specified URL when the request is forwarded (e.g. an entry &#039;&#039;&amp;lt;nowiki&amp;gt;http://&amp;lt;/nowiki&amp;gt;&amp;lt;host&amp;gt;/web/index.htm&#039;&#039; with the &#039;&#039;Default&#039;&#039; check-mark ticked will match requests with no path and the request is forwarded with the path set to &#039;&#039;/web/index.htm&#039;&#039;). Note that also, an implicit rule is created that forwards all requests for files in and beneath the folder where the default document is in (in the example rule, requests to all files under &#039;&#039;&amp;lt;nowiki&amp;gt;http://&amp;lt;/nowiki&amp;gt;&amp;lt;host&amp;gt;/web&#039;&#039; will be forwarded)&lt;br /&gt;
;MTLS:&lt;br /&gt;
:Request MTLS on incoming connections. The requesting client has to provide the TLS Server Name on the incoming TLS connection. The Server Name is used to match to the host. If the checkmark is set, MTLS is requested then. If no Server Name is provided or no valid client certificate a connection for this host is rejected. The name od the received and validated certificate is forwarded as X-Remote-Cert HTTP header.&lt;br /&gt;
;Network&lt;br /&gt;
:&#039;&#039;adddr:network&#039;&#039; to restrict a configured protocol to certain networks&lt;br /&gt;
&lt;br /&gt;
=== SMTP ===&lt;br /&gt;
The host is searched for using different criteria based on the incoming socket.&lt;br /&gt;
&lt;br /&gt;
The criteria are searched in the order given and the first match wins.&lt;br /&gt;
&lt;br /&gt;
;TLS: the SNI of the TLS handshake&lt;br /&gt;
;EHLO: the client hostname send inside the client EHLO SMTP protocol message&lt;br /&gt;
;AUTH: the username of an AUTH PLAIN login. The whole username is matched and if no match is found, the domain part after an @ sign if present.&lt;br /&gt;
;RCPT-TO: the recipient mail address. The whole mail address is matched and if no match is found, the domain part.&lt;br /&gt;
&lt;br /&gt;
==== STARTTLS ====&lt;br /&gt;
&lt;br /&gt;
* If the EHLO message is already suitable to detect the host, STARTTLS is handled by the server behind the RP and port forwarding must be done to the non TLS port in this case.&lt;br /&gt;
* Otherwise the RP itself handles the STARTTLS handshake. It then doesn&#039;t matter if you internally forward to the non TLS port or the TLS port but STARTTLS won&#039;t be done anymore in any case.&lt;br /&gt;
&lt;br /&gt;
== DNS Suffixes ==&lt;br /&gt;
&lt;br /&gt;
If you want to forward requests to internal DNS names instead of IP addresses and such an internal DNS name is longer than 15 chars, you must use DNS suffixes to reference it.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Id: a unique id which is used as reference&lt;br /&gt;
;Suffix: a suffix which is used as replacement of #Id&lt;br /&gt;
&lt;br /&gt;
If you want to use such a suffix inside &#039;&#039;&#039;Out&#039;&#039;&#039; of a host, you must write it like this: &lt;br /&gt;
&#039;&#039;&#039;@host1.#1&#039;&#039;&#039; -&amp;gt; this will be expanded to &#039;&#039;&#039;host1.example.com&#039;&#039;&#039;, if the suffix with Id 1 has the value example.com&lt;br /&gt;
&lt;br /&gt;
== Counter ==&lt;br /&gt;
&lt;br /&gt;
Current top ten address with suspicious requests&lt;br /&gt;
&lt;br /&gt;
== Addresses ==&lt;br /&gt;
&lt;br /&gt;
Blacklist/Whitelist addresses&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73924</id>
		<title>Reference14r1:Concept Let&#039;s Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73924"/>
		<updated>2024-11-07T21:54:46Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Reverse-Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|Let%27s%20Encrypt]]&lt;br /&gt;
&lt;br /&gt;
Certificates are automatically generated for innovaphone gateways and App Platforms.&lt;br /&gt;
&lt;br /&gt;
== Applies to ==&lt;br /&gt;
* innovaphone gateways from version 14r1&lt;br /&gt;
* innovaphone App Platform with version 14r1 apps (image version 110036 or higher)&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
* Each configured innovaphone client requests a new certificate &#039;&#039;&#039;30&#039;&#039;&#039; days before it&#039;s current certificate expires.&lt;br /&gt;
* Therefor an app websocket connection is opened to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The client sends a certificate signing request to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The Connector for Let&#039;s Encrypt App Service itself communitates via HTTPs and [https://en.wikipedia.org/wiki/JSON_Web_Token JWT] with Let&#039;s Encrypt to request a new certificate.&lt;br /&gt;
* Let&#039;s Encrypt triggers an HTTP challenge for every DNS entry where the token for the DNS entry is verified. (The Token is saved in the Let&#039;s Encrypt App Service)&lt;br /&gt;
** the HTTP challenge always works &#039;&#039;&#039;without&#039;&#039;&#039; HTTPS on Port 80 on a subpath of &#039;&#039;&#039;/.well-known/acme-challenge/&#039;&#039;&#039;, e.g. http://mydns.com/.well-known/acme-challenge/1290378712893z12983&lt;br /&gt;
* After successfull HTTP challenges for every DNS name, the new certificate is send back to the client.&lt;br /&gt;
* The certificate is installed X days before the old certificate expires, while X can be configured in the PBX Manager Plugin.&lt;br /&gt;
&lt;br /&gt;
=== Flow without Reverse Proxy ===&lt;br /&gt;
&lt;br /&gt;
[[Image:letsencrypt-flow.png]]&lt;br /&gt;
&lt;br /&gt;
=== Flow with Reverse Proxy ===&lt;br /&gt;
[[Image:letsencrypt-flow-rp.png]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== ACMEv2 compliant certification service ===&lt;br /&gt;
&lt;br /&gt;
Our Connector for Let&#039;s Encrypt App Service uses the ACMEv2 protocol. So in general every ACMEv2 compliant service could be used.&amp;lt;br/&amp;gt;&lt;br /&gt;
Officially tested is Let&#039;s Encrypt itself with this URL: https://acme-v02.api.letsencrypt.org&lt;br /&gt;
&lt;br /&gt;
=== Gateways and App Platform ===&lt;br /&gt;
* Firmware from version 14r1 or later&lt;br /&gt;
* innovaphone App Platform with App Platform Manager version 14r1 or higher and image version 110036 or higher&lt;br /&gt;
* innovaphone App Connector for Let&#039;s Encrypt version 14r1 or higher&lt;br /&gt;
* working DNS configuration&lt;br /&gt;
&lt;br /&gt;
=== Reverse-Proxy ===&lt;br /&gt;
&lt;br /&gt;
* Let&#039;s encrypt will send the certificate challenge using HTTP on port 80.  On your WAN interface (that is, the interface your DNS name points to), port 80 must be available therefore. Traffic must be forwarded to either the device itself or to a reverse proxy that forwards the certificate challenge to the device. &lt;br /&gt;
* On the reverse proxy there must be a rule for the host that corresponds to the DNS name of your AP where the Let&#039;s Encrypt App runs on that forwards HTTP path &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; to the Let&#039;s Encrypt App. Of course, an empty rule (such as the one that the reverse proxy PBX Manager plugin creates) will do.&lt;br /&gt;
* For 3rd-party devices behind the Reverse-Proxy which intend to obtain a certificate from Let&#039;s Encrypt (using their own client mechanism), a similar rule must be present that forwards the challenge to the 3rd-party device.&lt;br /&gt;
:: For innovaphone devices, such rules are not necessary (except for the AP as outlined above).&lt;br /&gt;
* The App Platform must be able to communicate with the Let&#039;s Encrypt URLs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conclusion&#039;&#039;&#039;: the recommended steps for obtaining certificates are as follows:&lt;br /&gt;
* configure the rule that forwards the challenge for your AP DNS name to the AP (&#039;&#039;your-ap.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;)&lt;br /&gt;
* configure the Connector for Let&#039;s Encrypt App on your AP&lt;br /&gt;
* configure the Let&#039;s Encrypt client on your AP&lt;br /&gt;
* configure rules for all 3rd party devices behind the RP that forward the challenge for the respective 3rd-party device&#039;s DNS names to the these devices (&#039;&#039;your-3rd-party-device.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;). This step is optional&lt;br /&gt;
&lt;br /&gt;
==Security Consideration==&lt;br /&gt;
We do not recommend that a device can be reached directly from the Internet on port 80. Please use the reverse proxy variant described above.&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
* You can configure up to &#039;&#039;&#039;100&#039;&#039;&#039; DNS entries for a single device. More DNS entries are not supported by Let&#039;s Encrypt.&amp;lt;br/&amp;gt;&lt;br /&gt;
* You cannot configure DNS entries with wildcards. Such wildcard entries require the so called DNS challenge mechanism which is not supported by our Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Connector for Let&#039;s Encrypt PBX Manager Plugin ===&lt;br /&gt;
Configure the [[Reference14r1:Concept_App_Service_Let%27s_Encrypt#Let.27s_Encypt_Config | PBX Manager Plugin]] of the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone Gateways ===&lt;br /&gt;
Configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] on every gateway which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone App Platform ===&lt;br /&gt;
Configure Let&#039;s Encrypt in the settings of the App Platform Manager on every App Platform which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== RP ===&lt;br /&gt;
If your gateways and/or App Platforms are behind an innovaphone reverse proxy, you must configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] here too.&amp;lt;br/&amp;gt;&lt;br /&gt;
You must configure all DNS names which are used by the individual devices behind the RP.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The RP will request a certificate with multiple SAN entries while every individual device will request an own certificate with a single SAN entry (or still multiple if a single device shall have multiple DNS entries).&lt;br /&gt;
&lt;br /&gt;
=== Devices certificate configuration ===&lt;br /&gt;
If you want to rollout the Let&#039;s Encrypt root certificates to your devices, configure the URL for Let&#039;s Encrypt root certificates in a certificates configuration (App Devices -&amp;gt; Domains -&amp;gt; your domain -&amp;gt; Device Configurations) which will then ensure that always the latest root certificates are available in the trust list of your devices.&amp;lt;br/&amp;gt;&lt;br /&gt;
You can find this URL in the [[Reference14r1:Apps/PbxManager/App_Connector_for_Let&#039;s_Encrypt | PBX Manager Plugin]].&lt;br /&gt;
&lt;br /&gt;
== Tracing and logging ==&lt;br /&gt;
=== Gateways ===&lt;br /&gt;
The following trace flags can be activated at [[{{NAMESPACE}}:Maintenance/Diagnostics/Tracing | Maintenance/Diagnostics/Tracing]].&lt;br /&gt;
&lt;br /&gt;
;Let&#039;s Encrypt&lt;br /&gt;
: communication between gateway and the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
: processing of incoming id_tokens&lt;br /&gt;
&lt;br /&gt;
;HTTP Client&lt;br /&gt;
: the HTTPS communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
=== App Platform ===&lt;br /&gt;
&lt;br /&gt;
Enable these trace flags for diagnostics:&lt;br /&gt;
&lt;br /&gt;
==== App Platform Manager ====&lt;br /&gt;
;App&lt;br /&gt;
: requests of new certificates&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
;Websocket Client&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
==== Connector for Let&#039;s Encrypt App Service ====&lt;br /&gt;
;App&lt;br /&gt;
: app logs&lt;br /&gt;
;HttpClient&lt;br /&gt;
: communication with Let&#039;s Encrypt itself&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the clients&lt;br /&gt;
&lt;br /&gt;
== Alarms and Events ==&lt;br /&gt;
* an event is generated for every failed certificate creation by the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
* an alarm is generated on the corresponding device as long as the certificate creation fails&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
&lt;br /&gt;
=== Not working TLS connection between a reverse proxy/gateway and the app platform with the Connector for Let&#039;s Encrypt ===&lt;br /&gt;
If a gateway/reverse proxy cannot establish a TLS connection to the app platform where the Connector for Let&#039;s Encrypt is running, no new certificate can be created anymore.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As a workaround, you can temporarily switch to a non TLS connection under Services -&amp;gt; Let&#039;s Encrypt &#039;&#039;&#039;Let&#039;s Encrypt App URL&#039;&#039;&#039; by using &#039;&#039;&#039;ws&#039;&#039;&#039; instead of &#039;&#039;&#039;wss&#039;&#039;&#039;.&amp;lt;br/&amp;gt;&lt;br /&gt;
If all your systems have a valid TLS certificate again, don&#039;t forget to switch back to &#039;&#039;&#039;wss&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
==Known Issue==&lt;br /&gt;
===Geoblocking can prevent confirmation===&lt;br /&gt;
To verify the correctness of DNS entries and HTTP Challenge, Let&#039;s Encrypt sends DNS/HTTP requests from multiple locations around the world. All of these requests must be successfully answered. If a request is not answered due to geoblocking, Let&#039;s Encrypt does not trust the issuer.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference14r1:Services/Letsencrypt]]&lt;br /&gt;
* [[Reference14r1:Concept_App_Service_Connector_for_Let%27s_Encrypt]]&lt;br /&gt;
* [[Reference14r1:Apps/PbxManager/App_Connector_for_Let%27s_Encrypt]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73915</id>
		<title>Reference14r1:Concept Let&#039;s Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73915"/>
		<updated>2024-11-06T14:39:21Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Reverse-Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|Let%27s%20Encrypt]]&lt;br /&gt;
&lt;br /&gt;
Certificates are automatically generated for innovaphone gateways and App Platforms.&lt;br /&gt;
&lt;br /&gt;
== Applies to ==&lt;br /&gt;
* innovaphone gateways from version 14r1&lt;br /&gt;
* innovaphone App Platform with version 14r1 apps (image version 110036 or higher)&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
* Each configured innovaphone client requests a new certificate &#039;&#039;&#039;30&#039;&#039;&#039; days before it&#039;s current certificate expires.&lt;br /&gt;
* Therefor an app websocket connection is opened to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The client sends a certificate signing request to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The Connector for Let&#039;s Encrypt App Service itself communitates via HTTPs and [https://en.wikipedia.org/wiki/JSON_Web_Token JWT] with Let&#039;s Encrypt to request a new certificate.&lt;br /&gt;
* Let&#039;s Encrypt triggers an HTTP challenge for every DNS entry where the token for the DNS entry is verified. (The Token is saved in the Let&#039;s Encrypt App Service)&lt;br /&gt;
** the HTTP challenge always works &#039;&#039;&#039;without&#039;&#039;&#039; HTTPS on Port 80 on a subpath of &#039;&#039;&#039;/.well-known/acme-challenge/&#039;&#039;&#039;, e.g. http://mydns.com/.well-known/acme-challenge/1290378712893z12983&lt;br /&gt;
* After successfull HTTP challenges for every DNS name, the new certificate is send back to the client.&lt;br /&gt;
* The certificate is installed X days before the old certificate expires, while X can be configured in the PBX Manager Plugin.&lt;br /&gt;
&lt;br /&gt;
=== Flow without Reverse Proxy ===&lt;br /&gt;
&lt;br /&gt;
[[Image:letsencrypt-flow.png]]&lt;br /&gt;
&lt;br /&gt;
=== Flow with Reverse Proxy ===&lt;br /&gt;
[[Image:letsencrypt-flow-rp.png]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== ACMEv2 compliant certification service ===&lt;br /&gt;
&lt;br /&gt;
Our Connector for Let&#039;s Encrypt App Service uses the ACMEv2 protocol. So in general every ACMEv2 compliant service could be used.&amp;lt;br/&amp;gt;&lt;br /&gt;
Officially tested is Let&#039;s Encrypt itself with this URL: https://acme-v02.api.letsencrypt.org&lt;br /&gt;
&lt;br /&gt;
=== Gateways and App Platform ===&lt;br /&gt;
* Firmware from version 14r1 or later&lt;br /&gt;
* innovaphone App Platform with App Platform Manager version 14r1 or higher and image version 110036 or higher&lt;br /&gt;
* innovaphone App Connector for Let&#039;s Encrypt version 14r1 or higher&lt;br /&gt;
* working DNS configuration&lt;br /&gt;
&lt;br /&gt;
=== Reverse-Proxy ===&lt;br /&gt;
&lt;br /&gt;
* Let&#039;s encrypt will send the certificate challenge using HTTP on port 80.  On your WAN interface (that is, the interface your DNS name points to), port 80 must be available therefore. Traffic must be forwarded to either the device itself or to a reverse proxy that forwards the certificate challenge to the device. &lt;br /&gt;
* On the reverse proxy there must be a rule for the host that corresponds to the DNS name of your AP where the Let&#039;s Encrypt App runs on that forwards HTTP path &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; to the Let&#039;s Encrypt App. &lt;br /&gt;
* For 3rd-party devices behind the Reverse-Proxy which intend to obtain a certificate from Let&#039;s Encrypt (using their own client mechanism), a similar rule must be present that forwards the challenge to the 3rd-party device.&lt;br /&gt;
:: For innovaphone devices, such rules are not necessary (except for the AP as outlined above).&lt;br /&gt;
* The App Platform must be able to communicate with the Let&#039;s Encrypt URLs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Conclusion&#039;&#039;&#039;: the recommended steps for obtaining certificates are as follows:&lt;br /&gt;
* configure the rule that forwards the challenge for your AP DNS name to the AP (&#039;&#039;your-ap.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;)&lt;br /&gt;
* configure the Connector for Let&#039;s Encrypt App on your AP&lt;br /&gt;
* configure the Let&#039;s Encrypt client on your AP&lt;br /&gt;
* configure rules for all 3rd party devices behind the RP that forward the challenge for the respective 3rd-party device&#039;s DNS names to the these devices (&#039;&#039;your-3rd-party-device.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;). This step is optional&lt;br /&gt;
&lt;br /&gt;
==Security Consideration==&lt;br /&gt;
We do not recommend that a device can be reached directly from the Internet on port 80. Please use the reverse proxy variant described above.&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
* You can configure up to &#039;&#039;&#039;100&#039;&#039;&#039; DNS entries for a single device. More DNS entries are not supported by Let&#039;s Encrypt.&amp;lt;br/&amp;gt;&lt;br /&gt;
* You cannot configure DNS entries with wildcards. Such wildcard entries require the so called DNS challenge mechanism which is not supported by our Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Connector for Let&#039;s Encrypt PBX Manager Plugin ===&lt;br /&gt;
Configure the [[Reference14r1:Concept_App_Service_Let%27s_Encrypt#Let.27s_Encypt_Config | PBX Manager Plugin]] of the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone Gateways ===&lt;br /&gt;
Configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] on every gateway which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone App Platform ===&lt;br /&gt;
Configure Let&#039;s Encrypt in the settings of the App Platform Manager on every App Platform which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== RP ===&lt;br /&gt;
If your gateways and/or App Platforms are behind an innovaphone reverse proxy, you must configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] here too.&amp;lt;br/&amp;gt;&lt;br /&gt;
You must configure all DNS names which are used by the individual devices behind the RP.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The RP will request a certificate with multiple SAN entries while every individual device will request an own certificate with a single SAN entry (or still multiple if a single device shall have multiple DNS entries).&lt;br /&gt;
&lt;br /&gt;
=== Devices certificate configuration ===&lt;br /&gt;
If you want to rollout the Let&#039;s Encrypt root certificates to your devices, configure the URL for Let&#039;s Encrypt root certificates in a certificates configuration (App Devices -&amp;gt; Domains -&amp;gt; your domain -&amp;gt; Device Configurations) which will then ensure that always the latest root certificates are available in the trust list of your devices.&amp;lt;br/&amp;gt;&lt;br /&gt;
You can find this URL in the [[Reference14r1:Apps/PbxManager/App_Connector_for_Let&#039;s_Encrypt | PBX Manager Plugin]].&lt;br /&gt;
&lt;br /&gt;
== Tracing and logging ==&lt;br /&gt;
=== Gateways ===&lt;br /&gt;
The following trace flags can be activated at [[{{NAMESPACE}}:Maintenance/Diagnostics/Tracing | Maintenance/Diagnostics/Tracing]].&lt;br /&gt;
&lt;br /&gt;
;Let&#039;s Encrypt&lt;br /&gt;
: communication between gateway and the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
: processing of incoming id_tokens&lt;br /&gt;
&lt;br /&gt;
;HTTP Client&lt;br /&gt;
: the HTTPS communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
=== App Platform ===&lt;br /&gt;
&lt;br /&gt;
Enable these trace flags for diagnostics:&lt;br /&gt;
&lt;br /&gt;
==== App Platform Manager ====&lt;br /&gt;
;App&lt;br /&gt;
: requests of new certificates&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
;Websocket Client&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
==== Connector for Let&#039;s Encrypt App Service ====&lt;br /&gt;
;App&lt;br /&gt;
: app logs&lt;br /&gt;
;HttpClient&lt;br /&gt;
: communication with Let&#039;s Encrypt itself&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the clients&lt;br /&gt;
&lt;br /&gt;
== Alarms and Events ==&lt;br /&gt;
* an event is generated for every failed certificate creation by the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
* an alarm is generated on the corresponding device as long as the certificate creation fails&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
&lt;br /&gt;
=== Not working TLS connection between a reverse proxy/gateway and the app platform with the Connector for Let&#039;s Encrypt ===&lt;br /&gt;
If a gateway/reverse proxy cannot establish a TLS connection to the app platform where the Connector for Let&#039;s Encrypt is running, no new certificate can be created anymore.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As a workaround, you can temporarily switch to a non TLS connection under Services -&amp;gt; Let&#039;s Encrypt &#039;&#039;&#039;Let&#039;s Encrypt App URL&#039;&#039;&#039; by using &#039;&#039;&#039;ws&#039;&#039;&#039; instead of &#039;&#039;&#039;wss&#039;&#039;&#039;.&amp;lt;br/&amp;gt;&lt;br /&gt;
If all your systems have a valid TLS certificate again, don&#039;t forget to switch back to &#039;&#039;&#039;wss&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
==Known Issue==&lt;br /&gt;
===Geoblocking can prevent confirmation===&lt;br /&gt;
To verify the correctness of DNS entries and HTTP Challenge, Let&#039;s Encrypt sends DNS/HTTP requests from multiple locations around the world. All of these requests must be successfully answered. If a request is not answered due to geoblocking, Let&#039;s Encrypt does not trust the issuer.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference14r1:Services/Letsencrypt]]&lt;br /&gt;
* [[Reference14r1:Concept_App_Service_Connector_for_Let%27s_Encrypt]]&lt;br /&gt;
* [[Reference14r1:Apps/PbxManager/App_Connector_for_Let%27s_Encrypt]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73914</id>
		<title>Reference14r1:Concept Let&#039;s Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73914"/>
		<updated>2024-11-06T14:34:55Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Reverse-Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|Let%27s%20Encrypt]]&lt;br /&gt;
&lt;br /&gt;
Certificates are automatically generated for innovaphone gateways and App Platforms.&lt;br /&gt;
&lt;br /&gt;
== Applies to ==&lt;br /&gt;
* innovaphone gateways from version 14r1&lt;br /&gt;
* innovaphone App Platform with version 14r1 apps (image version 110036 or higher)&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
* Each configured innovaphone client requests a new certificate &#039;&#039;&#039;30&#039;&#039;&#039; days before it&#039;s current certificate expires.&lt;br /&gt;
* Therefor an app websocket connection is opened to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The client sends a certificate signing request to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The Connector for Let&#039;s Encrypt App Service itself communitates via HTTPs and [https://en.wikipedia.org/wiki/JSON_Web_Token JWT] with Let&#039;s Encrypt to request a new certificate.&lt;br /&gt;
* Let&#039;s Encrypt triggers an HTTP challenge for every DNS entry where the token for the DNS entry is verified. (The Token is saved in the Let&#039;s Encrypt App Service)&lt;br /&gt;
** the HTTP challenge always works &#039;&#039;&#039;without&#039;&#039;&#039; HTTPS on Port 80 on a subpath of &#039;&#039;&#039;/.well-known/acme-challenge/&#039;&#039;&#039;, e.g. http://mydns.com/.well-known/acme-challenge/1290378712893z12983&lt;br /&gt;
* After successfull HTTP challenges for every DNS name, the new certificate is send back to the client.&lt;br /&gt;
* The certificate is installed X days before the old certificate expires, while X can be configured in the PBX Manager Plugin.&lt;br /&gt;
&lt;br /&gt;
=== Flow without Reverse Proxy ===&lt;br /&gt;
&lt;br /&gt;
[[Image:letsencrypt-flow.png]]&lt;br /&gt;
&lt;br /&gt;
=== Flow with Reverse Proxy ===&lt;br /&gt;
[[Image:letsencrypt-flow-rp.png]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== ACMEv2 compliant certification service ===&lt;br /&gt;
&lt;br /&gt;
Our Connector for Let&#039;s Encrypt App Service uses the ACMEv2 protocol. So in general every ACMEv2 compliant service could be used.&amp;lt;br/&amp;gt;&lt;br /&gt;
Officially tested is Let&#039;s Encrypt itself with this URL: https://acme-v02.api.letsencrypt.org&lt;br /&gt;
&lt;br /&gt;
=== Gateways and App Platform ===&lt;br /&gt;
* Firmware from version 14r1 or later&lt;br /&gt;
* innovaphone App Platform with App Platform Manager version 14r1 or higher and image version 110036 or higher&lt;br /&gt;
* innovaphone App Connector for Let&#039;s Encrypt version 14r1 or higher&lt;br /&gt;
* working DNS configuration&lt;br /&gt;
&lt;br /&gt;
=== Reverse-Proxy ===&lt;br /&gt;
&lt;br /&gt;
* Let&#039;s encrypt will send the certificate challenge using HTTP on port 80.  On your WAN interface (that is, the interface your DNS name points to), port 80 must be available therefore. Traffic must be forwarded to either the device itself or to a reverse proxy that forwards the certificate challenge to the device. &lt;br /&gt;
* On the reverse proxy there must be a rule for the host that corresponds to the DNS name of your AP where the Let&#039;s Encrypt App runs on that forwards HTTP path &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; to the Let&#039;s Encrypt App. &lt;br /&gt;
* For 3rd-party devices behind the Reverse-Proxy which intend to obtain a certificate from Let&#039;s Encrypt (using their own client mechanism), a similar rule must be present that forwards the challenge to the 3rd-party device&lt;br /&gt;
: for innovaphone devices, such rules are not necessary (except for the AP as outlined above)&lt;br /&gt;
* The App Platform must be able to communicate with the Let&#039;s Encrypt URLs.&lt;br /&gt;
&lt;br /&gt;
:: Conclusion: the recommended steps for obtaining certificates are as follows&lt;br /&gt;
::* configure the rule that forwards the challenge for your AP DNS name to the AP (&#039;&#039;your-ap.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;)&lt;br /&gt;
::* configure the Connector for Let&#039;s Encrypt App on your AP&lt;br /&gt;
::* configure the Let&#039;s Encrypt client on your AP&lt;br /&gt;
::* configure rules for all 3rd party devices behind the RP that forward the challenge for the respective 3rd-party device&#039;s DNS names to the these devices (&#039;&#039;your-3rd-party-device.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;). This step is optional&lt;br /&gt;
&lt;br /&gt;
==Security Consideration==&lt;br /&gt;
We do not recommend that a device can be reached directly from the Internet on port 80. Please use the reverse proxy variant described above.&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
* You can configure up to &#039;&#039;&#039;100&#039;&#039;&#039; DNS entries for a single device. More DNS entries are not supported by Let&#039;s Encrypt.&amp;lt;br/&amp;gt;&lt;br /&gt;
* You cannot configure DNS entries with wildcards. Such wildcard entries require the so called DNS challenge mechanism which is not supported by our Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Connector for Let&#039;s Encrypt PBX Manager Plugin ===&lt;br /&gt;
Configure the [[Reference14r1:Concept_App_Service_Let%27s_Encrypt#Let.27s_Encypt_Config | PBX Manager Plugin]] of the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone Gateways ===&lt;br /&gt;
Configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] on every gateway which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone App Platform ===&lt;br /&gt;
Configure Let&#039;s Encrypt in the settings of the App Platform Manager on every App Platform which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== RP ===&lt;br /&gt;
If your gateways and/or App Platforms are behind an innovaphone reverse proxy, you must configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] here too.&amp;lt;br/&amp;gt;&lt;br /&gt;
You must configure all DNS names which are used by the individual devices behind the RP.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The RP will request a certificate with multiple SAN entries while every individual device will request an own certificate with a single SAN entry (or still multiple if a single device shall have multiple DNS entries).&lt;br /&gt;
&lt;br /&gt;
=== Devices certificate configuration ===&lt;br /&gt;
If you want to rollout the Let&#039;s Encrypt root certificates to your devices, configure the URL for Let&#039;s Encrypt root certificates in a certificates configuration (App Devices -&amp;gt; Domains -&amp;gt; your domain -&amp;gt; Device Configurations) which will then ensure that always the latest root certificates are available in the trust list of your devices.&amp;lt;br/&amp;gt;&lt;br /&gt;
You can find this URL in the [[Reference14r1:Apps/PbxManager/App_Connector_for_Let&#039;s_Encrypt | PBX Manager Plugin]].&lt;br /&gt;
&lt;br /&gt;
== Tracing and logging ==&lt;br /&gt;
=== Gateways ===&lt;br /&gt;
The following trace flags can be activated at [[{{NAMESPACE}}:Maintenance/Diagnostics/Tracing | Maintenance/Diagnostics/Tracing]].&lt;br /&gt;
&lt;br /&gt;
;Let&#039;s Encrypt&lt;br /&gt;
: communication between gateway and the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
: processing of incoming id_tokens&lt;br /&gt;
&lt;br /&gt;
;HTTP Client&lt;br /&gt;
: the HTTPS communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
=== App Platform ===&lt;br /&gt;
&lt;br /&gt;
Enable these trace flags for diagnostics:&lt;br /&gt;
&lt;br /&gt;
==== App Platform Manager ====&lt;br /&gt;
;App&lt;br /&gt;
: requests of new certificates&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
;Websocket Client&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
==== Connector for Let&#039;s Encrypt App Service ====&lt;br /&gt;
;App&lt;br /&gt;
: app logs&lt;br /&gt;
;HttpClient&lt;br /&gt;
: communication with Let&#039;s Encrypt itself&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the clients&lt;br /&gt;
&lt;br /&gt;
== Alarms and Events ==&lt;br /&gt;
* an event is generated for every failed certificate creation by the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
* an alarm is generated on the corresponding device as long as the certificate creation fails&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
&lt;br /&gt;
=== Not working TLS connection between a reverse proxy/gateway and the app platform with the Connector for Let&#039;s Encrypt ===&lt;br /&gt;
If a gateway/reverse proxy cannot establish a TLS connection to the app platform where the Connector for Let&#039;s Encrypt is running, no new certificate can be created anymore.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As a workaround, you can temporarily switch to a non TLS connection under Services -&amp;gt; Let&#039;s Encrypt &#039;&#039;&#039;Let&#039;s Encrypt App URL&#039;&#039;&#039; by using &#039;&#039;&#039;ws&#039;&#039;&#039; instead of &#039;&#039;&#039;wss&#039;&#039;&#039;.&amp;lt;br/&amp;gt;&lt;br /&gt;
If all your systems have a valid TLS certificate again, don&#039;t forget to switch back to &#039;&#039;&#039;wss&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
==Known Issue==&lt;br /&gt;
===Geoblocking can prevent confirmation===&lt;br /&gt;
To verify the correctness of DNS entries and HTTP Challenge, Let&#039;s Encrypt sends DNS/HTTP requests from multiple locations around the world. All of these requests must be successfully answered. If a request is not answered due to geoblocking, Let&#039;s Encrypt does not trust the issuer.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference14r1:Services/Letsencrypt]]&lt;br /&gt;
* [[Reference14r1:Concept_App_Service_Connector_for_Let%27s_Encrypt]]&lt;br /&gt;
* [[Reference14r1:Apps/PbxManager/App_Connector_for_Let%27s_Encrypt]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73913</id>
		<title>Reference14r1:Concept Let&#039;s Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73913"/>
		<updated>2024-11-06T14:30:50Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Reverse-Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|Let%27s%20Encrypt]]&lt;br /&gt;
&lt;br /&gt;
Certificates are automatically generated for innovaphone gateways and App Platforms.&lt;br /&gt;
&lt;br /&gt;
== Applies to ==&lt;br /&gt;
* innovaphone gateways from version 14r1&lt;br /&gt;
* innovaphone App Platform with version 14r1 apps (image version 110036 or higher)&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
* Each configured innovaphone client requests a new certificate &#039;&#039;&#039;30&#039;&#039;&#039; days before it&#039;s current certificate expires.&lt;br /&gt;
* Therefor an app websocket connection is opened to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The client sends a certificate signing request to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The Connector for Let&#039;s Encrypt App Service itself communitates via HTTPs and [https://en.wikipedia.org/wiki/JSON_Web_Token JWT] with Let&#039;s Encrypt to request a new certificate.&lt;br /&gt;
* Let&#039;s Encrypt triggers an HTTP challenge for every DNS entry where the token for the DNS entry is verified. (The Token is saved in the Let&#039;s Encrypt App Service)&lt;br /&gt;
** the HTTP challenge always works &#039;&#039;&#039;without&#039;&#039;&#039; HTTPS on Port 80 on a subpath of &#039;&#039;&#039;/.well-known/acme-challenge/&#039;&#039;&#039;, e.g. http://mydns.com/.well-known/acme-challenge/1290378712893z12983&lt;br /&gt;
* After successfull HTTP challenges for every DNS name, the new certificate is send back to the client.&lt;br /&gt;
* The certificate is installed X days before the old certificate expires, while X can be configured in the PBX Manager Plugin.&lt;br /&gt;
&lt;br /&gt;
=== Flow without Reverse Proxy ===&lt;br /&gt;
&lt;br /&gt;
[[Image:letsencrypt-flow.png]]&lt;br /&gt;
&lt;br /&gt;
=== Flow with Reverse Proxy ===&lt;br /&gt;
[[Image:letsencrypt-flow-rp.png]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== ACMEv2 compliant certification service ===&lt;br /&gt;
&lt;br /&gt;
Our Connector for Let&#039;s Encrypt App Service uses the ACMEv2 protocol. So in general every ACMEv2 compliant service could be used.&amp;lt;br/&amp;gt;&lt;br /&gt;
Officially tested is Let&#039;s Encrypt itself with this URL: https://acme-v02.api.letsencrypt.org&lt;br /&gt;
&lt;br /&gt;
=== Gateways and App Platform ===&lt;br /&gt;
* Firmware from version 14r1 or later&lt;br /&gt;
* innovaphone App Platform with App Platform Manager version 14r1 or higher and image version 110036 or higher&lt;br /&gt;
* innovaphone App Connector for Let&#039;s Encrypt version 14r1 or higher&lt;br /&gt;
* working DNS configuration&lt;br /&gt;
&lt;br /&gt;
=== Reverse-Proxy ===&lt;br /&gt;
&lt;br /&gt;
* Let&#039;s encrypt will send the certificate challenge using HTTP on port 80.  On your WAN interface (that is, the interface your DNS name points to), port 80 must be available therefore. Traffic must be forwarded to either the device itself or to a reverse proxy that forwards the certificate challenge to the device. &lt;br /&gt;
* On the reverse proxy there must be a rule for the host that corresponds to the DNS name of your AP where the Let&#039;s Encrypt App runs on that forwards HTTP path &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; to the Let&#039;s Encrypt App. &lt;br /&gt;
* For 3rd-party devices behind the Reverse-Proxy which intend to obtain a certificate from Let&#039;s Encrypt (using their own client mechanism), a similar rule must be present that forwards the challenge to the 3rd-party device&lt;br /&gt;
* The App Platform must be able to communicate with the Let&#039;s Encrypt URLs.&lt;br /&gt;
&lt;br /&gt;
:: Conclusion: the recommended steps for obtaining certificates are as follows&lt;br /&gt;
::* configure the rule that forwards the challenge for your AP DNS name to the AP (&#039;&#039;your-ap.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;)&lt;br /&gt;
::* configure the Connector for Let&#039;s Encrypt App on your AP&lt;br /&gt;
::* configure the Let&#039;s Encrypt client on your AP&lt;br /&gt;
::* configure rules for all 3rd party devices behind the RP that forward the challenge for the respective 3rd-party device&#039;s DNS names to the these devices (&#039;&#039;your-3rd-party-device.example.com&#039;&#039;&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;). This step is optional&lt;br /&gt;
&lt;br /&gt;
==Security Consideration==&lt;br /&gt;
We do not recommend that a device can be reached directly from the Internet on port 80. Please use the reverse proxy variant described above.&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
* You can configure up to &#039;&#039;&#039;100&#039;&#039;&#039; DNS entries for a single device. More DNS entries are not supported by Let&#039;s Encrypt.&amp;lt;br/&amp;gt;&lt;br /&gt;
* You cannot configure DNS entries with wildcards. Such wildcard entries require the so called DNS challenge mechanism which is not supported by our Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Connector for Let&#039;s Encrypt PBX Manager Plugin ===&lt;br /&gt;
Configure the [[Reference14r1:Concept_App_Service_Let%27s_Encrypt#Let.27s_Encypt_Config | PBX Manager Plugin]] of the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone Gateways ===&lt;br /&gt;
Configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] on every gateway which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone App Platform ===&lt;br /&gt;
Configure Let&#039;s Encrypt in the settings of the App Platform Manager on every App Platform which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== RP ===&lt;br /&gt;
If your gateways and/or App Platforms are behind an innovaphone reverse proxy, you must configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] here too.&amp;lt;br/&amp;gt;&lt;br /&gt;
You must configure all DNS names which are used by the individual devices behind the RP.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The RP will request a certificate with multiple SAN entries while every individual device will request an own certificate with a single SAN entry (or still multiple if a single device shall have multiple DNS entries).&lt;br /&gt;
&lt;br /&gt;
=== Devices certificate configuration ===&lt;br /&gt;
If you want to rollout the Let&#039;s Encrypt root certificates to your devices, configure the URL for Let&#039;s Encrypt root certificates in a certificates configuration (App Devices -&amp;gt; Domains -&amp;gt; your domain -&amp;gt; Device Configurations) which will then ensure that always the latest root certificates are available in the trust list of your devices.&amp;lt;br/&amp;gt;&lt;br /&gt;
You can find this URL in the [[Reference14r1:Apps/PbxManager/App_Connector_for_Let&#039;s_Encrypt | PBX Manager Plugin]].&lt;br /&gt;
&lt;br /&gt;
== Tracing and logging ==&lt;br /&gt;
=== Gateways ===&lt;br /&gt;
The following trace flags can be activated at [[{{NAMESPACE}}:Maintenance/Diagnostics/Tracing | Maintenance/Diagnostics/Tracing]].&lt;br /&gt;
&lt;br /&gt;
;Let&#039;s Encrypt&lt;br /&gt;
: communication between gateway and the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
: processing of incoming id_tokens&lt;br /&gt;
&lt;br /&gt;
;HTTP Client&lt;br /&gt;
: the HTTPS communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
=== App Platform ===&lt;br /&gt;
&lt;br /&gt;
Enable these trace flags for diagnostics:&lt;br /&gt;
&lt;br /&gt;
==== App Platform Manager ====&lt;br /&gt;
;App&lt;br /&gt;
: requests of new certificates&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
;Websocket Client&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
==== Connector for Let&#039;s Encrypt App Service ====&lt;br /&gt;
;App&lt;br /&gt;
: app logs&lt;br /&gt;
;HttpClient&lt;br /&gt;
: communication with Let&#039;s Encrypt itself&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the clients&lt;br /&gt;
&lt;br /&gt;
== Alarms and Events ==&lt;br /&gt;
* an event is generated for every failed certificate creation by the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
* an alarm is generated on the corresponding device as long as the certificate creation fails&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
&lt;br /&gt;
=== Not working TLS connection between a reverse proxy/gateway and the app platform with the Connector for Let&#039;s Encrypt ===&lt;br /&gt;
If a gateway/reverse proxy cannot establish a TLS connection to the app platform where the Connector for Let&#039;s Encrypt is running, no new certificate can be created anymore.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As a workaround, you can temporarily switch to a non TLS connection under Services -&amp;gt; Let&#039;s Encrypt &#039;&#039;&#039;Let&#039;s Encrypt App URL&#039;&#039;&#039; by using &#039;&#039;&#039;ws&#039;&#039;&#039; instead of &#039;&#039;&#039;wss&#039;&#039;&#039;.&amp;lt;br/&amp;gt;&lt;br /&gt;
If all your systems have a valid TLS certificate again, don&#039;t forget to switch back to &#039;&#039;&#039;wss&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
==Known Issue==&lt;br /&gt;
===Geoblocking can prevent confirmation===&lt;br /&gt;
To verify the correctness of DNS entries and HTTP Challenge, Let&#039;s Encrypt sends DNS/HTTP requests from multiple locations around the world. All of these requests must be successfully answered. If a request is not answered due to geoblocking, Let&#039;s Encrypt does not trust the issuer.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference14r1:Services/Letsencrypt]]&lt;br /&gt;
* [[Reference14r1:Concept_App_Service_Connector_for_Let%27s_Encrypt]]&lt;br /&gt;
* [[Reference14r1:Apps/PbxManager/App_Connector_for_Let%27s_Encrypt]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73912</id>
		<title>Reference14r1:Concept Let&#039;s Encrypt</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference14r1:Concept_Let%27s_Encrypt&amp;diff=73912"/>
		<updated>2024-11-06T14:29:56Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Reverse-Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|Let%27s%20Encrypt]]&lt;br /&gt;
&lt;br /&gt;
Certificates are automatically generated for innovaphone gateways and App Platforms.&lt;br /&gt;
&lt;br /&gt;
== Applies to ==&lt;br /&gt;
* innovaphone gateways from version 14r1&lt;br /&gt;
* innovaphone App Platform with version 14r1 apps (image version 110036 or higher)&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
* Each configured innovaphone client requests a new certificate &#039;&#039;&#039;30&#039;&#039;&#039; days before it&#039;s current certificate expires.&lt;br /&gt;
* Therefor an app websocket connection is opened to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The client sends a certificate signing request to the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
* The Connector for Let&#039;s Encrypt App Service itself communitates via HTTPs and [https://en.wikipedia.org/wiki/JSON_Web_Token JWT] with Let&#039;s Encrypt to request a new certificate.&lt;br /&gt;
* Let&#039;s Encrypt triggers an HTTP challenge for every DNS entry where the token for the DNS entry is verified. (The Token is saved in the Let&#039;s Encrypt App Service)&lt;br /&gt;
** the HTTP challenge always works &#039;&#039;&#039;without&#039;&#039;&#039; HTTPS on Port 80 on a subpath of &#039;&#039;&#039;/.well-known/acme-challenge/&#039;&#039;&#039;, e.g. http://mydns.com/.well-known/acme-challenge/1290378712893z12983&lt;br /&gt;
* After successfull HTTP challenges for every DNS name, the new certificate is send back to the client.&lt;br /&gt;
* The certificate is installed X days before the old certificate expires, while X can be configured in the PBX Manager Plugin.&lt;br /&gt;
&lt;br /&gt;
=== Flow without Reverse Proxy ===&lt;br /&gt;
&lt;br /&gt;
[[Image:letsencrypt-flow.png]]&lt;br /&gt;
&lt;br /&gt;
=== Flow with Reverse Proxy ===&lt;br /&gt;
[[Image:letsencrypt-flow-rp.png]]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== ACMEv2 compliant certification service ===&lt;br /&gt;
&lt;br /&gt;
Our Connector for Let&#039;s Encrypt App Service uses the ACMEv2 protocol. So in general every ACMEv2 compliant service could be used.&amp;lt;br/&amp;gt;&lt;br /&gt;
Officially tested is Let&#039;s Encrypt itself with this URL: https://acme-v02.api.letsencrypt.org&lt;br /&gt;
&lt;br /&gt;
=== Gateways and App Platform ===&lt;br /&gt;
* Firmware from version 14r1 or later&lt;br /&gt;
* innovaphone App Platform with App Platform Manager version 14r1 or higher and image version 110036 or higher&lt;br /&gt;
* innovaphone App Connector for Let&#039;s Encrypt version 14r1 or higher&lt;br /&gt;
* working DNS configuration&lt;br /&gt;
&lt;br /&gt;
=== Reverse-Proxy ===&lt;br /&gt;
&lt;br /&gt;
* Let&#039;s encrypt will send the certificate challenge using HTTP on port 80.  On your WAN interface (that is, the interface your DNS name points to), port 80 must be available therefore. Traffic must be forwarded to either the device itself or to a reverse proxy that forwards the certificate challenge to the device. &lt;br /&gt;
* On the reverse proxy there must be a rule for the host that corresponds to the DNS name of your AP where the Let&#039;s Encrypt App runs on that forwards HTTP path &amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt; to the Let&#039;s Encrypt App. &lt;br /&gt;
* For 3rd-party devices behind the Reverse-Proxy which intend to obtain a certificate from Let&#039;s Encrypt (using their own client mechanism), a similar rule must be present that forwards the challenge to the 3rd-party device&lt;br /&gt;
* The App Platform must be able to communicate with the Let&#039;s Encrypt URLs.&lt;br /&gt;
&lt;br /&gt;
:: Conclusion: the recommended steps for obtaining certificates are as follows&lt;br /&gt;
::* configure the rule that forwards the challenge for your AP DNS name to the AP (&#039;&#039;your-ap.example.com&#039;&#039;/&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;)&lt;br /&gt;
::* configure the Connector for Let&#039;s Encrypt App on your AP&lt;br /&gt;
::* configure the Let&#039;s Encrypt client on your AP&lt;br /&gt;
::* configure rules for all 3rd party devices behind the RP that forward the challenge for the respective 3rd-party device&#039;s DNS names to the these devices (&#039;&#039;your-3rd-party-device.example.com&#039;&#039;/&amp;lt;code&amp;gt;/.well-known/acme-challenge/&amp;lt;/code&amp;gt;). This step is optional&lt;br /&gt;
&lt;br /&gt;
==Security Consideration==&lt;br /&gt;
We do not recommend that a device can be reached directly from the Internet on port 80. Please use the reverse proxy variant described above.&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
* You can configure up to &#039;&#039;&#039;100&#039;&#039;&#039; DNS entries for a single device. More DNS entries are not supported by Let&#039;s Encrypt.&amp;lt;br/&amp;gt;&lt;br /&gt;
* You cannot configure DNS entries with wildcards. Such wildcard entries require the so called DNS challenge mechanism which is not supported by our Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Connector for Let&#039;s Encrypt PBX Manager Plugin ===&lt;br /&gt;
Configure the [[Reference14r1:Concept_App_Service_Let%27s_Encrypt#Let.27s_Encypt_Config | PBX Manager Plugin]] of the Connector for Let&#039;s Encrypt App Service.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone Gateways ===&lt;br /&gt;
Configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] on every gateway which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== innovaphone App Platform ===&lt;br /&gt;
Configure Let&#039;s Encrypt in the settings of the App Platform Manager on every App Platform which shall get a Let&#039;s Encrypt certificate.&lt;br /&gt;
&lt;br /&gt;
=== RP ===&lt;br /&gt;
If your gateways and/or App Platforms are behind an innovaphone reverse proxy, you must configure the [[Reference14r1:Services/Letsencrypt | Let&#039;s Encrypt service]] here too.&amp;lt;br/&amp;gt;&lt;br /&gt;
You must configure all DNS names which are used by the individual devices behind the RP.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The RP will request a certificate with multiple SAN entries while every individual device will request an own certificate with a single SAN entry (or still multiple if a single device shall have multiple DNS entries).&lt;br /&gt;
&lt;br /&gt;
=== Devices certificate configuration ===&lt;br /&gt;
If you want to rollout the Let&#039;s Encrypt root certificates to your devices, configure the URL for Let&#039;s Encrypt root certificates in a certificates configuration (App Devices -&amp;gt; Domains -&amp;gt; your domain -&amp;gt; Device Configurations) which will then ensure that always the latest root certificates are available in the trust list of your devices.&amp;lt;br/&amp;gt;&lt;br /&gt;
You can find this URL in the [[Reference14r1:Apps/PbxManager/App_Connector_for_Let&#039;s_Encrypt | PBX Manager Plugin]].&lt;br /&gt;
&lt;br /&gt;
== Tracing and logging ==&lt;br /&gt;
=== Gateways ===&lt;br /&gt;
The following trace flags can be activated at [[{{NAMESPACE}}:Maintenance/Diagnostics/Tracing | Maintenance/Diagnostics/Tracing]].&lt;br /&gt;
&lt;br /&gt;
;Let&#039;s Encrypt&lt;br /&gt;
: communication between gateway and the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
: processing of incoming id_tokens&lt;br /&gt;
&lt;br /&gt;
;HTTP Client&lt;br /&gt;
: the HTTPS communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
=== App Platform ===&lt;br /&gt;
&lt;br /&gt;
Enable these trace flags for diagnostics:&lt;br /&gt;
&lt;br /&gt;
==== App Platform Manager ====&lt;br /&gt;
;App&lt;br /&gt;
: requests of new certificates&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
;Websocket Client&lt;br /&gt;
: communication with the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
&lt;br /&gt;
==== Connector for Let&#039;s Encrypt App Service ====&lt;br /&gt;
;App&lt;br /&gt;
: app logs&lt;br /&gt;
;HttpClient&lt;br /&gt;
: communication with Let&#039;s Encrypt itself&lt;br /&gt;
;AppWebsocket&lt;br /&gt;
: communication with the clients&lt;br /&gt;
&lt;br /&gt;
== Alarms and Events ==&lt;br /&gt;
* an event is generated for every failed certificate creation by the Connector for Let&#039;s Encrypt App Service&lt;br /&gt;
* an alarm is generated on the corresponding device as long as the certificate creation fails&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
&lt;br /&gt;
=== Not working TLS connection between a reverse proxy/gateway and the app platform with the Connector for Let&#039;s Encrypt ===&lt;br /&gt;
If a gateway/reverse proxy cannot establish a TLS connection to the app platform where the Connector for Let&#039;s Encrypt is running, no new certificate can be created anymore.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As a workaround, you can temporarily switch to a non TLS connection under Services -&amp;gt; Let&#039;s Encrypt &#039;&#039;&#039;Let&#039;s Encrypt App URL&#039;&#039;&#039; by using &#039;&#039;&#039;ws&#039;&#039;&#039; instead of &#039;&#039;&#039;wss&#039;&#039;&#039;.&amp;lt;br/&amp;gt;&lt;br /&gt;
If all your systems have a valid TLS certificate again, don&#039;t forget to switch back to &#039;&#039;&#039;wss&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
==Known Issue==&lt;br /&gt;
===Geoblocking can prevent confirmation===&lt;br /&gt;
To verify the correctness of DNS entries and HTTP Challenge, Let&#039;s Encrypt sends DNS/HTTP requests from multiple locations around the world. All of these requests must be successfully answered. If a request is not answered due to geoblocking, Let&#039;s Encrypt does not trust the issuer.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference14r1:Services/Letsencrypt]]&lt;br /&gt;
* [[Reference14r1:Concept_App_Service_Connector_for_Let%27s_Encrypt]]&lt;br /&gt;
* [[Reference14r1:Apps/PbxManager/App_Connector_for_Let%27s_Encrypt]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference14r1:Settings/Phone_settings/Device_settings&amp;diff=73902</id>
		<title>Reference14r1:Settings/Phone settings/Device settings</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference14r1:Settings/Phone_settings/Device_settings&amp;diff=73902"/>
		<updated>2024-11-06T10:31:21Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Configuration entries for automated deployment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;;Headset&lt;br /&gt;
:Enable/Disable headset support&lt;br /&gt;
;LCD light&lt;br /&gt;
:Set current display brightness. 0 (off) - 15 (max). Default 8.&lt;br /&gt;
;LCD light (idle state)&lt;br /&gt;
:Display brightness applied 30s after last action. 0 (off) - 15 (max). Default 2.&lt;br /&gt;
:To prevent display dimming, set &#039;&#039;LCD light&#039;&#039; and &#039;&#039;LCD light (idle state)&#039;&#039; to same level&lt;br /&gt;
;Energy saving&lt;br /&gt;
:Time frame in which the display is switched off instead of being dimmed if in idle state. Format &amp;lt;starthours&amp;gt;-&amp;lt;endhours&amp;gt; in 24h-notation with leading zeros. E.g. 17-09 turns off display between 17 o&#039;clock (5pm) until 9 o&#039;clock (9am). Default is 22-06. &lt;br /&gt;
:To prevent switching off the display, set &#039;&#039;Energy saving&#039;&#039; to &#039;&#039;00-00&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Configuration entries for automated deployment===&lt;br /&gt;
;LCD light&lt;br /&gt;
;&lt;br /&gt;
 vars create PHONE/LCD-BACKLIGHT p 8&lt;br /&gt;
;LCD light (idle state):&lt;br /&gt;
 vars create PHONE/LCD-IDLE-BACKLIGHT p 2&lt;br /&gt;
;Energy saving: &lt;br /&gt;
 vars create PHONE/ENERGY-SAVING-TIME p 22-06&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example to be used in Devices configuration/Expert configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use the [[{{NAMESPACE}}:Concept_Update_Server#Check_command | check command ]] as in the example below to prevent re-execution every 30 seconds&lt;br /&gt;
&lt;br /&gt;
 # Use check command to prevent boot loops (after vars create a reset is needed)&lt;br /&gt;
 mod cmd UP1 check iresetn Energy-Saving&lt;br /&gt;
 &lt;br /&gt;
 vars create PHONE/LCD-BACKLIGHT p 8&lt;br /&gt;
 vars create PHONE/LCD-IDLE-BACKLIGHT p 2&lt;br /&gt;
 vars create PHONE/ENERGY-SAVING-TIME p 22-07&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference14r1:Settings/Phone_settings/Device_settings&amp;diff=73901</id>
		<title>Reference14r1:Settings/Phone settings/Device settings</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference14r1:Settings/Phone_settings/Device_settings&amp;diff=73901"/>
		<updated>2024-11-06T10:25:09Z</updated>

		<summary type="html">&lt;p&gt;Ckl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;;Headset&lt;br /&gt;
:Enable/Disable headset support&lt;br /&gt;
;LCD light&lt;br /&gt;
:Set current display brightness. 0 (off) - 15 (max). Default 8.&lt;br /&gt;
;LCD light (idle state)&lt;br /&gt;
:Display brightness applied 30s after last action. 0 (off) - 15 (max). Default 2.&lt;br /&gt;
:To prevent display dimming, set &#039;&#039;LCD light&#039;&#039; and &#039;&#039;LCD light (idle state)&#039;&#039; to same level&lt;br /&gt;
;Energy saving&lt;br /&gt;
:Time frame in which the display is switched off instead of being dimmed if in idle state. Format &amp;lt;starthours&amp;gt;-&amp;lt;endhours&amp;gt; in 24h-notation with leading zeros. E.g. 17-09 turns off display between 17 o&#039;clock (5pm) until 9 o&#039;clock (9am). Default is 22-06. &lt;br /&gt;
:To prevent switching off the display, set &#039;&#039;Energy saving&#039;&#039; to &#039;&#039;00-00&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Configuration entries for automated deployment===&lt;br /&gt;
;LCD light&lt;br /&gt;
;&lt;br /&gt;
 vars create PHONE/LCD-BACKLIGHT p 8&lt;br /&gt;
;LCD light (idle state):&lt;br /&gt;
 vars create PHONE/LCD-IDLE-BACKLIGHT p 2&lt;br /&gt;
;Energy saving: &lt;br /&gt;
 vars create PHONE/ENERGY-SAVING-TIME p 22-06&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example to be used in Devices configuration/Expert configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use the check command as in the example below to prevent re-execution every 30 seconds&lt;br /&gt;
&lt;br /&gt;
 # Use check command to prevent boot loops (after vars create a reset is needed)&lt;br /&gt;
 mod cmd UP1 check iresetn Energy-Saving&lt;br /&gt;
 &lt;br /&gt;
 vars create PHONE/LCD-BACKLIGHT p 8&lt;br /&gt;
 vars create PHONE/LCD-IDLE-BACKLIGHT p 2&lt;br /&gt;
 vars create PHONE/ENERGY-SAVING-TIME p 22-07&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:PHP_based_Update_Server_V2&amp;diff=73896</id>
		<title>Howto:PHP based Update Server V2</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:PHP_based_Update_Server_V2&amp;diff=73896"/>
		<updated>2024-11-06T10:17:24Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Using vars create */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* all innovaphone devices&lt;br /&gt;
* web server running PHP 5 (e.g. Linux Application Platform)&lt;br /&gt;
&lt;br /&gt;
All Versions prior to 13r1 (for 13r1 and later, see [[Reference13r1:Concept App Service Devices]] instead). &lt;br /&gt;
&lt;br /&gt;
By default, the [[Reference10:Concept_Update_Server | Update Manager]] mechanism reads a file that corresponds to the device type (e.g. &amp;lt;code&amp;gt;update-ip222.htm&amp;lt;/code&amp;gt;).  While this makes sense (update scripts may vary by device type), it is sometimes tedious, as you have to edit a huge amount of files which typically are (at least partly) identical.&lt;br /&gt;
&lt;br /&gt;
Here is a PHP script that can be used as an &#039;&#039;Update Server&#039;&#039; that allows you to simplify the handling of update scripts. It also includes a mechanism that makes sure that all devices always have the same firmware installed as a given &#039;&#039;master device&#039;&#039; has.   Finally, it implements a straight forward configuration backup scheme.&lt;br /&gt;
&lt;br /&gt;
This article describes version 2 of this update server (build 2006 and up). The previous version is described in [[Howto:PHP_based_Update_Server]]. The enhancements are&lt;br /&gt;
* Status user interface showing all known devices&lt;br /&gt;
* Ability to roll out custom device certificates&lt;br /&gt;
* Ability to provide configuration files to MTLS-authenticated devices only (e.g. in order to keep certain configuration settings secure)&lt;br /&gt;
* Hide configuration files from public read access&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
The update server script requires a web server with working PHP 5.3 or higher platform.  It has been tested with Apache and ligHTTPD (on a [[Reference10:Concept Linux Application Platform | Linux Application Platform]]).   On IIS, neither the certificate roll-out nor the MTLS authentication or configuration backup works with IIS.&lt;br /&gt;
&lt;br /&gt;
The platform running the PHP scripts must have a valid time setting!&lt;br /&gt;
&lt;br /&gt;
PHP 8 is supported from build 2023.&lt;br /&gt;
&lt;br /&gt;
=== Features ===&lt;br /&gt;
The update server can&lt;br /&gt;
* update all your devices with boot code and firmware that corresponds to the versions running on a reference device of your choice&lt;br /&gt;
* save backups of your devices configuration. Backups are saved only if the configuration changed since the last backup&lt;br /&gt;
* invoke your own update scripts depending on &lt;br /&gt;
** various phases (e.g. you can have &#039;&#039;staging&#039;&#039; scripts which are only executed once and normal scripts which are executed in normal operation later on)&lt;br /&gt;
** devices classes (e.g. you can have different scripts for phones and gateways)&lt;br /&gt;
** environments (e.g. you can have scripts for your internal devices and others for devices in home offices)&lt;br /&gt;
** the device serial number&lt;br /&gt;
* roll out customer specific device certificates&lt;br /&gt;
* roll out update scripts to devices only that have identified themselves with a valid device certificate (MTLS)&lt;br /&gt;
* maintain a list of devices in your installation along with some vital information about each individual device&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
==== On the Linux Application Platform ====&lt;br /&gt;
Here is how you would install it on the [[Reference10:Concept_Linux_Application_Platform|LAP]].  Some of the steps may not be necessary if you don&#039;t want to use all features.&lt;br /&gt;
&lt;br /&gt;
On the &#039;&#039;Linux Application Platform&#039;&#039;, you would &lt;br /&gt;
* open the LAP&#039;s file system using a SFTP client such as e.g. [https://winscp.net/eng/index.php WinSCP] (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;root/iplinux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]). Note that you must use SFTP rather than WebDAV, as WebDAV will not give access to the executable web server files&lt;br /&gt;
* create a new root directory underneath &amp;lt;code&amp;gt;/var/www/innovaphone/mtls&amp;lt;/code&amp;gt;, e.g. &amp;lt;code&amp;gt;/var/www/innovaphone/mtls/update&amp;lt;/code&amp;gt;&lt;br /&gt;
* download the complete file package of scripts and files [https://github.com/innovaphone/php-update-server here] &lt;br /&gt;
* copy all files and directories in to this new directory&lt;br /&gt;
** create your local config files. We will never overwrite these in further updates.&lt;br /&gt;
***Rename &amp;lt;code&amp;gt;config/user-config-sample.xml&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;config/user-config.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
***Rename &amp;lt;code&amp;gt;scripts/all-all-all-sample.txt&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;scripts/all-all-all.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
* change owner and group of all files and directories to &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, change mode to 0600 for all files and 0700 for all directories (see [[#Migrating_from_build_2000_an_newer | below]] for how to do this with WinSCP)&lt;br /&gt;
&lt;br /&gt;
* log in to the LAP&#039;s admin UI (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;admin/linux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]) and open its &#039;&#039;Administration/Web Server/Change web server properties and public access to the web/webdav&#039;&#039; configuration UI. Add the following paths to &#039;&#039;Public Web Paths&#039;&#039; (assuming your base directory is called &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt;):&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/web&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/fw/&amp;lt;/code&amp;gt; (note the trailing slash!)&lt;br /&gt;
: make sure that no other sub-directories of &#039;&#039;update&#039;&#039; are listed&lt;br /&gt;
: make sure you have no trailing &#039;/&#039; in any of these paths (except &#039;&#039;fw/&#039;)&lt;br /&gt;
: this will make sure the update server&#039;s admin user interface is not accessible to the public&lt;br /&gt;
&lt;br /&gt;
At this point, you should be able to access the update server&#039;s admin user interface, e.g. &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php&amp;lt;/code&amp;gt;.  However, the only thing you see is a login page.  Please note that your browser should ask you for a password for this page (unless you already entered it before).  Cookies must be enabled for the login page to work properly. &lt;br /&gt;
&lt;br /&gt;
===== If you want to provide HTTPS Acess to the Update Server =====&lt;br /&gt;
For HTTPS access to the update server, you may want to install your own server certificate under &#039;&#039;Administration/Certificates/Current server certificate&#039;&#039;.  However, this is not strictly required (you will experience some warning messages when using your browser to access the update server, however, calling devices will work just fine). &lt;br /&gt;
&lt;br /&gt;
===== If you want to setup MTLS-restricted Delivery of Update Scripts =====&lt;br /&gt;
If you think you have sensitive information in your update scripts, you should make sure to deliver such scripts to your own verified devices only.  This can be done by authenticating calling devices with &#039;&#039;mutual TLS&#039;&#039; (MTLS).  In this case, the calling device must use HTTPS to retrieve the update script and present a trusted client certificate that identifies itself as the calling device (that is, has the device serial as the certificate&#039;s &#039;&#039;common name&#039;&#039; (CN)). &lt;br /&gt;
&lt;br /&gt;
For this feature, you need to &#039;&#039;Configure mutual TLS&#039;&#039; in the LAP&#039;s &#039;&#039;Administration/Web Server&#039;&#039; panel.  Simply tick the &#039;&#039;Active&#039;&#039; check-mark and select an appropriate &#039;&#039;MTLS Port&#039;&#039;.  The port must not conflict with any other TCP port used on the LAP, so neither 80 nor 443 is a good choice.  444 is a good choice.  Although it [http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&amp;amp;page=8 is assigned to the snpp protocol] by IANA, it is not used by the LAP (and probably rarely used anyway).&lt;br /&gt;
&lt;br /&gt;
If MTLS is already activated on your LAP, simply take note of the currently configured &#039;&#039;MTLS Port&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Please note that MTLS access is &#039;&#039;not possible&#039;&#039; through a &#039;&#039;reverse proxy&#039;&#039; (RP).  This is because the RP always will terminate the incoming TLS connection and establish its own to the target.  Therefore, the client certificate presented to the target server is the RP&#039;s certificate, not the original clients certificate.  In our context - where MTLS is used to verify the identity of the original caller - clients must not access the update server through an RP.&lt;br /&gt;
&lt;br /&gt;
You can either expose your update server directly to the internet (and carefully think through the security implications) or create specific TCP port forwarding towards the update server in your NAT-router/firewall.  In this case, we recommend to use non-standard HTTP and HTTPS ports on the NAT router (cause this will already keep most of the HTTP port scanners out there in the internet from functioning).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Also, you will need the public key of all the CAs you will trust.  These must be configured in to the web server so it can trust the certificates your devices will present to it.  See [[#Enforcing_Trust]] for details.&lt;br /&gt;
&lt;br /&gt;
==== On an Apache Server running on the Windows Operating System ====&lt;br /&gt;
The update server will run on Apache too.  However, as we did not test this setup thoroughly, we recommend to use the LAP&#039;s LigHTTPD instead.  &lt;br /&gt;
&lt;br /&gt;
* For hints on using MTLS on an Apache Web Server, see [[Reference10:Concept_Provisioning#Enforcing_mutual_TLS_on_Apache | Enforcing mutual TLS on Apache]]&lt;br /&gt;
* For hints on getting the &#039;&#039;innovaphone device certificate authority&#039;&#039; public keys (which you may or may not need), see [[Reference10:Concept_Provisioning#How_to_get_inno-dev-ca-certificate.crt | How to get inno-dev-ca-certificate.crt ]]&lt;br /&gt;
&lt;br /&gt;
==== On Microsoft&#039;s IIS ====&lt;br /&gt;
We do not recommend to use IIS as &lt;br /&gt;
* it does not support PUT easily&lt;br /&gt;
* it is not compatible with the innovaphone device&#039;s MTLS implementation&lt;br /&gt;
&lt;br /&gt;
===Update existing installation===&lt;br /&gt;
&lt;br /&gt;
* download the [https://github.com/innovaphone/php-update-server new sources]&lt;br /&gt;
* copy all files and directories to your existing installation folder (overwrite existing files)&lt;br /&gt;
* change owner and group of all files and directories to www-data, change mode to 0600 for all files and 0700 for all directories&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
If you intend to deliver your update scripts with MTLS (that is, with HTTPS and mutual certificate check)&lt;br /&gt;
* you will need to have the full name of your &#039;&#039;certificate Authority&#039;&#039; (CA) as it is noted as &#039;&#039;Common Name&#039;&#039; (CN) in your CA&#039;s certificate&lt;br /&gt;
* also, you will need a PEM version of your CA&#039;s public key (a &#039;&#039;PEM version&#039;&#039; of a certificate is a text file that begins with a line like &amp;lt;code&amp;gt;-----BEGIN CERTIFICATE-----&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Also, you need to know the &#039;&#039;MTLS Port&#039;&#039; configured in your LAP (see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts| If you want to setup MTLS-restricted Delivery of Update Scripts ]] above).&lt;br /&gt;
&lt;br /&gt;
All tweakable parameters are set in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  You may want to use an XML-capable editor such as notepad++, netbeans or Visual-Studio for editing.  if your editor supports it, you benefit from the &#039;&#039;document type description&#039;&#039; (DTD) provided in &amp;lt;code&amp;gt;full-config.dtd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;false&amp;quot; debugcerts=&amp;quot;false&amp;quot; debugscript=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The attributes of the &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; tag control some aspects of debugging.  For now, simply set all 3 to &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;&amp;quot;false&amp;quot;&amp;lt;/code&amp;gt;.  Do not forget to revert them back to &amp;lt;code&amp;gt;&amp;quot;false&amp;quot;&amp;lt;/code&amp;gt; when everything runs smoothly, large log files will result if not. &lt;br /&gt;
&lt;br /&gt;
==== Securing Access ====&lt;br /&gt;
To control access to the update server&#039;s data, you should set a login.  This can be done in the &#039;&#039;master&#039;&#039; tag by specifying both &#039;&#039;user&#039;&#039; and &#039;&#039;password&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;master ...  user=&amp;quot;myadmin&amp;quot; password=&amp;quot;mysecret&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Default username and password are admin/password.&lt;br /&gt;
&lt;br /&gt;
==== Delivering Firmware and Boot Code ====&lt;br /&gt;
At this point, you can simulate a device by requesting an update script using an URL like &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php?type=IP232&amp;amp;sn=00-90-33-00-00-00&amp;amp;hwid=IP232-00-00-00&amp;amp;ip=1.2.3.4&amp;lt;/code&amp;gt; in your browser (please note that this URL should not ask you for a password).  Most likely, your browser will wait a little while and then say something like:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # failed to use cached data (cache not current), retrieving info online&lt;br /&gt;
 # cannot get PBX info: cannot access http://yourmasterdevice.youdomain.tld/CMD0/box_info.xml, reading cache&lt;br /&gt;
 # cannot get cached PBX info: cannot access cache/master-info.xml - exit&lt;br /&gt;
&lt;br /&gt;
This is because you did not yet specify the &#039;&#039;master device&#039;&#039; which always runs the reference firmware.  &lt;br /&gt;
&lt;br /&gt;
The idea here is that you have one innovaphone device in your system where the firmware is always manually updated. All other devices shall follow this reference firmware.  The update server will deliver the firmware that runs on the master device to calling devices.  For this to work, you need to set the &#039;&#039;info&#039;&#039; attribute of the [[#master|&#039;&#039;master&#039;&#039;]] tag and leave everything else &#039;&#039;as is&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Remember that you do all your local configuration changes in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As &#039;&#039;master&#039;&#039; is a first level tag, you can add it directly underneath the opening &#039;&#039;&amp;lt;config&amp;gt;&#039;&#039; tag.  The only thing we need to define right now is the path to read the firmware information from your master device.  Let&#039;s say your reference device has the IP address &amp;lt;code&amp;gt;172.16.0.10&amp;lt;/code&amp;gt;, you end up with &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;true&amp;quot; debugcerts=&amp;quot;true&amp;quot; debugscript=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;  user=&amp;quot;myadmin&amp;quot; password=&amp;quot;mysecret&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(you could use a DNS name instead of the IP address of course). &lt;br /&gt;
The &#039;&#039;info&#039;&#039; URL is used by the update server itself only, it is never used by devices requesting an update script.&lt;br /&gt;
&lt;br /&gt;
When you refresh the page that simulates a device requesting an update script, the output should now change to something like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # failed to use cached data (cache not current), retrieving info online&lt;br /&gt;
 # current firmware (unknown) does not match required firmware (130178)&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
This is to say that your master device runs firmware 130178 and the calling device does not (actually, as the calling client is simulated by your browser, it does not transmit its current firmware to the update server so it is &#039;&#039;(unknown)&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
In order to actually update the clients with firmware and boot code, the files must be made available to the calling client somehow.  This is done by specifying an URL in the [[Reference10:Concept_Update_Server#Prot_command | prot ]] and [[Reference10:Concept_Update_Server#Boot_command | boot ]] commands sent to the calling device:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # current firmware (unknown) does not match required firmware (130178)&lt;br /&gt;
 mod cmd UP0 prot http://update.yourcompany.com/mtls/update/fw/130178/ ser 130178&lt;br /&gt;
 # current boot code (unknown) does not match required boot code (130112)&lt;br /&gt;
 mod cmd UP0 boot http://update.yourcompany.com/mtls/update/fw/130112/ ser 130112&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
By default, the URL generated points to a sub-directory of your update server called &#039;&#039;fw&#039;&#039;: &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/fw/130178/&amp;lt;/code&amp;gt;.  Note that this default URL expects sub-directories underneath the &#039;&#039;fw&#039;&#039; directory which correspond to the firmware and boot code build number.  The file structure thus would be like&lt;br /&gt;
&lt;br /&gt;
 /var/www/innovaphone/mtls/update/fw&lt;br /&gt;
                                    /130178&lt;br /&gt;
                                           /ip232.bin&lt;br /&gt;
                                    /130112&lt;br /&gt;
                                           /boot232.bin&lt;br /&gt;
&lt;br /&gt;
Note that the URL ends with a slash (&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;).  This instructs the calling device to append the appropriate file name itself when retrieving the file (see [[Reference10:Concept_Update_Server#Prot_command | the prot command ]] for details). &lt;br /&gt;
&lt;br /&gt;
However, you can also specify any other URL by setting the &#039;&#039;url&#039;&#039; attribute in the &#039;&#039;fwstorage&#039;&#039; tag of your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. In this attribute, certain meta words will be replaced (see [[#fwstorage | the &#039;&#039;fwstorage&#039;&#039; tag ]] for details).  The default setting for example is &amp;lt;code&amp;gt;fw/{build}/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can disable firmware and boot code updates altogether by setting the &#039;&#039;info&#039;&#039; attribute in the &#039;&#039;master&#039;&#039; tag to an empty value.&lt;br /&gt;
&lt;br /&gt;
==== Your own Update Script Files ====&lt;br /&gt;
The update server will deliver update scripts to calling devices which are synthesized from a number of &#039;&#039;update script snippets&#039;&#039; which you define yourself.  The idea is that many devices share parts of their configuration while other parts are different.  This depends on&lt;br /&gt;
* the device &#039;&#039;class&#039;&#039; (e.g. a phone or a gateway)&lt;br /&gt;
: the device class is automatically derived from its model.  In fact, a single device may be in multiple classes. For example, an IP232 is in these classes: &#039;&#039;phone, pre_opus_phone, phone_newui&#039;&#039; which basically says that its a phone and has no OPUS codec yet but a &amp;quot;new&amp;quot; user interface (as opposed to the old one found e.g. on an IP110). A number of useful classes are pre-defined, but you can add your own in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
* the device&#039;s environment (e.g. &#039;&#039;home-office&#039;&#039;, &#039;&#039;branch-office&#039;&#039;)&lt;br /&gt;
:  These reflect the fact that devices may need different configuration if they are in different locations (or environments).  The update server does not know about a device&#039;s environment, which is why you need to configure it in to the devices update URL if you need this.  By default, there is a single environment defined called &#039;&#039;default&#039;&#039;, but of course, you can add your own&lt;br /&gt;
* phase&lt;br /&gt;
: configuring devices may need multiple phases to go through.  If more than one phase is defined, the device will go through all phases sequentially, which is why a &#039;&#039;phase&#039;&#039; has a numerical &#039;&#039;seq&#039;&#039; attribute.  Phases are went through in order of this attribute. When the device has reached the last phase, it will stay there.  By default, there is only one phase called &#039;&#039;update&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can define update script snippets for any combination of device, environment and phase.  You do so simply by placing appropriate files in to the &#039;&#039;scripts&#039;&#039; directory on your update server.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a closer look at the web page we used to simulate a device calling for an update script before (&amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php?type=IP232&amp;amp;sn=00-90-33-00-00-00&amp;amp;hwid=IP232-00-00-00&amp;amp;ip=1.2.3.4&amp;lt;/code&amp;gt;).  It will show you all the possible files it would deliver to the device:&lt;br /&gt;
&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 # scripts/update-all-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-all-default.txt does not exist&lt;br /&gt;
 # scripts/update-phone-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-phone-default.txt does not exist&lt;br /&gt;
 # scripts/update-pre_opus_phone-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/update-phone_newui-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
&lt;br /&gt;
The update script snippet files need to have proper names to define when they should be delivered.  As you can see, they all start with &amp;lt;code&amp;gt;update-&amp;lt;/code&amp;gt; which means that they apply to devices which are in the &#039;&#039;update&#039;&#039; phase.  As by default there is only a single phase defined, all possible file names start with &amp;lt;code&amp;gt;update-&amp;lt;/code&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
The next part here is either &amp;lt;code&amp;gt;phone-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pre_opus_phone-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;phone_newui-&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;all-&amp;lt;/code&amp;gt;.  This is because the calling IP232 is in three classes, so all respective snippets will be delivered to it.  &#039;&#039;all&#039;&#039; however is a wild-card.  That is, such files will be delivered to all devices, no matter what class they are in.  You may wonder why there was no &#039;&#039;all&#039;&#039; for the phase.  This is because there is only a single phase defined.  If there would be more, the &#039;&#039;all&#039;&#039;-variation of the phase-part  of the file name would be appear.&lt;br /&gt;
&lt;br /&gt;
The third part finally is either &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;00_90_33_00_00_00&amp;lt;/code&amp;gt; in our case. &#039;&#039;default&#039;&#039; is the name of the only &#039;&#039;environment&#039;&#039; that is defined by default.  &#039;&#039;00_90_33_00_00_00&#039;&#039; is the device&#039;s serial number which is treated as an implicitly defined environment name. This allows you to deliver certain snippets to a single device only.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s create an update script snippet that is delivered to all phones in the default environment when they are in the update phase.  The file name (which looks like &#039;&#039;phase&#039;&#039;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&#039;&#039;class&#039;&#039;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&#039;&#039;environment&#039;&#039;&amp;lt;code&amp;gt;.txt&amp;lt;/code&amp;gt;) has to be &amp;lt;code&amp;gt;update-phone-default.txt&amp;lt;/code&amp;gt; therefore.  Just for an exercise, let us set the device name (as shown in the browser&#039;s title bar) to &#039;&#039;This is a Phone!&#039;&#039;.&lt;br /&gt;
The command to do so is &amp;lt;code&amp;gt;config add CMD0 /name This+is+a+Phone%21&amp;lt;/code&amp;gt;, so your file may look like this&lt;br /&gt;
&lt;br /&gt;
 # set the device name&lt;br /&gt;
 config add CMD0 /name This+is+a+Phone%21&lt;br /&gt;
&lt;br /&gt;
(btw: did you observe that config line arguments need to be url-encoded?).  Now create the file and upload it in to the &#039;&#039;scripts&#039;&#039; directory of you update server.  When you now refresh the page which simulates the device calling for an update script, you will see something like this:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # newest script (scripts/update-phone-default.txt) 11s old&lt;br /&gt;
 # files being updated (scripts/update-phone-default.txt 11s old, waiting for at least 90s to expire)&lt;br /&gt;
&lt;br /&gt;
When you update multiple script snippets, it is often undesirable that a device retrieves an inconsistent state of the scripts you are working on (e.g. if you already have saved one but not yet the other).  To avoid this, the update server will look at the files modification dates and if one of those that needs to be delivered to the device is younger than 90 seconds, it will not send any of them at all.  &lt;br /&gt;
&lt;br /&gt;
So when you wait for the 90 seconds to pass and refresh the page again, you will see something like this:&lt;br /&gt;
&lt;br /&gt;
 # firmware build info cache is current&lt;br /&gt;
 # phase: update, nextphase: , environment: default, type: IP232, classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone-default.txt 4.1 mins&lt;br /&gt;
 ...&lt;br /&gt;
 #     scripts/update-phone-default.txt&lt;br /&gt;
 # { begin script &#039;scripts/update-phone-default.txt&#039; &lt;br /&gt;
 # set the device name&lt;br /&gt;
 config add CMD0 /name This+is+a+Phone%21&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # end script &#039;scripts/update-phone-default.txt&#039; }&lt;br /&gt;
 &lt;br /&gt;
 # trigger reset if required&lt;br /&gt;
 config write&lt;br /&gt;
 config activate&lt;br /&gt;
 iresetn&lt;br /&gt;
&lt;br /&gt;
As you can see, your snippet has been delivered by the update script.  However, the update server has also added some trailing commands which write back the config to the devices flash memory (&amp;lt;code&amp;gt;config write&amp;lt;/code&amp;gt;), activate it (&amp;lt;code&amp;gt;config activate&amp;lt;/code&amp;gt;) and trigger a reset if needed (&amp;lt;code&amp;gt;iresetn&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If there are multiple snippets available for a calling device, all of them are concatenated in the sequence shown in the header of the returned script (where the possible file names are listed)&lt;br /&gt;
&lt;br /&gt;
==== Device Status ====&lt;br /&gt;
When you have a lot of devices which are served by the update server, you may want to have a list of these devices along with some useful information regarding each devices.  &lt;br /&gt;
&lt;br /&gt;
You can enable this by defining the &#039;&#039;status&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  So open the file and add the tag right next to the &#039;&#039;master&#039;&#039; tag you added before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config&amp;gt;&lt;br /&gt;
    &amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;status&lt;br /&gt;
        dir=&amp;quot;status&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you have done so, please refresh the page that simulates your calling device and then open &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php?mode=status&amp;lt;/code&amp;gt;.  You will now see a device list (well, a list with a single device, the one you simulated using your browser).   The list will show some information regarding the devices that requested an update script lately.   For more options, see [[#status]].&lt;br /&gt;
&lt;br /&gt;
==== Device Backup ====&lt;br /&gt;
It is generally useful to have recent backups of all of your device configurations.  The update server supports that if you enable it by defining the &#039;&#039;backup&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. Simply put it right next to the &#039;&#039;master&#039;&#039; or &#039;&#039;status&#039;&#039; tag you added before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;backup&lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have done so and then refresh the page that simulates your calling device, you will now see &lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
 &lt;br /&gt;
 mod cmd UP0 scfg http://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m&lt;br /&gt;
&lt;br /&gt;
instead of &lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
 &lt;br /&gt;
 # Backups not enabled in config&lt;br /&gt;
&lt;br /&gt;
When a client requests an update script the next time, this will initiate a configuration backup which is stored underneath the &#039;&#039;backup&#039;&#039; directory.  For each device, a sub-directory is created and all backup files are stored therein.  By default, the last 10 differing configuration backups are kept.&lt;br /&gt;
&lt;br /&gt;
==== Controlling the Time-frames when Snippets are delivered ====&lt;br /&gt;
The update client built-in to innovaphone devices allows to restrict updates to certain time frames (e.g. only during the night). This can be controlled using the [[Reference10:Concept_Update_Server#Times_command | times ]] command.&lt;br /&gt;
&lt;br /&gt;
You can configure the update server to use the time commands by setting the &#039;&#039;allow&#039;&#039; and &#039;&#039;initial&#039;&#039; attributes in the &#039;&#039;times&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        allow=&amp;quot;22,23,0,1,2,3,4&amp;quot; &lt;br /&gt;
        initial=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If either the &#039;&#039;allow&#039;&#039; or &#039;&#039;initial&#039;&#039; attribute is present, the update script will contain a line like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # Restricted times&lt;br /&gt;
 mod cmd UP1 times  /allow 22,23,0,1,2,3,4 /initial 1&lt;br /&gt;
&lt;br /&gt;
In the example above, all update script activity will occur only between 10pm and 5am (local device time).   For more details, see [[Reference10:Concept_Update_Server#Times_command | Concept Update Server]]&lt;br /&gt;
&lt;br /&gt;
==== Using and Enforcing HTTPS ====&lt;br /&gt;
Your devices can either use HTTP or HTTPS to access the update server.  In normal operation, the update server will generate URLs (e.g. the URLs used to retrieve firmware or to backup configurations) for the same protocol.  &lt;br /&gt;
&lt;br /&gt;
However, you can enforce use of HTTPS by setting the &#039;&#039;forcehttps&#039;&#039; attribute in the [[Howto:PHP_based_Update_Server_V2#times | &#039;&#039;times&#039;&#039; ]] tag to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. If so, a device calling in with HTTP will be re-configured to use HTTPS:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # using HTTP and &#039;forcehttps&#039; is set -&amp;gt; need to switch to HTTPS&lt;br /&gt;
 &lt;br /&gt;
 # changed state query args: polling, phase&lt;br /&gt;
 # new url=https://update.yourcompany.com/mtls/update/update.php?polling=5&amp;amp;phase=&amp;amp;type=#t&amp;amp;sn=#m&amp;amp;hwid=#h&amp;amp;ip=#i&lt;br /&gt;
 ...&lt;br /&gt;
(note that if you are using a non-standard port for HTTPS, you must define it using the &#039;&#039;httpsport&#039;&#039; attribute).&lt;br /&gt;
&lt;br /&gt;
==== Delivering Custom Certificates ====&lt;br /&gt;
innovaphone devices come with pre-defined, trustworthy device certificates. However, all &#039;&#039;soft&#039;&#039; devices (such as the softwarephone, myPBX for Android/iOS or the IPVA) do not.  Also, in many scenarios customers run their own &#039;&#039;public key infrastructure&#039;&#039; (PKI) and request their own certificates to be used instead of the pre-defined. This is why there is a need to roll-out custom certificates to devices. &lt;br /&gt;
&lt;br /&gt;
The update server supports this task to an extend.  It can&lt;br /&gt;
* check if a calling device has a proper certificate&lt;br /&gt;
* instruct a calling device without proper certificate to create a &#039;&#039;certificate signing request&#039;&#039; (CSR)&lt;br /&gt;
* download the CSR to the update server for easy access by the administrator&lt;br /&gt;
* upload a signed CSR to the device&lt;br /&gt;
* upload the public key(s) of the CA in to the device&#039;s trust list&lt;br /&gt;
&lt;br /&gt;
In order to roll-out custom certificates with the update server, the administrator needs to&lt;br /&gt;
* run his own PKI (a.k.a. &#039;&#039;certificate authority&#039;&#039; (CA))&lt;br /&gt;
* monitor CSRs that appear in the update server&#039;s device list&lt;br /&gt;
* approve the request by manually submitting it to his own CA&lt;br /&gt;
* upload the signed CSR to the update server&lt;br /&gt;
&lt;br /&gt;
Also, all devices must run &#039;&#039;V12r1 SR8&#039;&#039; or newer before the new certificate can be uploaded.  Devices with older firmware will be updated automatically (see [[#Delivering_Firmware_and_Boot_Code]] above). However, the new firmware must be &#039;&#039;V12r1 SR8&#039;&#039; or later. &lt;br /&gt;
&lt;br /&gt;
To learn how you can create proper device certificates with your own windows CA, see [[Howto:Creating custom Certificates using a Windows Certificate Authority]].&lt;br /&gt;
&lt;br /&gt;
By default, custom certificates are turned off and you will see a note like&lt;br /&gt;
&lt;br /&gt;
 # certificates: either certificate handling or state tracking not enabled - not doing any certificate checking&lt;br /&gt;
&lt;br /&gt;
in the delivered update script.&lt;br /&gt;
&lt;br /&gt;
Custom certificates are turned on by adding a &#039;&#039;customcerts&#039;&#039; tag to your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
	dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The page that simulates your calling device will now include a line saying:&lt;br /&gt;
&lt;br /&gt;
 # certificates: we dont know anything about the current certificate state - not doing any certificate checking &lt;br /&gt;
&lt;br /&gt;
In order to decide if or if not a calling device has a valid certificate, the device needs to send its current public key to the update server.  This is done by enabling &#039;&#039;queries&#039;&#039; in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  &#039;&#039;Queries&#039;&#039; is a means to have the device submit certain information to the update server.  In the update server&#039;s default configuration, two queries are defined but not enabled:&lt;br /&gt;
&lt;br /&gt;
* the query &#039;&#039;certificates&#039;&#039; sends the current certificate state &lt;br /&gt;
* the query &#039;&#039;admin&#039;&#039; sends the current device name (as set in &#039;&#039;General/Admin&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
To enable a query, you must specify the class a calling device must be in in order to execute the query.  This is done by adding an &#039;&#039;applies&#039;&#039; tag for the respective query in your configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;queries&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;admin&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
    &amp;lt;/queries&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically says that both queries should be executed by devices of just any class.  Unless you enable queries, your update script will include lines such as:&lt;br /&gt;
&lt;br /&gt;
 # no queries defined for any of callers classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
&lt;br /&gt;
Once you have enabled them, you will see something like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # query &#039;certificates&#039;&lt;br /&gt;
 mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=query&amp;amp;sn=#m&amp;amp;id=certificates ser nop /always mod%20cmd%20X509%20xml-info&lt;br /&gt;
 # query &#039;admin&#039;&lt;br /&gt;
 mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=query&amp;amp;sn=#m&amp;amp;id=admin ser nop /always mod%20cmd%20CMD0%20xml-info&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
You can display the data sent by a query in the device status display.  To do so, you need to define one or more &#039;&#039;show&#039;&#039; tags as part of the respective &#039;&#039;query&#039;&#039; tag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
        ...&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;!-- show device certificate CNs and Issuer CNs in status page --&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Subject&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@subject_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Issuer&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@issuer_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two steps however are still missing: &lt;br /&gt;
&lt;br /&gt;
* a) you need to tell the update server the names of all the CAs you consider trustworthy.  This is done by listing their names in the &#039;&#039;CAname&#039;&#039; attribute of the &#039;&#039;customcerts&#039;&#039; tag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
        dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
        CAname=&amp;quot;innovaphone Device Certification Authority,innovaphone Device Certification Authority 2,innovaphone-INNO-DC-W2K8-Zertifizierungsserver&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
: The example shown defines that you will accept both of innovaphone&#039;s device certificate authorities and also your own CA called &#039;&#039;innovaphone-INNO-DC-W2K8-Zertifizierungsserver&#039;&#039;.  Devices with device certificates issued by one of these CAs will be left untouched.  For all other devices (for example, any &#039;&#039;myPBX for Android/iOS&#039;&#039; device that has a self-signed certificate), the generation of a custom certificate will be initiated.&lt;br /&gt;
&lt;br /&gt;
* And b) you need to provide the public key of your CA (so it can be uploaded to the calling device&#039;s trust list).  You need to place the DER (not PEM) encoded public key in to a file called &amp;lt;code&amp;gt;certs/CAkey-01.cer&amp;lt;/code&amp;gt; on your update server (if you want to upload the whole certificate chain, put all of the public keys in the chain in to separate additional files called &amp;lt;code&amp;gt;certs/CAkey-02.cer&amp;lt;/code&amp;gt; and so forth.&lt;br /&gt;
&lt;br /&gt;
For more details on how to approve certificate signing requests, see [[#Approving Certificate Signing Requests]] below.&lt;br /&gt;
&lt;br /&gt;
==== Enforcing Trust ====&lt;br /&gt;
Update script snippets may include sensitive information which you do not want to disclose to the public.  Even though you can force the use of HTTPS (see above), this still does not keep your data secure.  After all, an attacker could simply request an update script from your update server using HTTPS.  To secure your data, you need to make sure that snippets are only sent to devices which identify themselves using a trusted certificate with a correct &#039;&#039;common name&#039;&#039; (CN).  This is done using &#039;&#039;mutual transport layer security&#039;&#039; (MTLS).  Therefore, you need to configure MTLS in the LAP (see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts | If you want to setup MTLS-restricted Delivery of Update Scripts]] above). &lt;br /&gt;
&lt;br /&gt;
You can enable this by setting &#039;&#039;forcetrust&#039;&#039; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &#039;&#039;httpsport&#039;&#039; to the port configured as &#039;&#039;MTLS Port&#039;&#039; in your web server.  This is done in the &#039;&#039;times&#039;&#039; tag of your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        ...&lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot;&lt;br /&gt;
        httpsport=&amp;quot;444&amp;quot;&lt;br /&gt;
        forcetrust=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Please note that &#039;&#039;forcetrust&#039;&#039; does nothing unless &#039;&#039;forcehttps&#039;&#039; is also set!&lt;br /&gt;
&lt;br /&gt;
If so, the update server will deliver update script snippets only to clients which identify themselves with a proper certificate.    For this to work, you will need to add the public key of your certificate authority to your web server&#039;s list of trusted certificates.  &lt;br /&gt;
&lt;br /&gt;
When using the &#039;&#039;Linux Application Platform&#039;&#039; (LAP), you need to add the PEM-encoded public key of your certificate authority to the &#039;&#039;innovaphone-ca.pem&#039;&#039; file in &amp;lt;code&amp;gt;/home/root/ssl_cert&amp;lt;/code&amp;gt;.  When you have installed the LAP, this file will contain the PEM-encoded public keys of the 2 innovaphone device certificate authorities.  You can simply add the public key of your CA to the end of this file:&lt;br /&gt;
&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...inno-ca public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...inno-ca2 public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...your-ca public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
&lt;br /&gt;
You will need to restart the LigHTTPD then (most easily done by restarting the entire LAP (&#039;&#039;Diagnose/Reset&#039;&#039;) or by issuing the command &amp;lt;code&amp;gt;/etc/rc2.d/S02lighttpd restart&amp;lt;/code&amp;gt; from the linux root command prompt). Finally, you must set the &#039;&#039;forcetrust&#039;&#039; attribute. &lt;br /&gt;
(Note that the &#039;&#039;innovaphone-ca.pem&#039;&#039; file may be overwritten when a new LAP version is installed.  It is thus a good idea to keep a copy and check it after an upgrade).&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;forcetrust&#039;&#039; is effective and the calling device does not use HTTPS, it will be reconfigured to do so:&lt;br /&gt;
&lt;br /&gt;
 # using HTTP and &#039;forcehttps&#039; is set -&amp;gt; need to switch to HTTPS&lt;br /&gt;
 ...&lt;br /&gt;
 # new url=https://update.yourcompany.com:444/update/update.php?polling=5&amp;amp;phase=&amp;amp;type=#t&amp;amp;sn=#m&amp;amp;hwid=#h&amp;amp;ip=#i&amp;amp;env=default&lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS but sends no certificate, you will see a message like&lt;br /&gt;
&lt;br /&gt;
 # cannot verify CN with HTTPS: SSL_CLIENT_S_DN_CN not present - fix web server configuration or use MTLS-enabled port!&lt;br /&gt;
&lt;br /&gt;
This is probably because it is using a non-MTLS enabled port for HTTPS (e.g. the standard port 443) although MTLS is configured for a different port. &lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS and sends a certificate but the CN does not match the serial number of the device, you will see a message such as&lt;br /&gt;
&lt;br /&gt;
 # Device claims to be &#039;IP232-30-00-af&#039; but identifies as &#039;CKL-CELSIUS-W10.innovaphone.sifi&#039; by TLS&lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS and sends a certificate but the certificate is not trusted because its issuer is not listed in &#039;&#039;innovaphone-ca.pem&#039;&#039; (see above), the connection will be refused &lt;br /&gt;
&lt;br /&gt;
In all such cases, no snippet will be delivered.  If the certificate is good, you will see a message like &lt;br /&gt;
&lt;br /&gt;
 # good certificate(CN=&#039;IP232-30-00-af&#039;)&lt;br /&gt;
&lt;br /&gt;
followed by the appropriate snippets.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple Phases ====&lt;br /&gt;
When you configure multiple phases, all phases up to the final phase are stepped through and when all associated update script snippets for all phases are done, the device will ultimately stay in the final phase.  This can be used e.g. to implement update script snippets which are executed once only when the device is initialized.  Settings made in all but the last phase can later be overridden by the user or an administrator.  The settings done in the update script settings for the final phase however are re-executed whenever one of your update script files for this phase changes.&lt;br /&gt;
The process of deploying some initial settings is often called &#039;&#039;staging&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To enable staging, you therefore create a new phase that comes before the default phase (which is &#039;&#039;update&#039;&#039;).  Phases are sorted numerical by an attribute called &#039;&#039;seq&#039;&#039;.  As the default phase &#039;&#039;update&#039;&#039; is defined with &#039;&#039;seq=200&#039;&#039;, your new staging phase must be defined with a lower seq value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
	    &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you define such a phase, there will be new possible update script snippet file names: &lt;br /&gt;
&lt;br /&gt;
 # phase: staging, nextphase: update, environment: default, type: IP232, classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 # scripts/all-all-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-all-default.txt does not exist&lt;br /&gt;
 # scripts/all-phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-phone-default.txt does not exist&lt;br /&gt;
 # scripts/all-pre_opus_phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/all-phone_newui-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-phone_newui-default.txt does not exist&lt;br /&gt;
 # scripts/staging-all-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-all-default.txt does not exist&lt;br /&gt;
 # scripts/staging-phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-phone-default.txt does not exist&lt;br /&gt;
 # scripts/staging-pre_opus_phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/staging-phone_newui-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-phone_newui-default.txt does not exist&lt;br /&gt;
&lt;br /&gt;
First of all, there are new names for this particular phase.  Furthermore, as we now have multiple phases, the new wild-card name &#039;&#039;all&#039;&#039; is possible.  &lt;br /&gt;
&lt;br /&gt;
An example for a staging script snippet might be a file called &amp;lt;code&amp;gt;staging-all-all.txt&amp;lt;/code&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
 # change admin password&lt;br /&gt;
 config add CMD0 /user admin,my-admin-password&lt;br /&gt;
 config activate&lt;br /&gt;
 config rem CMD0 /user&lt;br /&gt;
&lt;br /&gt;
This will set the admin password to &amp;lt;code&amp;gt;my-admin-password&amp;lt;/code&amp;gt; during staging (it should be obvious that such staging should only be done in combination with [[#Enforcing_Trust|Enforcing Trust]], see above).&lt;br /&gt;
&lt;br /&gt;
=== A complete &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt; Sample ===&lt;br /&gt;
Here is a complete sample of a configuration file. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;status&lt;br /&gt;
	    dir=&amp;quot;status&amp;quot;&lt;br /&gt;
	    missing=&amp;quot;1000&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;backup&lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        allow=&amp;quot;22,23,0,1,2,3,4&amp;quot; &lt;br /&gt;
        initial=&amp;quot;1&amp;quot;&lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot;&lt;br /&gt;
	httpsport=&amp;quot;444&amp;quot;&lt;br /&gt;
        forcetrust=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
        dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
	CAname=&amp;quot;innovaphone Device Certification Authority,innovaphone Device Certification Authority 2&amp;quot;&lt;br /&gt;
        CSRsan-dns-1=&amp;quot;{name}.company.com&amp;quot;&lt;br /&gt;
        CSRsan-dns-2=&amp;quot;{hwid}.company.com&amp;quot;&lt;br /&gt;
        CSRsan-dns-3=&amp;quot;{rdns}&amp;quot;&lt;br /&gt;
        CSRsan-ip-1=&amp;quot;{realip}&amp;quot;&lt;br /&gt;
	/&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
	    &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
    &amp;lt;environments&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&amp;quot;intranet&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;sifi&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;berlin&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;verona&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;homeoffice&#039;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;mobile&#039;/&amp;gt;&lt;br /&gt;
   &amp;lt;/environments&lt;br /&gt;
    &amp;lt;queries&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;admin&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Subject&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@subject_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Issuer&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@issuer_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
    &amp;lt;/queries&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operation ===&lt;br /&gt;
&lt;br /&gt;
==== Configuring and Debugging a real Device ====&lt;br /&gt;
To configure your device for use with the update server, you simply set &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php&amp;lt;/code&amp;gt; as &#039;&#039;Command File URL&#039;&#039; in &#039;&#039;Services/Update&#039;&#039; (you can optionally add a &amp;lt;code&amp;gt;?env=envname1,envname2&amp;lt;/code&amp;gt; query argument if you want to set one or more specific environments for your device).  The update server will re-configure the device later on so that it uses all the required query arguments.&lt;br /&gt;
&lt;br /&gt;
Generally, there are the following methods to set the &#039;&#039;Command File URL&#039;&#039;&lt;br /&gt;
* configure it manually using the admin GUI&lt;br /&gt;
* provide it to the device using DHCP (this will however not work for the softwarephone or &#039;&#039;myPBX for Android/iOS&#039;&#039;)&lt;br /&gt;
* use the innovaphone provisioning service (see [[Reference10:Concept_Provisioning|Reference10:Concept Provisioning]] for details)&lt;br /&gt;
&lt;br /&gt;
Once the &#039;&#039;Command File URL&#039;&#039; is set on the device, you can debug what the update client in the device does, using the normal trace mechanism.  For this, you will want to open the &#039;&#039;Debug&#039;&#039; page (&amp;lt;code&amp;gt;http://x.x.x.x/debug.xml&amp;lt;/code&amp;gt;) and set the &#039;&#039;Update/Polling&#039;&#039; and &#039;&#039;Update/Execution&#039;&#039; check-marks.  When  the update client queries the update server, you will see lines like &lt;br /&gt;
&lt;br /&gt;
 0:0826:465:5 - upd_poll: state IDLE -&amp;gt; RECV&lt;br /&gt;
 0:0826:465:7 - IP.0 -&amp;gt; UPD-POLL.0 : SOCKET_GET_LOCAL_ADDR_RESULT(172.16.100.201,255.255.0.0,0,&#039;&#039;,ANY)&lt;br /&gt;
 0:0826:466:0 - IP.0 -&amp;gt; UPD-POLL.0 : SOCKET_GET_LOCAL_ADDR_RESULT(172.16.100.201,255.255.0.0,0,&#039;&#039;,ANY)&lt;br /&gt;
 0:0826:695:0 - upd_poll: state=RECV sent()&lt;br /&gt;
 0:0826:752:0 - upd_poll: status 200 headercomplete=1 contentlength=0&lt;br /&gt;
 0:0826:754:0 - upd_poll: recv_data(2199)&lt;br /&gt;
 0:0826:754:1 - upd_poll: recv_data(0) EOF&lt;br /&gt;
 0:0826:754:1 - upd_poll: GET EOF - state=RECV http-status=200 length=2199&lt;br /&gt;
 0:0826:754:1 - upd_poll: do commands&lt;br /&gt;
 0:0826:754:1 - upd_poll: state RECV -&amp;gt; EXEC&lt;br /&gt;
&lt;br /&gt;
in the trace.  Commands included in the update script will look like&lt;br /&gt;
&lt;br /&gt;
 0:0826:754:5 - script::get_line: &amp;gt;line(mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m)&lt;br /&gt;
 0:0826:754:5 - upd_poll: pass &#039;mod cmd UP0 /sync scfg https://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m&#039;)&lt;br /&gt;
&lt;br /&gt;
Finally, you do not need to wait for the next time the device decides to contact the update server.  Instead, you can force this by sending an &amp;lt;code&amp;gt;http://&amp;lt;/code&amp;gt;&#039;&#039;your-device-ip&amp;lt;code&amp;gt;/!mod cmd UP1 poll&amp;lt;/code&amp;gt; to the device.&lt;br /&gt;
&lt;br /&gt;
==== The Device Status Update Page ====&lt;br /&gt;
If status tracking is enabled (see [[#Device_Status | Device Status]] above), the update server will keep a list of devices it knows of.  You can see this list by calling &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php?mode=status&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
By default, the list will not be updated unless you refresh the page.  However, if you set the &#039;&#039;refresh&#039;&#039; attribute in the &#039;&#039;status&#039;&#039; tag in your &#039;&#039;user-config.xml&#039;&#039; file to &amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;, all entries in this list will be refreshed every 60 seconds (however, the list itself will not be reloaded, so to see new devices, you need to refresh the entire page).  Devices that have not been seen for more than 7 days are shown in a different colour.  Devices that have not been seen for longer than 90 days will be silently removed from the list.&lt;br /&gt;
&lt;br /&gt;
===== Filtering =====&lt;br /&gt;
From build 2011, you can filter the devices shown using the &#039;&#039;device filter&#039;&#039; field in the &#039;&#039;Device&#039;&#039; column header.  The filter string is matched against ip-address, serial number, type, name, phase, class, environment, firmware and bootcode.  Also, you can filter by using the keywords &#039;&#039;present&#039;&#039; and &#039;&#039;missing&#039;&#039; (based on the &#039;&#039;missing&#039;&#039; attribute of the &#039;&#039;status&#039;&#039; tag in your configuration file). If one of these attributes match your filter expression, the device is shown.&lt;br /&gt;
&lt;br /&gt;
A filter expression must match a complete &#039;&#039;word&#039;&#039;.  For example, if you filter by &amp;lt;code&amp;gt;16&amp;lt;/code&amp;gt; this would match the ip-address &amp;lt;code&amp;gt;172.&amp;lt;/code&amp;gt;16&amp;lt;code&amp;gt;.0.20&amp;lt;/code&amp;gt; but it would not match &amp;lt;code&amp;gt;192.&amp;lt;/code&amp;gt;16&amp;lt;code&amp;gt;8.0.1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you specify multiple filter expressions (separated by white space), only devices which match all of the expressions will be shown.  For example, if you filter by &amp;lt;code&amp;gt;172.16. ip222&amp;lt;/code&amp;gt; this might match all IP222 in your 172.16.*.* network.  Filter expressions are case insensitive.&lt;br /&gt;
&lt;br /&gt;
==== Approving Certificate Signing Requests ====&lt;br /&gt;
When you use custom certificate roll-out, you will see a column &#039;&#039;Certificates&#039;&#039; in the device status list, showing the devices certificate status.  &lt;br /&gt;
&lt;br /&gt;
[[Image:PHP_based_Update_Server_V2_Device_Status.png]]&lt;br /&gt;
&lt;br /&gt;
If a CSR has been created on the device, this will be available for download in the &#039;&#039;Files&#039;&#039; section of the &#039;&#039;Info&#039;&#039; column.  You can submit the CSR to your CA and then upload the signed request (using the &#039;&#039;Upload&#039;&#039; button in the &#039;&#039;Files&#039;&#039; section of the &#039;&#039;Info&#039;&#039; column).  The signed request will eventually be uploaded to the device then.  On  the device itself, the CSR is shown in &#039;&#039;General/Certificates&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[Image:PHP_based_Update_Server_V2_CSR.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Certificate Errors ====&lt;br /&gt;
When a signed certificate request uploaded to the device can not be installed on the device, you will see a message like &amp;lt;code&amp;gt;Certificate upload error - certificate handling stopped&amp;lt;/code&amp;gt; in the &#039;&#039;Certificates&#039;&#039; columns for the device.  In this case, any further processing will be stopped.  Most likely, the reason is that you uploaded the wrong file as signed certificate request (either not a signed certificate at all or a signed request for another device).&lt;br /&gt;
&lt;br /&gt;
In this case&lt;br /&gt;
* remove any certificate request from the device&lt;br /&gt;
* remove the &amp;lt;code&amp;gt;X509/REQUESTERROR&amp;lt;/code&amp;gt; from the device configuration (i.e. &amp;lt;code&amp;gt;vars del X509/REQUESTERROR&amp;lt;/code&amp;gt;)&lt;br /&gt;
: these 2 steps can be easily done by resetting the device to factory defaults and then set the &#039;&#039;Update URL&#039;&#039; again&lt;br /&gt;
* remove any stored files for the device on the update server (shown in the &#039;&#039;Certificates&#039;&#039; column)&lt;br /&gt;
&lt;br /&gt;
The normal process will start all over again then.&lt;br /&gt;
&lt;br /&gt;
=== Migrating old PHP Update Server Installations ===&lt;br /&gt;
==== Migrating from build 2000 and newer ====&lt;br /&gt;
* Copy all files and folders, &#039;&#039;&#039;except&#039;&#039;&#039; the &#039;&#039;scripts&#039;&#039; and &#039;&#039;config&#039;&#039; folder, from the source to your destination&lt;br /&gt;
* make sure all files and directories have correct owner (&#039;&#039;www-data&#039;&#039;), group (&#039;&#039;www-data&#039;&#039;) and mode (&#039;&#039;read&#039;&#039;/&#039;&#039;write&#039;&#039; plus &#039;&#039;execute&#039;&#039; for directories)&lt;br /&gt;
: for example, in WinSCP you can use the &#039;&#039;Properties (F9)&#039;&#039; dialogue on the installations root folder:&lt;br /&gt;
: [[Image:PHP based Update Server V2-WinSCP-Properties.png]]&lt;br /&gt;
* open the &#039;&#039;StatusPage&#039;&#039; and make sure you refresh all cached files in your browser (depending on your browser, this may happen with Ctrl-R or Ctrl-F5)&lt;br /&gt;
&lt;br /&gt;
==== Migrating from build 1011 and older ====&lt;br /&gt;
To upgrade from the [http://download.innovaphone.com/ice/wiki-src/index.php?urloffset=php-update-server%2F&amp;amp;name=php-update-server+%28all+available+builds%29&amp;amp;reverselevel=0&amp;amp;maxbuilds=999&amp;amp;root=c%3A%2Finetpub%2Fwwwroot%2Fdownload%2Fice%2Fdownload%2Fp%2Fwiki-src%2Fphp-update-server%2F1010+%28PHP+based+Update+Server+final%29%2F.. old version (builds up to 1011)] of the PHP based update server (as described in [[Howto:PHP based Update Server]]), do the following&lt;br /&gt;
&lt;br /&gt;
* diff your &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; to the one originally shipped (you can download it at [http://download.innovaphone.com/ice/download/p/wiki-src/php-update-server/1011%20(PHP%20based%20Update%20Server%20final)/php-update-server-1011.zip download.innovaphone.com/ice/wiki-src])&lt;br /&gt;
: take note of all the changes you made to it&lt;br /&gt;
* install the new version of the update server to a different URL&lt;br /&gt;
* configure it according to your needs by modifying &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  Do not modify the new &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt;!&lt;br /&gt;
** apply all modifications you did to your old &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; to your new &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
** if you have used a custom setting for fwstorage/@url, you need to change it a bit.  Change for example &amp;lt;code&amp;gt;url=&amp;quot;http://myfwserver.mycompany.com&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;http://myfwserver.mycompany.com/{build}/&amp;lt;/code&amp;gt; (note the trailing slash!)&lt;br /&gt;
* copy all your update script snippet files from the old server (these are all the .txt files in the old server&#039;s root directory) to the &amp;lt;code&amp;gt;scripts&amp;lt;/code&amp;gt; directory of your new server&lt;br /&gt;
* copy the complete &amp;lt;code&amp;gt;fw&amp;lt;/code&amp;gt; tree from the old server to the &amp;lt;code&amp;gt;fw&amp;lt;/code&amp;gt; directory of your new server&lt;br /&gt;
* thoroughly test your new installation with some test devices&lt;br /&gt;
* when satisfied, edit &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; and change the code as described in the comment inside the file&lt;br /&gt;
* copy &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; from the new installation to the old installation&lt;br /&gt;
* on one of the devices which are currently served by the old update server, change the &#039;&#039;Command File URL&#039;&#039; so that it points to &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt;.  Do not change anything else in the URL. So if it currently is set to e.g. &lt;br /&gt;
: &amp;lt;code&amp;gt;https://172.16.0.90/update/update.php?type=#t&amp;amp;env=sifi&amp;amp;polling=0&amp;amp;phase=update&amp;lt;/code&amp;gt;, change it to&lt;br /&gt;
: &amp;lt;code&amp;gt;https://172.16.0.90/update/update-migrate.php?type=#t&amp;amp;env=sifi&amp;amp;polling=0&amp;amp;phase=update&amp;lt;/code&amp;gt;&lt;br /&gt;
* verify that this device properly switches to your new installation&lt;br /&gt;
** the &#039;&#039;Command File URL&#039;&#039; is changed so that it points to the new installation&lt;br /&gt;
** the device shows up in the device status page of your new server&lt;br /&gt;
&lt;br /&gt;
* rename &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;update-old.php&amp;lt;/code&amp;gt; in your old update server&lt;br /&gt;
* rename &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt; in your old update server&lt;br /&gt;
* verify that all of your devices start showing up in the new server&#039;s status page&lt;br /&gt;
&lt;br /&gt;
=== Complete Parameter Reference ===&lt;br /&gt;
Note: attributes are marked with an &#039;&#039;at&#039;&#039; (&amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;) prefix.  So &#039;&#039;master/@info&#039;&#039; refers to the &#039;&#039;info&#039;&#039; attribute in the &#039;&#039;master&#039;&#039; tag.&lt;br /&gt;
&lt;br /&gt;
The following tags and attributes are available in the &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt; file, their default values are configured in &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; (which you should not modify):&lt;br /&gt;
&lt;br /&gt;
==== master ====&lt;br /&gt;
Defines the reference device where the firmware and boot code information is taken from.&lt;br /&gt;
; master/@info : the URL to the device info data.  Set it to an URL like &amp;lt;code&amp;gt;http://&amp;lt;/code&amp;gt;&#039;&#039;your-reference-device&#039;&#039;&amp;lt;code&amp;gt;/CMD0/box_info.xml&amp;lt;/code&amp;gt;. Please note that this device must not have the &#039;&#039;Password protect all HTTP pages&#039;&#039; set in &#039;&#039;Services/HTTP/Server&#039;&#039;.  If you use the literal &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt;, the master device will not be queried&lt;br /&gt;
; master/@expire : the firmware info cache lifetime.  The firmware information is cached in a file (to make sure this information is present even if the reference device is off-line).  The cache will not be refreshed before the &#039;&#039;expire&#039;&#039; time (in seconds) is expired&lt;br /&gt;
; master/@cache : the cache file name.  The web server must be able to write this file (see [[#Installation | &#039;&#039;Installation&#039;&#039; ]] above)&lt;br /&gt;
; master/@user : if non-empty, this is the user name required to access the update server&#039;s web ui&lt;br /&gt;
; master/@password : the password&lt;br /&gt;
&lt;br /&gt;
From build 2009, you can control the firmware and bootcode version to use on update:&lt;br /&gt;
; master/@firmware : if set, it may be one of &lt;br /&gt;
:: &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt; (default if not set) : the firmware version is derived from the master device&lt;br /&gt;
:: &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt; : the firmware update is generally disabled&lt;br /&gt;
:: &#039;&#039;build-number&#039;&#039; : the firmware is set to a certain &#039;&#039;build-number&#039;&#039; regardless of the firmware running on the master device&lt;br /&gt;
; master/@bootcode: if set, it may be one of &lt;br /&gt;
:: &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt; (default if not set) : the bootcode version is derived from the master device&lt;br /&gt;
:: &amp;lt;code&amp;gt;firmware&amp;lt;/code&amp;gt; : the bootcode version is set to the firmware version. This may be useful if the master device has no bootcode (e.g. the ipva)&lt;br /&gt;
:: &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt; : the bootcode update is generally disabled&lt;br /&gt;
:: &#039;&#039;build-number&#039;&#039; : the bootcode is set to a certain &#039;&#039;build-number&#039;&#039; regardless of the bootcode running on the master device&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;master &lt;br /&gt;
        info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;&lt;br /&gt;
        expire=&amp;quot;3600&amp;quot;&lt;br /&gt;
        cache=&amp;quot;cache/master-info.xml&amp;quot;&lt;br /&gt;
        user=&amp;quot;myadmin&amp;quot;&lt;br /&gt;
        password=&amp;quot;mysecret&amp;quot;&lt;br /&gt;
        firmware=&amp;quot;4711&amp;quot;&lt;br /&gt;
        bootcode=&amp;quot;firmware&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== master/applies ====&lt;br /&gt;
Available from build 2009.&lt;br /&gt;
&lt;br /&gt;
Boot code and firmware updates are only executed by devices which match all of the given &amp;lt;applies&amp;gt; conditions. A condition is met if the device belongs to the class that is given as tag content.  If the &#039;&#039;env&#039;&#039; attribute is set, the tag content is interpreted as an &#039;&#039;environment&#039;&#039; name which has to match.&lt;br /&gt;
&lt;br /&gt;
; master/applies/@env : if this attribute exists, the tag content is compared with the environments the device is in.  Otherwise, it is compared with the classes it is in &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;master &lt;br /&gt;
    info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;&lt;br /&gt;
    expire=&amp;quot;3600&amp;quot;&lt;br /&gt;
    cache=&amp;quot;cache/master-info.xml&amp;quot;&lt;br /&gt;
    user=&amp;quot;myadmin&amp;quot;&lt;br /&gt;
    password=&amp;quot;mysecret&amp;quot;&lt;br /&gt;
    firmware=&amp;quot;4711&amp;quot;&lt;br /&gt;
    bootcode=&amp;quot;firmware&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- applied to phones in berlin only --&amp;gt;&lt;br /&gt;
    &amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
    &amp;lt;applies env=&amp;quot;&amp;quot;&amp;gt;berlin&amp;lt;/applies&amp;gt;&lt;br /&gt;
&amp;lt;/master&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== fwstorage ====&lt;br /&gt;
Defines from where the device will retrieve the firmware files for updates.&lt;br /&gt;
; fwstorage/@url :  defines the URL to retrieve the files from.  In this URL, the following meta words will be replaced as follows:&lt;br /&gt;
:* &amp;lt;code&amp;gt;{build}&amp;lt;/code&amp;gt; - the requested firmware or boot-code &lt;br /&gt;
:* &amp;lt;code&amp;gt;{model}&amp;lt;/code&amp;gt; - the devices type (e.g. &amp;lt;code&amp;gt;IP232&amp;lt;/code&amp;gt;).  This is derived from the &#039;&#039;type&#039;&#039; query argument used in the update URL which is set to the value &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; which in turn is expanded to the [[Reference10:Concept_Update_Server#Scfg_command|&#039;&#039;device type&#039;&#039;]] of the device requesting the update script&lt;br /&gt;
:* &amp;lt;code&amp;gt;{filetype}&amp;lt;/code&amp;gt; - the type of the required file, either &amp;lt;code&amp;gt;boot&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;prot&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code&amp;gt;{filename}&amp;lt;/code&amp;gt; - (from build 2014) the boot code or firmware filename for the device in lower case.  Required if you use the LAP as firmware storage and firmware files are falsely requested in uppercase letters (as URLs on the LAP are case sensitive and if the files are requested with upper case names, the original files with lowercase name are not found).  This also allows you to use alternate firmware file names (such as e.g. &amp;lt;code&amp;gt;ip110-sip.bin&amp;lt;/code&amp;gt;).  See the &#039;&#039;filenames&#039;&#039; tag&lt;br /&gt;
Note that if the &#039;&#039;url&#039;&#039; ends with a slash (&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;), the calling device will automatically [[Reference10:Concept_Update_Server#Prot_command|append the name of the requested file]]. In this case, the file system the URL points to must therefore contain sub-directories for each firmware build which contain the corresponding firmware builds (e.g, &#039;&#039;fw/12345/ip232.bin&#039;&#039;).  If &#039;&#039;url&#039;&#039; is not an URL (as is the case for the default value &amp;lt;code&amp;gt;fw/{build}/&amp;lt;/code&amp;gt;), it is treated as a sub-directory underneath the update server&#039;s root directory&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;fwstorage url=&amp;quot;fw/{build}/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Loading firmware files from innovaphone.com =====&lt;br /&gt;
You can also load firmware from the innovaphone.com web site.  To do so, set &#039;&#039;url&#039;&#039; like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;fwstorage url=&amp;quot;http://webbuild.innovaphone.com/{build}/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that &#039;&#039;this is a voluntary service, no guarantee of availability, no service level agreement&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[User:Ckl|ckl]] 15:40, 21 February 2023 (CET) This service has been discontinued. You may consider using &amp;lt;code&amp;gt;https://store.innovaphone.com/release/download/{build}/&amp;lt;/code&amp;gt; instead.&lt;br /&gt;
&lt;br /&gt;
==== backup ====&lt;br /&gt;
Defines where backup files are kept.&lt;br /&gt;
; backup/@dir :  the directory underneath the script directory where backups are stored&lt;br /&gt;
; backup/@nbackups :  the number of different backup files kept&lt;br /&gt;
; backup/@scfg :  the target URL for the scfg command.  If this is not an url, it is interpreted relative to the script directory URL. You can add more options for the &#039;&#039;scfg&#039;&#039; command, like in &amp;lt;code&amp;gt;scfg=&amp;quot;update.php?mode=backup&amp;amp;amp;hwid=#h&amp;amp;amp;sn=#m ser hourly /force 1&amp;quot;&amp;lt;/code&amp;gt; (this example will make sure backups are attempted only once per hour, so as to reduce load on the server).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;backup &lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
        nbackups=&amp;quot;10&amp;quot;&lt;br /&gt;
        scfg=&amp;quot;update.php?mode=backup&amp;amp;amp;hwid=#h&amp;amp;amp;sn=#m&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== status ====&lt;br /&gt;
Defines details regarding the state kept for a device requesting an update script.&lt;br /&gt;
; status/@dir : the directory the status files are kept in (e.g. &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;).  Used as the name for a sub-directory underneath your install directory on your web server. You must make sure that files in this directory cannot be read by anyone without proper authentication, as such files may contain sensitive information.&lt;br /&gt;
; status/@expire : if set and not empty, devices which have not requested an update script will be removed from the inventory after &#039;&#039;n&#039;&#039; seconds.  For example, &#039;&#039;expire=&amp;quot;7776000&amp;quot;&#039;&#039; will forget about devices after 90 days with no contact&lt;br /&gt;
; status/@missing : devices are shown in a different colour (indicating that they are &#039;&#039;missing&#039;&#039;) after &#039;&#039;n&#039;&#039; seconds. For example, &#039;&#039;missing=&amp;quot;604800&amp;quot;&#039;&#039; will flag devices as missing after 7 days with no contact&lt;br /&gt;
; status/@refresh : if set and not empty and larger than zero, the admin user interface showing the known devices will refresh the status of all shown devices each &#039;&#039;n&#039;&#039; seconds&lt;br /&gt;
; status/@logkeep : number of seconds log messages for individual devices will be kept&lt;br /&gt;
; status/usehttpsdevlinks : if set to true, links to devices in the status page are created using the https:// scheme&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;status &lt;br /&gt;
        dir=&amp;quot;status&amp;quot; &lt;br /&gt;
        expire=&amp;quot;7776000&amp;quot; &lt;br /&gt;
        missing=&amp;quot;200&amp;quot; &lt;br /&gt;
        refresh=&amp;quot;10&amp;quot;&lt;br /&gt;
        logkeep=&amp;quot;90&amp;quot;&lt;br /&gt;
        usehttpsdevlinks=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== times ====&lt;br /&gt;
Defines details regarding the delivery of update scripts to requesting devices. &lt;br /&gt;
&lt;br /&gt;
; times/@dir : the directory the update scripts are stored in.  For security reasons, you may want to make sure that files in this directory cannot be read without proper authentication.&lt;br /&gt;
&lt;br /&gt;
These attributes define the arguments of the [[Reference10:Concept_Update_Server#Times_command | times command]].  If neither &#039;&#039;allow&#039;&#039; nor &#039;&#039;initial&#039;&#039; is set, no &#039;&#039;times&#039;&#039; command is used (that is, the update scripts will be processed at all times).&lt;br /&gt;
; times/@allow :  the hours to be used in the &#039;&#039;times&#039;&#039; command (as in &amp;lt;code&amp;gt;mod cmd UP1 times /allow &amp;lt;/code&amp;gt;&#039;&#039;hours&#039;&#039;)&lt;br /&gt;
; times/@initial &lt;br /&gt;
: the minutes to be used in the &#039;&#039;times&#039;&#039; command (as in &amp;lt;code&amp;gt;mod cmd UP1 times /initial &amp;lt;/code&amp;gt;&#039;&#039;minutes&#039;&#039;). If you want to use initial staging of virgin devices &#039;&#039;forcestaging&#039;&#039; must be &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Delivered update scripts can include a [[Reference10:Concept_Update_Server#Check_command | check command ]] if the &#039;&#039;check&#039;&#039; attribute is set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.  . In this case, the devices will executed the scripts again only when you have edited/changed them.&lt;br /&gt;
; times/@check :  if set to true, update scripts will be executed once only (unless their contents change)&lt;br /&gt;
&lt;br /&gt;
When editing a number of update scripts, it is often not desirable if one changed script is already executed before another is changed too.   When the &#039;&#039;grace&#039;&#039; attribute is set to a positive value, no script at all is delivered to requesting devices unless &#039;&#039;n&#039;&#039; seconds have expired since the last edit.  For example, setting &#039;&#039;grace&#039;&#039; to 90 gives you one and a half minute to finish all your edits. &lt;br /&gt;
&lt;br /&gt;
; times/@grace :  defines the number of seconds that must expire before update script changes take effect&lt;br /&gt;
&lt;br /&gt;
The update server works in either &#039;&#039;fast&#039;&#039; or &#039;&#039;normal&#039;&#039; mode. In &#039;&#039;fast&#039;&#039; mode, update scripts have to be requested more frequently, for example to step through multiple staging phases faster. This is enforced by modifying the calling device&#039;s &#039;&#039;Interval&#039;&#039; setting in [[Reference11r1:Services/Update | &#039;&#039;Services/Update &#039;&#039;]] and setting it to 1 in &#039;&#039;fast&#039;&#039; mode.&lt;br /&gt;
&lt;br /&gt;
; times/@interval :  polling interval in minutes for normal operation (that is, when all staging is done)&lt;br /&gt;
; times/@polling :  when you are using multiple &#039;&#039;phases&#039;&#039; (e.g. &#039;&#039;staging&#039;&#039; and &#039;&#039;update&#039;&#039;), this defines the number of seconds to wait before the device reads the scripts for the next phase (see [[Reference10:Concept_Update_Server#Provision_command | provision command]]) (please do not modify the default value)&lt;br /&gt;
&lt;br /&gt;
In some installations it may be desired to deliver update scripts with HTTPS only or even only to calling devices which have identified themselves with a proper TLS certificate.  &lt;br /&gt;
&lt;br /&gt;
; times/@forcehttps : if set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, update scripts will only be delivered if the device call in with HTTPS.  If the device is ready to receive an update script and still calls in with HTTP only, its &#039;&#039;Command File URL&#039;&#039; will be re-configured to use HTTPS automatically.&lt;br /&gt;
; times/@httpsport : if you use a non-standard port for HTTPS access to update scripts, it can be defined here&lt;br /&gt;
; times/@httpsurlmod : if your HTTPS URL differs from the HTTP URL, you can specifiy a &#039;&#039;modifier&#039;&#039;.  It has the form &amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&#039;&#039;pattern&#039;&#039;&amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&#039;&#039;replacement&#039;&#039;&amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt; where &#039;&#039;pattern&#039;&#039; is a [http://docs.php.net/manual/en/pcre.pattern.php PHP PCRE pattern]. For example, &amp;lt;code&amp;gt;!mtls/!!i&amp;lt;/code&amp;gt; will remove the string &amp;lt;code&amp;gt;mtls/&amp;lt;/code&amp;gt; from the URL used by the device to create the HTTPS URL to use. The delimiter (in this case &amp;quot;!&amp;quot;) can be changed according to your own wishes, the first character defines the delimiter. The &amp;quot;i&amp;quot; at the end ignores uppercase.&lt;br /&gt;
&lt;br /&gt;
Note: If you want to change the hostname of your URL, you have to add the Port 444 to your hostname. The code should then look like this: &amp;lt;code&amp;gt;!hostname1:444/mtls/!hostname2:444/!i&amp;lt;/code&amp;gt;.&lt;br /&gt;
; times/@forcetrust : if set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, update scripts will only be delivered if the device call in with HTTPS and a valid and trusted client certificate that identifies itself as the devices it claims to be&lt;br /&gt;
; times/@forcestaging : before build 2009, the restrictions imposed by the times/@allow settings affected all update &#039;&#039;phases&#039;&#039;.  This however makes staging cumbersome, as you usually want to restrict normal configuration changes to off-working-hours.  If it is &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the restriction will be applied only to the last phase (that is, the &#039;&#039;staging&#039;&#039; phases will execute immediately). Also, the final phase will be executed once by staged devices. &lt;br /&gt;
: Since build 2021 the standard value was changed to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        dir=&amp;quot;scripts&amp;quot; &lt;br /&gt;
        allow=&amp;quot;&amp;quot; &lt;br /&gt;
        initial=&amp;quot;&amp;quot; &lt;br /&gt;
        check=&amp;quot;true&amp;quot; &lt;br /&gt;
        polling=&amp;quot;5&amp;quot; &lt;br /&gt;
        interval=&amp;quot;15&amp;quot; &lt;br /&gt;
        grace=&amp;quot;90&amp;quot; &lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot; &lt;br /&gt;
        httpsport=&amp;quot;444&amp;quot; &lt;br /&gt;
        forcetrust=&amp;quot;false&amp;quot; &lt;br /&gt;
        httpsurlmod=&amp;quot;!mtls/!!i&amp;quot;&lt;br /&gt;
        forcestaging=&amp;quot;true&amp;quot;&lt;br /&gt;
/&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== phases ==== &lt;br /&gt;
Defines the scripting phases.  In many installations, there are initializations which should be performed once only.  This is known as the &#039;&#039;staging&#039;&#039; phase.  Once this is done, the devices continue with the execution of the normal update scripts (this phase is known as &#039;&#039;update&#039;&#039; by default).  In the (unlikely) event that you want more or less phases, you can add/remove &#039;&#039;phase&#039;&#039; tags.&lt;br /&gt;
==== phases/phase ====&lt;br /&gt;
; phases/phase/@id :  the name for the phase&lt;br /&gt;
; phases/phase/@seq:  the sequential number for the phase. Phases are stepped-through in the numeric order defined by their &#039;&#039;seq&#039;&#039; attribute. &lt;br /&gt;
&lt;br /&gt;
By virtue of the &#039;&#039;seq&#039;&#039; attribute, you can insert phases in to the set of phases defined by default, which is&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
        &amp;lt;!-- sequence is important! --&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;update&amp;quot; seq=&amp;quot;200&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For example,&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;phase&amp;quot; seq=&amp;quot;150&amp;quot;&amp;gt;&amp;lt;/phase&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
will insert a custom phase &#039;&#039;myphase&#039;&#039; as second phase.&lt;br /&gt;
&lt;br /&gt;
==== environments ====&lt;br /&gt;
Defines the distinguished environments.  Devices can have zero or more &#039;&#039;environments&#039;&#039; associated.  The environments a device is considered to be in must be passed as &amp;lt;code&amp;gt;?env=&amp;lt;/code&amp;gt;&#039;&#039;name1,name2,..&#039;&#039; URL query arg in the update url.  &lt;br /&gt;
&lt;br /&gt;
Update scripts for all environments listed will be applied.&lt;br /&gt;
First the environment scripts itself, then all implied environments in the same order as the &#039;&#039;implies&#039;&#039; tags are listed in the config. &lt;br /&gt;
&lt;br /&gt;
The default config file defines the environments &#039;&#039;intern&#039;&#039; and &#039;&#039;homeoffice&#039;&#039; but you can define your own if you like.&lt;br /&gt;
&lt;br /&gt;
==== environments/environment ====&lt;br /&gt;
; environments/environment/@id :  the name for the environment&lt;br /&gt;
&lt;br /&gt;
==== environments/environment/implies ====&lt;br /&gt;
Each &#039;&#039;environment&#039;&#039; may have a number of sub-tags of type &#039;&#039;implies&#039;&#039;. It contains the &#039;&#039;id&#039;&#039; of another &#039;&#039;environment&#039;&#039;.   If a device is in an environment with an &#039;&#039;implies&#039;&#039; sub-tag, it is assumed that it is in the implied environment also. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;environments&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;hq&#039;&amp;gt;&lt;br /&gt;
            &amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
        &amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;intranet&#039;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;homeoffice&#039;/&amp;gt;&lt;br /&gt;
    &amp;lt;/environments&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &amp;lt;code&amp;gt;implies&amp;lt;/code&amp;gt; tag handles no recursion (therefore, in the above example, if &#039;&#039;intranet&#039;&#039; would have an implies, a device in environment &#039;&#039;hq&#039;&#039; would not inherit this implication.  Instead, you must list it explicitly for the &#039;&#039;hq&#039;&#039; environment).&lt;br /&gt;
&lt;br /&gt;
If multiple environments will be used they will be applied also in the same order as the &#039;&#039;environment&#039;&#039; tags are listed in the config.&lt;br /&gt;
&lt;br /&gt;
;There are some special things to keep in mind when adding multiple environments in the &#039;&#039;env&#039;&#039; attribute and they use the &#039;&#039;implies&#039;&#039; tag in the config.&lt;br /&gt;
:- The first environment specified in the arg &#039;&#039;env&#039;&#039; will be processed as expected with all children.&lt;br /&gt;
:- Recursive &#039;&#039;implies&#039;&#039; from an environment added via &#039;&#039;implies&#039;&#039; is not performed. (No children&#039;s children)&lt;br /&gt;
:- Only the first environment which is specified in the &#039;&#039;env&#039;&#039; arg with implies is processed, all additional values in the arg &#039;&#039;env&#039;&#039; will be ignored.&lt;br /&gt;
:- If the environment in the arg &#039;&#039;env&#039;&#039; it is not the first value, then it must also use the &#039;&#039;implies&#039;&#039; config to implies itself. Otherwise only child are processed.&lt;br /&gt;
&lt;br /&gt;
==== classes ====&lt;br /&gt;
Defines the available device classes.  Devices of different classes (e.g. phones and gateways) can have different update scripts. The device class is derived from the &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; (device type) query arg of the update script URL (which is why you must configure it in the update URL).  By default, the classes &#039;&#039;phone&#039;&#039;, &#039;&#039;opus_phone&#039;&#039;, &#039;&#039;pre_opus_phone&#039;&#039;, &#039;&#039;phone_oldui&#039;&#039;, &#039;&#039;phone_newui&#039;&#039;, &#039;&#039;mobile&#039;&#039;, &#039;&#039;gw&#039;&#039;, &#039;&#039;fxogw&#039;&#039;, &#039;&#039;fxsgw&#039;&#039;, &#039;&#039;brigw&#039;&#039;, &#039;&#039;prigw&#039;&#039; are recognized (newer versions may include more and/or updated class definitions).   Also, any device is considered to be member of a class that has the device type as class-name.  For example, an IP112 is in a class called &#039;&#039;ip112&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A given device can be in multiple classes and will execute all update scripts available for these classes.&lt;br /&gt;
&lt;br /&gt;
==== classes/class ====&lt;br /&gt;
Each &#039;&#039;class&#039;&#039; has a number of sub-tags of type &#039;&#039;model&#039;&#039;. It contains the value replaced for the &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; query arg.  The models listed belong to the class.&lt;br /&gt;
; classes/class/@id :  the name of the class&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;classes&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;gw&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip0010&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip110&amp;lt;/model&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip232&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone_oldui&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip110&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone_newui&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip232&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
    &amp;lt;/classes&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== nobootdev ====&lt;br /&gt;
Device types listed here do not receive boot code updates.&lt;br /&gt;
===== nobootdev/model =====&lt;br /&gt;
Each model tag defines a device type that shall not receive boot code updates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;nobootdev&amp;gt; &lt;br /&gt;
        &amp;lt;model&amp;gt;ipva&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;ipvadec&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;swphone&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxa&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxi&amp;lt;/model&amp;gt;&lt;br /&gt;
    &amp;lt;/nobootdev&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== nofirmdev ====&lt;br /&gt;
Device types listed here do not receive firmware updates.&lt;br /&gt;
===== nofirmdev/model =====&lt;br /&gt;
Each model tag defines a device type that shall not receive firmware updates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;nofirmdev&amp;gt; &lt;br /&gt;
        &amp;lt;model&amp;gt;swphone&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxi&amp;lt;/model&amp;gt;&lt;br /&gt;
    &amp;lt;/nofirmdev&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== filenames ====&lt;br /&gt;
Available from build 2014. Allows you to define alternate firmware and boocode names for use with the &amp;lt;code&amp;gt;{filename}&amp;lt;/code&amp;gt; replacement (see the &#039;&#039;fwstorage&#039;&#039; tag), if required.&lt;br /&gt;
&lt;br /&gt;
===== filenames/model =====&lt;br /&gt;
Each model defines a set of alternative file names for a certain device type.&lt;br /&gt;
; filenames/model/@id : the (lowercase) device type identfier (e.g. &amp;lt;code&amp;gt;ip112&amp;lt;/code&amp;gt;). If this matches the device type of the calling device, the alternate file names are replaced&lt;br /&gt;
; filenames/model/@prot: the alternate firmware file name&lt;br /&gt;
; filenames/model/@boot: the alternate boot file name&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;filenames&amp;gt;&lt;br /&gt;
        &amp;lt;model id=&amp;quot;mypbxa&amp;quot; prot=&amp;quot;mypbx.apk&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/filenames&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
defines the firmware file name &amp;lt;code&amp;gt;mypbx.apk&amp;lt;/code&amp;gt; for the device type &amp;lt;code&amp;gt;mypbxa&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== stdargs ====&lt;br /&gt;
Better don&#039;t touch :-)&lt;br /&gt;
&lt;br /&gt;
==== customcerts ====&lt;br /&gt;
innovaphone hardware devices come with a device specific, trust-able &#039;&#039;device certificate&#039;&#039;.  However, in many situations it is desirable to roll-out customer-created &#039;&#039;custom  certificates&#039;&#039; to all devices.  The update server can do this.  This will replace the shipped devices certificates both on hardware devices (where all such certificates are derived from innovaphone&#039;s certificate authority) as well as on soft devices which run with a self.-signed certificate by default (such as the software-phone or &#039;&#039;myPBX for Android/iOS&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
; customcerts/@dir : the name of the directory underneath your installation directory which stores device certificates. you should make sure that this directory cannot be accessed without proper authentication&lt;br /&gt;
; customcerts/@CAkeys : a file name pattern (e.g. &amp;lt;code&amp;gt;CAkey*&amp;lt;/code&amp;gt;).  All files in &#039;&#039;customcerts/@dir&#039;&#039; which match the pattern must contain DER or PEM encoded public keys which form the &#039;&#039;certificate chain&#039;&#039; of your CA (usually it is only one and the public key of your CA). One key per file.  The files, when sorted by name, must contain the CA key itself in the last file (any intermediate certificates, if any, in the other files in correct order)&lt;br /&gt;
; customcerts/@CAtype : must be &amp;lt;code&amp;gt;manual&amp;lt;/code&amp;gt; currently&lt;br /&gt;
; customcerts/@CAname : a comma-separated list of CA names.  Devices presenting a certificate signed by one of these CAs will be considered as having a valid certificate.  Otherwise, they wil be instructed to create a &#039;&#039;certificate signing request&#039;&#039; (CSR) for subsequent submission to your CA&lt;br /&gt;
; customcerts/@CAnamesep : defines the name separator for &#039;&#039;customcerts/@CAname&#039;&#039;.  The default is &#039;&amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;&#039; and you must change it to a different value if one of your CAs includes a comma in its name&lt;br /&gt;
; customcerts/@renew : if set and not 0, certificates are replaced by new ones &#039;&#039;n&#039;&#039; days before they expire&lt;br /&gt;
; customcerts/@CAwildcard : normally, the update server will accept a certificate only if its CN matches the device&#039;s serial number.  However, sometimes, so-called &#039;&#039;wildcard certificates&#039;&#039; such as &amp;lt;code&amp;gt;*.innovaphone.com&amp;lt;/code&amp;gt; are used on a device (e.g. on a PBX or on a &#039;&#039;reverse proxy&#039;&#039;).  If set, the update server will also accept a certificate that contains a CN which equals the value of &#039;&#039;customcerts/@CAwildcard&#039;&#039;. Note that the CN must match literally.  For example, if &#039;&#039;&#039;&#039;customcerts/@CAwildcard&#039;&#039; is set to &amp;lt;code&amp;gt;*.innovaphone.com&amp;lt;/code&amp;gt; a CN like &amp;lt;code&amp;gt;host.innovaphone.com&amp;lt;/code&amp;gt; is not accepted&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the update server determines that a device calls in with an un-trusted or expired certificate, it will have it create a signing-request for a new certificate.  The requested certificate properties can be defined:&lt;br /&gt;
&lt;br /&gt;
; customcerts/@CSRkey : the key size, e.g. &amp;lt;code&amp;gt;2048-bit&amp;lt;/code&amp;gt;. Note that we do not recommend keys larger than 2048 bit (see [[Reference7:Certificate_management#Certificate_Key_Length_and_CPU_Usage]] for details)&lt;br /&gt;
; customcerts/@CSRsignature : the signature algorithm, e.g. &amp;lt;code&amp;gt;SH256&amp;lt;/code&amp;gt;&lt;br /&gt;
; customcerts/@CSRdn-cn : the CN (&#039;&#039;common name&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-ou : the OU (&#039;&#039;organizational unit&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-o : the O (&#039;&#039;organization&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-l : the L (&#039;&#039;locality&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-st : the ST (&#039;&#039;state or province&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-c : the C (&#039;&#039;country&#039;&#039;) part used for the DN (note: &#039;&#039;CSRdn&#039;&#039; for many CAs, must be a 2-letter ISO country code)&lt;br /&gt;
; customcerts/@CSRsan-dns-1 : the first of up to three DNS names &lt;br /&gt;
; customcerts/@CSRsan-ip-1 : the first of up to two IP addresses&lt;br /&gt;
&lt;br /&gt;
Within the set of CSR attributes, the following meta-words will be replaced:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;{realip}&amp;lt;/code&amp;gt; : the real IP address of the device as reported in the &amp;lt;code&amp;gt;ip=#i&amp;lt;/code&amp;gt; query argument&lt;br /&gt;
* &amp;lt;code&amp;gt;{ip}&amp;lt;/code&amp;gt; : the IP address of the device as seen by the update server&lt;br /&gt;
* &amp;lt;code&amp;gt;{proxy}&amp;lt;/code&amp;gt; : the IP address of the reverse proxy the device used to reach the update server&lt;br /&gt;
* &amp;lt;code&amp;gt;{sn}&amp;lt;/code&amp;gt; : the serial number of the device as reported in the &amp;lt;code&amp;gt;sn=#m&amp;lt;/code&amp;gt; query argument (e.g. &amp;lt;code&amp;gt;009033030df0&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;{hwid}&amp;lt;/code&amp;gt; : the hardware-id of the device as reported in the &amp;lt;code&amp;gt;sn=#m&amp;lt;/code&amp;gt; query argument (e.g. &amp;lt;code&amp;gt;IP1200-03-0d-f0&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;{name}&amp;lt;/code&amp;gt; : the &#039;&#039;Device Name&#039;&#039; (set in &#039;&#039;General/Admin&#039;&#039;) of the device&lt;br /&gt;
* &amp;lt;code&amp;gt;{rdns}&amp;lt;/code&amp;gt; : the DNS name found in a reverse DNS lookup for the real-ip address reported by the device (see &#039;&#039;{realip}&#039;&#039;) above&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;customcerts &lt;br /&gt;
        dir=&amp;quot;certs&amp;quot; &lt;br /&gt;
        CAkeys=&amp;quot;CAkey*&amp;quot; &lt;br /&gt;
        CAtype=&amp;quot;manual&amp;quot; &lt;br /&gt;
        CAname=&amp;quot;innovaphone-INNO-DC-W2K8-Zertifizierungsserver&amp;quot; &lt;br /&gt;
        CAnamesep=&amp;quot;,&amp;quot; &lt;br /&gt;
        CAwildcard=&amp;quot;*.innovaphone.com&amp;quot;&lt;br /&gt;
        CSRkey=&amp;quot;2048-bit&amp;quot; &lt;br /&gt;
        CSRsignature=&amp;quot;SH256&amp;quot; &lt;br /&gt;
        CSRdn-cn=&amp;quot;{hwid}&amp;quot; &lt;br /&gt;
        CSRdn-ou=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-o=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-l=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-st=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-c=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRsan-dns-1=&amp;quot;{name}.company.com&amp;quot; &lt;br /&gt;
        CSRsan-dns-2=&amp;quot;{hwid}.company.com&amp;quot; &lt;br /&gt;
        CSRsan-dns-3=&amp;quot;{rdns}&amp;quot; &lt;br /&gt;
        CSRsan-ip-1=&amp;quot;{realip}&amp;quot; &lt;br /&gt;
        CSRsan-ip-2=&amp;quot;&amp;quot; &lt;br /&gt;
        renew=&amp;quot;90&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries ====&lt;br /&gt;
If queries are defined and applicable for the calling device, it will be instructed to send certain information to the update server which will be stored in the device status file kept on the server.  Each piece of such information is defined using a separate &#039;&#039;query&#039;&#039; tag.&lt;br /&gt;
&lt;br /&gt;
; queries/@scfg : defines the URL used by the device to send the information.  Normally not changed from the default&lt;br /&gt;
&lt;br /&gt;
==== queries/query ====&lt;br /&gt;
Defines one piece of information to be submitted to the update server.&lt;br /&gt;
&lt;br /&gt;
; queries/query/@id : a unique name for the query&lt;br /&gt;
; queries/query/@title : a title for this piece of information shown in the device status&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;.&lt;br /&gt;
        &amp;lt;!-- retrieve and show some details from IP4/General/STUN page --&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;media&amp;quot; title=&amp;quot;Media&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd MEDIA xml-info&amp;lt;/cmd&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;NAT&amp;quot;&amp;gt;concat(/state/queries/media/info/nat/@result, &#039; (&#039;, /state/queries/media/info/nat/@public-addr, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Server&amp;quot;&amp;gt;concat(&#039;STUN: &#039;, /state/queries/media/info/@stun, &#039; TURN: &#039;, /state/queries/media/info/@turn, &#039; (&#039;, /state/queries/media/info/@turn-user, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;!-- show primary phone registration --&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;registration&amp;quot; title=&amp;quot;Registration&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd PHONE/USER phone-regs /cmd phone-regs&amp;lt;/cmd&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;State: User/Number&amp;quot;&amp;gt;concat(/state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@state, &#039;: &#039; , /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@h323, &#039;/&#039;, /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@e164)&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;PBX/ID&amp;quot;&amp;gt;concat(/state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@gk-addr, &#039;/&#039;, /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@gk-id)&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries/query/cmd ====&lt;br /&gt;
The content of this tag defines the command to be executed on the device which outputs the requested information. These are &#039;&#039;mod cmd&#039;&#039;s typically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;!-- get info for custom certificates --&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd X509 xml-info&amp;lt;/cmd&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Howto:Effect_arbitrary_Configuration_Changes_using_a_HTTP_Command_Line_Client_or_from_an_Update#Using_the_Mechanism_for_Device_Status_Queries ]] for details on how to find out which commands to use.&lt;br /&gt;
&lt;br /&gt;
==== queries/query/applies ====&lt;br /&gt;
Defined queries are only executed by devices which belong to the class that is given as tag content.  If the &#039;&#039;env&#039;&#039; atribute is set, the tag content is interpreted as an &#039;&#039;environment&#039;&#039; name which has to match.&lt;br /&gt;
&lt;br /&gt;
; queries/query/applies/@env : if this attribute exists, the tag content is compared with the environments the device is in.  Otherwise, it is compared with the classes it is in (unfortunately, you can not combine both)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- applied to phones only --&amp;gt;&lt;br /&gt;
&amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries/query/show====&lt;br /&gt;
If one or more  &#039;&#039;show&#039;&#039; tags are defined for the &#039;&#039;query&#039;&#039; tag, the data will be shown in the device status page.  The values shown are defined by the tag content which is an XPath expression selecting the data from the device state.  The XPath expression always begins with &amp;lt;code&amp;gt;/state/queries/&amp;lt;/code&amp;gt;&#039;&#039;query-id&#039;&#039; (as defined by the &#039;&#039;id&#039;&#039; attribute in the query tag).  &lt;br /&gt;
&lt;br /&gt;
; queries/query/show/@title : used as title when the values are displayed in the status page&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;show title=&amp;quot;NAT&amp;quot;&amp;gt;concat(/state/queries/media/info/nat/@result, &#039; (&#039;, /state/queries/media/info/nat/@public-addr, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hints for writing your update snippets ==&lt;br /&gt;
Writing update scripts is largely undocumented and sometimes tricky.  Here are some general guidelines.&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;config add/del&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Many setting are done using &amp;lt;code&amp;gt;config change&amp;lt;/code&amp;gt; commands.  So these are very useful in update scripts too.&lt;br /&gt;
&lt;br /&gt;
The straight forward method to find out which commands you need is as follows:&lt;br /&gt;
* get a device of the type in question and do factory reset&lt;br /&gt;
* save the configuration to a file&lt;br /&gt;
* do the desired settings using the normal web admin UI&lt;br /&gt;
* save the resulting configuration to another file&lt;br /&gt;
* compare the saved files&lt;br /&gt;
&lt;br /&gt;
Usually, you want to set only specific parts of the configuration line.  For example, assume you want to set the default coder to &#039;&#039;OPUS-WB&#039;&#039;. Your saved configuration line might look like&lt;br /&gt;
&lt;br /&gt;
 config change PHONE SIG /prot SH323 /gk-addr pbx.innovaphone.com /gk-id innovaphone.com /tones 0 /lcoder OPUS-WB,20, /coder OPUS-WB,20,k1&lt;br /&gt;
&lt;br /&gt;
To set only the coder settings, you would set the relevant options with the &amp;lt;code&amp;gt;config add&amp;lt;/code&amp;gt; command as follows:&lt;br /&gt;
&lt;br /&gt;
 config add PHONE SIG /lcoder OPUS-WB,20,&lt;br /&gt;
 config add PHONE SIG /coder OPUS-WB,20,k1&lt;br /&gt;
&lt;br /&gt;
You can also remove specific options, as in &lt;br /&gt;
&lt;br /&gt;
 config rem PHONE SIG /tones&lt;br /&gt;
&lt;br /&gt;
which would remove the &amp;lt;code&amp;gt;/tones 0&amp;lt;/code&amp;gt; from the configuration line for &amp;lt;code&amp;gt;PHONE SIG&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Note that the PHP update server will add the&lt;br /&gt;
&lt;br /&gt;
 config write&lt;br /&gt;
 config activate &lt;br /&gt;
 iresetn&lt;br /&gt;
&lt;br /&gt;
at the end of the delivered script automatically, so you do not need to do it yourself.  In fact, it is not recommended to have any reset command in your snippets.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;config change&amp;lt;/code&amp;gt; Lines with associated Passwords ====&lt;br /&gt;
Sometimes, there is a password associated with certain configurations.  Consider the STUN/TURN configuration: &lt;br /&gt;
&lt;br /&gt;
 config change MEDIA /stun stun.innovaphone.com /turn turn.innovaphone.com /turn-user innovaphone /turn-pwd 2 /nat-detect 61&lt;br /&gt;
&lt;br /&gt;
The TURN password, being sensitive, needs to be encrypted in your configuration.  This is why it is stored as a &#039;&#039;VAR&#039;&#039;, which provides encryption support (see below):&lt;br /&gt;
&lt;br /&gt;
 vars create MEDIA/TURN-PWD pc ....&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the relationship between an option and an associated VAR needs to be guessed.  You can be sure that the module name in the &amp;lt;code&amp;gt;config change&amp;lt;/code&amp;gt; matches the modules name in the &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; command. However, the variable name must be guessed. &lt;br /&gt;
&lt;br /&gt;
You can also set the password in your script using the &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt;&amp;lt;!-- , but this does make sense only in staging (that is pre-update-phase) scripts (see below for a discussion why). If you need to do it in a script snippet for the update phase, you should --&amp;gt;, however, you may also consider using a &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; (see below) such as e.g.&lt;br /&gt;
&lt;br /&gt;
 mod cmd MEDIA form /cmd form /del %2Fstun-slow /stun stun.innovaphone.com /turn turn.innovaphone.com /turn-user innovaphone /turn-pwd my-turn-pw /nat-detect 61&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Sometimes it makes sense to use &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; commands.  The syntax is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; vars create &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;name&amp;gt; &amp;lt;flags&amp;gt; &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&amp;lt;name&amp;gt;&#039;&#039; is a module name followed by a variable name, optionally followed by an index.  For example, a phone will store the currently selected main registration as &amp;lt;code&amp;gt;vars create PHONE/ACTIVE-USER p &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;index&amp;gt;&#039;&#039;.  So the module is &amp;lt;code&amp;gt;PHONE&amp;lt;/code&amp;gt; and the variable name is &amp;lt;code&amp;gt;ACTIVE-USER&amp;lt;/code&amp;gt;.  When the variable is multi-valued, an index is added to the name.  For example, the registration settings for all but the first registration are stored as indexed variable, as in &amp;lt;code&amp;gt;vars create PHONE/USER-REG/00001 p &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;settings&amp;gt;&#039;&#039;, where &amp;lt;code&amp;gt;00001&amp;lt;/code&amp;gt; is the index (registrations count from 0 in this case).&lt;br /&gt;
&lt;br /&gt;
There are a number of flags which can be combined, the most prominent used in update scripts are:&lt;br /&gt;
; p : permanent.  The var is stored in flash memory (you will almost always use this flag in update scripts)&lt;br /&gt;
; b : binary. The var value is binary.  Its &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is given as a bin2hex string&lt;br /&gt;
; c : crypted.  The var value needs to be encrypted and the &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; given is crypted&lt;br /&gt;
; x : crypted, plain value.  The var needs to be encrypted but the &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is given as plain (that is, un-encrypted) text. This allows you to set an encrypted variable without encrypting the desired value&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
undocumented flags&lt;br /&gt;
; h : hidden. The value is not shown in config dump&lt;br /&gt;
; s : secret. No sure what that does - ckl --&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
; l : log. Creates trace output whenever this VAR is modified&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
; a : auto-index.  ???&lt;br /&gt;
; u : unique, ???&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
; n : no-reset. If the &#039;n&#039; flag is given, setting the variable will not trigger the &#039;reset needed&#039; condition.  Whether or not setting a variable has an effect without a reset depends on the module using the variable.  Unfortunately, there is no documentation on which variables this works for, and we do not intend to provide such documentation.  In the end, you have to try it out. &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
; i : init. ???&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Please note that, unless the &#039;n&#039; flag is given, using &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; will &#039;&#039;always&#039;&#039; set the internal &#039;&#039;reset needed condition&#039;&#039; in the device (regardless which &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is set, even when the current value is set again).  This means that a subsequent &amp;lt;code&amp;gt;resetn&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;iresetn&amp;lt;/code&amp;gt; will always trigger a reset.  So if you use it, make sure that you use the &#039;&#039;times/@check&#039;&#039; ([[#times | see above]]) to protect your script from re-executing the snippet (and thus rebooting the device) all the time. &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
When you use a &amp;lt;code&amp;gt;mod cmd UP1 check ...&amp;lt;/code&amp;gt; command in your script (see times/@check [[#times | above]]), this will create an endless loop if you use &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; followed by one of the &amp;lt;code&amp;gt;resetn&amp;lt;/code&amp;gt; commands in the code guarded by the &amp;lt;code&amp;gt;check&amp;lt;/code&amp;gt; command. This code will never be fully executed, as the &#039;&#039;reset needed&#039;&#039; condition will always be set and the reset will always happen.  You can use it in &#039;&#039;pre-update-phase&#039;&#039; scripts (that is, during the staging process) as this is not protected by a &amp;lt;code&amp;gt;check&amp;lt;/code&amp;gt; command.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
See [[Howto:Effect arbitrary Configuration Changes using a HTTP Command Line Client or from an Update]] for a discussion of how to use &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; in update scripts.&lt;br /&gt;
&lt;br /&gt;
== Writing your own Dynamic Scripting Code ==&lt;br /&gt;
NB: this feature is available from build 2020.&lt;br /&gt;
&lt;br /&gt;
By default, the update server delivers update scripts which are composed from a number of static files (so-called &#039;&#039;snippets&#039;&#039;).  Sometimes it makes sense however, to create such snippets dynamically (e.g. based on a database lookup).  Here is how to do this.&lt;br /&gt;
&lt;br /&gt;
Dynamic scripting is implemented by a user-supplied custom &amp;lt;code&amp;gt;class CustomUpdateSnippet&amp;lt;/code&amp;gt;.  The code for this class must be placed in to the file &amp;lt;code&amp;gt;config/scripting.class.php&amp;lt;/code&amp;gt;.  As a starter, sample class code is available in &amp;lt;code&amp;gt;config/scripting.class-sample.php&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * to provide your own runtime generated snippets, rename this file to &#039;scripting.class.php&#039; and &lt;br /&gt;
 * implement the member functions&lt;br /&gt;
 * $property will have one member called &lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
class CustomUpdateSnippet extends UpdateSnippet {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * snippet to deliver after standard text snippets&lt;br /&gt;
     * @return array of string&lt;br /&gt;
     */&lt;br /&gt;
    public function getPostSnippet() {&lt;br /&gt;
        return parent::getPostSnippet();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * snippet to deliver before standard text snippets&lt;br /&gt;
     * @return array of strings&lt;br /&gt;
     */&lt;br /&gt;
    public function getPreSnippet() {&lt;br /&gt;
        return parent::getPreSnippet();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /** &lt;br /&gt;
     * do we want to suppress the standard text snippets?&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function sendStandardSnippets() {&lt;br /&gt;
        return parent::sendStandardSnippets();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample code overrides of the classes member functions just call the base classes which do nothing at all. So if you just copy the sample code into &amp;lt;code&amp;gt;scripting.class.php&amp;lt;/code&amp;gt;, nothing will change.  However, if &amp;lt;code&amp;gt;getPreSnippet()&amp;lt;/code&amp;gt; returns an array of strings (the parent class function returns an empty array), each array member will be sent to the calling device &#039;&#039;before&#039;&#039; the standard snippets are sent.  Likewise, if &amp;lt;code&amp;gt;getPostSnippet()&amp;lt;/code&amp;gt; returns an array of strings (the parent class function returns an empty array), each array member will be sent to the calling device &#039;&#039;after&#039;&#039; the standard snippets are sent. If &amp;lt;code&amp;gt;sendStandardSnippets()&amp;lt;/code&amp;gt; returns false, the standard snippets will not be sent.&lt;br /&gt;
&lt;br /&gt;
To determine the dynamic snippets to send, the user-provided &amp;lt;code&amp;gt;class CustomUpdateSnippet&amp;lt;/code&amp;gt; has access to the members of its base &amp;lt;code&amp;gt;class UpdateSnippet&amp;lt;/code&amp;gt;, namely the &amp;lt;code&amp;gt;var $statexml&amp;lt;/code&amp;gt; member. This member contains a &amp;lt;code&amp;gt;SimpleXMLElement&amp;lt;/code&amp;gt; object with all state information available for the calling device.&lt;br /&gt;
&lt;br /&gt;
Here is a sample state found in &amp;lt;code&amp;gt;$statexml&amp;lt;/code&amp;gt; (as output by the &amp;lt;code&amp;gt;dump()&amp;lt;/code&amp;gt; member function): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;state seen=&amp;quot;1522065435&amp;quot; requested=&amp;quot;130774bootcode&amp;quot; phase=&amp;quot;update&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;device sn=&amp;quot;00-90-33-3e-0c-57&amp;quot; type=&amp;quot;IP112&amp;quot; classes=&amp;quot;phone, opus_phone, phone_newui, hstrace, ip112&amp;quot; ip=&amp;quot;127.0.0.1&amp;quot; rp=&amp;quot;false&amp;quot; phase=&amp;quot;update&amp;quot;&lt;br /&gt;
    environments=&amp;quot;sifi, 172net&amp;quot; certstat=&amp;quot;either certificate handling or state tracking not enabled - not doing any certificate checking&amp;quot; hwid=&amp;quot;IP222-46-5c-77&amp;quot; realip=&amp;quot;172.16.80.241&amp;quot; requestDownloaded=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;firmware requested=&amp;quot;130986&amp;quot; requested-at=&amp;quot;1522065435&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;bootcode requested-at=&amp;quot;1522065435&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;config filename=&amp;quot;scripts/all-all-all.txt&amp;quot; delivered=&amp;quot;1522065426&amp;quot; version=&amp;quot;1486559970&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/state&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The most interesting elements in this XML are probably the attributes of the &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;device&amp;lt;/code&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
== Hints for using custom SSL Certificates ==&lt;br /&gt;
&lt;br /&gt;
Using your own SSL certificates can be useful depending on the scenario.&lt;br /&gt;
&lt;br /&gt;
We have two methods to accomplish this:&lt;br /&gt;
&lt;br /&gt;
=== Standard scenario as described in this wiki article ===&lt;br /&gt;
The idea is that each certificate request is checked manually, edited and the UpdateServer is provided with the new device certificate.&lt;br /&gt;
&lt;br /&gt;
=== Special scenario with automated certificate renewal ===&lt;br /&gt;
The idea is that every new/unknown (untrusted) device connects to the staging server. Here the device is released by manual checking/authorization by getting its first certificate. All further extensions can happen automatically afterwards.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: All important settings concerning file permissions, access and co must be used from the above article and are only skipped in this part!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We will create two Update-Server instances with the following configuration.&lt;br /&gt;
&lt;br /&gt;
# Staging Server (HTTPS/443)&lt;br /&gt;
#*Put the sources in &amp;lt;code&amp;gt;/var/www/innovaphone/update&amp;lt;/code&amp;gt;&lt;br /&gt;
#*Use your specific SSL configuration &#039;&#039;&amp;lt;customcerts&amp;gt;&#039;&#039; as described [[#customcerts | above]].&lt;br /&gt;
#*Use the following settings in the configuration of &#039;&#039;&amp;lt;times&amp;gt;&#039;&#039;:&lt;br /&gt;
#*:&amp;lt;code&amp;gt;force https = &amp;quot;true&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*:&amp;lt;code&amp;gt;httpsport = &amp;quot;444&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*:&amp;lt;code&amp;gt;force trust = &amp;quot;true&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*:&amp;lt;code&amp;gt;httpsurlmod = &amp;quot;!update/i!!&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*Activate the query &#039;&#039;certificates&#039;&#039; as described [[#Delivering_Custom_Certificates | above]]&lt;br /&gt;
#*Configure the firmware update via the master tag as described [[#Delivering_Firmware_and_Boot_Code| above]]&lt;br /&gt;
#* &#039;&#039;&#039;Important&#039;&#039;&#039;: Do not submit any further customer specific device configurations in the staging Server&lt;br /&gt;
# Final MTLS / 444 update server&lt;br /&gt;
#*Put the sources in &amp;lt;code&amp;gt;/var/www/innovaphone/mts&amp;lt;/code&amp;gt;&lt;br /&gt;
#*Use your specific SSL configuration &#039;&#039;&amp;lt;customcerts&amp;gt;&#039;&#039; as described [[#customcerts | above]] with &amp;lt;code&amp;gt;renew = &amp;quot;x&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*Use the following settings in the configuration of &#039;&#039;&amp;lt;times&amp;gt;&#039;&#039;:&lt;br /&gt;
#*:&amp;lt;code&amp;gt;force https = &amp;quot;true&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*:&amp;lt;code&amp;gt;httpsport = &amp;quot;444&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*:&amp;lt;code&amp;gt;force trust = &amp;quot;true&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*:&amp;lt;code&amp;gt;httpsurlmod = &amp;quot;!mtls/i!!&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*Activate the query &#039;&#039;certificates&#039;&#039; as described [[#Delivering_Custom_Certificates | above]]&lt;br /&gt;
#*Configure the firmware update via the master tag as described [[#Delivering_Firmware_and_Boot_Code | above]]&lt;br /&gt;
#*Store all customer specific device configurations&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The meaning of the two different instances is:&lt;br /&gt;
*The staging server &amp;lt;code&amp;gt;https://[ip]/update/admin/admin.php&amp;lt;/code&amp;gt; will generate the provisioning URLs for new devices.&lt;br /&gt;
*All new/unknown (untrusted) devices are only in the staging server.&lt;br /&gt;
**Here you can check the devices and provide them a valid certificate after check/authorization.&lt;br /&gt;
*With a valid certificate, the UpdateURL is automatically changed to the MTLS instance.&lt;br /&gt;
*As soon as a device connects via MTLS we trust this device and we can use an automatic extension of the certificates.&lt;br /&gt;
** Waiting CSR requests are in the configured folder &#039;&#039;certs&#039;&#039; in the notation &amp;lt;code&amp;gt;&amp;quot;[mac]-request.p10.pem&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** If you operate your own CA, feel free to automate the reissue of the certificates via a sheduled Cronjob&lt;br /&gt;
*** Help for Linux: [[Howto:Creating_custom_Certificates_using_a_OpenSSL_Certificate_Authority]]&lt;br /&gt;
*** Help for Windows: [[Howto:Creating_custom_Certificates_using_a_Windows_Certificate_Authority]]&lt;br /&gt;
** If a signed certificate with the format &amp;lt;code&amp;gt;&amp;quot;[mac]-signedrequest.cer&amp;quot;&amp;lt;/code&amp;gt; is placed in the certs folder, the certificate is automatically updated on the device.&lt;br /&gt;
&lt;br /&gt;
== Optional Configurations on the Linux Application Platform ==&lt;br /&gt;
===Support for more Connections===&lt;br /&gt;
By default the LAP&#039;s web server lighttpd allows for 512 concurrent connections with 1024 open file descriptors.  When you serve a huge number of devices with the update server, then this might be too low.  You will see some devices not being able to contact the update server for a while.  This should not be a real issue as the devices will retry.  However, updating all devices may take long due to this.&lt;br /&gt;
&lt;br /&gt;
In the lighttpd log (in &amp;lt;code&amp;gt;/var/log/lighttpd&amp;lt;/code&amp;gt; on the LAP), you will see entries like this:&lt;br /&gt;
&lt;br /&gt;
 2017-10-16 13:45:18: (network_linux_sendfile.c.140) open failed:  Too many open files &lt;br /&gt;
 2017-10-16 13:45:18: (mod_fastcgi.c.3075) write failed: Too many open files 24 &lt;br /&gt;
 2017-10-16 13:45:18: (server.c.1434) [note] sockets disabled, out-of-fds &lt;br /&gt;
 2017-10-16 16:23:25: (response.c.634) file not found ... or so:  Too many open files /mtls/updatev2/web/innovaphone_logo_claim_fisch.png -&amp;gt;&lt;br /&gt;
 2017-10-16 17:57:45: (server.c.1432) [note] sockets disabled, connection limit reached &lt;br /&gt;
&lt;br /&gt;
If you experience such issues, proceed as follows:&lt;br /&gt;
&lt;br /&gt;
* connect to the LAP with SFTP (e.g. using WinSCP)&lt;br /&gt;
* change directory to &amp;lt;code&amp;gt;/etc/lighttpd&amp;lt;/code&amp;gt;&lt;br /&gt;
* edit &amp;lt;code&amp;gt;lighttpd.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
* search for the 2 lines which set &amp;lt;code&amp;gt;server.max-fds&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;server.max-connections&amp;lt;/code&amp;gt;&lt;br /&gt;
* replace the standard values.  We recommend to set the number of file descriptors to 4 times the number of requests when using the update server, e.g. &lt;br /&gt;
: old&lt;br /&gt;
:: server.max-fds             = 1024&lt;br /&gt;
:: server.max-connections     =  512&lt;br /&gt;
: new&lt;br /&gt;
:: server.max-fds             = 8000&lt;br /&gt;
:: server.max-connections     =  2000&lt;br /&gt;
* save the file&lt;br /&gt;
* restart linux (&#039;&#039;Diagnostics/Reset/Reboot&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Be sure to closely monitor the &#039;&#039;Diagnostics/Status&#039;&#039; page for a while after such configuration.  &lt;br /&gt;
&lt;br /&gt;
Also, when you update the LAP, you will have to re-do the changes (as always when you change something &#039;&#039;under the hood&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Debug files rotation based on logrotate ===&lt;br /&gt;
If you have to debug during operation and a lot of devices access the PHP Update Server V2, you have to keep track of the debug files or automatically limit them. For this you can use logrotate on the innovaphone Linux AP. With logrotate you can apply time-based or size-based rules when files are packed and when they are deleted.&lt;br /&gt;
* open the LAP&#039;s file system using a SFTP client such as e.g. [https://winscp.net/eng/index.php WinSCP] (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;root/iplinux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]). Note that you must use SFTP rather than WebDAV, as WebDAV will not give access to the executable web server files. &lt;br /&gt;
* Under the path &amp;lt;code&amp;gt;/etc/logrotate.d&amp;lt;/code&amp;gt; create a file e.g. &amp;lt;code&amp;gt;updateserver&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/etc/logrotate.d/updateserver&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this file now enter the following content and save it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 /var/www/innovaphone/mtls/update/debug/*.txt {&lt;br /&gt;
 size 5M&lt;br /&gt;
 missingok&lt;br /&gt;
 rotate 2&lt;br /&gt;
 compress&lt;br /&gt;
 delaycompress&lt;br /&gt;
 notifempty&lt;br /&gt;
 create 644 www-data www-data&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will include all *.txt files from the debug directory of the PHP Update Server V2 in the logrotate process of the operating system.&lt;br /&gt;
&lt;br /&gt;
; size 5M : means every 5MB the file is rotated or zipped&lt;br /&gt;
; size 5k : means every 5kB the file is rotated or zipped&lt;br /&gt;
Alternatively, you can also rotate the file based on time&lt;br /&gt;
; daily : means that every day the file is rotated or zipped&lt;br /&gt;
; weekly : means that the file is rotated or zipped daily&lt;br /&gt;
&lt;br /&gt;
; missingok : if a debug file does not exist, it will be ignored&lt;br /&gt;
; rotate n : files are removed before the last ones are deleted.&lt;br /&gt;
; compress : compresses the old debug files&lt;br /&gt;
; delaycompress : compresses the debug data only after it has been moved once&lt;br /&gt;
; notifempty : empty log files are not rotated&lt;br /&gt;
; create 644 www-data www-data : creates a new, empty debug file with appropriate permissions&lt;br /&gt;
&lt;br /&gt;
== Update Server and Reverse Proxy ==&lt;br /&gt;
It is possible to implement access to the update server through a &#039;&#039;reverse proxy&#039;&#039; (RP).  However, you have to keep some issues in mind:&lt;br /&gt;
* &#039;&#039;Mutual Transport Layer Security&#039;&#039; (MTLS) is not possible&lt;br /&gt;
: MTLS requires a direct TLS connection between the two parties. An RP however would terminate the TLS connection and entertain two independent connections to the parties.  This breaks MTLS.  If you want to use MTLS and serve external clients, you must therefore provide a direct access to the update server (that is an external IP address either directly or through port forwarding)&lt;br /&gt;
: see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts]] for details&lt;br /&gt;
* When using the RP, you can choose to forward encrypted traffic (HTTPS) arriving from external to the update server using HTTP (unencrypted). The update server however eventually rewrites the update URL in the calling devices configuration.  In order to do this, it determines the type of the internal connection.  So if the connection from the RP to the update server is using HTTP, it would create a &#039;&#039;http://...&#039;&#039; URL.  Otherwise it would create an &#039;&#039;https://..&#039;&#039; URL (also, it would be using the same port). This way, if the RP forwards requests to the update server with HTTP, the synthesized new URL for the calling client would use HTTP too, even though the original request was sent with HTTPS.  This may or may not be what you want (as all of your clients would end up using non-encrypted traffic). Even worse, it might not work at all, if the RP does not accept HTTP for example.&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
* [[Reference10:Concept_Update_Server]]&lt;br /&gt;
* [[Reference12r1:DHCP_client]]&lt;br /&gt;
* [[Reference10:Concept_Linux_Application_Platform]]&lt;br /&gt;
* [[Reference10:Concept_Provisioning]]&lt;br /&gt;
* [[Howto:PHP_based_Update_Server]] (old version)&lt;br /&gt;
* [[Howto:Creating_custom_Certificates_using_a_OpenSSL_Certificate_Authority]]&lt;br /&gt;
* [[Howto:Creating custom Certificates using a Windows Certificate Authority]]&lt;br /&gt;
* [[Howto:Effect arbitrary Configuration Changes using a HTTP Command Line Client or from an Update]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Sample|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference8:TAPI_Service_Provider&amp;diff=73879</id>
		<title>Reference8:TAPI Service Provider</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference8:TAPI_Service_Provider&amp;diff=73879"/>
		<updated>2024-11-04T17:23:54Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Related Articles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;innovaphone PBX V8.0 based TAPI Service Provider&#039;&#039; (TSP) is an enhanced version of the [[ Reference7:Unified Win32 and x64 TAPI Service Provider | previous TSP version ]] that takes advantage of the [[ Reference8:SOAP API | new SOAP features ]] provided with version 8 PBX firmware. It implements - like the previous versions - TAPI Version 3.0 without MSP (Media Service Provider).&lt;br /&gt;
&lt;br /&gt;
The [[Reference7:Unified Win32 and x64 TAPI Service Provider| previous TSP ]] still must be used for V7 PBX systems. &lt;br /&gt;
&lt;br /&gt;
This article describes how to install and use it as well how to configure the PBX in order for the TSP to work properly.&lt;br /&gt;
&lt;br /&gt;
==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
* innovaphone PBX V8.0 based TAPI Service Provider, Build 8001 and later&lt;br /&gt;
* innovaphone PBX V8 and later (that is, this Service Provider runs with PBX Firmware V8 and later)&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Enhancements ===&lt;br /&gt;
; Support for V8 firmware [[Reference8:Administration/PBX/Objects#Devices | devices]] : Each user object device is represented as a TAPI line (all sharing an identical address, the objects extension a.k.a. &#039;&#039;Number&#039;&#039; property).  This now allows to select individual registration devices when multiple devices are registered with the same PBX.  Please note that in V8, [[ Reference8:Administration/PBX/Objects/Edit_Forks | mobility devices ]] are not shown and thus not represented by  TAPI line device.  This was introduced in V9 only.&lt;br /&gt;
; Support for presence based lines :  These are TAPI lines shown which reflect the users presence state.  Presence state &#039;&#039;open&#039;&#039; is mapped to a TAPI device status &#039;&#039;in service&#039;&#039;.  Presence activity &#039;&#039;on-the-phone&#039;&#039; is mapped to a virtual call in state &#039;&#039;connected&#039;&#039;.&lt;br /&gt;
: &#039;&#039;&#039;NB&#039;&#039;&#039;: V8 PBX Firmware did set presence activity &#039;&#039;on-the-phone&#039;&#039; for each user object having a call.  Unfortunately, as this does create performance issues, this behaviour has been removed from V9 PBX Firmware.  The &#039;&#039;presence line&#039;&#039; feature may be useless with V9 PBX when the application did rely on this particular V8 PBX behaviour.&lt;br /&gt;
&lt;br /&gt;
===System Requirements===&lt;br /&gt;
The TSP will install on any Windows 32bit and x64 platform down to Windows XP/Server 2003.  For older systems, you must use a deprecated [[Reference7:TAPI_Service_Provider | previous TSP version]].  For systems running PBX firmware version 6 or earlier, you must use the even older [[Reference:TAPI_Service_Provider | version 5 based TSP]].  Note that there is no x64 version of the version 5 TSP!&lt;br /&gt;
&lt;br /&gt;
The TSP needs to maintain parallel connections to each individual PBX in the system.  For larger systems (i.e. systems with a huge number of PBXs), this may create substantial load to the underlying windows machine.  The number of parallel activities scheduled by the TSP is thus limited as a function of the available main memory and number of processors.  In particular, a maximum of 20 activities per available processor is allowed (up to build 8088, the limit is 60/processor for later builds).  If this limit is exceeded, the TSP will issue performance warnings of class WARNINGS in the TSP log file and system TAPI performance will be poor.  Use a more capable machine then.&lt;br /&gt;
&lt;br /&gt;
Microsoft Windows operating system version for desktop clients (as opposed to server systems) limit the number and performance of TCP/IP connections.  This may lead to bad performance or occasional request failures.  We generally recommend to use server operating systems for 3rd party TAPI installations thus.&lt;br /&gt;
&lt;br /&gt;
No special PBX licenses are required to use the innovaphone TSP.&lt;br /&gt;
&lt;br /&gt;
=== Download === &lt;br /&gt;
The TSP will be available on the tab &#039;&#039;Software&#039;&#039; in the [https://store.innovaphone.com/ Store].&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
Windows cannot run a Win32 TSP on an x64 platform (although it can run Win32 applications on such platforms).  This is why there are 2 versions of the setup, the x64 installer (&amp;lt;code&amp;gt;setup64-release.msi&amp;lt;/code&amp;gt;) and the Win32 installer (&amp;lt;code&amp;gt;setup32-release.msi&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;release&#039;&#039; setup packages provided will install the retail version.  This is recommended for production purposes but provides no debug options whatsoever.  To track down possible problems, support may instruct you to install the debug version.  &lt;br /&gt;
&lt;br /&gt;
The TSP may be installed on each machine where a desired TAPI based&lt;br /&gt;
application is to be run.  If for example, Outlook is to be used, then&lt;br /&gt;
each client PC running Outlook may have the TSP installed.  Although&lt;br /&gt;
this is typical for a 1st party configuration, all clients may have full&lt;br /&gt;
3rd party functionality, that is, they may control all existing lines.&lt;br /&gt;
&lt;br /&gt;
As an alternative, the TSP can be installed on a single machine and a&lt;br /&gt;
3rd party TAPI server product (such as the IXI-Call Server available as&lt;br /&gt;
a separate product) may be used to provide the network clients with a&lt;br /&gt;
TAPI interface.  Also, Microsoft’s Remote TAPI Server should work but is not being tested, so you use it on your own risk.&lt;br /&gt;
&lt;br /&gt;
To install, &lt;br /&gt;
* select and download the &amp;lt;code&amp;gt;setup32-release.msi&amp;lt;/code&amp;gt; install packages on 32bit platforms or the &amp;lt;code&amp;gt;setup64-release.msi&amp;lt;/code&amp;gt; install package on 64bit platforms.&lt;br /&gt;
* double-click the install package to launch the installer&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - zipcontent.png]]&lt;br /&gt;
* accept the license agreement&lt;br /&gt;
* select the target folder&lt;br /&gt;
* complete the installer&lt;br /&gt;
&lt;br /&gt;
When the installer has copied all files to the target machine, you need to add the TSP to the machine&#039;s TAPI system&lt;br /&gt;
* open the &#039;&#039;Telephone and Modem&#039;&#039; control panel&lt;br /&gt;
* Switch to the rightmost tab (&#039;&#039;Extras&#039;&#039;)&lt;br /&gt;
* Click on the &#039;&#039;Add...&#039;&#039; button&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - Control Panel Add.png]]&lt;br /&gt;
* Select the innovaphone TAPI provider driver&lt;br /&gt;
* Fill out the configuration dialogue&lt;br /&gt;
* Install the provider by clicking &#039;&#039;OK&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== File Organization ====&lt;br /&gt;
Windows forces all TAPI service provider files to reside in Windows&#039; &#039;&#039;System Folder&#039;&#039;.  This is the &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt; folder in your windows install directory (usually &amp;lt;code&amp;gt;C:\windows\system32&amp;lt;/code&amp;gt;), even if you are running an x64 platform!  The installer will thus copy these files (&amp;lt;code&amp;gt;tsp8.tsp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tsp8UI.dll&amp;lt;/code&amp;gt;) in to this directory.  All other files however will be copied to the &amp;lt;code&amp;gt;innovaphone AG\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt; folder underneath your systems &#039;&#039;Program Files Folder&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
The subdirectories &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Logs&amp;lt;/code&amp;gt; are created.  &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; contains the driver&#039;s debug version, &amp;lt;code&amp;gt;Logs&amp;lt;/code&amp;gt; will receive the log files when a debug version is used.&lt;br /&gt;
&lt;br /&gt;
On x64 platform systems, the Win32 version of the configuration DLL (&amp;lt;code&amp;gt;tsp8UI.dll&amp;lt;/code&amp;gt;) will be installed to the windows &#039;&#039;Windows on Windows64 System Folder&#039;&#039; (&amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
====Upgrading to a newer Version====&lt;br /&gt;
When you attempt to upgrade the TSP from a previous version, the Windows&lt;br /&gt;
installer will first remove any previous installation.  When the new&lt;br /&gt;
software is installed then, the TSP will be installed again into the&lt;br /&gt;
TAPI system.  &lt;br /&gt;
&lt;br /&gt;
There is no need to remove the driver from the &#039;&#039;Telephone and Modem Control Panel&#039;&#039;, as this would make you loose your driver configuration.&lt;br /&gt;
&lt;br /&gt;
====Upgrading from the old Win32-only Version====&lt;br /&gt;
If you upgrade from the older Win32-only versions of the TSP (soap-appl/tapi/7.00 or soap-appl/tapi/5.00), you must first remove the old TSP from &#039;&#039;telephone and modem&#039;&#039; control panel and uninstall the old product from the &#039;&#039;Software&#039;&#039; (or &#039;&#039;Programs and Functions&#039;&#039;) control panel.&lt;br /&gt;
&lt;br /&gt;
When you upgrade from the old V7 64-bit TSP (soap-appl/tapi/7.00-64), you should first update this older version to the latest build available.&lt;br /&gt;
&lt;br /&gt;
This procedure ensures that during the upgrade your TAPI lines retain their internal identifiers and thus their meaning in your TAPI application&#039;s configuration.&lt;br /&gt;
&lt;br /&gt;
==== Uninstalling the TSP ====&lt;br /&gt;
To uninstall the TSP proceed as follows&lt;br /&gt;
* Remove the TAPI driver from the TAPI system using &#039;&#039;Telephony and Modem Control Panel&#039;&#039;&lt;br /&gt;
* close &#039;&#039;Telephony and Modem Control Panel&#039;&#039;&lt;br /&gt;
* shut down windows telephony service. This can be done from the Windows &#039;&#039;Service Control Panel&#039;&#039; or by invoking &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt; from a command prompt&lt;br /&gt;
* remove the installation using windows &#039;&#039;Programs Control Panel&#039;&#039; or by invoking the original .msi again&lt;br /&gt;
&lt;br /&gt;
You will notice that Windows may fail to remove the driver files from the &#039;&#039;Windows System Directory&#039;&#039;.  To clean up remove &amp;lt;code&amp;gt;tsp8.tsp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tsp8UI.dll&amp;lt;/code&amp;gt; from the &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt; folder as well as - on x64 systems - from the &amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Also, if you did file tracing, any remaining debug files in the &amp;lt;code&amp;gt;Logs&amp;lt;/code&amp;gt; folder are left over and need to be removed manually.&lt;br /&gt;
&lt;br /&gt;
The TSP will create some entries in the windows registry which will not be removed on uninstall.  It is recommended to leave these entries as is.  Only if you are sure you will never install the TSP again on this system or you are sure you will never use it with the PBX installation you used so far, you may want to delete them from the registry.&lt;br /&gt;
&lt;br /&gt;
==== Rolling out First Party TSPs to multiple PCs ====&lt;br /&gt;
Normally, when multiple users require CTI and hence TAPI functionality, the best way is to use a server based, multi-client 3rd party CTI application.  This will share all functions among all client PCs.  If this is not an option, e.g. because the TAPI application in use does not support it, you may want to consider using Microsoft&#039;s TAPI Server and remote TSP.  See Microsoft&#039;s [http://technet.microsoft.com/en-us/library/cc786297%28v=ws.10%29.aspx Telephony service providers overview] and [http://technet.microsoft.com/en-us/library/cc770373.aspx Manage Telephony Servers] documents.  &lt;br /&gt;
&lt;br /&gt;
If you still want to use the native innovaphone TSP on a number of PCs (instead of once on a server), you can roll out the TSP using some of the [http://support.microsoft.com/kb/816102/EN-US software deployment schemes Microsoft Server provide].  In such a case, you will likely want to deploy identical configurations to all these PCs. While this theoretically can be done by distributing registry settings, there will be a problem with the PBX access credentials.  These are stored in encrypted format in the registry and can only be decrypted on the PC on which they have been set.  That is, deploying such registry settings to other PCs will result in a non-functional setup.&lt;br /&gt;
&lt;br /&gt;
To work around this problem, you may store the credentials in clear text in the registry.  To do so, you would put the &#039;&#039;Password&#039;&#039; in a REG_SZ value named &amp;lt;code&amp;gt;admin1-free&amp;lt;/code&amp;gt; and the &#039;&#039;Account&#039;&#039; into a REG_SZ value named &amp;lt;code&amp;gt;admin2-free&amp;lt;/code&amp;gt;.  If such a value is found in the proper place in the registry, the values configured using the telephony control panel are ignored.  &lt;br /&gt;
&lt;br /&gt;
[[Image:TAPI Service Provider-tsp8-nocrypt.png]]&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;Keep in mind that having credentials in clear in the registry presents a security risk!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This feature is available in build 8079 and later.&lt;br /&gt;
&lt;br /&gt;
=== Upgrade from Build 8164 or earlier ===&lt;br /&gt;
From build 8165, the TAPI configuration has been moved to a different registry location.  This has been done because latest windows versions (namely, Windows 10) do not allow the TSP to access registry information in the location used so far (&amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;).   To work around this issue, it is now stored in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The TSP configuration dialogue however runs with user privileges (as opposed to the TSP which runs with limited service privileges). It can therefore read the old configuration information and copy it to the new location.  From build 8165, the configuration dialogue will thus copy any old configuration information to the new location when it is opened.  When you upgrade an existing installation and open the configuration dialogue, you will see no change.  However, when the configuration is saved, it is then present in the new location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;To upgrade an installation from build 8164 or earlier (that is TAPI &#039;V8 TAPI Service Provider (32 and 64bit) - hotfix14&#039;&#039; available in the &#039;&#039;V8 applications hotfix20&#039;&#039; package or earlier), proceed as follows:&#039;&#039;&#039;&lt;br /&gt;
* stop the telephony service (e.g. &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt;)&lt;br /&gt;
* install the new TSP&lt;br /&gt;
* open the TSP configuration dialogue&lt;br /&gt;
* verify the configuration data&lt;br /&gt;
* save the configuration&lt;br /&gt;
* (re) start your TAPI application&lt;br /&gt;
&lt;br /&gt;
If you fail to migrate the configuration as described, the TSP will start, but not work!&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
The TSP configuration dialogue looks like this:&lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - Config UI.png]]&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;VERIFY&#039;&#039; button will verify the configuration.  Note that the &#039;&#039;Username&#039;&#039; drop down list will only be populated after a successful verify. &lt;br /&gt;
* The &#039;&#039;OK&#039;&#039; button will save the configuration.&lt;br /&gt;
* The &#039;&#039;CANCEL&#039;&#039; button will quit the configuration without saving any changes.  If it is the initial configuration while you add the TSP via the telephone and modem control panel, the TSP will not be added &lt;br /&gt;
&lt;br /&gt;
TAPI talks to the PBX using [[Reference7:SOAP_API | SOAP ]] which in turn uses HTTP for communication.  Both secure (https) and non-secure (http) communication is supported.  In any case, HTTP basic authentication is used.  &lt;br /&gt;
To be able to connect to the PBX, the TSP needs to know proper credentials to use during HTTP authentication. These are referred to as &#039;&#039;PBX Account&#039;&#039; and &#039;&#039;PBX Password&#039;&#039;.  Also, a suitable &#039;&#039;TAPI User&#039;&#039; must be selected.&lt;br /&gt;
&lt;br /&gt;
==== Controlling the Line Devices handled by TAPI ====&lt;br /&gt;
&lt;br /&gt;
TAPI connects to your PBX as a PBX user referred to as &#039;&#039;TAPI User&#039;&#039;.  It will see all PBX objects that are members of groups in which the &#039;&#039;TAPI User&#039;&#039; is an active member.  If the &#039;&#039;TAPI User&#039;&#039; is not an active member in any group, TAPI will see the &#039;&#039;TAPI User&#039;&#039; object only. This may be useful in a [http://en.wikipedia.org/wiki/Telephony_Application_Programming_Interface 1st party TAPI scenario].  PBX objects are represented as TAPI lines.  &lt;br /&gt;
&lt;br /&gt;
The PBX object you use as &#039;&#039;TAPI User&#039;&#039; needs to have at least &#039;&#039;Viewing only&#039;&#039; [[Reference:Administration/PBX/Objects/Edit Rights | PBX user rights]].  Its &#039;&#039;Long Name&#039;&#039; property is used as &#039;&#039;TAPI User Username&#039;&#039;, its &#039;&#039;Name&#039;&#039; property as &#039;&#039;PBX Account&#039;&#039; and the password as &#039;&#039;PBX Password&#039;&#039;.  This is why the PBX object used as &#039;&#039;TAPI User&#039;&#039; must have a password configured. &lt;br /&gt;
&lt;br /&gt;
===== 1st Party Configuration =====&lt;br /&gt;
In a 1st party scenario, the TSP will only work on a single PBX object.  This will typically be a user&#039;s phone and thus the user itself will be used as the &#039;&#039;TAPI User&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - FirstParty.png ]]&lt;br /&gt;
&lt;br /&gt;
In such a configuration the TSP is typically installed on the users PC and the CTI software is accessing TAPI directly (such as e.g. Microsoft Outlook does).   &lt;br /&gt;
&lt;br /&gt;
The TSP configuration dialogue will check for the number of lines seen.  If it is only one, then it will issue a warning message:&lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - OnlyOne.png]]&lt;br /&gt;
&lt;br /&gt;
This is because 3rd party configurations are much more common and this situation often indicates a configuration problem.  In a first party configuration, you can safely ignore this message. &lt;br /&gt;
&lt;br /&gt;
===== 3rd Party Configuration =====&lt;br /&gt;
In a 3rd party configuration, the TSP will work with multiple PBX objects.  &lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - ThirdParty.png]]&lt;br /&gt;
&lt;br /&gt;
Typically, you will share a single TSP instance on a server system for use by several users on their desktop PCs.  This is done by virtue of a &#039;&#039;TAPI Server&#039;&#039;.  There are various TAPI server products available on the market, including but not limit to the Estos ProCall product and the remote TAPI server included in Microsoft Windows server operating systems.  &lt;br /&gt;
&lt;br /&gt;
In this scenario, it is recommended to create a pseudo PBX user object for use as the &#039;&#039;TAPI User&#039;&#039;.  This pseudo user is often called &amp;lt;code&amp;gt;_TAPI_&amp;lt;/code&amp;gt;.  You would create a dedicated group to control the list of PBX objects the TSP creates a line device for.  This group is often called &amp;lt;code&amp;gt;tapi&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Selective Call Forwards ====&lt;br /&gt;
Many CTI applications support distinct call forwards for internal and/or external calls.  The TSP will translate such requests to a call forward on the PBX which has the [[Reference7:Administration/PBX/Objects/Edit_CFs | &#039;&#039;Only&#039;&#039; or &#039;&#039;Only not&#039;&#039; property]] set to the number of the trunk line.  For this to work, it needs to know this number.  To know the number, the trunk line PBX object must be seen by the TSP (see above).  If this is not the case, the TSP configuration dialogue will issue a warning:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - NoTrunk.png]]&lt;br /&gt;
&lt;br /&gt;
In a vanilla first party scenario, this is obviously not the case.  If you don&#039;t care, you can safely ignore this issue.  Attempts to set such call forward will be rejected then as &#039;&#039;operation unavailable&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In a Master/Slave PBX scenario where there is no Trunk Line object on the Master PBX, but only on the Slave PBXs, a workaround is required to suppress the warning and enable selective call forwarding on the Slave PBXs. In this case, create a dummy &amp;quot;Trunk Line&amp;quot; object on the Master PBX with the same extension number used by the &amp;quot;Trunk Line&amp;quot; objects on the Slave PBXs (usually 0).&lt;br /&gt;
&lt;br /&gt;
==== Multi Site Configuration ====&lt;br /&gt;
In a system with multiple PBXs, the TSP needs to connect to each of the individual PBXs.  &lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - MultiSite.png]]&lt;br /&gt;
&lt;br /&gt;
In this case, you would specify your master PBX as &#039;&#039;PBX Master&#039;&#039;.  There is no need to configure the complete PBX tree to the TSP as it is determined dynamically on runtime by analysing the PBX/Node objects in the master PBX and their registration status.  If a registered PBX is found, this PBX is added to the list of active PBXs and a new connection is established.  The PBX tree is built and maintained dynamically.  A reconfiguration or restart of the TSP is not required on changes thus.&lt;br /&gt;
For this to work&lt;br /&gt;
&lt;br /&gt;
* the PBX object used as &#039;&#039;TAPI User&#039;&#039; must exist in each PBX with same properties (including name and the password). You may want to use &amp;lt;code&amp;gt;_TAPI_&amp;lt;/code&amp;gt; as &#039;&#039;Name&#039;&#039;/&#039;&#039;Long Name&#039;&#039;.  This object must be &#039;&#039;active&#039;&#039; member in a group (which you may want to call &amp;lt;code&amp;gt;tapi&amp;lt;/code&amp;gt;).  A password must be set.  The object must have at least &#039;&#039;Viewing only&#039;&#039; rights&lt;br /&gt;
* the slave PBX-objects (or in older firmware versions the slave PBX Node-objects)  must be visible to the TSP (that is, must be non-active member of the group the &#039;&#039;TAPI User&#039;&#039; object is an active member of, e.g. &amp;lt;code&amp;gt;tapi&amp;lt;/code&amp;gt;) so that the slaves are made known to the TSP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In a replicated scenario, you would create a &#039;&#039;TAPI user&#039;&#039; as recommended above and [[Reference8:Administration/PBX/Objects#Objects_with_empty_node_or_PBX | leave the &#039;&#039;PBX&#039;&#039; and &#039;&#039;Node&#039;&#039; properties empty ]].  This user should then be used as both &#039;&#039;PBX Account&#039;&#039; and &#039;&#039;TAPI User Username&#039;&#039; in the TAPI configuration dialog.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Further relevant settings&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
You can disable slave detection by checking &#039;&#039;Do not monitor slaves&#039;&#039; property in the TSP configuration dialogue. &lt;br /&gt;
&lt;br /&gt;
TAPI maintains an &#039;&#039;address&#039;&#039; property per line device.  This usually is the lines extension.  In a multi site configuration, the address property will be set to the &#039;&#039;Number&#039;&#039; property of the node the respective PBX object is configured in, plus the &#039;&#039;Number&#039;&#039; property of the object itself.  So if an object has &#039;&#039;Number&#039;&#039; &amp;lt;code&amp;gt;42&amp;lt;/code&amp;gt; and lives in node &amp;lt;code&amp;gt;801&amp;lt;/code&amp;gt;, then its correspondence line device will have address &amp;lt;code&amp;gt;80142&amp;lt;/code&amp;gt;.  By checking the &#039;&#039;Use pure node extensions&#039;&#039; property in the TSP configuration dialogue, you change the algorithm so that only the objects own &#039;&#039;Number&#039;&#039; is used (&amp;lt;code&amp;gt;42&amp;lt;/code&amp;gt; in our example).&lt;br /&gt;
&lt;br /&gt;
==== Standby Configurations ====&lt;br /&gt;
In a system with standby PBX for the master PBX, you need to specify the &#039;&#039;PBX Standby&#039;&#039; IP address.  This will be connected if the master is unavailable.  Note that there is no need to explicitly configure slave-standby PBXs.&lt;br /&gt;
&lt;br /&gt;
==== Working with multiple, unrelated PBXs ====&lt;br /&gt;
When working with multiple, unrelated PBXs (that is, PBXs that do &#039;&#039;not&#039;&#039; form a PBX tree as slaves and masters do), the TSP cannot derive the list of PBXs to track from the registration status.  To support such a configuration, you will need to configure the extraneous master PBXs manually using regedit.  Please note that using regedit may harm your system and may even cause inability to boot!&lt;br /&gt;
&lt;br /&gt;
To find and edit the right registry entries, proceed as follows:&lt;br /&gt;
&lt;br /&gt;
* open the key &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;&lt;br /&gt;
* open its subkey &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&#039;&#039;n&#039;&#039; where &#039;&#039;n&#039;&#039; is the provider id of the installed innovaphone TSP (for builds before 8164 only)&lt;br /&gt;
* Open the &amp;lt;code&amp;gt;FQDN&amp;lt;/code&amp;gt; key and add all extra PBXs&lt;br /&gt;
* For those PBXs that have a standby PBX, add a value to the &amp;lt;code&amp;gt;StandbyFQDN&amp;lt;/code&amp;gt; key (please note: these are parallel lists.  So master and standby need to have the same respective index in the &amp;lt;code&amp;gt;FQDN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;StandbyFQDN&amp;lt;/code&amp;gt; value lists)&lt;br /&gt;
&lt;br /&gt;
The standard configuration UI will not show these extra values.  However, it will also not touch them.  So even if you use the standard UI to edit, only the first value in the lists will be changed and the remainder left unchanged. You can thus safely use the standard UI to edit all other values.   As with multi site configurations, all PBXs need to be accessible using the same &#039;&#039;TAPI User&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Please note that this method is deprecated and will likely be removed from future versions of the TSP.  &lt;br /&gt;
&lt;br /&gt;
==== Setting the Line Device Name ====&lt;br /&gt;
The TSP will derive the line device&#039;s name from the properties of the respective PBX object.  By default the name will be the objects &#039;&#039;Long Name&#039;&#039; followed by the name of the PBX the user ought to register with in parentheses.  So if the users &#039;&#039;Long Name&#039;&#039; is &amp;lt;code&amp;gt;Foo Bar&amp;lt;/code&amp;gt; and the registration PBX is &amp;lt;code&amp;gt;branch1&amp;lt;/code&amp;gt;, the line device will be called &amp;lt;code&amp;gt;Foo Bar [branch1]&amp;lt;/code&amp;gt;.  You can specify a different pattern by changing the &#039;&#039;TAPI Line Names&#039;&#039; property of the TSP configuration dialogue.  The following replacement characters are available:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|+&lt;br /&gt;
| Meta || Replacement&lt;br /&gt;
|+&lt;br /&gt;
| %c || The objects &#039;&#039;Long Name&#039;&#039; (cn)&lt;br /&gt;
|+&lt;br /&gt;
| %C || The objects &#039;&#039;Long Name&#039;&#039; (cn) followed by the &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents in braces &amp;lt;code&amp;gt;[name]&amp;lt;/code&amp;gt; if it differs from the &#039;&#039;Long Name&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
| %d || The objects &#039;&#039;Display Name&#039;&#039; (dn)&lt;br /&gt;
|+&lt;br /&gt;
| %D || The objects &#039;&#039;Display Name&#039;&#039; (dn) followed by the &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents in braces &amp;lt;code&amp;gt;[name]&amp;lt;/code&amp;gt; if it differs from the &#039;&#039;Display Name&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
| %h || The objects &#039;&#039;Name&#039;&#039; (h323 alias)&lt;br /&gt;
|+&lt;br /&gt;
| %H || The objects &#039;&#039;Name&#039;&#039; (h323 alias) followed by the &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents in braces &amp;lt;code&amp;gt;[name]&amp;lt;/code&amp;gt; if it differs from the &#039;&#039;Name&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
| %t || The &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents&lt;br /&gt;
|+&lt;br /&gt;
| %T || The &#039;&#039;Hardware Id&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents (from build 8181)&lt;br /&gt;
|+&lt;br /&gt;
| %e || The objects extension (e164)&lt;br /&gt;
|+&lt;br /&gt;
| %E || The objects extension (e164) prefixed with the objects node number&lt;br /&gt;
|+&lt;br /&gt;
| %N || The line address as reported to TAPI&lt;br /&gt;
|+&lt;br /&gt;
| %n || host name (of master pbx)&lt;br /&gt;
|+&lt;br /&gt;
| %p || &#039;&#039;&#039;:&#039;&#039;&#039;&#039;&#039;port-number&#039;&#039; (of master pbx&#039;s http access, empty if 80)&lt;br /&gt;
|+&lt;br /&gt;
| %P || raw port number of master pbx&lt;br /&gt;
|+&lt;br /&gt;
| %u || url-like user name (&#039;&#039;&#039;&#039;&#039;user&#039;&#039;@&#039;&#039;host&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
|+&lt;br /&gt;
| %U || user url as per draft-levin-iptel-h323-url-scheme-04 (&#039;&#039;&#039;h323:://&#039;&#039;user&#039;&#039;@&#039;&#039;host&#039;&#039;:&#039;&#039;port&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
|+&lt;br /&gt;
| %X || the PBX name the user is registered with (note that using this pattern may result in a change of the name when a standby situation occurs)&lt;br /&gt;
|+&lt;br /&gt;
| %x || the PBX name the user is reported by (note that using this pattern may result in a change of the name when the users &#039;&#039;PBX&#039;&#039; attribute changes)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The default pattern is &amp;lt;code&amp;gt;%C (%x)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- rufumleitung, extern, intern, amtsleitung, vom amt, zum amt --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Miscellaneous Flags ====&lt;br /&gt;
; Show full E164 Numbers : when set, the TSP will announce the full calling number from the root when indicated by the PBX in the TAPI &#039;&#039;calling party name&#039;&#039; attribute.  The number will be appended to the calling name with a &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;.&lt;br /&gt;
; Do not show parked Calls : will hide parked calls from the TAPI application (as some get confused and don&#039;t know how to handle them)&lt;br /&gt;
; Map PBX Devices to Lines : if set, the TSP will create one TAPI line for each individual [[Reference9:PBX/Objects#Devices|PBX device]] configured in a user object.  See [[#Enhancements]] above.  If you do not set this flag, see [[Support:How should TAPI line device be registered?]]&lt;br /&gt;
; Map Presence Status to TAPI Lines : if set, the TSP will create one extra TAPI line for each PBX device object.  See [[#Enhancements]] above.&lt;br /&gt;
; No special Disconnect Behaviour : normally, lines monitored by TAPI will behave slightly different when a call is terminated.  With no TAPI on the line, the call will be disconnected immediately (from a PBX point of view).  In cases where the phone would play some tones after termination of the call (e.g. a busy tone when the call has never been connected to the far end), this state is simulated by the phone and not visible to TAPI.  Therefore, it is not possible to use TAPI functions on this call any more (as it in reality does not exist any more).  When this flag is set, monitored lines will not be treated specially.  Available from hotfix 6. To prevent the IP-Phone to play any tones after the call is disconnected, the phone preferences option &#039;&#039;&#039;Go onhook if final call is released by remote side even if handset is lifted&#039;&#039;&#039; can be activated. This is the feature of the IP-Phone is useful in a e.g. call center at agent phones and can be configured here [[Reference11r1:Phone/Preferences]].&lt;br /&gt;
: To prevent an innovaphone IP-Phone from playing any tones after a call is disconnected, the phone preferences option &#039;&#039;&#039;Go onhook if final call is released by remote side even if handset is lifted&#039;&#039;&#039; can be activated. This feature is useful for agent phones in a call center for example and can be configured in [[Reference11r1:Phone/Preferences]]&lt;br /&gt;
&lt;br /&gt;
===Trouble Shooting===&lt;br /&gt;
The TSP will (from build 8095) write messages of type INFO (&#039;&#039;informational messages&#039;&#039;) or WARNING (&#039;&#039;Warnings/Errors&#039;&#039;) to the windows event log. Such events are always logged to the application log and event source is the provider name (&#039;&#039;innovaphone® PBX V8 TAPI Service Provider&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==== Turning on Debugging ====&lt;br /&gt;
There are 2 versions of the TSP, debug and retail, which are both copied to the machine during setup.  The retail version is installed into the system directories, whereas the debug version is stored in a separate directory.  This is available through a short cut in the Start menu.&lt;br /&gt;
&lt;br /&gt;
The TSP can produce a number of debugging messages which can be helpful to debug issues (in both &#039;&#039;retail&#039;&#039; and &#039;&#039;debug&#039;&#039; builds).  By default, debug messages are written to the systems debug buffer mechanism (using OutputDebugString()).  Such messages can be examined using standard debugging tools, such as for example &amp;lt;code&amp;gt;dbgview&amp;lt;/code&amp;gt; which is [http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx available from Microsoft]. &lt;br /&gt;
&lt;br /&gt;
Debug messages have a class associated with it and the amount of messages written can be controlled by enabling or disabling specific classes.  This is done by setting a bitmask in the registry value &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; in the &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt; key. &lt;br /&gt;
&lt;br /&gt;
The easiest way to set the TSP&#039;s debug level is with the &#039;&#039;TSP Control&#039;&#039; utility (&#039;&#039;tsptray.exe&#039;&#039;) which is installed with the TSP.&lt;br /&gt;
&lt;br /&gt;
The available classes include&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| Bit in &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; || Class &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000001 || Minimum tracing &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000002 || TAPI api traces &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000020 || Basic telephony object creation/destruction  &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000040 || Thread creation/destruction &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000080 || Request creation/destruction &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000100 || call related messages &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000200 || Call id map &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000400 || Warnings/Errors &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000800 || Worker thread execution &lt;br /&gt;
|-&lt;br /&gt;
| 0x00001000 || Full lock/unlock notifications &lt;br /&gt;
|-&lt;br /&gt;
| 0x00002000 || Win32 Critical section create/destroy &lt;br /&gt;
|-&lt;br /&gt;
| 0x00004000 || Agent proxy support &lt;br /&gt;
|-&lt;br /&gt;
| 0x00008000 || constructor/destructor debug &lt;br /&gt;
|-&lt;br /&gt;
| 0x00010000 || development debugs &lt;br /&gt;
|-&lt;br /&gt;
| 0x00100000 || verbose debugging  &lt;br /&gt;
|-&lt;br /&gt;
| 0x00200000 || SOAP trace &lt;br /&gt;
|-&lt;br /&gt;
| 0x00400000 || SOAP message dumps &lt;br /&gt;
|-&lt;br /&gt;
| 0x01000000 || ATL debug &lt;br /&gt;
|-&lt;br /&gt;
| 0x02000000 || line related messages &lt;br /&gt;
|-&lt;br /&gt;
| 0x04000000 || informational messages &lt;br /&gt;
|-&lt;br /&gt;
| 0x10000000 || dump call infos &lt;br /&gt;
|-&lt;br /&gt;
| 0x20000000 || dump PBX infos &lt;br /&gt;
|-&lt;br /&gt;
| 0x80000000 || output log messages to file &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; is not set, it defaults to (hex) &amp;lt;code&amp;gt;04000400&amp;lt;/code&amp;gt; in retail builds and to (hex) FFFFFFFF in debug builds.  A nice value to use is (hex) &amp;lt;code&amp;gt;92200580&amp;lt;/code&amp;gt;.  The &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; can be changed during runtime of the provider (it may take up to 10 seconds though for the setting to take effect).  In normal scenarios there is no need to install the debug version.&lt;br /&gt;
&lt;br /&gt;
Both &#039;&#039;informational messages&#039;&#039; and &#039;&#039;Warnings/Errors&#039;&#039; are always turned on (from build 8095).&lt;br /&gt;
&lt;br /&gt;
: A problem has been reported on Server 2008 x64 systems which may also apply to others.  On such systems, the value of &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; may be reset to its default every 10 seconds.  A workaround is to change the account the Telephony service is running in from its default (usually &#039;&#039;Network Service&#039;&#039;) to e.g. &#039;&#039;Local System&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===== Crash Dumps =====&lt;br /&gt;
From build 8063 the TSP will write crash dumps to the log directory (usually something like &amp;lt;code&amp;gt;C:\Program Files\innovaphone AG\innovaphone® PBX V8 TSP\Logs&amp;lt;/code&amp;gt;) in case of a trap.  In release installs, these are not very useful. For debug builds though, they include helfpul information.  Please provide these files (the can be zipped to a great extent) to support if requested. A crash dump file will be called something like &amp;lt;code&amp;gt;TSP8&amp;lt;i&amp;gt;build&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;hour&amp;lt;/i&amp;gt;#&amp;lt;i&amp;gt;minute&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;day&amp;lt;/i&amp;gt;.&amp;lt;i&amp;gt;month&amp;lt;/i&amp;gt;#&amp;lt;i&amp;gt;seqnr&amp;lt;/i&amp;gt;.dmp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Forcing a Crash Dump =====&lt;br /&gt;
In rare cases, it may be useful to force a TAPI crash for debug reasons.  This can be done by issueing a &amp;lt;code&amp;gt;lineMakeCall&amp;lt;/code&amp;gt; with called number &amp;lt;code&amp;gt;0815&amp;lt;/code&amp;gt;, called-subaddress &amp;lt;code&amp;gt;4711&amp;lt;/code&amp;gt; and called-name &amp;lt;code&amp;gt;!crash!&amp;lt;/code&amp;gt; or simply calling &amp;lt;code&amp;gt;0815|4711^!crash!&amp;lt;/code&amp;gt; from phone.exe.&lt;br /&gt;
&lt;br /&gt;
==== Saving Log Messages to a File ====&lt;br /&gt;
The &amp;lt;code&amp;gt;0x80000000&amp;lt;/code&amp;gt; value is special, as it does not denote a message class.  Instead, it turns on log file writing, both in retail and debug versions.  For this to work, the registry value &amp;lt;code&amp;gt;DoTraceFile&amp;lt;/code&amp;gt; must be set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt; when the TSP starts.  If this value is not present, it defaults to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; in both retail and debug builds.  Setting it to 0 disables log file writing regardless of any other setting.  This may save some CPU cycles for installations with a real large number of lines.&lt;br /&gt;
&lt;br /&gt;
The TSP will keep 24 log files (a days worth) by default.   This value can be changed using the &amp;lt;code&amp;gt;NumLogFiles&amp;lt;/code&amp;gt; value in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;.  Older log files will be removed.  Also, when the TSP shuts down, it by default will remove all log files it created so far.  However, any TSP will only remove log files created by itself.  This ensures that if the TSP or the system terminates prematurely, the log files will be kept even if a new instance is started and terminated later on.  Form TSP V8 hotfix 8 on, this behaviour can be tweaked by setting the DWORD registry value &amp;lt;code&amp;gt;KeepLogFiles&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;:&lt;br /&gt;
{|&lt;br /&gt;
| 0 || default || remove all log files on termination&lt;br /&gt;
|-&lt;br /&gt;
| 1 || || keep the last &#039;&#039;n&#039;&#039; log files (depending on &amp;lt;code&amp;gt;NumLogFiles&amp;lt;/code&amp;gt;) on termination&lt;br /&gt;
|-&lt;br /&gt;
| 2 || || keep all log files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Larger systems (500 monitored lines and more) can slow down considerably when writing extensive logs.&lt;br /&gt;
&lt;br /&gt;
==== Installing the Debug Version ====&lt;br /&gt;
To install the debug version, you first install the retail version as outlined above.  You then copy the debug driver files from the &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; directory to your windows system directory &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt;.  You may want to use the shortcut to the &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; folder which has been installed to the start menu for convenience.  &lt;br /&gt;
&lt;br /&gt;
For the copy to work, proceed as follows&lt;br /&gt;
* close &#039;&#039;Telephony and Modem Control Panel&#039;&#039; if you have it open&lt;br /&gt;
* shut down windows telephony service. This can be done from the Windows &#039;&#039;Service Control Panel&#039;&#039; or by invoking &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt; from a command prompt&lt;br /&gt;
* copy the debug driver files to your system directory.  On x64 systems, be sure to use a 64bit application such as &#039;&#039;Windows File Explorer for&#039;&#039; (&amp;lt;code&amp;gt;explorer.exe&amp;lt;/code&amp;gt;) for this.  Windows will silently redirect any 32bit application to the &amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt; directory when accessing &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt;.(if the copying fails, we recommend to deactivate the telephony service. But don’t forget to reset it to automatically if you are done copying). Overwrite the existing files: &amp;lt;code&amp;gt;installer.dll, installer.pdb, TSP8.pdb, TSP8.tsp&amp;lt;/code&amp;gt;&lt;br /&gt;
* if the copy does not succeed or the debug driver is not shown n the modem control panel after, it might be that a TAPI application re-starts the windows telephony before you actually to the copy.  If so, you can set the &#039;&#039;Startup type&#039;&#039; of the Windows &#039;&#039;Telephony&#039;&#039; service to &amp;lt;code&amp;gt;Disabled&amp;lt;/code&amp;gt; instead of &#039;&#039;Manual&#039;&#039; in the services control panel (&#039;&#039;services.msc&#039;&#039;). You can then &#039;&#039;Stop&#039;&#039; the services, copy the file and finally set the services mode back to &amp;lt;code&amp;gt;Manual&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you open &#039;&#039;Telephony and Modem Control Panel&#039;&#039; again, you should notice that the TSP driver name has changed to the debug version.&lt;br /&gt;
&lt;br /&gt;
==== Switching back to the Retail Version ====&lt;br /&gt;
To go back from the debug to the release version, proceed as follows:&lt;br /&gt;
* close &#039;&#039;Telephony and Modem Control Panel&#039;&#039; if you have it open&lt;br /&gt;
* shut down windows telephony service. This can be done from the Windows &#039;&#039;Service Control Panel&#039;&#039; or by invoking &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt; from a command prompt&lt;br /&gt;
* delete the debug driver files from your system directory.  On x64 systems, be sure to use a 64bit application such as &#039;&#039;Windows File Explorer for&#039;&#039; (&amp;lt;code&amp;gt;explorer.exe&amp;lt;/code&amp;gt;) for this.  Windows will silently redirect any 32bit application to the &amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt; directory when accessing &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt;&lt;br /&gt;
* repair the installation using windows &#039;&#039;Programs Control Panel&#039;&#039; or by invoking the original .msi again&lt;br /&gt;
&lt;br /&gt;
There is no need to remove the driver from the &#039;&#039;Telephone and Modem Control Panel&#039;&#039;, as this would make you loose your driver configuration.&lt;br /&gt;
&lt;br /&gt;
Please note that simply re-installing the driver from the original .msi without removing it from the system directory will not work.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
The test applications provided with this setup comes from [http://www.julmar.com Julmar Technology Inc].&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===&lt;br /&gt;
&lt;br /&gt;
Please note that there currently is a limitation to 2000 users being in&lt;br /&gt;
all active groups of a particular user.  Thus, you cannot configure more&lt;br /&gt;
than 2000 users to be handled by TAPI on a single PBX.  This is a PBX&lt;br /&gt;
limitation (and applies for all PBX groups).&lt;br /&gt;
&lt;br /&gt;
TAPI has a flat line model.  That is, all line numbers (aka&lt;br /&gt;
&#039;&#039;extensions&#039;&#039;) are considered to live in a single name space.  As a&lt;br /&gt;
result, lines with identical numbers cannot be distinguished in TAPI&lt;br /&gt;
(although they can exist).   All extensions in all nodes of a PBX&lt;br /&gt;
numbering tree are represented as TAPI lines.  When the TSP works with a&lt;br /&gt;
PBX that implements a hierarchical numbering tree, then some lines may&lt;br /&gt;
receive identical numbers (their node-local extension which may overlap&lt;br /&gt;
between nodes depending on the setting of the &#039;&#039;Use pure node extensions&#039;&#039; property).  When a TAPI application uses these numbers to initiate&lt;br /&gt;
calls to such lines, the call will work or not work depending on the&lt;br /&gt;
calling lines position in the numbering tree (that is, lines within the&lt;br /&gt;
same node as the called line will be fine, others may fail).&lt;br /&gt;
&lt;br /&gt;
The PBX&#039;s SOAP interface (on top of which the TSP is built) has no primitives to initiate a directed call pick-up based on a target number.  The TSP will reject such requests with &#039;&#039;Operation not available&#039;&#039;.  Pickup by name (which is understood as a group name) or unspecific is supported though.&lt;br /&gt;
&lt;br /&gt;
==== Citrix Environments ====&lt;br /&gt;
What happens is that all Citrix sessions share the same TAPI driver. This allows all users in the Citrix sessions to select &amp;quot;their&amp;quot; line from the set of all TAPI lines. Then everything works as desired. It is important to note that theoretically one user can select the line of another user.&lt;br /&gt;
You can use the &amp;quot;Microsoft Remote TAPI Server&amp;quot;, to implement access rights for lines for separate Citrix sessions.&lt;br /&gt;
&lt;br /&gt;
===Known Problems===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* The TSP is not tested with Microsoft’s Remote Tapi Server.  While some installation have reported this to work fine, others have encountered problems.  This scenario is not supported by innovaphone&lt;br /&gt;
* The TSP will read its configuration when it is loaded by the system.  Thus, configuration changes require a re-load of the TSP.  Unfortunately, there is no reliable way to force the system to unload the TSP, so you may have to reboot the system for changes to take effect.  See the [[ Howto:Troubleshooting_the_TAPI_service_provider | TAPI trouble shooting article ]] for details&lt;br /&gt;
* The TSP will use HTTP basic authentication to talk the PBX.  So if you disable basic authentication in the PBX&#039;s configuration, the TSP will not work.  It is recommended to use HTTPS&lt;br /&gt;
* TAPI requires the TSP to assign a unique id to each line device.  This ID must not change between re-boots of the system or between upgrades of the TSP.  This is done by keeping a persistent table in the windows registry (in the &amp;lt;code&amp;gt;lineGUIDs&amp;lt;/code&amp;gt; subkey of &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;) that maps the PBX&#039;s line GUID to a fixed integer value (known as &#039;&#039;permanent line id&#039;&#039; in TAPI speak).  This key is retained even on uninstall.  To get rid of it, you must remove it manually&lt;br /&gt;
* Microsoft installer fails to remove driver files installed to the windows system folder.  This is why the TSP driver files are still present after an uninstall of the software.  To get rid of them, remove &amp;lt;code&amp;gt;TSP8.tsp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TSP8UI.dll&amp;lt;/code&amp;gt; from both &#039;&#039;%windir%&#039;&#039;&amp;lt;code&amp;gt;\system32&amp;lt;/code&amp;gt; and &#039;&#039;%windir%&#039;&#039;&amp;lt;code&amp;gt;\sysWOW64&amp;lt;/code&amp;gt;&lt;br /&gt;
* From Version 9, hotfix 1, the PBX firmware will not list objects tagged as [[Reference9:PBX/Objects#General_Object_Properties | &#039;&#039;hide from LDAP&#039;&#039; ]] in the result of a [[Reference9:Concept_SOAP_API#UserInfo.5B.5D_FindUser.28string_v501.2C_string_v700.2C_string_v800.2C_string_cn.2C_string_h323.2C_string_e164.2C_integer_count.2C_integer_next.29 | FindUser() ]] call.  As a result, such objects will not be shown in the TAPI configuration dialogue &#039;&#039;Username&#039;&#039; drop-down.  If you want to use such an object as &#039;&#039;TAPI User&#039;&#039; you can simply type in the name without selecting it from the drop down.&lt;br /&gt;
* Sometimes, setting configuration with &#039;&#039;TSP Control&#039;&#039; (not the telephone control panel dialogue) does not work due to windows&#039; &#039;&#039;User Access Control (UAC)&#039;&#039;, see [[Howto:TAPI_TSP_Control_Windows7]] for Details&lt;br /&gt;
* Various users have reported that first party TSP installations do not work reliably with Microsoft Outlook.  Symptoms reported are spurious error pop-ups from Outlook although there was no real problem.  We do not recommend first party installations anyway (see [[#Rolling_out_First_Party_TSPs_to_multiple_PCs]] for a reasoning), but these issues are related to Microsoft Outlook only.  No such problems have been reported with other first party TAPI applications. Consider using solutions like Estos ProCall instead.&lt;br /&gt;
* The number of parallel threads used within the TSP is limited to max. 60 per CPU.  As each connected PBX (amongst other things) is handled by a separate thread, if you have a large number of PBXs connected and only have a single CPU, you may run out of threads, resulting in a WARNING messages &#039;&#039;about to spawn new workerthread (n requests, m threads) -- but limit l exceeded&#039;&#039;.  This usually happens when you run the TSP on a virtualized platform such as vmWare and only dedicate a single CPU.  Ignoring this warning results in sluggish behaviour.  &lt;br /&gt;
* The TSP can work with dynamic PBXs too.  However, the TSP needs to determine the slave PBXs IP addresses from the master. If the slave is a dynamic PBX and it is hosted on the same device as the master and it is registered to the master using 127.0.0.1, the TSP will only learn the 127.0.0.1 as the slave&#039;s IP address.  Of course, connection to the slave PBX will fail then. &lt;br /&gt;
&lt;br /&gt;
==== TAPI Operation with 3rd party Phones or innovaphone Phones registered with SIP ====&lt;br /&gt;
Various TAPI functions rely on use of the [[Reference:Remote Control Facility|Remote Control Facility]] message.  This message is not supported in 3rd party phones and also not fully supported in innovaphone Phones when they are registered to the PBX using SIP.  Full TAPI functionality is thus only available for innovaphone phones registered to the PBX using H.323.&lt;br /&gt;
&lt;br /&gt;
Known Limitations:&lt;br /&gt;
* Accepting an incoming call (lineAnswer)&lt;br /&gt;
* Automatic initiation of an outgoing call in handsfree mode (instead, the calling phone first rings and starts the outgoing call upon of-hook)&lt;br /&gt;
* toggle between 2 calls active on a phone (lineSwapHold)&lt;br /&gt;
* initiation and termination of a 3PTY (lineCompleteTransfer with mode LINETRANSFERMODE_CONFERENCE, lineDrop on a conference call)&lt;br /&gt;
&lt;br /&gt;
==== TAPI on Windows8 / Server 2012 ====&lt;br /&gt;
&lt;br /&gt;
Windows8 doesn&#039;t let you disable &#039;&#039;User Access Control&#039;&#039; (UAC) completely.  This has the disadvantage that &#039;&#039;TSP Control&#039;&#039; (tsptray.exe) cannot change system registry entries, which it needs to do to e.g. change debug settings for the TSP.&lt;br /&gt;
&lt;br /&gt;
There are 2 ways around it: &lt;br /&gt;
# use the hidden &#039;&#039;Administrator&#039;&#039; account on Windows 8&lt;br /&gt;
# elevate the tsptray.exe application&lt;br /&gt;
&lt;br /&gt;
To use the elevated &#039;&#039;Administrator&#039;&#039; account on Windows 8 you first need to un-hide it:&lt;br /&gt;
* log in to an account with administrator rights  &lt;br /&gt;
* use the &#039;&#039;Windows-Key+X&#039;&#039; shortcut and select &#039;&#039;Command Prompt (Administrator)&#039;&#039; (&#039;&#039;Eingabeaufforderung (Administrator)&#039;&#039;). An elevated cmd prompt appears&lt;br /&gt;
* type &amp;lt;code&amp;gt;net user administrator /active:yes&amp;lt;/code&amp;gt;&lt;br /&gt;
* the fully elevated &#039;&#039;Administrator&#039;&#039; account is now available and you can log-in to this account as usual&lt;br /&gt;
* &#039;&#039;&#039;Please make sure the account has a password set - by default, it does not!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To elevate the tsptray.exe application;&lt;br /&gt;
* log in to an account with administrator rights  &lt;br /&gt;
* start a windows explorer&lt;br /&gt;
* change directory to &amp;lt;code&amp;gt;C:\Program Files\innovaphone AG\innovaphone® PBX V8-x64 TSP&amp;lt;/code&amp;gt;&lt;br /&gt;
* right click on &amp;lt;code&amp;gt;tsptray.exe&amp;lt;/code&amp;gt; and open the &#039;&#039;properties&#039;&#039; (&#039;&#039;Eigenschaften&#039;&#039;) menu&lt;br /&gt;
* switch to the &#039;&#039;Compatibility&#039;&#039; (&#039;&#039;Kompatibilität&#039;&#039;) tab&lt;br /&gt;
* tick the &#039;&#039;Run as administrator&#039;&#039; (&#039;&#039;Program als Administrator ausführen&#039;&#039;) check mark&lt;br /&gt;
* save the settings&lt;br /&gt;
&lt;br /&gt;
Please note that Windows 8 will not let you run any &amp;quot;Metro App&amp;quot; in elevated mode!&lt;br /&gt;
&lt;br /&gt;
===== HTTPS ===== &lt;br /&gt;
The TSP will not be able to talk to the PBX using HTTPS with Windows8 or Server2012.  This [[Reference8:Release_Notes_TAPI_V8#3722_-_HTTPS_SOAP_connections_did_not_work_on_Windows8_.2F_Server_2012|has been fixed]] with V8 TAPI Service Provider (32 and 64bit) - hotfix10.&lt;br /&gt;
===== .Net 3.5 missing on Server 2012 =====&lt;br /&gt;
Server 2012 has no support for .Net 3.5 by default.  Even more, it cannot be installed just by downloading it.  Instead, the &#039;&#039;NetFX3 Feature&#039;&#039; needs to be enabled.  Here is how:&lt;br /&gt;
&lt;br /&gt;
 Microsoft Windows [Version 6.2.9200]&lt;br /&gt;
 (c) 2012 Microsoft Corporation. Alle Rechte vorbehalten.&lt;br /&gt;
 &lt;br /&gt;
 C:\Users\Administrator&amp;gt;dism /online /enable-feature /featurename:NetFX3 /all /Source:&#039;&#039;&amp;lt;path to windows setup, e.g. d:&amp;gt;&#039;&#039;\sources\sxs /LimitAccess&lt;br /&gt;
&lt;br /&gt;
See also&lt;br /&gt;
* [http://blogs.technet.com/b/aviraj/archive/2012/08/04/windows-8-enable-net-framework-3-5-includes-net-2-0-and-3-0-i-e-netfx3-feature-in-online-amp-offline-mode.aspx?PageIndex=2 Windows 8: Enable .NET Framework 3.5]&lt;br /&gt;
* [http://msdn.microsoft.com/en-us/library/hh506443.aspx Installing the .NET Framework 3.5 on Windows 8]&lt;br /&gt;
&lt;br /&gt;
==== TAPI dialer fails from Outlook when Lync client was/is installed ====&lt;br /&gt;
We have received reports that 1st-party TAPI dial-out from Outlook does not work anymore when a Lync client was installed.  Some users report that this phenomenon occurred only after an upgrade to Windows 8.  Reportedly, this can be [http://support.microsoft.com/kb/959625/en-us fixed by setting a registry key as outlined in Microsoft&#039;s knowledge-base].  You may want to give this a try.  However, we have not seen this issue ourselves and thus can&#039;t comment on it further.&lt;br /&gt;
&lt;br /&gt;
==== Slow Network Performance ====&lt;br /&gt;
TAPI is pretty sensitive to slow network performance.  While the TSP is multi-threaded, some internal locking must be done so that slow requests to a PBX my block other pending requests, resulting in unpleasant performance.  The TSP will create &#039;&#039;Windows Event Log&#039;&#039; entries of type &#039;&#039;slow SOAP call performance&#039;&#039; if this is detected.  You should inspect your event log regularly and resolve the reason for such network performance.&lt;br /&gt;
&lt;br /&gt;
Long PBX request round-trips may have a number of reasons:&lt;br /&gt;
&lt;br /&gt;
; slow WAN performance : of course, if the WAN is slow or unstable, bad performance is the result&lt;br /&gt;
; inappropriate QoS : SOAP is using HTTP/HTTPS.  In a QoS enabled network, call signalling and RTP may work fine, whereas HTTP/HTTPS is considered to be of no importance.  You need to keep in mind that such QoS policy may lead to bad TAPI performance, as the SOAP traffic used by the TSP (being based on HTTP/HTTPS) may be delayed.  You should assign SOAP traffic a similar priority as you do for VoIP signalling&lt;br /&gt;
; overloaded PBX : HTTP traffic is treated on a low priority level in the PBX.  If the PBX runs near to 100% CPU load, while all RTP and VoIP signalling will work well still, HTTP traffic may get severely delayed.  You should make sure your PBX runs well under 100% CPU load to get good TAPI performance.  See [[Reference:Device Health Check]] for more details&lt;br /&gt;
&lt;br /&gt;
==== TAPI on Windows 10 ====&lt;br /&gt;
In Windows 10, the TSP is not allowed any longer to read/write its own registry tree.  For this reason, it is not possible to store or read the configuration.  As a result, the TSP will not work.  To fix this, you need to modify the registry access rights so that the TSP has read/write access to &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on windows registry paths&amp;lt;ref name=&amp;quot;regkey&amp;quot;&amp;gt;&lt;br /&gt;
Due to a change in &#039;&#039;Windows Registry Access Rights&#039;&#039; in Windows 10, from Build 8165, the configuration is stored in &lt;br /&gt;
: &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&lt;br /&gt;
(a place that is suitable for Windows 10 too). Before, the configuration was stored in &lt;br /&gt;
: &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[#Upgrade_from_Build_8164_or_earlier| Upgrade from Build 8164 or_earlier ]] above for more details.&lt;br /&gt;
&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tweaks ===&lt;br /&gt;
There are a few configuration options which should be used rarely.  They can be enabled by setting an appropriate registry key.&lt;br /&gt;
&lt;br /&gt;
Since Hotfix 15 the location to set the interop tweaks has been changed to &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
; ProcessorMask : REG_DWORD. If set, the TSP will use &amp;lt;code&amp;gt;SetProcessAffinityMask(GetCurrentProcess(), set)&amp;lt;/code&amp;gt; to limit TSP execution to one or more of the existing processors.  Set to &amp;lt;code&amp;gt;0xff&amp;lt;/code&amp;gt; by default.&lt;br /&gt;
&lt;br /&gt;
; LineTimeOut : REG_DWORD. Can be set to a number of seconds the TSP should wait for the determination of lines to finish (default 90). On a large PBX, or a PBX with slow slaves, the determination might not finish in the default time frame.  If this happens, TAPI applications may show &#039;&#039;Line unnamed&#039;&#039; line entries in their line list.  If this is a problem, set it to a larger value (e.g. &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
; IgnoreDevStatus : REG_DWORD. Some applications get confused if TAPI reports line to be disconnected or out-of-service dynamically.  Setting this to a non-zero value will disable any such notification.&lt;br /&gt;
&lt;br /&gt;
; ClearFwdOnSet : REG_DWORD.  If set to a non-zero value, the TSP will clear all current call forward settings before a lineForward request is executed.  This implies that all call forward settings are &#039;&#039;replaced&#039;&#039; by the new settings.  Standard behaviour is to only modify the settings, that is, replace all current settings of the same type with the settings found in the lineForward request (for example, if there is only one setting in the request that defines a CFU, then the current CFU settings are replaced by the new one provided. All others, such as e.g. CFNR settings, are left untouched).&lt;br /&gt;
&lt;br /&gt;
: Tapi spec is pretty clear on how this should work: &#039;&#039;The provider should &amp;quot;unforward everything&amp;quot; prior to setting the new forwarding instructions&#039;&#039;.  Even though, for historical reasons, ClearFwdOnSet=0 has been the default in all TAPI versions prior to V8 hotfix 6, from hotfix 6 on, the default changes to 1, as this has turned out to be the widely accepted interpretation.&lt;br /&gt;
&lt;br /&gt;
; No3PTY : REG_DWORD. See [[Reference8:TAPI_Service_Provider#Notes_on_3PTY_Conferences | Notes_on_3PTY_Conferences]] below.&lt;br /&gt;
&lt;br /&gt;
; HiddenRecordingNumber: REG_SZ. Active recording in an innovaphone PBX is implemented as an implicit 3PTY conference with the recording sink as one of the parties.  These will be shown as usual in the TAPI callstate.  However, some applications get confused as this results in a situation, where a normal endpoint (read: phone) has more than one active (i.e. &#039;&#039;not on hold&#039;&#039;) call.  To suppress such calls in the TAPI call states, you can set this tweak to the number of the recording sink as configured in the phone&#039;s recording configuration tab.  If so, any outgoing call from an endpoint that is registered with a PBX user object with a called number that equals the setting of this tweak, will be suppressed.  So if your recording sink has the number &amp;lt;code&amp;gt;44&amp;lt;/code&amp;gt;, you would set this registry value to &amp;lt;code&amp;gt;44&amp;lt;/code&amp;gt; (this is available from TAPI V8 hotfix 8). Please note that this feature actually suppresses any call info for such calls, however, it does not revert previously announced call infos.  So if the call is initiated using &#039;&#039;overlapped dialling&#039;&#039;, all call states will be shown until the called number matches the value of &amp;lt;code&amp;gt;HiddenRecordingNumber&amp;lt;/code&amp;gt; and all subsequent call states will be suppressed.  This will probably leave the call shown in &#039;&#039;dialling&#039;&#039; state.  The feature should be used for destinations which are called using &#039;&#039;block dialling&#039;&#039; only thus.  &lt;br /&gt;
&lt;br /&gt;
; SilentHold : REG_DWORD. When a call is put on hold using &amp;lt;code&amp;gt;lineHold&amp;lt;/code&amp;gt;, the held party will hear &#039;&#039;music on hold&#039;&#039; emitted by the PBX. The hold-initiator will hear a dialling tone (PBX firmware v11r2 and up, with older versions the initiator would hear &#039;&#039;music on hold&#039;&#039;).  When &amp;lt;code&amp;gt;SilentHold&amp;lt;/code&amp;gt; is set to a non-zero value, the initiating party will hear silence - i.e. no dialling tone (this is available from TAPI V8 hotfix 8).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- There are some more values in a key underneath &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt; called &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&#039;&#039;XX&#039;&#039;: --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; NoDuplicateConnectedCalls : REG_DWORD. If set to 1, the TSP will never show more than one call per line to be active.  Extra active calls will be shown as &#039;&#039;on-hold&#039;&#039;. The situation occurs e.g. when a user initiates a 3PTY conference on the phone.  This essentially is a bug fix for Microsoft&#039;s OCS client which forces any extra active call on-hold, thereby disturbing the 3PTY function.  If your are using [http://www.estos.de/download/software/eccg.htm ESTOS&#039; Call Control Gateway]: from version &#039;&#039;2.0.1.1474 - 05.11.2008&#039;&#039; there is a fix for this same problem available.  This option thus is deprecated.&lt;br /&gt;
&lt;br /&gt;
; UseFirstLeg2 : REG_DWORD. TAPI allows only for a single leg-2 info (redirection information in case of a call forward).  If a call is forwarded mutliple times, by default the last redirection is shown in TAPI. If &amp;lt;code&amp;gt;UseFirstLeg2&amp;lt;/code&amp;gt; is set to 1 however, the first redirection is shown.&lt;br /&gt;
&lt;br /&gt;
; UseNameForDeviceGuid : REG_DWORD. The TSP will create a TAPI line for each &#039;&#039;Device&#039;&#039; of each PBX object (if &#039;&#039;MapDevices&#039;&#039; is set).  The internal unique identifier includes the &#039;&#039;Hardware Id&#039;&#039; found in the &#039;&#039;Device&#039;&#039;.  If this changes, the TAPI line representing the &#039;&#039;Device&#039;&#039; is considered new and a new TAPI &#039;&#039;permanent line id&#039;&#039; is allocated.  This may be annoying cause when a device serial number (e.g. for a telephone) is used as &#039;&#039;Hardware Id&#039;&#039;, replacing the device creates a new TAPI line.  If &#039;&#039;UseNameForDeviceGuid&#039;&#039; is set to 1, the TSP will use the &#039;&#039;Device&#039;&#039;s &#039;&#039;Name&#039;&#039; instead (which usually not changes).  While this might be more convenient, be aware that you &#039;&#039;must&#039;&#039; make sure that no PBX object has duplicate &#039;&#039;Name&#039;&#039;s!  Otherwise, TAPI will get confused.   Available from build 8178&lt;br /&gt;
&lt;br /&gt;
; ShowConfGUID : REG_DWORD.  If set and not 0, the TSP will implicitly set each call&#039;s CallData to a string such as &amp;quot;&amp;lt;code&amp;gt;conf-guid:&amp;lt;/code&amp;gt;&#039;&#039;call-guid&#039;&#039;&amp;quot;.   &#039;&#039;call-guid&#039;&#039; is a 66-byte Unicode16 string (32 hex characters plus terminating 0). Note that this will interfere with an application&#039;s use of the lineSetCallData function (tapi.h) and is therefore disabled by default. Available from build 8190&lt;br /&gt;
&lt;br /&gt;
; NoFix : REG_DWORD. If set and not 0, the TSP will not trigger a full re-synchronization if it receives implausible state messages. Available from build 8197.&lt;br /&gt;
&lt;br /&gt;
===List of supported TSPI functions===&lt;br /&gt;
&lt;br /&gt;
The TSP supports the following TAPI Service Provider Interface Functions.  Note that these do not map one to one with TAPI user functions. For more information, see the Microsoft TAPI documentation.&lt;br /&gt;
&lt;br /&gt;
*TSPI_lineAnswer&lt;br /&gt;
*TSPI_lineBlindTransfer&lt;br /&gt;
*TSPI_lineClose                      &lt;br /&gt;
*TSPI_lineCloseCall                  &lt;br /&gt;
*TSPI_lineCompleteTransfer&lt;br /&gt;
*TSPI_lineDevSpecific&lt;br /&gt;
*TSPI_lineDevSpecificFeature&lt;br /&gt;
*TSPI_lineDial&lt;br /&gt;
*TSPI_lineDrop  &lt;br /&gt;
*TSPI_lineForward&lt;br /&gt;
*TSPI_lineGenerateDigits                     &lt;br /&gt;
*TSPI_lineGetAddressCaps             &lt;br /&gt;
*TSPI_lineGetAddressID               &lt;br /&gt;
*TSPI_lineGetAddressStatus           &lt;br /&gt;
*TSPI_lineGetCallAddressID           &lt;br /&gt;
*TSPI_lineGetCallHubTracking&lt;br /&gt;
*TSPI_lineGetCallIDs&lt;br /&gt;
*TSPI_lineGetCallInfo                &lt;br /&gt;
*TSPI_lineGetCallStatus              &lt;br /&gt;
*TSPI_lineGetDevCaps                 &lt;br /&gt;
*TSPI_lineGetExtensionID&lt;br /&gt;
*TSPI_lineGetID                      &lt;br /&gt;
*TSPI_lineGetLineDevStatus           &lt;br /&gt;
*TSPI_lineGetNumAddressIDs&lt;br /&gt;
*TSPI_lineHold&lt;br /&gt;
*TSPI_lineMakeCall      &lt;br /&gt;
*TSPI_lineNegotiateExtVersion&lt;br /&gt;
*TSPI_lineNegotiateTSPIVersion       &lt;br /&gt;
*TSPI_lineOpen    &lt;br /&gt;
*TSPI_linePark&lt;br /&gt;
*TSPI_linePickup&lt;br /&gt;
*TSPI_lineRedirect&lt;br /&gt;
*TSPI_lineSelectExtVersion&lt;br /&gt;
*TSPI_lineSendUserUserInfo&lt;br /&gt;
*TSPI_lineSetAppSpecific             &lt;br /&gt;
*TSPI_lineSetCallData&lt;br /&gt;
*TSPI_lineSetCallHubTracking&lt;br /&gt;
*TSPI_lineSetCallParams                 &lt;br /&gt;
*TSPI_lineSetCurrentLocation         &lt;br /&gt;
*TSPI_lineSetDefaultMediaDetection   &lt;br /&gt;
*TSPI_lineSetMediaMode               &lt;br /&gt;
*TSPI_lineSetStatusMessages          &lt;br /&gt;
*TSPI_lineSetupTransfer&lt;br /&gt;
*TSPI_lineSwapHold&lt;br /&gt;
*TSPI_lineUnhold&lt;br /&gt;
*TSPI_lineUnpark&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*TSPI_providerConfig                 &lt;br /&gt;
*TSPI_providerCreateLineDevice&lt;br /&gt;
*TSPI_providerEnumDevices            &lt;br /&gt;
*TSPI_providerGenericDialogData&lt;br /&gt;
*TSPI_providerInit                   &lt;br /&gt;
*TSPI_providerInstall                &lt;br /&gt;
*TSPI_providerRemove                 &lt;br /&gt;
*TSPI_providerShutdown               &lt;br /&gt;
*TSPI_providerUIIdentify     &lt;br /&gt;
=====Notes on Consultation Calls=====        &lt;br /&gt;
This TSP supports the &amp;lt;code&amp;gt;lineSetupTransfer&amp;lt;/code&amp;gt; function.  However, strictly speaking, this function is not needed and should not be used.  It is merely intended for applications which do not offer a consultation call interface to the user when this function is not available.  Instead, &amp;lt;code&amp;gt;TSPI_lineMakeCall&amp;lt;/code&amp;gt; can be used where &amp;lt;code&amp;gt;lineSetupTransfer&amp;lt;/code&amp;gt; would be otherwise.  The notion of a special &#039;&#039;consultation call&#039;&#039; is an idiosyncrasy forced by legacy PBX technologies which were not able to transfer two arbitrary calls.   In these scenarios, a potentially to-be-transferred call needed to be linked to the primary call.  The PBX can transfer two arbitrary calls and thus there is no need for &amp;lt;code&amp;gt;lineSetupTransfer&amp;lt;/code&amp;gt;.  This ability is indicated by the &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_TRANSFERMAKE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFERENCEMAKE &amp;lt;/code&amp;gt; flags.   The transfer is then requested by using &amp;lt;code&amp;gt;TSPI_lineCompleteTransfer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=====Notes on 3PTY Conferences=====&lt;br /&gt;
The TSP supports the management of 3PTY conferences.  These can be initiated by using &amp;lt;code&amp;gt;TSPI_lineCompleteTransfer&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;LINETRANSFERMODE_CONFERENCE&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;LINETRANSFERMODE_TRANSFER&amp;lt;/code&amp;gt;.  This is indicated by the flags &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFERENCEHELD&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFERENCEMAKE&amp;lt;/code&amp;gt;.  The 3PTY function is actually implemented by the innovaphone IP phones (such as IP2xx).  Therefore, these capabilities are only advertised if the line is based on a PBX user object.  Still, some lines where the capabilities are advertised cannot do 3PTY (such as e.g. DECT lines, analogue lines, 3rd party devices, ...). So the call to &amp;lt;code&amp;gt;TSPI_lineCompleteTransfer&amp;lt;/code&amp;gt; will succeed but the conference will not be initiated and the subsequent call states will not indicate a conference (as there is no).  &lt;br /&gt;
&lt;br /&gt;
Also, if non-telephone devices are registered with a PBX user object and these device have multiple concurrent calls (e.g. a call center connected with a multi-channel XCapi), these will be viewed as 3PTY calls (as this is the way such calls appear to the TAPI: a line with more than one non-held call).  If these calls are in fact no 3PTY, this may lead to confusing call indications from TAPI.  It is better to register such objects as a PBX gateway object.  Special treatment of 3PTY calls can be disabled by setting the registry flag &amp;lt;code&amp;gt;No3PTY&amp;lt;/code&amp;gt; (from build 8087 onwards).&lt;br /&gt;
&lt;br /&gt;
A 3PTY conference will create a new call handle for the conference.  The only operation available for such a handle is &amp;lt;code&amp;gt;TSPI_lineDrop&amp;lt;/code&amp;gt;. This will terminate the conference and restore the state active before the conference was initiated (that is, the phone that implemented the conference will now have 2 calls, one active and one on hold).  This is indicated by not setting &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFDROP&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;lineDrop()&amp;lt;/code&amp;gt; on one of the 2 &#039;&#039;real&#039;&#039; calls involved will of course cancel this call and thus remove the 3PTY.&lt;br /&gt;
&lt;br /&gt;
======Notes on Intrusion Calls======&lt;br /&gt;
A special case of 3PTY is an intrusion call initiated by a [[Reference9:Phone/User/Function-Keys/Partner | partner function key]].  To TAPI, this looks like a 3PTY (which it in fact is).  However, phones before firmware version 9 hotfix 19 will not be able to release this 3PTY upon request.  Thus, you will see a 3PTY in TAPI which cannot be dropped.  From phone firmware 9 hotfix 19 on, the request to drop this 3PTY will cancel the intrusion call.  Note that TAPI will nevertheless &#039;&#039;not&#039;&#039; set &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFDROP&amp;lt;/code&amp;gt; on such conferences (as TAPI does not know that this is an intrusion call).&lt;br /&gt;
&lt;br /&gt;
======Notes on Recording Calls======&lt;br /&gt;
A special case of 3PTY is a recording call.  This effectively creates an user-invisible 3PTY on the phone.  To TAPI, this looks like a 3PTY (which it in fact is).  However, phones before firmware version 9 hotfix 19 will not be able to release this 3PTY upon request.  Thus, you will see a 3PTY in TAPI which cannot be dropped.  From phone firmware 9 hotfix 19 on, the request to drop this 3PTY will cancel the recording call.   Note that TAPI will nevertheless &#039;&#039;not&#039;&#039; set &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFDROP&amp;lt;/code&amp;gt; on such conferences (as TAPI does not know that this is a recording call).&lt;br /&gt;
&lt;br /&gt;
Recording calls are shown as normal conferences (unless &amp;lt;code&amp;gt;No3PTY&amp;lt;/code&amp;gt; is set).  This might be confusing to applications and/or users.  See the &amp;lt;code&amp;gt;HiddenRecordingNumber&amp;lt;/code&amp;gt; tweak above for a method to hide such calls.&lt;br /&gt;
&lt;br /&gt;
=====Notes on parked Calls=====&lt;br /&gt;
The PBX can park calls from and to any existing PBX object, e.g. by virtue of [[Reference8:Configuration/Registration/Function-Keys/Park | specific feature keys]].  They are parked to/from a numeric &#039;&#039;park position&#039;&#039;.  In SOAP however, calls are parked to an object by providing the objects &#039;&#039;&#039;UserInitialize()&#039;&#039;&#039; handle and a park position.  Parked calls are then reported as straight calls with a distinct signalling state (8).  The park position is not conveyed as part of the &#039;&#039;&#039;CallInfo&#039;&#039;&#039; record.  To unpark, &#039;&#039;&#039;[[Reference8:SOAP_API#integer_UserPickup.28int_user.2C_string_cn.2C_integer_call.2C_string_group.2C_int_reg.2C_InfoArray_info.29 | UserPickup]]&#039;&#039;&#039; can be used providing the parked calls call handle as &#039;&#039;&#039;call&#039;&#039;&#039; argument.  &lt;br /&gt;
&lt;br /&gt;
The TAPI specification is unclear on how the address information required to &#039;&#039;&#039;lineUnpark()&#039;&#039;&#039; a call can be obtained by an application (except that it is returned from &#039;&#039;&#039;linePark()&#039;&#039;&#039; if the call was parked using TAPI).    The TSP thus indicates parked calls on a line with a call reason &amp;lt;code&amp;gt;LINECALLREASON_PARKED&amp;lt;/code&amp;gt;.  The caller id information is set to the parked calls call handle.  This way, the application can take the caller id information and provide it to &#039;&#039;&#039;lineUnpark()&#039;&#039;&#039; to unpark a call.  If the appication does not support this mode of operation but supports &#039;&#039;&#039;lineUnpark()&#039;&#039;&#039; and lets the user input the park identifier, the user can just provide the caller id information.&lt;br /&gt;
&lt;br /&gt;
Some applications do not care for parked calls (by examining the call reason) and just blindly report these calls like ordinary connected calls (thereby confusing the user).  To work around this problem, reporting parked calls can be turned off in the TSP configuration dialogue.&lt;br /&gt;
&lt;br /&gt;
=====Notes on sending User to User Information =====&lt;br /&gt;
The TAPI specification for sending UserUserInfo closely resembles the way ISDN defines this service.  Although the innovaphone PBX supports this service both with H.323 and SIP, it is &#039;&#039;not&#039;&#039; supported in this TSP.  Instead, sending user to user information is implemented using H.323/SIP messaging.  However, there are some important deviations and limitations caused hereby:&lt;br /&gt;
* data is &#039;&#039;not transparent&#039;&#039;.  That is, the TSP only allows for null-terminated unicode to be sent.  The data must be of even length and the last two bytes must be null. &lt;br /&gt;
* data is &#039;&#039;not sent within the call&#039;&#039;, but by initiating a separate call.  This implies that the target number used to send the message carrying the data to is &#039;guessed&#039; from the available call data.  For example, if the call is in a connected state and a connected number is known, the message is sent to the connected number.  If the call is in the ringback state, then either the called number or - if available - the redirection number is used and so forth.&lt;br /&gt;
* message calls are not indicated by the SOAP CallInfo records.  As a result, messages sent with lineSendUserUserInfo cannot be received with TAPI&lt;br /&gt;
=====Notes on receiving User to User Information =====&lt;br /&gt;
From build 8200, the TSP will deliver incoming UUI on a call. Although lineSendUserUserInfo will still send H.323/SIP messages instead of native UUI, you can now receive incoming UUI (for example from ISDN) in a LINE_CALLINFO  message.&lt;br /&gt;
&lt;br /&gt;
=====Notes on sending proprietary innovaphone Remote Control Facilities  =====&lt;br /&gt;
The SOAP  [[Reference10:SOAP_API#UserRc.28integer_call.2C_integer_rc.29|UserRc]] function allows to send various [[Reference:Remote Control Facility|facility messages]] to an innovaphone phone device.  In some cases, it is useful to be able to invoke this function through a standard TAPI mechanism.  This can be achieved by using the TAPI &#039;&#039;&#039;lineBlindTransfer&#039;&#039;&#039; function.  If the &#039;&#039;called party name&#039;&#039; provided as destination for the &#039;&#039;lineBlindTransfer&#039;&#039; (in &#039;&#039;lpszDestAddress&#039;&#039;) has the magic value &amp;lt;code&amp;gt;USERRC&amp;lt;/code&amp;gt;, then the &#039;&#039;called subaddress&#039;&#039; is converted to an integer and the result is sent as remote control facility to the call the blind transfer is applied for.  For details on how to code the &#039;&#039;called party name&#039;&#039; and the &#039;&#039;called subaddress&#039;&#039; into &#039;&#039;lpszDestAddress&#039;&#039; see [http://msdn.microsoft.com/en-us/library/windows/desktop/ms726017%28v=vs.85%29.aspx Microsoft&#039;s &#039;&#039;Canonical Address&#039;&#039; specification].     This works from TAPI8 hotfix 4.&lt;br /&gt;
&lt;br /&gt;
For example, initiating a blind transfer to &amp;lt;code&amp;gt;|16^USERRC&amp;lt;/code&amp;gt; (empty address, subaddress 16 (that is, [[Reference:Remote Control Facility|&#039;&#039;change to handset mode&#039;&#039;]]), called name &amp;lt;code&amp;gt;USERRC&amp;lt;/code&amp;gt;) will switch the phone having the call to be transferred into handset mode (and &amp;lt;code&amp;gt;|18^USERRC&amp;lt;/code&amp;gt; will switch it back to handsfree mode).  Of course, no actual transfer will happen in these cases (&#039;&#039;lineBlindTransfer&#039;&#039; is merely used as a vehicle to send the facility to the proper call).&lt;br /&gt;
&lt;br /&gt;
Such proprietary facility message can also be sent with &#039;&#039;lineMakeCall&#039;&#039; (that is, in SOAP&#039;s [[Reference10:SOAP_API#integer_UserCall.28integer_user.2C_string_cn.2C_string_e164.2C_string_h323.2C_int_reg.2C_InfoArray_info.2C_int_rc.2C_string_srce164.29|UserCall]] function).  For example, setting up a call to &amp;lt;code&amp;gt;123|21^USERRC&amp;lt;/code&amp;gt; will send an intrusion call to extension 123 and intrude any call that might be active there. This works from TAPI8 hotfix 6. Please note that the innovaphone TAPI service provider does not support TAPI&#039;s &#039;&#039;lineCompleteCall&#039;&#039; function with &amp;lt;code&amp;gt;LINECALLCOMPLMODE_INTRUDE&amp;lt;/code&amp;gt; though (as TAPI&#039;s call model here does not fit with the PBX&#039;s call model).  Please also note that intrusion calls look like 3PTY calls to TAPI (see [[#Notes_on_Intrusion_Calls|notes on intrusion calls]] above).&lt;br /&gt;
&lt;br /&gt;
Remote control facilities are implemented by the telephone devices, so these functions are subject to the phone firmware in use.&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto|{{PAGENAME}}]]&lt;br /&gt;
[[Category:Concept|{{PAGENAME}}]]&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
* [[Howto:Troubleshooting the TAPI service provider]]&lt;br /&gt;
* [[ReleaseNotes8:TAPI]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference8:TAPI_Service_Provider&amp;diff=73878</id>
		<title>Reference8:TAPI Service Provider</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference8:TAPI_Service_Provider&amp;diff=73878"/>
		<updated>2024-11-04T17:22:55Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Notes on sending User to User Information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;innovaphone PBX V8.0 based TAPI Service Provider&#039;&#039; (TSP) is an enhanced version of the [[ Reference7:Unified Win32 and x64 TAPI Service Provider | previous TSP version ]] that takes advantage of the [[ Reference8:SOAP API | new SOAP features ]] provided with version 8 PBX firmware. It implements - like the previous versions - TAPI Version 3.0 without MSP (Media Service Provider).&lt;br /&gt;
&lt;br /&gt;
The [[Reference7:Unified Win32 and x64 TAPI Service Provider| previous TSP ]] still must be used for V7 PBX systems. &lt;br /&gt;
&lt;br /&gt;
This article describes how to install and use it as well how to configure the PBX in order for the TSP to work properly.&lt;br /&gt;
&lt;br /&gt;
==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
* innovaphone PBX V8.0 based TAPI Service Provider, Build 8001 and later&lt;br /&gt;
* innovaphone PBX V8 and later (that is, this Service Provider runs with PBX Firmware V8 and later)&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Enhancements ===&lt;br /&gt;
; Support for V8 firmware [[Reference8:Administration/PBX/Objects#Devices | devices]] : Each user object device is represented as a TAPI line (all sharing an identical address, the objects extension a.k.a. &#039;&#039;Number&#039;&#039; property).  This now allows to select individual registration devices when multiple devices are registered with the same PBX.  Please note that in V8, [[ Reference8:Administration/PBX/Objects/Edit_Forks | mobility devices ]] are not shown and thus not represented by  TAPI line device.  This was introduced in V9 only.&lt;br /&gt;
; Support for presence based lines :  These are TAPI lines shown which reflect the users presence state.  Presence state &#039;&#039;open&#039;&#039; is mapped to a TAPI device status &#039;&#039;in service&#039;&#039;.  Presence activity &#039;&#039;on-the-phone&#039;&#039; is mapped to a virtual call in state &#039;&#039;connected&#039;&#039;.&lt;br /&gt;
: &#039;&#039;&#039;NB&#039;&#039;&#039;: V8 PBX Firmware did set presence activity &#039;&#039;on-the-phone&#039;&#039; for each user object having a call.  Unfortunately, as this does create performance issues, this behaviour has been removed from V9 PBX Firmware.  The &#039;&#039;presence line&#039;&#039; feature may be useless with V9 PBX when the application did rely on this particular V8 PBX behaviour.&lt;br /&gt;
&lt;br /&gt;
===System Requirements===&lt;br /&gt;
The TSP will install on any Windows 32bit and x64 platform down to Windows XP/Server 2003.  For older systems, you must use a deprecated [[Reference7:TAPI_Service_Provider | previous TSP version]].  For systems running PBX firmware version 6 or earlier, you must use the even older [[Reference:TAPI_Service_Provider | version 5 based TSP]].  Note that there is no x64 version of the version 5 TSP!&lt;br /&gt;
&lt;br /&gt;
The TSP needs to maintain parallel connections to each individual PBX in the system.  For larger systems (i.e. systems with a huge number of PBXs), this may create substantial load to the underlying windows machine.  The number of parallel activities scheduled by the TSP is thus limited as a function of the available main memory and number of processors.  In particular, a maximum of 20 activities per available processor is allowed (up to build 8088, the limit is 60/processor for later builds).  If this limit is exceeded, the TSP will issue performance warnings of class WARNINGS in the TSP log file and system TAPI performance will be poor.  Use a more capable machine then.&lt;br /&gt;
&lt;br /&gt;
Microsoft Windows operating system version for desktop clients (as opposed to server systems) limit the number and performance of TCP/IP connections.  This may lead to bad performance or occasional request failures.  We generally recommend to use server operating systems for 3rd party TAPI installations thus.&lt;br /&gt;
&lt;br /&gt;
No special PBX licenses are required to use the innovaphone TSP.&lt;br /&gt;
&lt;br /&gt;
=== Download === &lt;br /&gt;
The TSP will be available on the tab &#039;&#039;Software&#039;&#039; in the [https://store.innovaphone.com/ Store].&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
Windows cannot run a Win32 TSP on an x64 platform (although it can run Win32 applications on such platforms).  This is why there are 2 versions of the setup, the x64 installer (&amp;lt;code&amp;gt;setup64-release.msi&amp;lt;/code&amp;gt;) and the Win32 installer (&amp;lt;code&amp;gt;setup32-release.msi&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;release&#039;&#039; setup packages provided will install the retail version.  This is recommended for production purposes but provides no debug options whatsoever.  To track down possible problems, support may instruct you to install the debug version.  &lt;br /&gt;
&lt;br /&gt;
The TSP may be installed on each machine where a desired TAPI based&lt;br /&gt;
application is to be run.  If for example, Outlook is to be used, then&lt;br /&gt;
each client PC running Outlook may have the TSP installed.  Although&lt;br /&gt;
this is typical for a 1st party configuration, all clients may have full&lt;br /&gt;
3rd party functionality, that is, they may control all existing lines.&lt;br /&gt;
&lt;br /&gt;
As an alternative, the TSP can be installed on a single machine and a&lt;br /&gt;
3rd party TAPI server product (such as the IXI-Call Server available as&lt;br /&gt;
a separate product) may be used to provide the network clients with a&lt;br /&gt;
TAPI interface.  Also, Microsoft’s Remote TAPI Server should work but is not being tested, so you use it on your own risk.&lt;br /&gt;
&lt;br /&gt;
To install, &lt;br /&gt;
* select and download the &amp;lt;code&amp;gt;setup32-release.msi&amp;lt;/code&amp;gt; install packages on 32bit platforms or the &amp;lt;code&amp;gt;setup64-release.msi&amp;lt;/code&amp;gt; install package on 64bit platforms.&lt;br /&gt;
* double-click the install package to launch the installer&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - zipcontent.png]]&lt;br /&gt;
* accept the license agreement&lt;br /&gt;
* select the target folder&lt;br /&gt;
* complete the installer&lt;br /&gt;
&lt;br /&gt;
When the installer has copied all files to the target machine, you need to add the TSP to the machine&#039;s TAPI system&lt;br /&gt;
* open the &#039;&#039;Telephone and Modem&#039;&#039; control panel&lt;br /&gt;
* Switch to the rightmost tab (&#039;&#039;Extras&#039;&#039;)&lt;br /&gt;
* Click on the &#039;&#039;Add...&#039;&#039; button&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - Control Panel Add.png]]&lt;br /&gt;
* Select the innovaphone TAPI provider driver&lt;br /&gt;
* Fill out the configuration dialogue&lt;br /&gt;
* Install the provider by clicking &#039;&#039;OK&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== File Organization ====&lt;br /&gt;
Windows forces all TAPI service provider files to reside in Windows&#039; &#039;&#039;System Folder&#039;&#039;.  This is the &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt; folder in your windows install directory (usually &amp;lt;code&amp;gt;C:\windows\system32&amp;lt;/code&amp;gt;), even if you are running an x64 platform!  The installer will thus copy these files (&amp;lt;code&amp;gt;tsp8.tsp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tsp8UI.dll&amp;lt;/code&amp;gt;) in to this directory.  All other files however will be copied to the &amp;lt;code&amp;gt;innovaphone AG\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt; folder underneath your systems &#039;&#039;Program Files Folder&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
The subdirectories &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Logs&amp;lt;/code&amp;gt; are created.  &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; contains the driver&#039;s debug version, &amp;lt;code&amp;gt;Logs&amp;lt;/code&amp;gt; will receive the log files when a debug version is used.&lt;br /&gt;
&lt;br /&gt;
On x64 platform systems, the Win32 version of the configuration DLL (&amp;lt;code&amp;gt;tsp8UI.dll&amp;lt;/code&amp;gt;) will be installed to the windows &#039;&#039;Windows on Windows64 System Folder&#039;&#039; (&amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
====Upgrading to a newer Version====&lt;br /&gt;
When you attempt to upgrade the TSP from a previous version, the Windows&lt;br /&gt;
installer will first remove any previous installation.  When the new&lt;br /&gt;
software is installed then, the TSP will be installed again into the&lt;br /&gt;
TAPI system.  &lt;br /&gt;
&lt;br /&gt;
There is no need to remove the driver from the &#039;&#039;Telephone and Modem Control Panel&#039;&#039;, as this would make you loose your driver configuration.&lt;br /&gt;
&lt;br /&gt;
====Upgrading from the old Win32-only Version====&lt;br /&gt;
If you upgrade from the older Win32-only versions of the TSP (soap-appl/tapi/7.00 or soap-appl/tapi/5.00), you must first remove the old TSP from &#039;&#039;telephone and modem&#039;&#039; control panel and uninstall the old product from the &#039;&#039;Software&#039;&#039; (or &#039;&#039;Programs and Functions&#039;&#039;) control panel.&lt;br /&gt;
&lt;br /&gt;
When you upgrade from the old V7 64-bit TSP (soap-appl/tapi/7.00-64), you should first update this older version to the latest build available.&lt;br /&gt;
&lt;br /&gt;
This procedure ensures that during the upgrade your TAPI lines retain their internal identifiers and thus their meaning in your TAPI application&#039;s configuration.&lt;br /&gt;
&lt;br /&gt;
==== Uninstalling the TSP ====&lt;br /&gt;
To uninstall the TSP proceed as follows&lt;br /&gt;
* Remove the TAPI driver from the TAPI system using &#039;&#039;Telephony and Modem Control Panel&#039;&#039;&lt;br /&gt;
* close &#039;&#039;Telephony and Modem Control Panel&#039;&#039;&lt;br /&gt;
* shut down windows telephony service. This can be done from the Windows &#039;&#039;Service Control Panel&#039;&#039; or by invoking &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt; from a command prompt&lt;br /&gt;
* remove the installation using windows &#039;&#039;Programs Control Panel&#039;&#039; or by invoking the original .msi again&lt;br /&gt;
&lt;br /&gt;
You will notice that Windows may fail to remove the driver files from the &#039;&#039;Windows System Directory&#039;&#039;.  To clean up remove &amp;lt;code&amp;gt;tsp8.tsp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tsp8UI.dll&amp;lt;/code&amp;gt; from the &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt; folder as well as - on x64 systems - from the &amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Also, if you did file tracing, any remaining debug files in the &amp;lt;code&amp;gt;Logs&amp;lt;/code&amp;gt; folder are left over and need to be removed manually.&lt;br /&gt;
&lt;br /&gt;
The TSP will create some entries in the windows registry which will not be removed on uninstall.  It is recommended to leave these entries as is.  Only if you are sure you will never install the TSP again on this system or you are sure you will never use it with the PBX installation you used so far, you may want to delete them from the registry.&lt;br /&gt;
&lt;br /&gt;
==== Rolling out First Party TSPs to multiple PCs ====&lt;br /&gt;
Normally, when multiple users require CTI and hence TAPI functionality, the best way is to use a server based, multi-client 3rd party CTI application.  This will share all functions among all client PCs.  If this is not an option, e.g. because the TAPI application in use does not support it, you may want to consider using Microsoft&#039;s TAPI Server and remote TSP.  See Microsoft&#039;s [http://technet.microsoft.com/en-us/library/cc786297%28v=ws.10%29.aspx Telephony service providers overview] and [http://technet.microsoft.com/en-us/library/cc770373.aspx Manage Telephony Servers] documents.  &lt;br /&gt;
&lt;br /&gt;
If you still want to use the native innovaphone TSP on a number of PCs (instead of once on a server), you can roll out the TSP using some of the [http://support.microsoft.com/kb/816102/EN-US software deployment schemes Microsoft Server provide].  In such a case, you will likely want to deploy identical configurations to all these PCs. While this theoretically can be done by distributing registry settings, there will be a problem with the PBX access credentials.  These are stored in encrypted format in the registry and can only be decrypted on the PC on which they have been set.  That is, deploying such registry settings to other PCs will result in a non-functional setup.&lt;br /&gt;
&lt;br /&gt;
To work around this problem, you may store the credentials in clear text in the registry.  To do so, you would put the &#039;&#039;Password&#039;&#039; in a REG_SZ value named &amp;lt;code&amp;gt;admin1-free&amp;lt;/code&amp;gt; and the &#039;&#039;Account&#039;&#039; into a REG_SZ value named &amp;lt;code&amp;gt;admin2-free&amp;lt;/code&amp;gt;.  If such a value is found in the proper place in the registry, the values configured using the telephony control panel are ignored.  &lt;br /&gt;
&lt;br /&gt;
[[Image:TAPI Service Provider-tsp8-nocrypt.png]]&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;Keep in mind that having credentials in clear in the registry presents a security risk!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This feature is available in build 8079 and later.&lt;br /&gt;
&lt;br /&gt;
=== Upgrade from Build 8164 or earlier ===&lt;br /&gt;
From build 8165, the TAPI configuration has been moved to a different registry location.  This has been done because latest windows versions (namely, Windows 10) do not allow the TSP to access registry information in the location used so far (&amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;).   To work around this issue, it is now stored in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The TSP configuration dialogue however runs with user privileges (as opposed to the TSP which runs with limited service privileges). It can therefore read the old configuration information and copy it to the new location.  From build 8165, the configuration dialogue will thus copy any old configuration information to the new location when it is opened.  When you upgrade an existing installation and open the configuration dialogue, you will see no change.  However, when the configuration is saved, it is then present in the new location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;To upgrade an installation from build 8164 or earlier (that is TAPI &#039;V8 TAPI Service Provider (32 and 64bit) - hotfix14&#039;&#039; available in the &#039;&#039;V8 applications hotfix20&#039;&#039; package or earlier), proceed as follows:&#039;&#039;&#039;&lt;br /&gt;
* stop the telephony service (e.g. &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt;)&lt;br /&gt;
* install the new TSP&lt;br /&gt;
* open the TSP configuration dialogue&lt;br /&gt;
* verify the configuration data&lt;br /&gt;
* save the configuration&lt;br /&gt;
* (re) start your TAPI application&lt;br /&gt;
&lt;br /&gt;
If you fail to migrate the configuration as described, the TSP will start, but not work!&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
The TSP configuration dialogue looks like this:&lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - Config UI.png]]&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;VERIFY&#039;&#039; button will verify the configuration.  Note that the &#039;&#039;Username&#039;&#039; drop down list will only be populated after a successful verify. &lt;br /&gt;
* The &#039;&#039;OK&#039;&#039; button will save the configuration.&lt;br /&gt;
* The &#039;&#039;CANCEL&#039;&#039; button will quit the configuration without saving any changes.  If it is the initial configuration while you add the TSP via the telephone and modem control panel, the TSP will not be added &lt;br /&gt;
&lt;br /&gt;
TAPI talks to the PBX using [[Reference7:SOAP_API | SOAP ]] which in turn uses HTTP for communication.  Both secure (https) and non-secure (http) communication is supported.  In any case, HTTP basic authentication is used.  &lt;br /&gt;
To be able to connect to the PBX, the TSP needs to know proper credentials to use during HTTP authentication. These are referred to as &#039;&#039;PBX Account&#039;&#039; and &#039;&#039;PBX Password&#039;&#039;.  Also, a suitable &#039;&#039;TAPI User&#039;&#039; must be selected.&lt;br /&gt;
&lt;br /&gt;
==== Controlling the Line Devices handled by TAPI ====&lt;br /&gt;
&lt;br /&gt;
TAPI connects to your PBX as a PBX user referred to as &#039;&#039;TAPI User&#039;&#039;.  It will see all PBX objects that are members of groups in which the &#039;&#039;TAPI User&#039;&#039; is an active member.  If the &#039;&#039;TAPI User&#039;&#039; is not an active member in any group, TAPI will see the &#039;&#039;TAPI User&#039;&#039; object only. This may be useful in a [http://en.wikipedia.org/wiki/Telephony_Application_Programming_Interface 1st party TAPI scenario].  PBX objects are represented as TAPI lines.  &lt;br /&gt;
&lt;br /&gt;
The PBX object you use as &#039;&#039;TAPI User&#039;&#039; needs to have at least &#039;&#039;Viewing only&#039;&#039; [[Reference:Administration/PBX/Objects/Edit Rights | PBX user rights]].  Its &#039;&#039;Long Name&#039;&#039; property is used as &#039;&#039;TAPI User Username&#039;&#039;, its &#039;&#039;Name&#039;&#039; property as &#039;&#039;PBX Account&#039;&#039; and the password as &#039;&#039;PBX Password&#039;&#039;.  This is why the PBX object used as &#039;&#039;TAPI User&#039;&#039; must have a password configured. &lt;br /&gt;
&lt;br /&gt;
===== 1st Party Configuration =====&lt;br /&gt;
In a 1st party scenario, the TSP will only work on a single PBX object.  This will typically be a user&#039;s phone and thus the user itself will be used as the &#039;&#039;TAPI User&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - FirstParty.png ]]&lt;br /&gt;
&lt;br /&gt;
In such a configuration the TSP is typically installed on the users PC and the CTI software is accessing TAPI directly (such as e.g. Microsoft Outlook does).   &lt;br /&gt;
&lt;br /&gt;
The TSP configuration dialogue will check for the number of lines seen.  If it is only one, then it will issue a warning message:&lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - OnlyOne.png]]&lt;br /&gt;
&lt;br /&gt;
This is because 3rd party configurations are much more common and this situation often indicates a configuration problem.  In a first party configuration, you can safely ignore this message. &lt;br /&gt;
&lt;br /&gt;
===== 3rd Party Configuration =====&lt;br /&gt;
In a 3rd party configuration, the TSP will work with multiple PBX objects.  &lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - ThirdParty.png]]&lt;br /&gt;
&lt;br /&gt;
Typically, you will share a single TSP instance on a server system for use by several users on their desktop PCs.  This is done by virtue of a &#039;&#039;TAPI Server&#039;&#039;.  There are various TAPI server products available on the market, including but not limit to the Estos ProCall product and the remote TAPI server included in Microsoft Windows server operating systems.  &lt;br /&gt;
&lt;br /&gt;
In this scenario, it is recommended to create a pseudo PBX user object for use as the &#039;&#039;TAPI User&#039;&#039;.  This pseudo user is often called &amp;lt;code&amp;gt;_TAPI_&amp;lt;/code&amp;gt;.  You would create a dedicated group to control the list of PBX objects the TSP creates a line device for.  This group is often called &amp;lt;code&amp;gt;tapi&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Selective Call Forwards ====&lt;br /&gt;
Many CTI applications support distinct call forwards for internal and/or external calls.  The TSP will translate such requests to a call forward on the PBX which has the [[Reference7:Administration/PBX/Objects/Edit_CFs | &#039;&#039;Only&#039;&#039; or &#039;&#039;Only not&#039;&#039; property]] set to the number of the trunk line.  For this to work, it needs to know this number.  To know the number, the trunk line PBX object must be seen by the TSP (see above).  If this is not the case, the TSP configuration dialogue will issue a warning:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - NoTrunk.png]]&lt;br /&gt;
&lt;br /&gt;
In a vanilla first party scenario, this is obviously not the case.  If you don&#039;t care, you can safely ignore this issue.  Attempts to set such call forward will be rejected then as &#039;&#039;operation unavailable&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In a Master/Slave PBX scenario where there is no Trunk Line object on the Master PBX, but only on the Slave PBXs, a workaround is required to suppress the warning and enable selective call forwarding on the Slave PBXs. In this case, create a dummy &amp;quot;Trunk Line&amp;quot; object on the Master PBX with the same extension number used by the &amp;quot;Trunk Line&amp;quot; objects on the Slave PBXs (usually 0).&lt;br /&gt;
&lt;br /&gt;
==== Multi Site Configuration ====&lt;br /&gt;
In a system with multiple PBXs, the TSP needs to connect to each of the individual PBXs.  &lt;br /&gt;
&lt;br /&gt;
[[Image:Unified Win32 and x64 TAPI Service Provider - MultiSite.png]]&lt;br /&gt;
&lt;br /&gt;
In this case, you would specify your master PBX as &#039;&#039;PBX Master&#039;&#039;.  There is no need to configure the complete PBX tree to the TSP as it is determined dynamically on runtime by analysing the PBX/Node objects in the master PBX and their registration status.  If a registered PBX is found, this PBX is added to the list of active PBXs and a new connection is established.  The PBX tree is built and maintained dynamically.  A reconfiguration or restart of the TSP is not required on changes thus.&lt;br /&gt;
For this to work&lt;br /&gt;
&lt;br /&gt;
* the PBX object used as &#039;&#039;TAPI User&#039;&#039; must exist in each PBX with same properties (including name and the password). You may want to use &amp;lt;code&amp;gt;_TAPI_&amp;lt;/code&amp;gt; as &#039;&#039;Name&#039;&#039;/&#039;&#039;Long Name&#039;&#039;.  This object must be &#039;&#039;active&#039;&#039; member in a group (which you may want to call &amp;lt;code&amp;gt;tapi&amp;lt;/code&amp;gt;).  A password must be set.  The object must have at least &#039;&#039;Viewing only&#039;&#039; rights&lt;br /&gt;
* the slave PBX-objects (or in older firmware versions the slave PBX Node-objects)  must be visible to the TSP (that is, must be non-active member of the group the &#039;&#039;TAPI User&#039;&#039; object is an active member of, e.g. &amp;lt;code&amp;gt;tapi&amp;lt;/code&amp;gt;) so that the slaves are made known to the TSP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In a replicated scenario, you would create a &#039;&#039;TAPI user&#039;&#039; as recommended above and [[Reference8:Administration/PBX/Objects#Objects_with_empty_node_or_PBX | leave the &#039;&#039;PBX&#039;&#039; and &#039;&#039;Node&#039;&#039; properties empty ]].  This user should then be used as both &#039;&#039;PBX Account&#039;&#039; and &#039;&#039;TAPI User Username&#039;&#039; in the TAPI configuration dialog.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Further relevant settings&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
You can disable slave detection by checking &#039;&#039;Do not monitor slaves&#039;&#039; property in the TSP configuration dialogue. &lt;br /&gt;
&lt;br /&gt;
TAPI maintains an &#039;&#039;address&#039;&#039; property per line device.  This usually is the lines extension.  In a multi site configuration, the address property will be set to the &#039;&#039;Number&#039;&#039; property of the node the respective PBX object is configured in, plus the &#039;&#039;Number&#039;&#039; property of the object itself.  So if an object has &#039;&#039;Number&#039;&#039; &amp;lt;code&amp;gt;42&amp;lt;/code&amp;gt; and lives in node &amp;lt;code&amp;gt;801&amp;lt;/code&amp;gt;, then its correspondence line device will have address &amp;lt;code&amp;gt;80142&amp;lt;/code&amp;gt;.  By checking the &#039;&#039;Use pure node extensions&#039;&#039; property in the TSP configuration dialogue, you change the algorithm so that only the objects own &#039;&#039;Number&#039;&#039; is used (&amp;lt;code&amp;gt;42&amp;lt;/code&amp;gt; in our example).&lt;br /&gt;
&lt;br /&gt;
==== Standby Configurations ====&lt;br /&gt;
In a system with standby PBX for the master PBX, you need to specify the &#039;&#039;PBX Standby&#039;&#039; IP address.  This will be connected if the master is unavailable.  Note that there is no need to explicitly configure slave-standby PBXs.&lt;br /&gt;
&lt;br /&gt;
==== Working with multiple, unrelated PBXs ====&lt;br /&gt;
When working with multiple, unrelated PBXs (that is, PBXs that do &#039;&#039;not&#039;&#039; form a PBX tree as slaves and masters do), the TSP cannot derive the list of PBXs to track from the registration status.  To support such a configuration, you will need to configure the extraneous master PBXs manually using regedit.  Please note that using regedit may harm your system and may even cause inability to boot!&lt;br /&gt;
&lt;br /&gt;
To find and edit the right registry entries, proceed as follows:&lt;br /&gt;
&lt;br /&gt;
* open the key &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;&lt;br /&gt;
* open its subkey &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&#039;&#039;n&#039;&#039; where &#039;&#039;n&#039;&#039; is the provider id of the installed innovaphone TSP (for builds before 8164 only)&lt;br /&gt;
* Open the &amp;lt;code&amp;gt;FQDN&amp;lt;/code&amp;gt; key and add all extra PBXs&lt;br /&gt;
* For those PBXs that have a standby PBX, add a value to the &amp;lt;code&amp;gt;StandbyFQDN&amp;lt;/code&amp;gt; key (please note: these are parallel lists.  So master and standby need to have the same respective index in the &amp;lt;code&amp;gt;FQDN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;StandbyFQDN&amp;lt;/code&amp;gt; value lists)&lt;br /&gt;
&lt;br /&gt;
The standard configuration UI will not show these extra values.  However, it will also not touch them.  So even if you use the standard UI to edit, only the first value in the lists will be changed and the remainder left unchanged. You can thus safely use the standard UI to edit all other values.   As with multi site configurations, all PBXs need to be accessible using the same &#039;&#039;TAPI User&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Please note that this method is deprecated and will likely be removed from future versions of the TSP.  &lt;br /&gt;
&lt;br /&gt;
==== Setting the Line Device Name ====&lt;br /&gt;
The TSP will derive the line device&#039;s name from the properties of the respective PBX object.  By default the name will be the objects &#039;&#039;Long Name&#039;&#039; followed by the name of the PBX the user ought to register with in parentheses.  So if the users &#039;&#039;Long Name&#039;&#039; is &amp;lt;code&amp;gt;Foo Bar&amp;lt;/code&amp;gt; and the registration PBX is &amp;lt;code&amp;gt;branch1&amp;lt;/code&amp;gt;, the line device will be called &amp;lt;code&amp;gt;Foo Bar [branch1]&amp;lt;/code&amp;gt;.  You can specify a different pattern by changing the &#039;&#039;TAPI Line Names&#039;&#039; property of the TSP configuration dialogue.  The following replacement characters are available:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|+&lt;br /&gt;
| Meta || Replacement&lt;br /&gt;
|+&lt;br /&gt;
| %c || The objects &#039;&#039;Long Name&#039;&#039; (cn)&lt;br /&gt;
|+&lt;br /&gt;
| %C || The objects &#039;&#039;Long Name&#039;&#039; (cn) followed by the &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents in braces &amp;lt;code&amp;gt;[name]&amp;lt;/code&amp;gt; if it differs from the &#039;&#039;Long Name&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
| %d || The objects &#039;&#039;Display Name&#039;&#039; (dn)&lt;br /&gt;
|+&lt;br /&gt;
| %D || The objects &#039;&#039;Display Name&#039;&#039; (dn) followed by the &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents in braces &amp;lt;code&amp;gt;[name]&amp;lt;/code&amp;gt; if it differs from the &#039;&#039;Display Name&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
| %h || The objects &#039;&#039;Name&#039;&#039; (h323 alias)&lt;br /&gt;
|+&lt;br /&gt;
| %H || The objects &#039;&#039;Name&#039;&#039; (h323 alias) followed by the &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents in braces &amp;lt;code&amp;gt;[name]&amp;lt;/code&amp;gt; if it differs from the &#039;&#039;Name&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
| %t || The &#039;&#039;Name&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents&lt;br /&gt;
|+&lt;br /&gt;
| %T || The &#039;&#039;Hardware Id&#039;&#039; of the &#039;&#039;Device&#039;&#039; the line represents (from build 8181)&lt;br /&gt;
|+&lt;br /&gt;
| %e || The objects extension (e164)&lt;br /&gt;
|+&lt;br /&gt;
| %E || The objects extension (e164) prefixed with the objects node number&lt;br /&gt;
|+&lt;br /&gt;
| %N || The line address as reported to TAPI&lt;br /&gt;
|+&lt;br /&gt;
| %n || host name (of master pbx)&lt;br /&gt;
|+&lt;br /&gt;
| %p || &#039;&#039;&#039;:&#039;&#039;&#039;&#039;&#039;port-number&#039;&#039; (of master pbx&#039;s http access, empty if 80)&lt;br /&gt;
|+&lt;br /&gt;
| %P || raw port number of master pbx&lt;br /&gt;
|+&lt;br /&gt;
| %u || url-like user name (&#039;&#039;&#039;&#039;&#039;user&#039;&#039;@&#039;&#039;host&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
|+&lt;br /&gt;
| %U || user url as per draft-levin-iptel-h323-url-scheme-04 (&#039;&#039;&#039;h323:://&#039;&#039;user&#039;&#039;@&#039;&#039;host&#039;&#039;:&#039;&#039;port&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
|+&lt;br /&gt;
| %X || the PBX name the user is registered with (note that using this pattern may result in a change of the name when a standby situation occurs)&lt;br /&gt;
|+&lt;br /&gt;
| %x || the PBX name the user is reported by (note that using this pattern may result in a change of the name when the users &#039;&#039;PBX&#039;&#039; attribute changes)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The default pattern is &amp;lt;code&amp;gt;%C (%x)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- rufumleitung, extern, intern, amtsleitung, vom amt, zum amt --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Miscellaneous Flags ====&lt;br /&gt;
; Show full E164 Numbers : when set, the TSP will announce the full calling number from the root when indicated by the PBX in the TAPI &#039;&#039;calling party name&#039;&#039; attribute.  The number will be appended to the calling name with a &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;.&lt;br /&gt;
; Do not show parked Calls : will hide parked calls from the TAPI application (as some get confused and don&#039;t know how to handle them)&lt;br /&gt;
; Map PBX Devices to Lines : if set, the TSP will create one TAPI line for each individual [[Reference9:PBX/Objects#Devices|PBX device]] configured in a user object.  See [[#Enhancements]] above.  If you do not set this flag, see [[Support:How should TAPI line device be registered?]]&lt;br /&gt;
; Map Presence Status to TAPI Lines : if set, the TSP will create one extra TAPI line for each PBX device object.  See [[#Enhancements]] above.&lt;br /&gt;
; No special Disconnect Behaviour : normally, lines monitored by TAPI will behave slightly different when a call is terminated.  With no TAPI on the line, the call will be disconnected immediately (from a PBX point of view).  In cases where the phone would play some tones after termination of the call (e.g. a busy tone when the call has never been connected to the far end), this state is simulated by the phone and not visible to TAPI.  Therefore, it is not possible to use TAPI functions on this call any more (as it in reality does not exist any more).  When this flag is set, monitored lines will not be treated specially.  Available from hotfix 6. To prevent the IP-Phone to play any tones after the call is disconnected, the phone preferences option &#039;&#039;&#039;Go onhook if final call is released by remote side even if handset is lifted&#039;&#039;&#039; can be activated. This is the feature of the IP-Phone is useful in a e.g. call center at agent phones and can be configured here [[Reference11r1:Phone/Preferences]].&lt;br /&gt;
: To prevent an innovaphone IP-Phone from playing any tones after a call is disconnected, the phone preferences option &#039;&#039;&#039;Go onhook if final call is released by remote side even if handset is lifted&#039;&#039;&#039; can be activated. This feature is useful for agent phones in a call center for example and can be configured in [[Reference11r1:Phone/Preferences]]&lt;br /&gt;
&lt;br /&gt;
===Trouble Shooting===&lt;br /&gt;
The TSP will (from build 8095) write messages of type INFO (&#039;&#039;informational messages&#039;&#039;) or WARNING (&#039;&#039;Warnings/Errors&#039;&#039;) to the windows event log. Such events are always logged to the application log and event source is the provider name (&#039;&#039;innovaphone® PBX V8 TAPI Service Provider&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==== Turning on Debugging ====&lt;br /&gt;
There are 2 versions of the TSP, debug and retail, which are both copied to the machine during setup.  The retail version is installed into the system directories, whereas the debug version is stored in a separate directory.  This is available through a short cut in the Start menu.&lt;br /&gt;
&lt;br /&gt;
The TSP can produce a number of debugging messages which can be helpful to debug issues (in both &#039;&#039;retail&#039;&#039; and &#039;&#039;debug&#039;&#039; builds).  By default, debug messages are written to the systems debug buffer mechanism (using OutputDebugString()).  Such messages can be examined using standard debugging tools, such as for example &amp;lt;code&amp;gt;dbgview&amp;lt;/code&amp;gt; which is [http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx available from Microsoft]. &lt;br /&gt;
&lt;br /&gt;
Debug messages have a class associated with it and the amount of messages written can be controlled by enabling or disabling specific classes.  This is done by setting a bitmask in the registry value &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; in the &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt; key. &lt;br /&gt;
&lt;br /&gt;
The easiest way to set the TSP&#039;s debug level is with the &#039;&#039;TSP Control&#039;&#039; utility (&#039;&#039;tsptray.exe&#039;&#039;) which is installed with the TSP.&lt;br /&gt;
&lt;br /&gt;
The available classes include&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| Bit in &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; || Class &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000001 || Minimum tracing &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000002 || TAPI api traces &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000020 || Basic telephony object creation/destruction  &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000040 || Thread creation/destruction &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000080 || Request creation/destruction &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000100 || call related messages &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000200 || Call id map &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000400 || Warnings/Errors &lt;br /&gt;
|-&lt;br /&gt;
| 0x00000800 || Worker thread execution &lt;br /&gt;
|-&lt;br /&gt;
| 0x00001000 || Full lock/unlock notifications &lt;br /&gt;
|-&lt;br /&gt;
| 0x00002000 || Win32 Critical section create/destroy &lt;br /&gt;
|-&lt;br /&gt;
| 0x00004000 || Agent proxy support &lt;br /&gt;
|-&lt;br /&gt;
| 0x00008000 || constructor/destructor debug &lt;br /&gt;
|-&lt;br /&gt;
| 0x00010000 || development debugs &lt;br /&gt;
|-&lt;br /&gt;
| 0x00100000 || verbose debugging  &lt;br /&gt;
|-&lt;br /&gt;
| 0x00200000 || SOAP trace &lt;br /&gt;
|-&lt;br /&gt;
| 0x00400000 || SOAP message dumps &lt;br /&gt;
|-&lt;br /&gt;
| 0x01000000 || ATL debug &lt;br /&gt;
|-&lt;br /&gt;
| 0x02000000 || line related messages &lt;br /&gt;
|-&lt;br /&gt;
| 0x04000000 || informational messages &lt;br /&gt;
|-&lt;br /&gt;
| 0x10000000 || dump call infos &lt;br /&gt;
|-&lt;br /&gt;
| 0x20000000 || dump PBX infos &lt;br /&gt;
|-&lt;br /&gt;
| 0x80000000 || output log messages to file &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; is not set, it defaults to (hex) &amp;lt;code&amp;gt;04000400&amp;lt;/code&amp;gt; in retail builds and to (hex) FFFFFFFF in debug builds.  A nice value to use is (hex) &amp;lt;code&amp;gt;92200580&amp;lt;/code&amp;gt;.  The &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; can be changed during runtime of the provider (it may take up to 10 seconds though for the setting to take effect).  In normal scenarios there is no need to install the debug version.&lt;br /&gt;
&lt;br /&gt;
Both &#039;&#039;informational messages&#039;&#039; and &#039;&#039;Warnings/Errors&#039;&#039; are always turned on (from build 8095).&lt;br /&gt;
&lt;br /&gt;
: A problem has been reported on Server 2008 x64 systems which may also apply to others.  On such systems, the value of &amp;lt;code&amp;gt;TraceLevel&amp;lt;/code&amp;gt; may be reset to its default every 10 seconds.  A workaround is to change the account the Telephony service is running in from its default (usually &#039;&#039;Network Service&#039;&#039;) to e.g. &#039;&#039;Local System&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===== Crash Dumps =====&lt;br /&gt;
From build 8063 the TSP will write crash dumps to the log directory (usually something like &amp;lt;code&amp;gt;C:\Program Files\innovaphone AG\innovaphone® PBX V8 TSP\Logs&amp;lt;/code&amp;gt;) in case of a trap.  In release installs, these are not very useful. For debug builds though, they include helfpul information.  Please provide these files (the can be zipped to a great extent) to support if requested. A crash dump file will be called something like &amp;lt;code&amp;gt;TSP8&amp;lt;i&amp;gt;build&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;hour&amp;lt;/i&amp;gt;#&amp;lt;i&amp;gt;minute&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;day&amp;lt;/i&amp;gt;.&amp;lt;i&amp;gt;month&amp;lt;/i&amp;gt;#&amp;lt;i&amp;gt;seqnr&amp;lt;/i&amp;gt;.dmp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Forcing a Crash Dump =====&lt;br /&gt;
In rare cases, it may be useful to force a TAPI crash for debug reasons.  This can be done by issueing a &amp;lt;code&amp;gt;lineMakeCall&amp;lt;/code&amp;gt; with called number &amp;lt;code&amp;gt;0815&amp;lt;/code&amp;gt;, called-subaddress &amp;lt;code&amp;gt;4711&amp;lt;/code&amp;gt; and called-name &amp;lt;code&amp;gt;!crash!&amp;lt;/code&amp;gt; or simply calling &amp;lt;code&amp;gt;0815|4711^!crash!&amp;lt;/code&amp;gt; from phone.exe.&lt;br /&gt;
&lt;br /&gt;
==== Saving Log Messages to a File ====&lt;br /&gt;
The &amp;lt;code&amp;gt;0x80000000&amp;lt;/code&amp;gt; value is special, as it does not denote a message class.  Instead, it turns on log file writing, both in retail and debug versions.  For this to work, the registry value &amp;lt;code&amp;gt;DoTraceFile&amp;lt;/code&amp;gt; must be set to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt; when the TSP starts.  If this value is not present, it defaults to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; in both retail and debug builds.  Setting it to 0 disables log file writing regardless of any other setting.  This may save some CPU cycles for installations with a real large number of lines.&lt;br /&gt;
&lt;br /&gt;
The TSP will keep 24 log files (a days worth) by default.   This value can be changed using the &amp;lt;code&amp;gt;NumLogFiles&amp;lt;/code&amp;gt; value in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;.  Older log files will be removed.  Also, when the TSP shuts down, it by default will remove all log files it created so far.  However, any TSP will only remove log files created by itself.  This ensures that if the TSP or the system terminates prematurely, the log files will be kept even if a new instance is started and terminated later on.  Form TSP V8 hotfix 8 on, this behaviour can be tweaked by setting the DWORD registry value &amp;lt;code&amp;gt;KeepLogFiles&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;:&lt;br /&gt;
{|&lt;br /&gt;
| 0 || default || remove all log files on termination&lt;br /&gt;
|-&lt;br /&gt;
| 1 || || keep the last &#039;&#039;n&#039;&#039; log files (depending on &amp;lt;code&amp;gt;NumLogFiles&amp;lt;/code&amp;gt;) on termination&lt;br /&gt;
|-&lt;br /&gt;
| 2 || || keep all log files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Larger systems (500 monitored lines and more) can slow down considerably when writing extensive logs.&lt;br /&gt;
&lt;br /&gt;
==== Installing the Debug Version ====&lt;br /&gt;
To install the debug version, you first install the retail version as outlined above.  You then copy the debug driver files from the &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; directory to your windows system directory &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt;.  You may want to use the shortcut to the &amp;lt;code&amp;gt;Debug&amp;lt;/code&amp;gt; folder which has been installed to the start menu for convenience.  &lt;br /&gt;
&lt;br /&gt;
For the copy to work, proceed as follows&lt;br /&gt;
* close &#039;&#039;Telephony and Modem Control Panel&#039;&#039; if you have it open&lt;br /&gt;
* shut down windows telephony service. This can be done from the Windows &#039;&#039;Service Control Panel&#039;&#039; or by invoking &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt; from a command prompt&lt;br /&gt;
* copy the debug driver files to your system directory.  On x64 systems, be sure to use a 64bit application such as &#039;&#039;Windows File Explorer for&#039;&#039; (&amp;lt;code&amp;gt;explorer.exe&amp;lt;/code&amp;gt;) for this.  Windows will silently redirect any 32bit application to the &amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt; directory when accessing &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt;.(if the copying fails, we recommend to deactivate the telephony service. But don’t forget to reset it to automatically if you are done copying). Overwrite the existing files: &amp;lt;code&amp;gt;installer.dll, installer.pdb, TSP8.pdb, TSP8.tsp&amp;lt;/code&amp;gt;&lt;br /&gt;
* if the copy does not succeed or the debug driver is not shown n the modem control panel after, it might be that a TAPI application re-starts the windows telephony before you actually to the copy.  If so, you can set the &#039;&#039;Startup type&#039;&#039; of the Windows &#039;&#039;Telephony&#039;&#039; service to &amp;lt;code&amp;gt;Disabled&amp;lt;/code&amp;gt; instead of &#039;&#039;Manual&#039;&#039; in the services control panel (&#039;&#039;services.msc&#039;&#039;). You can then &#039;&#039;Stop&#039;&#039; the services, copy the file and finally set the services mode back to &amp;lt;code&amp;gt;Manual&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you open &#039;&#039;Telephony and Modem Control Panel&#039;&#039; again, you should notice that the TSP driver name has changed to the debug version.&lt;br /&gt;
&lt;br /&gt;
==== Switching back to the Retail Version ====&lt;br /&gt;
To go back from the debug to the release version, proceed as follows:&lt;br /&gt;
* close &#039;&#039;Telephony and Modem Control Panel&#039;&#039; if you have it open&lt;br /&gt;
* shut down windows telephony service. This can be done from the Windows &#039;&#039;Service Control Panel&#039;&#039; or by invoking &amp;lt;code&amp;gt;net stop tapisrv&amp;lt;/code&amp;gt; from a command prompt&lt;br /&gt;
* delete the debug driver files from your system directory.  On x64 systems, be sure to use a 64bit application such as &#039;&#039;Windows File Explorer for&#039;&#039; (&amp;lt;code&amp;gt;explorer.exe&amp;lt;/code&amp;gt;) for this.  Windows will silently redirect any 32bit application to the &amp;lt;code&amp;gt;SysWOW64&amp;lt;/code&amp;gt; directory when accessing &amp;lt;code&amp;gt;system32&amp;lt;/code&amp;gt;&lt;br /&gt;
* repair the installation using windows &#039;&#039;Programs Control Panel&#039;&#039; or by invoking the original .msi again&lt;br /&gt;
&lt;br /&gt;
There is no need to remove the driver from the &#039;&#039;Telephone and Modem Control Panel&#039;&#039;, as this would make you loose your driver configuration.&lt;br /&gt;
&lt;br /&gt;
Please note that simply re-installing the driver from the original .msi without removing it from the system directory will not work.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
The test applications provided with this setup comes from [http://www.julmar.com Julmar Technology Inc].&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===&lt;br /&gt;
&lt;br /&gt;
Please note that there currently is a limitation to 2000 users being in&lt;br /&gt;
all active groups of a particular user.  Thus, you cannot configure more&lt;br /&gt;
than 2000 users to be handled by TAPI on a single PBX.  This is a PBX&lt;br /&gt;
limitation (and applies for all PBX groups).&lt;br /&gt;
&lt;br /&gt;
TAPI has a flat line model.  That is, all line numbers (aka&lt;br /&gt;
&#039;&#039;extensions&#039;&#039;) are considered to live in a single name space.  As a&lt;br /&gt;
result, lines with identical numbers cannot be distinguished in TAPI&lt;br /&gt;
(although they can exist).   All extensions in all nodes of a PBX&lt;br /&gt;
numbering tree are represented as TAPI lines.  When the TSP works with a&lt;br /&gt;
PBX that implements a hierarchical numbering tree, then some lines may&lt;br /&gt;
receive identical numbers (their node-local extension which may overlap&lt;br /&gt;
between nodes depending on the setting of the &#039;&#039;Use pure node extensions&#039;&#039; property).  When a TAPI application uses these numbers to initiate&lt;br /&gt;
calls to such lines, the call will work or not work depending on the&lt;br /&gt;
calling lines position in the numbering tree (that is, lines within the&lt;br /&gt;
same node as the called line will be fine, others may fail).&lt;br /&gt;
&lt;br /&gt;
The PBX&#039;s SOAP interface (on top of which the TSP is built) has no primitives to initiate a directed call pick-up based on a target number.  The TSP will reject such requests with &#039;&#039;Operation not available&#039;&#039;.  Pickup by name (which is understood as a group name) or unspecific is supported though.&lt;br /&gt;
&lt;br /&gt;
==== Citrix Environments ====&lt;br /&gt;
What happens is that all Citrix sessions share the same TAPI driver. This allows all users in the Citrix sessions to select &amp;quot;their&amp;quot; line from the set of all TAPI lines. Then everything works as desired. It is important to note that theoretically one user can select the line of another user.&lt;br /&gt;
You can use the &amp;quot;Microsoft Remote TAPI Server&amp;quot;, to implement access rights for lines for separate Citrix sessions.&lt;br /&gt;
&lt;br /&gt;
===Known Problems===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* The TSP is not tested with Microsoft’s Remote Tapi Server.  While some installation have reported this to work fine, others have encountered problems.  This scenario is not supported by innovaphone&lt;br /&gt;
* The TSP will read its configuration when it is loaded by the system.  Thus, configuration changes require a re-load of the TSP.  Unfortunately, there is no reliable way to force the system to unload the TSP, so you may have to reboot the system for changes to take effect.  See the [[ Howto:Troubleshooting_the_TAPI_service_provider | TAPI trouble shooting article ]] for details&lt;br /&gt;
* The TSP will use HTTP basic authentication to talk the PBX.  So if you disable basic authentication in the PBX&#039;s configuration, the TSP will not work.  It is recommended to use HTTPS&lt;br /&gt;
* TAPI requires the TSP to assign a unique id to each line device.  This ID must not change between re-boots of the system or between upgrades of the TSP.  This is done by keeping a persistent table in the windows registry (in the &amp;lt;code&amp;gt;lineGUIDs&amp;lt;/code&amp;gt; subkey of &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;) that maps the PBX&#039;s line GUID to a fixed integer value (known as &#039;&#039;permanent line id&#039;&#039; in TAPI speak).  This key is retained even on uninstall.  To get rid of it, you must remove it manually&lt;br /&gt;
* Microsoft installer fails to remove driver files installed to the windows system folder.  This is why the TSP driver files are still present after an uninstall of the software.  To get rid of them, remove &amp;lt;code&amp;gt;TSP8.tsp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TSP8UI.dll&amp;lt;/code&amp;gt; from both &#039;&#039;%windir%&#039;&#039;&amp;lt;code&amp;gt;\system32&amp;lt;/code&amp;gt; and &#039;&#039;%windir%&#039;&#039;&amp;lt;code&amp;gt;\sysWOW64&amp;lt;/code&amp;gt;&lt;br /&gt;
* From Version 9, hotfix 1, the PBX firmware will not list objects tagged as [[Reference9:PBX/Objects#General_Object_Properties | &#039;&#039;hide from LDAP&#039;&#039; ]] in the result of a [[Reference9:Concept_SOAP_API#UserInfo.5B.5D_FindUser.28string_v501.2C_string_v700.2C_string_v800.2C_string_cn.2C_string_h323.2C_string_e164.2C_integer_count.2C_integer_next.29 | FindUser() ]] call.  As a result, such objects will not be shown in the TAPI configuration dialogue &#039;&#039;Username&#039;&#039; drop-down.  If you want to use such an object as &#039;&#039;TAPI User&#039;&#039; you can simply type in the name without selecting it from the drop down.&lt;br /&gt;
* Sometimes, setting configuration with &#039;&#039;TSP Control&#039;&#039; (not the telephone control panel dialogue) does not work due to windows&#039; &#039;&#039;User Access Control (UAC)&#039;&#039;, see [[Howto:TAPI_TSP_Control_Windows7]] for Details&lt;br /&gt;
* Various users have reported that first party TSP installations do not work reliably with Microsoft Outlook.  Symptoms reported are spurious error pop-ups from Outlook although there was no real problem.  We do not recommend first party installations anyway (see [[#Rolling_out_First_Party_TSPs_to_multiple_PCs]] for a reasoning), but these issues are related to Microsoft Outlook only.  No such problems have been reported with other first party TAPI applications. Consider using solutions like Estos ProCall instead.&lt;br /&gt;
* The number of parallel threads used within the TSP is limited to max. 60 per CPU.  As each connected PBX (amongst other things) is handled by a separate thread, if you have a large number of PBXs connected and only have a single CPU, you may run out of threads, resulting in a WARNING messages &#039;&#039;about to spawn new workerthread (n requests, m threads) -- but limit l exceeded&#039;&#039;.  This usually happens when you run the TSP on a virtualized platform such as vmWare and only dedicate a single CPU.  Ignoring this warning results in sluggish behaviour.  &lt;br /&gt;
* The TSP can work with dynamic PBXs too.  However, the TSP needs to determine the slave PBXs IP addresses from the master. If the slave is a dynamic PBX and it is hosted on the same device as the master and it is registered to the master using 127.0.0.1, the TSP will only learn the 127.0.0.1 as the slave&#039;s IP address.  Of course, connection to the slave PBX will fail then. &lt;br /&gt;
&lt;br /&gt;
==== TAPI Operation with 3rd party Phones or innovaphone Phones registered with SIP ====&lt;br /&gt;
Various TAPI functions rely on use of the [[Reference:Remote Control Facility|Remote Control Facility]] message.  This message is not supported in 3rd party phones and also not fully supported in innovaphone Phones when they are registered to the PBX using SIP.  Full TAPI functionality is thus only available for innovaphone phones registered to the PBX using H.323.&lt;br /&gt;
&lt;br /&gt;
Known Limitations:&lt;br /&gt;
* Accepting an incoming call (lineAnswer)&lt;br /&gt;
* Automatic initiation of an outgoing call in handsfree mode (instead, the calling phone first rings and starts the outgoing call upon of-hook)&lt;br /&gt;
* toggle between 2 calls active on a phone (lineSwapHold)&lt;br /&gt;
* initiation and termination of a 3PTY (lineCompleteTransfer with mode LINETRANSFERMODE_CONFERENCE, lineDrop on a conference call)&lt;br /&gt;
&lt;br /&gt;
==== TAPI on Windows8 / Server 2012 ====&lt;br /&gt;
&lt;br /&gt;
Windows8 doesn&#039;t let you disable &#039;&#039;User Access Control&#039;&#039; (UAC) completely.  This has the disadvantage that &#039;&#039;TSP Control&#039;&#039; (tsptray.exe) cannot change system registry entries, which it needs to do to e.g. change debug settings for the TSP.&lt;br /&gt;
&lt;br /&gt;
There are 2 ways around it: &lt;br /&gt;
# use the hidden &#039;&#039;Administrator&#039;&#039; account on Windows 8&lt;br /&gt;
# elevate the tsptray.exe application&lt;br /&gt;
&lt;br /&gt;
To use the elevated &#039;&#039;Administrator&#039;&#039; account on Windows 8 you first need to un-hide it:&lt;br /&gt;
* log in to an account with administrator rights  &lt;br /&gt;
* use the &#039;&#039;Windows-Key+X&#039;&#039; shortcut and select &#039;&#039;Command Prompt (Administrator)&#039;&#039; (&#039;&#039;Eingabeaufforderung (Administrator)&#039;&#039;). An elevated cmd prompt appears&lt;br /&gt;
* type &amp;lt;code&amp;gt;net user administrator /active:yes&amp;lt;/code&amp;gt;&lt;br /&gt;
* the fully elevated &#039;&#039;Administrator&#039;&#039; account is now available and you can log-in to this account as usual&lt;br /&gt;
* &#039;&#039;&#039;Please make sure the account has a password set - by default, it does not!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To elevate the tsptray.exe application;&lt;br /&gt;
* log in to an account with administrator rights  &lt;br /&gt;
* start a windows explorer&lt;br /&gt;
* change directory to &amp;lt;code&amp;gt;C:\Program Files\innovaphone AG\innovaphone® PBX V8-x64 TSP&amp;lt;/code&amp;gt;&lt;br /&gt;
* right click on &amp;lt;code&amp;gt;tsptray.exe&amp;lt;/code&amp;gt; and open the &#039;&#039;properties&#039;&#039; (&#039;&#039;Eigenschaften&#039;&#039;) menu&lt;br /&gt;
* switch to the &#039;&#039;Compatibility&#039;&#039; (&#039;&#039;Kompatibilität&#039;&#039;) tab&lt;br /&gt;
* tick the &#039;&#039;Run as administrator&#039;&#039; (&#039;&#039;Program als Administrator ausführen&#039;&#039;) check mark&lt;br /&gt;
* save the settings&lt;br /&gt;
&lt;br /&gt;
Please note that Windows 8 will not let you run any &amp;quot;Metro App&amp;quot; in elevated mode!&lt;br /&gt;
&lt;br /&gt;
===== HTTPS ===== &lt;br /&gt;
The TSP will not be able to talk to the PBX using HTTPS with Windows8 or Server2012.  This [[Reference8:Release_Notes_TAPI_V8#3722_-_HTTPS_SOAP_connections_did_not_work_on_Windows8_.2F_Server_2012|has been fixed]] with V8 TAPI Service Provider (32 and 64bit) - hotfix10.&lt;br /&gt;
===== .Net 3.5 missing on Server 2012 =====&lt;br /&gt;
Server 2012 has no support for .Net 3.5 by default.  Even more, it cannot be installed just by downloading it.  Instead, the &#039;&#039;NetFX3 Feature&#039;&#039; needs to be enabled.  Here is how:&lt;br /&gt;
&lt;br /&gt;
 Microsoft Windows [Version 6.2.9200]&lt;br /&gt;
 (c) 2012 Microsoft Corporation. Alle Rechte vorbehalten.&lt;br /&gt;
 &lt;br /&gt;
 C:\Users\Administrator&amp;gt;dism /online /enable-feature /featurename:NetFX3 /all /Source:&#039;&#039;&amp;lt;path to windows setup, e.g. d:&amp;gt;&#039;&#039;\sources\sxs /LimitAccess&lt;br /&gt;
&lt;br /&gt;
See also&lt;br /&gt;
* [http://blogs.technet.com/b/aviraj/archive/2012/08/04/windows-8-enable-net-framework-3-5-includes-net-2-0-and-3-0-i-e-netfx3-feature-in-online-amp-offline-mode.aspx?PageIndex=2 Windows 8: Enable .NET Framework 3.5]&lt;br /&gt;
* [http://msdn.microsoft.com/en-us/library/hh506443.aspx Installing the .NET Framework 3.5 on Windows 8]&lt;br /&gt;
&lt;br /&gt;
==== TAPI dialer fails from Outlook when Lync client was/is installed ====&lt;br /&gt;
We have received reports that 1st-party TAPI dial-out from Outlook does not work anymore when a Lync client was installed.  Some users report that this phenomenon occurred only after an upgrade to Windows 8.  Reportedly, this can be [http://support.microsoft.com/kb/959625/en-us fixed by setting a registry key as outlined in Microsoft&#039;s knowledge-base].  You may want to give this a try.  However, we have not seen this issue ourselves and thus can&#039;t comment on it further.&lt;br /&gt;
&lt;br /&gt;
==== Slow Network Performance ====&lt;br /&gt;
TAPI is pretty sensitive to slow network performance.  While the TSP is multi-threaded, some internal locking must be done so that slow requests to a PBX my block other pending requests, resulting in unpleasant performance.  The TSP will create &#039;&#039;Windows Event Log&#039;&#039; entries of type &#039;&#039;slow SOAP call performance&#039;&#039; if this is detected.  You should inspect your event log regularly and resolve the reason for such network performance.&lt;br /&gt;
&lt;br /&gt;
Long PBX request round-trips may have a number of reasons:&lt;br /&gt;
&lt;br /&gt;
; slow WAN performance : of course, if the WAN is slow or unstable, bad performance is the result&lt;br /&gt;
; inappropriate QoS : SOAP is using HTTP/HTTPS.  In a QoS enabled network, call signalling and RTP may work fine, whereas HTTP/HTTPS is considered to be of no importance.  You need to keep in mind that such QoS policy may lead to bad TAPI performance, as the SOAP traffic used by the TSP (being based on HTTP/HTTPS) may be delayed.  You should assign SOAP traffic a similar priority as you do for VoIP signalling&lt;br /&gt;
; overloaded PBX : HTTP traffic is treated on a low priority level in the PBX.  If the PBX runs near to 100% CPU load, while all RTP and VoIP signalling will work well still, HTTP traffic may get severely delayed.  You should make sure your PBX runs well under 100% CPU load to get good TAPI performance.  See [[Reference:Device Health Check]] for more details&lt;br /&gt;
&lt;br /&gt;
==== TAPI on Windows 10 ====&lt;br /&gt;
In Windows 10, the TSP is not allowed any longer to read/write its own registry tree.  For this reason, it is not possible to store or read the configuration.  As a result, the TSP will not work.  To fix this, you need to modify the registry access rights so that the TSP has read/write access to &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on windows registry paths&amp;lt;ref name=&amp;quot;regkey&amp;quot;&amp;gt;&lt;br /&gt;
Due to a change in &#039;&#039;Windows Registry Access Rights&#039;&#039; in Windows 10, from Build 8165, the configuration is stored in &lt;br /&gt;
: &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&lt;br /&gt;
(a place that is suitable for Windows 10 too). Before, the configuration was stored in &lt;br /&gt;
: &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[#Upgrade_from_Build_8164_or_earlier| Upgrade from Build 8164 or_earlier ]] above for more details.&lt;br /&gt;
&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tweaks ===&lt;br /&gt;
There are a few configuration options which should be used rarely.  They can be enabled by setting an appropriate registry key.&lt;br /&gt;
&lt;br /&gt;
Since Hotfix 15 the location to set the interop tweaks has been changed to &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
; ProcessorMask : REG_DWORD. If set, the TSP will use &amp;lt;code&amp;gt;SetProcessAffinityMask(GetCurrentProcess(), set)&amp;lt;/code&amp;gt; to limit TSP execution to one or more of the existing processors.  Set to &amp;lt;code&amp;gt;0xff&amp;lt;/code&amp;gt; by default.&lt;br /&gt;
&lt;br /&gt;
; LineTimeOut : REG_DWORD. Can be set to a number of seconds the TSP should wait for the determination of lines to finish (default 90). On a large PBX, or a PBX with slow slaves, the determination might not finish in the default time frame.  If this happens, TAPI applications may show &#039;&#039;Line unnamed&#039;&#039; line entries in their line list.  If this is a problem, set it to a larger value (e.g. &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
; IgnoreDevStatus : REG_DWORD. Some applications get confused if TAPI reports line to be disconnected or out-of-service dynamically.  Setting this to a non-zero value will disable any such notification.&lt;br /&gt;
&lt;br /&gt;
; ClearFwdOnSet : REG_DWORD.  If set to a non-zero value, the TSP will clear all current call forward settings before a lineForward request is executed.  This implies that all call forward settings are &#039;&#039;replaced&#039;&#039; by the new settings.  Standard behaviour is to only modify the settings, that is, replace all current settings of the same type with the settings found in the lineForward request (for example, if there is only one setting in the request that defines a CFU, then the current CFU settings are replaced by the new one provided. All others, such as e.g. CFNR settings, are left untouched).&lt;br /&gt;
&lt;br /&gt;
: Tapi spec is pretty clear on how this should work: &#039;&#039;The provider should &amp;quot;unforward everything&amp;quot; prior to setting the new forwarding instructions&#039;&#039;.  Even though, for historical reasons, ClearFwdOnSet=0 has been the default in all TAPI versions prior to V8 hotfix 6, from hotfix 6 on, the default changes to 1, as this has turned out to be the widely accepted interpretation.&lt;br /&gt;
&lt;br /&gt;
; No3PTY : REG_DWORD. See [[Reference8:TAPI_Service_Provider#Notes_on_3PTY_Conferences | Notes_on_3PTY_Conferences]] below.&lt;br /&gt;
&lt;br /&gt;
; HiddenRecordingNumber: REG_SZ. Active recording in an innovaphone PBX is implemented as an implicit 3PTY conference with the recording sink as one of the parties.  These will be shown as usual in the TAPI callstate.  However, some applications get confused as this results in a situation, where a normal endpoint (read: phone) has more than one active (i.e. &#039;&#039;not on hold&#039;&#039;) call.  To suppress such calls in the TAPI call states, you can set this tweak to the number of the recording sink as configured in the phone&#039;s recording configuration tab.  If so, any outgoing call from an endpoint that is registered with a PBX user object with a called number that equals the setting of this tweak, will be suppressed.  So if your recording sink has the number &amp;lt;code&amp;gt;44&amp;lt;/code&amp;gt;, you would set this registry value to &amp;lt;code&amp;gt;44&amp;lt;/code&amp;gt; (this is available from TAPI V8 hotfix 8). Please note that this feature actually suppresses any call info for such calls, however, it does not revert previously announced call infos.  So if the call is initiated using &#039;&#039;overlapped dialling&#039;&#039;, all call states will be shown until the called number matches the value of &amp;lt;code&amp;gt;HiddenRecordingNumber&amp;lt;/code&amp;gt; and all subsequent call states will be suppressed.  This will probably leave the call shown in &#039;&#039;dialling&#039;&#039; state.  The feature should be used for destinations which are called using &#039;&#039;block dialling&#039;&#039; only thus.  &lt;br /&gt;
&lt;br /&gt;
; SilentHold : REG_DWORD. When a call is put on hold using &amp;lt;code&amp;gt;lineHold&amp;lt;/code&amp;gt;, the held party will hear &#039;&#039;music on hold&#039;&#039; emitted by the PBX. The hold-initiator will hear a dialling tone (PBX firmware v11r2 and up, with older versions the initiator would hear &#039;&#039;music on hold&#039;&#039;).  When &amp;lt;code&amp;gt;SilentHold&amp;lt;/code&amp;gt; is set to a non-zero value, the initiating party will hear silence - i.e. no dialling tone (this is available from TAPI V8 hotfix 8).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- There are some more values in a key underneath &amp;lt;code&amp;gt;HKEY_LOCAL_MACHINE\SOFTWARE\innovaphone\innovaphone® PBX V8 TAPI Service Provider&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;regkey&amp;quot;/&amp;gt; called &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&#039;&#039;XX&#039;&#039;: --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; NoDuplicateConnectedCalls : REG_DWORD. If set to 1, the TSP will never show more than one call per line to be active.  Extra active calls will be shown as &#039;&#039;on-hold&#039;&#039;. The situation occurs e.g. when a user initiates a 3PTY conference on the phone.  This essentially is a bug fix for Microsoft&#039;s OCS client which forces any extra active call on-hold, thereby disturbing the 3PTY function.  If your are using [http://www.estos.de/download/software/eccg.htm ESTOS&#039; Call Control Gateway]: from version &#039;&#039;2.0.1.1474 - 05.11.2008&#039;&#039; there is a fix for this same problem available.  This option thus is deprecated.&lt;br /&gt;
&lt;br /&gt;
; UseFirstLeg2 : REG_DWORD. TAPI allows only for a single leg-2 info (redirection information in case of a call forward).  If a call is forwarded mutliple times, by default the last redirection is shown in TAPI. If &amp;lt;code&amp;gt;UseFirstLeg2&amp;lt;/code&amp;gt; is set to 1 however, the first redirection is shown.&lt;br /&gt;
&lt;br /&gt;
; UseNameForDeviceGuid : REG_DWORD. The TSP will create a TAPI line for each &#039;&#039;Device&#039;&#039; of each PBX object (if &#039;&#039;MapDevices&#039;&#039; is set).  The internal unique identifier includes the &#039;&#039;Hardware Id&#039;&#039; found in the &#039;&#039;Device&#039;&#039;.  If this changes, the TAPI line representing the &#039;&#039;Device&#039;&#039; is considered new and a new TAPI &#039;&#039;permanent line id&#039;&#039; is allocated.  This may be annoying cause when a device serial number (e.g. for a telephone) is used as &#039;&#039;Hardware Id&#039;&#039;, replacing the device creates a new TAPI line.  If &#039;&#039;UseNameForDeviceGuid&#039;&#039; is set to 1, the TSP will use the &#039;&#039;Device&#039;&#039;s &#039;&#039;Name&#039;&#039; instead (which usually not changes).  While this might be more convenient, be aware that you &#039;&#039;must&#039;&#039; make sure that no PBX object has duplicate &#039;&#039;Name&#039;&#039;s!  Otherwise, TAPI will get confused.   Available from build 8178&lt;br /&gt;
&lt;br /&gt;
; ShowConfGUID : REG_DWORD.  If set and not 0, the TSP will implicitly set each call&#039;s CallData to a string such as &amp;quot;&amp;lt;code&amp;gt;conf-guid:&amp;lt;/code&amp;gt;&#039;&#039;call-guid&#039;&#039;&amp;quot;.   &#039;&#039;call-guid&#039;&#039; is a 66-byte Unicode16 string (32 hex characters plus terminating 0). Note that this will interfere with an application&#039;s use of the lineSetCallData function (tapi.h) and is therefore disabled by default. Available from build 8190&lt;br /&gt;
&lt;br /&gt;
; NoFix : REG_DWORD. If set and not 0, the TSP will not trigger a full re-synchronization if it receives implausible state messages. Available from build 8197.&lt;br /&gt;
&lt;br /&gt;
===List of supported TSPI functions===&lt;br /&gt;
&lt;br /&gt;
The TSP supports the following TAPI Service Provider Interface Functions.  Note that these do not map one to one with TAPI user functions. For more information, see the Microsoft TAPI documentation.&lt;br /&gt;
&lt;br /&gt;
*TSPI_lineAnswer&lt;br /&gt;
*TSPI_lineBlindTransfer&lt;br /&gt;
*TSPI_lineClose                      &lt;br /&gt;
*TSPI_lineCloseCall                  &lt;br /&gt;
*TSPI_lineCompleteTransfer&lt;br /&gt;
*TSPI_lineDevSpecific&lt;br /&gt;
*TSPI_lineDevSpecificFeature&lt;br /&gt;
*TSPI_lineDial&lt;br /&gt;
*TSPI_lineDrop  &lt;br /&gt;
*TSPI_lineForward&lt;br /&gt;
*TSPI_lineGenerateDigits                     &lt;br /&gt;
*TSPI_lineGetAddressCaps             &lt;br /&gt;
*TSPI_lineGetAddressID               &lt;br /&gt;
*TSPI_lineGetAddressStatus           &lt;br /&gt;
*TSPI_lineGetCallAddressID           &lt;br /&gt;
*TSPI_lineGetCallHubTracking&lt;br /&gt;
*TSPI_lineGetCallIDs&lt;br /&gt;
*TSPI_lineGetCallInfo                &lt;br /&gt;
*TSPI_lineGetCallStatus              &lt;br /&gt;
*TSPI_lineGetDevCaps                 &lt;br /&gt;
*TSPI_lineGetExtensionID&lt;br /&gt;
*TSPI_lineGetID                      &lt;br /&gt;
*TSPI_lineGetLineDevStatus           &lt;br /&gt;
*TSPI_lineGetNumAddressIDs&lt;br /&gt;
*TSPI_lineHold&lt;br /&gt;
*TSPI_lineMakeCall      &lt;br /&gt;
*TSPI_lineNegotiateExtVersion&lt;br /&gt;
*TSPI_lineNegotiateTSPIVersion       &lt;br /&gt;
*TSPI_lineOpen    &lt;br /&gt;
*TSPI_linePark&lt;br /&gt;
*TSPI_linePickup&lt;br /&gt;
*TSPI_lineRedirect&lt;br /&gt;
*TSPI_lineSelectExtVersion&lt;br /&gt;
*TSPI_lineSendUserUserInfo&lt;br /&gt;
*TSPI_lineSetAppSpecific             &lt;br /&gt;
*TSPI_lineSetCallData&lt;br /&gt;
*TSPI_lineSetCallHubTracking&lt;br /&gt;
*TSPI_lineSetCallParams                 &lt;br /&gt;
*TSPI_lineSetCurrentLocation         &lt;br /&gt;
*TSPI_lineSetDefaultMediaDetection   &lt;br /&gt;
*TSPI_lineSetMediaMode               &lt;br /&gt;
*TSPI_lineSetStatusMessages          &lt;br /&gt;
*TSPI_lineSetupTransfer&lt;br /&gt;
*TSPI_lineSwapHold&lt;br /&gt;
*TSPI_lineUnhold&lt;br /&gt;
*TSPI_lineUnpark&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*TSPI_providerConfig                 &lt;br /&gt;
*TSPI_providerCreateLineDevice&lt;br /&gt;
*TSPI_providerEnumDevices            &lt;br /&gt;
*TSPI_providerGenericDialogData&lt;br /&gt;
*TSPI_providerInit                   &lt;br /&gt;
*TSPI_providerInstall                &lt;br /&gt;
*TSPI_providerRemove                 &lt;br /&gt;
*TSPI_providerShutdown               &lt;br /&gt;
*TSPI_providerUIIdentify     &lt;br /&gt;
=====Notes on Consultation Calls=====        &lt;br /&gt;
This TSP supports the &amp;lt;code&amp;gt;lineSetupTransfer&amp;lt;/code&amp;gt; function.  However, strictly speaking, this function is not needed and should not be used.  It is merely intended for applications which do not offer a consultation call interface to the user when this function is not available.  Instead, &amp;lt;code&amp;gt;TSPI_lineMakeCall&amp;lt;/code&amp;gt; can be used where &amp;lt;code&amp;gt;lineSetupTransfer&amp;lt;/code&amp;gt; would be otherwise.  The notion of a special &#039;&#039;consultation call&#039;&#039; is an idiosyncrasy forced by legacy PBX technologies which were not able to transfer two arbitrary calls.   In these scenarios, a potentially to-be-transferred call needed to be linked to the primary call.  The PBX can transfer two arbitrary calls and thus there is no need for &amp;lt;code&amp;gt;lineSetupTransfer&amp;lt;/code&amp;gt;.  This ability is indicated by the &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_TRANSFERMAKE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFERENCEMAKE &amp;lt;/code&amp;gt; flags.   The transfer is then requested by using &amp;lt;code&amp;gt;TSPI_lineCompleteTransfer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=====Notes on 3PTY Conferences=====&lt;br /&gt;
The TSP supports the management of 3PTY conferences.  These can be initiated by using &amp;lt;code&amp;gt;TSPI_lineCompleteTransfer&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;LINETRANSFERMODE_CONFERENCE&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;LINETRANSFERMODE_TRANSFER&amp;lt;/code&amp;gt;.  This is indicated by the flags &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFERENCEHELD&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFERENCEMAKE&amp;lt;/code&amp;gt;.  The 3PTY function is actually implemented by the innovaphone IP phones (such as IP2xx).  Therefore, these capabilities are only advertised if the line is based on a PBX user object.  Still, some lines where the capabilities are advertised cannot do 3PTY (such as e.g. DECT lines, analogue lines, 3rd party devices, ...). So the call to &amp;lt;code&amp;gt;TSPI_lineCompleteTransfer&amp;lt;/code&amp;gt; will succeed but the conference will not be initiated and the subsequent call states will not indicate a conference (as there is no).  &lt;br /&gt;
&lt;br /&gt;
Also, if non-telephone devices are registered with a PBX user object and these device have multiple concurrent calls (e.g. a call center connected with a multi-channel XCapi), these will be viewed as 3PTY calls (as this is the way such calls appear to the TAPI: a line with more than one non-held call).  If these calls are in fact no 3PTY, this may lead to confusing call indications from TAPI.  It is better to register such objects as a PBX gateway object.  Special treatment of 3PTY calls can be disabled by setting the registry flag &amp;lt;code&amp;gt;No3PTY&amp;lt;/code&amp;gt; (from build 8087 onwards).&lt;br /&gt;
&lt;br /&gt;
A 3PTY conference will create a new call handle for the conference.  The only operation available for such a handle is &amp;lt;code&amp;gt;TSPI_lineDrop&amp;lt;/code&amp;gt;. This will terminate the conference and restore the state active before the conference was initiated (that is, the phone that implemented the conference will now have 2 calls, one active and one on hold).  This is indicated by not setting &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFDROP&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;lineDrop()&amp;lt;/code&amp;gt; on one of the 2 &#039;&#039;real&#039;&#039; calls involved will of course cancel this call and thus remove the 3PTY.&lt;br /&gt;
&lt;br /&gt;
======Notes on Intrusion Calls======&lt;br /&gt;
A special case of 3PTY is an intrusion call initiated by a [[Reference9:Phone/User/Function-Keys/Partner | partner function key]].  To TAPI, this looks like a 3PTY (which it in fact is).  However, phones before firmware version 9 hotfix 19 will not be able to release this 3PTY upon request.  Thus, you will see a 3PTY in TAPI which cannot be dropped.  From phone firmware 9 hotfix 19 on, the request to drop this 3PTY will cancel the intrusion call.  Note that TAPI will nevertheless &#039;&#039;not&#039;&#039; set &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFDROP&amp;lt;/code&amp;gt; on such conferences (as TAPI does not know that this is an intrusion call).&lt;br /&gt;
&lt;br /&gt;
======Notes on Recording Calls======&lt;br /&gt;
A special case of 3PTY is a recording call.  This effectively creates an user-invisible 3PTY on the phone.  To TAPI, this looks like a 3PTY (which it in fact is).  However, phones before firmware version 9 hotfix 19 will not be able to release this 3PTY upon request.  Thus, you will see a 3PTY in TAPI which cannot be dropped.  From phone firmware 9 hotfix 19 on, the request to drop this 3PTY will cancel the recording call.   Note that TAPI will nevertheless &#039;&#039;not&#039;&#039; set &amp;lt;code&amp;gt;LINEADDRCAPFLAGS_CONFDROP&amp;lt;/code&amp;gt; on such conferences (as TAPI does not know that this is a recording call).&lt;br /&gt;
&lt;br /&gt;
Recording calls are shown as normal conferences (unless &amp;lt;code&amp;gt;No3PTY&amp;lt;/code&amp;gt; is set).  This might be confusing to applications and/or users.  See the &amp;lt;code&amp;gt;HiddenRecordingNumber&amp;lt;/code&amp;gt; tweak above for a method to hide such calls.&lt;br /&gt;
&lt;br /&gt;
=====Notes on parked Calls=====&lt;br /&gt;
The PBX can park calls from and to any existing PBX object, e.g. by virtue of [[Reference8:Configuration/Registration/Function-Keys/Park | specific feature keys]].  They are parked to/from a numeric &#039;&#039;park position&#039;&#039;.  In SOAP however, calls are parked to an object by providing the objects &#039;&#039;&#039;UserInitialize()&#039;&#039;&#039; handle and a park position.  Parked calls are then reported as straight calls with a distinct signalling state (8).  The park position is not conveyed as part of the &#039;&#039;&#039;CallInfo&#039;&#039;&#039; record.  To unpark, &#039;&#039;&#039;[[Reference8:SOAP_API#integer_UserPickup.28int_user.2C_string_cn.2C_integer_call.2C_string_group.2C_int_reg.2C_InfoArray_info.29 | UserPickup]]&#039;&#039;&#039; can be used providing the parked calls call handle as &#039;&#039;&#039;call&#039;&#039;&#039; argument.  &lt;br /&gt;
&lt;br /&gt;
The TAPI specification is unclear on how the address information required to &#039;&#039;&#039;lineUnpark()&#039;&#039;&#039; a call can be obtained by an application (except that it is returned from &#039;&#039;&#039;linePark()&#039;&#039;&#039; if the call was parked using TAPI).    The TSP thus indicates parked calls on a line with a call reason &amp;lt;code&amp;gt;LINECALLREASON_PARKED&amp;lt;/code&amp;gt;.  The caller id information is set to the parked calls call handle.  This way, the application can take the caller id information and provide it to &#039;&#039;&#039;lineUnpark()&#039;&#039;&#039; to unpark a call.  If the appication does not support this mode of operation but supports &#039;&#039;&#039;lineUnpark()&#039;&#039;&#039; and lets the user input the park identifier, the user can just provide the caller id information.&lt;br /&gt;
&lt;br /&gt;
Some applications do not care for parked calls (by examining the call reason) and just blindly report these calls like ordinary connected calls (thereby confusing the user).  To work around this problem, reporting parked calls can be turned off in the TSP configuration dialogue.&lt;br /&gt;
&lt;br /&gt;
=====Notes on sending User to User Information =====&lt;br /&gt;
The TAPI specification for sending UserUserInfo closely resembles the way ISDN defines this service.  Although the innovaphone PBX supports this service both with H.323 and SIP, it is &#039;&#039;not&#039;&#039; supported in this TSP.  Instead, sending user to user information is implemented using H.323/SIP messaging.  However, there are some important deviations and limitations caused hereby:&lt;br /&gt;
* data is &#039;&#039;not transparent&#039;&#039;.  That is, the TSP only allows for null-terminated unicode to be sent.  The data must be of even length and the last two bytes must be null. &lt;br /&gt;
* data is &#039;&#039;not sent within the call&#039;&#039;, but by initiating a separate call.  This implies that the target number used to send the message carrying the data to is &#039;guessed&#039; from the available call data.  For example, if the call is in a connected state and a connected number is known, the message is sent to the connected number.  If the call is in the ringback state, then either the called number or - if available - the redirection number is used and so forth.&lt;br /&gt;
* message calls are not indicated by the SOAP CallInfo records.  As a result, messages sent with lineSendUserUserInfo cannot be received with TAPI&lt;br /&gt;
=====Notes on receiving User to User Information =====&lt;br /&gt;
From build 8200, the TSP will deliver incoming UUI on a call. Although lineSendUserUserInfo will still send H.323/SIP messages instead of native UUI, you can now receive incoming UUI (for example from ISDN) in a LINE_CALLINFO  message.&lt;br /&gt;
&lt;br /&gt;
=====Notes on sending proprietary innovaphone Remote Control Facilities  =====&lt;br /&gt;
The SOAP  [[Reference10:SOAP_API#UserRc.28integer_call.2C_integer_rc.29|UserRc]] function allows to send various [[Reference:Remote Control Facility|facility messages]] to an innovaphone phone device.  In some cases, it is useful to be able to invoke this function through a standard TAPI mechanism.  This can be achieved by using the TAPI &#039;&#039;&#039;lineBlindTransfer&#039;&#039;&#039; function.  If the &#039;&#039;called party name&#039;&#039; provided as destination for the &#039;&#039;lineBlindTransfer&#039;&#039; (in &#039;&#039;lpszDestAddress&#039;&#039;) has the magic value &amp;lt;code&amp;gt;USERRC&amp;lt;/code&amp;gt;, then the &#039;&#039;called subaddress&#039;&#039; is converted to an integer and the result is sent as remote control facility to the call the blind transfer is applied for.  For details on how to code the &#039;&#039;called party name&#039;&#039; and the &#039;&#039;called subaddress&#039;&#039; into &#039;&#039;lpszDestAddress&#039;&#039; see [http://msdn.microsoft.com/en-us/library/windows/desktop/ms726017%28v=vs.85%29.aspx Microsoft&#039;s &#039;&#039;Canonical Address&#039;&#039; specification].     This works from TAPI8 hotfix 4.&lt;br /&gt;
&lt;br /&gt;
For example, initiating a blind transfer to &amp;lt;code&amp;gt;|16^USERRC&amp;lt;/code&amp;gt; (empty address, subaddress 16 (that is, [[Reference:Remote Control Facility|&#039;&#039;change to handset mode&#039;&#039;]]), called name &amp;lt;code&amp;gt;USERRC&amp;lt;/code&amp;gt;) will switch the phone having the call to be transferred into handset mode (and &amp;lt;code&amp;gt;|18^USERRC&amp;lt;/code&amp;gt; will switch it back to handsfree mode).  Of course, no actual transfer will happen in these cases (&#039;&#039;lineBlindTransfer&#039;&#039; is merely used as a vehicle to send the facility to the proper call).&lt;br /&gt;
&lt;br /&gt;
Such proprietary facility message can also be sent with &#039;&#039;lineMakeCall&#039;&#039; (that is, in SOAP&#039;s [[Reference10:SOAP_API#integer_UserCall.28integer_user.2C_string_cn.2C_string_e164.2C_string_h323.2C_int_reg.2C_InfoArray_info.2C_int_rc.2C_string_srce164.29|UserCall]] function).  For example, setting up a call to &amp;lt;code&amp;gt;123|21^USERRC&amp;lt;/code&amp;gt; will send an intrusion call to extension 123 and intrude any call that might be active there. This works from TAPI8 hotfix 6. Please note that the innovaphone TAPI service provider does not support TAPI&#039;s &#039;&#039;lineCompleteCall&#039;&#039; function with &amp;lt;code&amp;gt;LINECALLCOMPLMODE_INTRUDE&amp;lt;/code&amp;gt; though (as TAPI&#039;s call model here does not fit with the PBX&#039;s call model).  Please also note that intrusion calls look like 3PTY calls to TAPI (see [[#Notes_on_Intrusion_Calls|notes on intrusion calls]] above).&lt;br /&gt;
&lt;br /&gt;
Remote control facilities are implemented by the telephone devices, so these functions are subject to the phone firmware in use.&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto|{{PAGENAME}}]]&lt;br /&gt;
[[Category:Concept|{{PAGENAME}}]]&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
* [[Howto:Troubleshooting the TAPI service provider]]&lt;br /&gt;
* [[Reference8:Release Notes TAPI]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_09_Custom_certificates&amp;diff=73774</id>
		<title>Courseware:IT Advanced - 09 Custom certificates</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_09_Custom_certificates&amp;diff=73774"/>
		<updated>2024-10-16T15:31:43Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 09 Custom certificates&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Custom certificates | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_09_Custom_certificates&amp;diff=73773</id>
		<title>Courseware:IT Advanced - 09 Custom certificates</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_09_Custom_certificates&amp;diff=73773"/>
		<updated>2024-10-16T15:31:34Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | Custom certificates | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Custom certificates | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_08_Using_a_custom_DNS_on_your_mobile_phone&amp;diff=73772</id>
		<title>Courseware:IT Advanced - 08 Using a custom DNS on your mobile phone</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_08_Using_a_custom_DNS_on_your_mobile_phone&amp;diff=73772"/>
		<updated>2024-10-16T15:30:29Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 08 Using a custom DNS on your mobile phone&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Using a custom DNS on your mobile phone | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_08_Using_a_custom_DNS_on_your_mobile_phone&amp;diff=73771</id>
		<title>Courseware:IT Advanced - 08 Using a custom DNS on your mobile phone</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_08_Using_a_custom_DNS_on_your_mobile_phone&amp;diff=73771"/>
		<updated>2024-10-16T15:30:19Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | Using a custom DNS on your mobile phone | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Using a custom DNS on your mobile phone | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_07_Public_access_to_PBX_resources_(practice)&amp;diff=73770</id>
		<title>Courseware:IT Advanced - 07 Public access to PBX resources (practice)</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_07_Public_access_to_PBX_resources_(practice)&amp;diff=73770"/>
		<updated>2024-10-16T15:28:34Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 07 Public access to PBX resources (practice)&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Public access to PBX resources (practice)| 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_07_Public_access_to_PBX_resources_(practice)&amp;diff=73769</id>
		<title>Courseware:IT Advanced - 07 Public access to PBX resources (practice)</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_07_Public_access_to_PBX_resources_(practice)&amp;diff=73769"/>
		<updated>2024-10-16T15:28:24Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | Public access to PBX resources (practice)| 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Public access to PBX resources (practice)| 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_06_Public_Access_to_PBX_Resources_(theory)_-_optional&amp;diff=73768</id>
		<title>Courseware:IT Advanced - 06 Public Access to PBX Resources (theory) - optional</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_06_Public_Access_to_PBX_Resources_(theory)_-_optional&amp;diff=73768"/>
		<updated>2024-10-16T15:26:46Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 06 Public Access to PBX Resources (theory) - optional&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Public Access to PBX Resources (theory) - optional | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_06_Public_Access_to_PBX_Resources_(theory)_-_optional&amp;diff=73767</id>
		<title>Courseware:IT Advanced - 06 Public Access to PBX Resources (theory) - optional</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_06_Public_Access_to_PBX_Resources_(theory)_-_optional&amp;diff=73767"/>
		<updated>2024-10-16T15:26:39Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | Public Access to PBX Resources (theory) - optional | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Public Access to PBX Resources (theory) - optional | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_05_Setting_up_the_Apps&amp;diff=73766</id>
		<title>Courseware:IT Advanced - 05 Setting up the Apps</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_05_Setting_up_the_Apps&amp;diff=73766"/>
		<updated>2024-10-16T15:25:02Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 05 Setting up the Apps&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Setting up the Apps | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_05_Setting_up_the_Apps&amp;diff=73765</id>
		<title>Courseware:IT Advanced - 05 Setting up the Apps</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_05_Setting_up_the_Apps&amp;diff=73765"/>
		<updated>2024-10-16T15:24:41Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | Setting up the Apps | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Setting up the Apps | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_04_Setting_up_the_Application_Platform&amp;diff=73764</id>
		<title>Courseware:IT Advanced - 04 Setting up the Application Platform</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_04_Setting_up_the_Application_Platform&amp;diff=73764"/>
		<updated>2024-10-16T15:21:49Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 04 Setting up the Application Platform&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Setting up the Application Platform | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_04_Setting_up_the_Application_Platform&amp;diff=73763</id>
		<title>Courseware:IT Advanced - 04 Setting up the Application Platform</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_04_Setting_up_the_Application_Platform&amp;diff=73763"/>
		<updated>2024-10-16T15:21:39Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | Setting up the Application Platform | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | Setting up the Application Platform | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_03_The_Application_Platform&amp;diff=73762</id>
		<title>Courseware:IT Advanced - 03 The Application Platform</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_03_The_Application_Platform&amp;diff=73762"/>
		<updated>2024-10-16T15:20:36Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 03 The Application Platform&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | The Application Platform | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_03_The_Application_Platform&amp;diff=73761</id>
		<title>Courseware:IT Advanced - 03 The Application Platform</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_03_The_Application_Platform&amp;diff=73761"/>
		<updated>2024-10-16T15:20:29Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | The Application Platform | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | The Application Platform | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_02_PBX_-_initial_Configuration&amp;diff=73760</id>
		<title>Courseware:IT Advanced - 02 PBX - initial Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_02_PBX_-_initial_Configuration&amp;diff=73760"/>
		<updated>2024-10-16T15:18:53Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 02 PBX - initial Configuration&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | PBX - initial Configuration | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_02_PBX_-_initial_Configuration&amp;diff=73759</id>
		<title>Courseware:IT Advanced - 02 PBX - initial Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_02_PBX_-_initial_Configuration&amp;diff=73759"/>
		<updated>2024-10-16T15:18:45Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | PBX - initial Configuration | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | PBX - initial Configuration | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_01_innovaphone_overall_Product_Design&amp;diff=73758</id>
		<title>Courseware:IT Advanced - 01 innovaphone overall Product Design</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_01_innovaphone_overall_Product_Design&amp;diff=73758"/>
		<updated>2024-10-16T15:16:28Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Protected &amp;quot;Course14:IT Advanced - 01 innovaphone overall Product Design&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | innovaphone overall Product Design | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_01_innovaphone_overall_Product_Design&amp;diff=73757</id>
		<title>Courseware:IT Advanced - 01 innovaphone overall Product Design</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Courseware:IT_Advanced_-_01_innovaphone_overall_Product_Design&amp;diff=73757"/>
		<updated>2024-10-16T15:15:53Z</updated>

		<summary type="html">&lt;p&gt;Ckl: Created page with &amp;quot;{{#moodlebook: Master Templates / V14 Templates / Advanced | innovaphone overall Product Design | 142 }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#moodlebook: Master Templates / V14 Templates / Advanced | innovaphone overall Product Design | 142 }}&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference10:Concept_SOAP_API&amp;diff=73592</id>
		<title>Reference10:Concept SOAP API</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference10:Concept_SOAP_API&amp;diff=73592"/>
		<updated>2024-09-25T08:27:58Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Info record */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;innovaphone®&#039;s PBX web services, also known as SOAP API, while no longer actively extended, remains available and functional. A transition to WebSocket API, specifically the RCC API (https://sdk.innovaphone.com/13r3/doc/appwebsocket/RCC.htm), was introduced with version 13 firmware.&lt;br /&gt;
&lt;br /&gt;
For ongoing development, we recommend utilizing [http://www.innovaphone.com/wsdl/pbx10_00.wsdl WSDL version 10 &#039;&#039;pbx10_00.wsdl&#039;&#039;] (also available on the gateway &amp;lt;code&amp;gt;http://xx.xx.xx.xx/pbx10_00.wsdl&amp;lt;/code&amp;gt;) in conjunction with this Wiki article. It&#039;s advisable to disregard the higher versions of WSDL for your development.&lt;br /&gt;
&lt;br /&gt;
For upcoming developments the WebSocket API should be used, as it represents the current and future direction of our API development.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
For an overview of the basic architecture, see the [[Reference:SOAP_API_%28pbx501.wsdl%29#Overview|corresponding chapter in the pbx501.wsdl related article]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Concept|{{PAGENAME}}]]&lt;br /&gt;
&lt;br /&gt;
== Definition of PBX object (WSDL) == &lt;br /&gt;
Within the SOAP framework there is a mechanism to formally decribe the definition of remote objects. This is done by so called WSDL (Web Service Description Language) files. This [[http://www.innovaphone.com/wsdl/pbx10_00.wsdl wsdl file]] defines the PBX web services  described in this document.&lt;br /&gt;
&lt;br /&gt;
NB: while you can access and retrieve the WSDL file through this URL on runtime of your application, we&#039;d rather recommend to install a local copy with your application and use this on runtime.  This way, your application will be immune against failures of www.innovaphone.com.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;There is also an [[http://www.innovaphone.com/wsdl/pbx900.wsdl old version of the wsdl]] available which has less interface functions.  This interface can still be accessed by legacy applications and is activated on the PBX by calling the &#039;&#039;&#039;Initialize&#039;&#039;&#039; Function with fewer arguments (&#039;&#039;&#039;Integer Initialize(string user, string appl, out key)&#039;&#039;&#039;).  It should not be used for new develoments though.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SOAP URL ===&lt;br /&gt;
The SOAP service URI is &#039;&#039;&#039;/PBX0/user.soap&#039;&#039;&#039; for the standard PBX and &#039;&#039;&#039;/PBX-&#039;&#039;id&#039;&#039;/user.soap&#039;&#039;&#039; for a dynamic PBX (where &#039;&#039;id&#039;&#039; corresponds to the &#039;&#039;Id&#039;&#039; field in the [[Reference10:PBX/Dyn-PBXs]] configuration dialog).  SOAP is accessible via plain HTTP or HTTPS, so valid URLs might be &amp;lt;code&amp;gt;http://172.16.0.1/PBX0/user.soap&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;https://172.16.0.1/PBX0-mydynpbxid/user.soap&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==PBX Objects and Methods==&lt;br /&gt;
&lt;br /&gt;
This section contains a language agnostic description of the PBX API’s object model.  Despite of the fact that we are discussing an object model, the PBX API is in fact not an object oriented API.  This is because SOAP itself is not really object oriented.  In particular, there is no object creation, activation or lifetime concept.  This is left up to the service designer.  SOAP is more a message exchange mechanism than an object method invocation mechanism.  This is reflected in the API structure.&lt;br /&gt;
&lt;br /&gt;
Specifically, objects are represented through handles, which are integers.  Objects are created and destroyed using dedicated methods and it’s the users responsibility to manage the lifetime of all objects.&lt;br /&gt;
&lt;br /&gt;
The syntax shown here actually is no valid syntax in any existing language.  Please refer to the various sample codes for working syntax.&lt;br /&gt;
&lt;br /&gt;
===Session===&lt;br /&gt;
&lt;br /&gt;
All PBX API methods are executed in the context of a session.  A session is created using the &#039;&#039;&#039;initialize&#039;&#039;&#039; method and is identified by a handle.  This handle must be provided to all subsequent method calls.&lt;br /&gt;
&lt;br /&gt;
A session is owned by the PBX API user, i.e. there is no way to have access to a session of another application.  Each session has a scope, which defines the view of the PBX the session user has.  The scope determines the set of PBX registrations seen by the session.&lt;br /&gt;
&lt;br /&gt;
Scopes are defined and configured in the PBX and are bound to particular PBX users. Thus, a session has a user attribute, which defines the scope.   It includes all users which are members of groups &#039;&#039;&#039;user&#039;&#039;&#039; is active member of.  If &#039;&#039;&#039;user&#039;&#039;&#039; is not an active member of any group, the scope is the user itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Initialize(string user, string appl, bool $v, bool $v501, bool v700, bool v800, bool vx1000, out int key)====&lt;br /&gt;
&lt;br /&gt;
To access the current web services implementation, &#039;&#039;&#039;v&#039;&#039;&#039;, &#039;&#039;&#039;v501&#039;&#039;&#039;, &#039;&#039;&#039;v700&#039;&#039;&#039;, &#039;&#039;&#039;v800&#039;&#039;&#039; and &#039;&#039;&#039;vx10000&#039;&#039;&#039; must be present and set to &#039;&#039;&#039;true&#039;&#039;&#039;. &lt;br /&gt;
These parameters actually convey the wsdl version used by the client.  Different versions of the interface use different parameter sets for the Initialize call.  Applications should always use the wsdl version current at the time of writing the application.&lt;br /&gt;
&lt;br /&gt;
The method creates a session.  The session will have the user &#039;&#039;&#039;user&#039;&#039;&#039;’s scope (&#039;&#039;&#039;user&#039;&#039;&#039; is the &#039;&#039;Long Name&#039;&#039; of a PBX user).  The session handle is returned and is 0 for failure and positive for a valid session handle.  &#039;&#039;&#039;appl&#039;&#039;&#039; specifies the name of the calling application and is used for administrative purposes.  The output parameter &#039;&#039;&#039;key&#039;&#039;&#039; is a random number associated to the session.   It may be used in subsequent &#039;&#039;&#039;Echo&#039;&#039;&#039; operations.&lt;br /&gt;
&lt;br /&gt;
When a session is created, &#039;&#039;&#039;UserInfo&#039;&#039;&#039; events for all PBX registrations in the scope can be received by the &#039;&#039;&#039;Poll&#039;&#039;&#039; function.  Initially, one &#039;&#039;&#039;UserInfo&#039;&#039;&#039; per registration within the session’s scope is received (the list is terminated by a &#039;&#039;&#039;UserInfo&#039;&#039;&#039; with empty &#039;&#039;&#039;cn&#039;&#039;&#039; and may require multiple &#039;&#039;&#039;Poll&#039;&#039;&#039; calls to retrieve).  Subsequently, &#039;&#039;&#039;UserInfo&#039;&#039;&#039; events are received when a registrations state changes.&lt;br /&gt;
&lt;br /&gt;
The underlying transport session (HTTP) must authenticate itself  either as &#039;&#039;&#039;user&#039;&#039;&#039;  (using the users long name and PBX password) or as the admin user (using the gateway administrator account name and password) to perform an &#039;&#039;&#039;Initialize&#039;&#039;&#039; and any session related function.   Note that if you use a PBX user account, the user needs to have at least &#039;&#039;Group/Call Forwards&#039;&#039; rights. &lt;br /&gt;
&lt;br /&gt;
Note that the method to force the SOAP system you are using to authenticate to the PBX is entirely up to the system itself.  Some systems even do not support authentication at all.  If your SOAP implementation does not support digest authentication, make sure the gateway accepts basic authentication by setting the “&#039;&#039;allow HTTP basic authentication&#039;&#039;” in the “&#039;&#039;General settings&#039;&#039;”.&lt;br /&gt;
&lt;br /&gt;
Note that although many HTTP connections may be used in a single session, at least one HTTP connection must remain open during the lifetime of the session.  When the last connection disappears, the logical session is terminated after a short timeout. Some SOAP libraries may per default always close the HTTP connection and reconnect on subsequent SOAP calls, which will not work. The SOAP library should either be configured to keep at least one HTTP connection alive or, if this is not an option, the application should take care to always have a an active request pending (such as &#039;&#039;&#039;Poll&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
====Echo(integer session, integer key)====&lt;br /&gt;
&lt;br /&gt;
Verifies a session.  You need to supply the &#039;&#039;session&#039;&#039; identifier and &#039;&#039;key&#039;&#039; returned by a previous call to &#039;&#039;&#039;Initialize&#039;&#039;&#039;.  Returns nonzero if successful.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====End(integer session)====&lt;br /&gt;
&lt;br /&gt;
Terminates the session referenced by &#039;&#039;session&#039;&#039;.  No further events will be received.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Integer Version(out string gkId, out string location, out string firmware, out string serial)====&lt;br /&gt;
&lt;br /&gt;
Returns the version number of the WSDL file the PBX supports.  The first released WSDL file had version number 500.  The version described by this document has version number 501. Also delivers information about the connected PBX (in &#039;&#039;gkId&#039;&#039;, &#039;&#039;location&#039;&#039;, &#039;&#039;firmware&#039;&#039; and &#039;&#039;serial&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====AnyInfo Poll(integer session)====&lt;br /&gt;
&lt;br /&gt;
Returns pending events for the session referenced by &#039;&#039;session&#039;&#039;.  &#039;&#039;AnyInfo&#039;&#039; is a struct with four arrays as members: &#039;&#039;user&#039;&#039;, &#039;&#039;call&#039;&#039;, &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039;. &#039;&#039;user&#039;&#039; is an array of type &#039;&#039;UserInfo&#039;&#039; and call is an array of type CallInfo.  The other two arrays &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039; are currently not used.&lt;br /&gt;
&lt;br /&gt;
After a successful &#039;&#039;&#039;Initialize()&#039;&#039; there will be a &#039;&#039;UserInfo&#039;&#039; event for each defined and visible user in the system.  This allows the application to synchronize on the state of all visible users.  The list will be terminated by an &#039;&#039;UserInfo&#039;&#039; event for a user with an empty &#039;&#039;cn&#039;&#039; which normally cannot happen since a user entry must have a cn.&lt;br /&gt;
&lt;br /&gt;
===User===&lt;br /&gt;
&lt;br /&gt;
A user represents a configured object within the PBX (a “PBX user”). The PBX API provides the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; method to obtain a handle to the user.&lt;br /&gt;
&lt;br /&gt;
====UserInfo====&lt;br /&gt;
The user’s properties are stored in a &#039;&#039;UserInfo&#039;&#039; structure, which has the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;boolean active&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
true if the user exists.  The only case where active can be false is when a user is moved out of the session context. This may happen if the users group assignment is changed or the user is deleted. A single UserInfo event will be posted with active set to false then.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1 if the user is registered, 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer channel&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
number of current calls.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer  alert&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
number of alerting calls&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the type of the users device.  Currently defined are “&#039;&#039;&#039;ep&#039;&#039;&#039;” (it is an endpoint), “&#039;&#039;&#039;gw&#039;&#039;&#039;” (it is a gateway, for example a trunk line), “&#039;&#039;&#039;waiting&#039;&#039;&#039;” (a call queue) or “&#039;&#039;&#039;broadcast&#039;&#039;&#039;” (a group).  Others may be defined over time.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string guid&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the users GUID.  This is a globally unique identifier for the user.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string cn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the common name of the user. This is what the PBX’s LDAP server recognizes as the CN of this user.  The user’s name in the PBX configuration applet.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string e164&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the extension number the user is registered with.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string h323&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the alias the user is registered with.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string dn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the users display name.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string domain&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the PBX domain if the Gatekeeper ID is used as domain&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;boolean h323email&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If true, the h323 name shall be used as primary email address when sending emails to this user.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string email[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
email addresses of the user. If &#039;h323email&#039; is not set, the first address in this list shall be used as primary email address when sending emails to this user.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Group groups&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An array of &#039;&#039;&#039;Group&#039;&#039;&#039; records (see below).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Presence presence&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An array of &#039;&#039;&#039;Presence&#039;&#039;&#039; records (see below).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;boolean cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If set to true indicates that the config of the user has changed&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The type of the user object&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string loc&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If the object described is not local to the PBX the &#039;&#039;&#039;UserInfo&#039;&#039;&#039; is sent from, the name of the location the object is homed in is given in this element.  See &#039;&#039;&#039;LocationUrl&#039;&#039;&#039; to find out how to proceed further.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string node&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The node of the object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string nodenum&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The object nodes node number (prefix).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Info&#039;&#039;&#039;&lt;br /&gt;
An &#039;&#039;&#039;Info&#039;&#039;&#039; record describing various aspects of the user.  The type of the information described in an individual &#039;&#039;&#039;Info&#039;&#039;&#039; record is determined by the value of its &#039;&#039;type&#039;&#039; member.  Currently defined values for &#039;&#039;type&#039;&#039; are:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;fake&#039;&#039;&#039;&lt;br /&gt;
: The value configured as &#039;Send Number&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;groups&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The users group memberships are stored in a &#039;&#039;&#039;Group&#039;&#039;&#039; record which has the following elements:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string group&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: the name of the group the user is a member of&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;bool active&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: true if the user is an active member of the group&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;presence&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The users presence status is stored in a &#039;&#039;&#039;Presence&#039;&#039;&#039; record which has the following elements:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string status&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: either &#039;&#039;&#039;open&#039;&#039;&#039; or &#039;&#039;&#039;closed&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string activity&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The users current activity (optional)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string note&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The user provided additional note (optional)&lt;br /&gt;
&lt;br /&gt;
====integer UserInitialize(integer session, string user, bool xfer, bool disc, string hw)====&lt;br /&gt;
&lt;br /&gt;
Returns a handle to the named &#039;&#039;user&#039;&#039; (0 on failure). String &amp;lt;code&amp;gt;user&amp;lt;/code&amp;gt; must be a Long Name(cn). Phone number(e164) is not supported. Use FindUser instead, to retrieve cn to specified e164 number.&lt;br /&gt;
&lt;br /&gt;
Once a user handle is obtained with &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;, &#039;&#039;&#039;CallInfo&#039;&#039;&#039; events will be posted and retrieved via &#039;&#039;&#039;Poll&#039;&#039;&#039; for all calls related to the user.  If &#039;&#039;&#039;xfer&#039;&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, &#039;&#039;&#039;CallInfo&#039;&#039;&#039; events will also be posted for calls which are transferred away from &#039;&#039;&#039;user&#039;&#039;&#039;.  Otherwise, such events will be posted only for the user handle which the call has been transferred to. Thus, without setting follow to true, an application will generally not be able to track calls after a transfer unless it has called &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; for any PBX object a call may be transferred to and matches the new call on the transferred-to user via the &#039;&#039;&#039;conf&#039;&#039;&#039; information in the &#039;&#039;&#039;Info&#039;&#039;&#039; record of the new call (which will be identical to the &#039;&#039;&#039;conf&#039;&#039;&#039; information for the transferred call).&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;xfer&#039;&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, transferred calls will show up in the &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records with a &#039;&#039;&#039;No&#039;&#039;&#039; element of type &#039;&#039;&#039;xfer&#039;&#039;&#039; that indicates the number the call has been transferred to.&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;disc&#039;&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, calls to phones of the monitored user are cleared only after the user hangs up the phone. This way it can be avoided that the SOAP application assumes the phone is free but is still off-hook. This only works with innovaphone H.323 endpoints since the Disconnect message used to do this is not defined in the SIP standard.&lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;&#039;hw&#039;&#039;&#039; argument is provided only the device identified by this is monitored. Please note that a valid handle will be returned even if there is no matching device for &#039;&#039;&#039;user&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Also, the user handle can be used to create and control calls on behalf of the user.&lt;br /&gt;
&lt;br /&gt;
====void UserEnd(integer user)====&lt;br /&gt;
&lt;br /&gt;
Frees the handle &#039;&#039;user&#039;&#039; obtained with &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;. No events will be posted for this user anymore.&lt;br /&gt;
&lt;br /&gt;
====int SetPresence(inno:Presence presence, bool im, string contact, string guid, string h323)====&lt;br /&gt;
&lt;br /&gt;
Sets the presence of a PBX user.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;presence&#039;&#039;&#039;: &lt;br /&gt;
:* &#039;&#039;&#039;inno:PresenceStatus&#039;&#039;&#039;: the status &#039;&#039;&#039;closed&#039;&#039;&#039;/&#039;&#039;&#039;open&#039;&#039;&#039; or empty&lt;br /&gt;
:* &#039;&#039;&#039;inno:PresenceActivity&#039;&#039;&#039;: the activity like &#039;&#039;&#039;busy&#039;&#039;&#039;&lt;br /&gt;
:* string &#039;&#039;&#039;note&#039;&#039;&#039;: the presence note&lt;br /&gt;
* &#039;&#039;&#039;im&#039;&#039;&#039;: from im client?&lt;br /&gt;
* &#039;&#039;&#039;contact&#039;&#039;&#039;: the presence contact like &#039;&#039;&#039;tel:&#039;&#039;&#039;, &#039;&#039;&#039;calendar:&#039;&#039;&#039;...&lt;br /&gt;
* &#039;&#039;&#039;guid&#039;&#039;&#039;: the user guid&lt;br /&gt;
* &#039;&#039;&#039;h323&#039;&#039;&#039;: the h323 name of the user&lt;br /&gt;
&lt;br /&gt;
You can use &#039;&#039;&#039;guid&#039;&#039;&#039; or &#039;&#039;&#039;h323&#039;&#039;&#039; to identify the user! If no guid is known, use &#039;&#039;&#039;*&#039;&#039;&#039; as guid value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
If the setting of the presence was ok, the method returns &#039;&#039;&#039;1&#039;&#039;&#039;. Otherwise &#039;&#039;&#039;0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Device===&lt;br /&gt;
&lt;br /&gt;
For each User object multiple devices can be configured within the PBX. A device represents the physical endpoint used for calls (e.g. phones). Any registration to the PBX is associated to a configured device by the name/number used for the registration. Even thou it is possible that one configured device in the PBX accepts multiple registrations, it is recommened to configure the PBX in a way that there is one registration to a device. This way an application can control which physical endpoint is used for a call.&lt;br /&gt;
&lt;br /&gt;
====Device[] Devices(int session, string user)====&lt;br /&gt;
&lt;br /&gt;
This function returns an array of devices configured for a user identified by its cn (long name). The &#039;&#039;&#039;cfg&#039;&#039;&#039; flag in &#039;&#039;&#039;UserInfo&#039;&#039;&#039; is set when this information is changed. The structure &#039;Device&#039; contains the following members:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|valign=top nowrap=true|&#039;&#039;&#039;hw&#039;&#039;&#039;&lt;br /&gt;
|The Hardware Id used to identify the device. This string is used to associate any calls to devices.&lt;br /&gt;
|-&lt;br /&gt;
|valign=top nowrap=true|&#039;&#039;&#039;text&#039;&#039;&#039;&lt;br /&gt;
|A text configured as a description of the device. It can be used to be presented to the user for the user to select a device.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Call===&lt;br /&gt;
A call represents one leg of an existing call in the PBX.  &lt;br /&gt;
&lt;br /&gt;
====CallInfo====&lt;br /&gt;
The calls attributes are stored in a &#039;&#039;&#039;CallInfo&#039;&#039;&#039; structure, which has the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;int user&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the user handle the call belongs to&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;int call&#039;&#039;&#039;&lt;br /&gt;
the call handle&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;int reg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
currently unused&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;bool active&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;true&#039;&#039;&#039; if the call exists, &#039;&#039;&#039;false&#039;&#039;&#039; if not.  The only case where &#039;&#039;active&#039;&#039; can be &#039;&#039;&#039;false&#039;&#039;&#039; is when a call is terminated. A single &#039;&#039;&#039;CallInfo&#039;&#039;&#039; event will be posted with &#039;&#039;active&#039;&#039; set to &#039;&#039;&#039;false&#039;&#039;&#039; then&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A calls state. A bit field made up as follows:&lt;br /&gt;
{|border=&amp;quot;2&amp;quot; cellspacing=&amp;quot;4&amp;quot; cellpadding=&amp;quot;3&amp;quot; rules=&amp;quot;all&amp;quot; style=&amp;quot;margin:1em 1em 1em 0; border:solid 1px #AAAAAA; border-collapse:collapse;empty-cells:show;&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
| Value &lt;br /&gt;
| Mask &lt;br /&gt;
| Meaning&lt;br /&gt;
|-&lt;br /&gt;
| 1 &lt;br /&gt;
| 0xF &lt;br /&gt;
| setup&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 0xF || setup-ack&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 0xF || call-proc&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 0xF || Alert&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 0xF || Connect&lt;br /&gt;
|-&lt;br /&gt;
| 6 || 0xF || disconnect sent&lt;br /&gt;
|-&lt;br /&gt;
| 7 || 0xF || disconnect received&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 0xF || parked&lt;br /&gt;
|-&lt;br /&gt;
| 0 ||	0x80    || inbound  call&lt;br /&gt;
|-&lt;br /&gt;
| 128 ||	0x80    || outbound call&lt;br /&gt;
|-&lt;br /&gt;
| 0 ||	0x100   || active call&lt;br /&gt;
|-&lt;br /&gt;
| 256 ||	0x100   || call on hold&lt;br /&gt;
|-&lt;br /&gt;
| 0 ||	0x200   || active call&lt;br /&gt;
|-&lt;br /&gt;
| 512 ||	0x200   || active call put on hold by peer&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that the PBX API is PBX-centric, not terminal centric.  As such, it considers a call &#039;&#039;from&#039;&#039; the PBX &#039;&#039;to&#039;&#039; the terminal as &#039;&#039;outbound&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Refer to the [[Howto:SOAP API PHP5 Sample Code#Working with Call States from CallInfo]] Article to learn how to work with the call state values.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string msg&#039;&#039;&#039;&lt;br /&gt;
A textual representation of the signalling message causing this event. E.g. “&#039;&#039;&#039;x-setup&#039;&#039;&#039;”.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;No No&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An array of &#039;&#039;&#039;No&#039;&#039;&#039; records (see below).  This can include information about various peers related to the call itself.  The type of the peer described in an individual &#039;&#039;&#039;No&#039;&#039;&#039; record is determined by the value of its &#039;&#039;&#039;type&#039;&#039;&#039; member.  Currently defined values for &#039;&#039;&#039;type&#039;&#039;&#039; are:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;peer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The current remote end of the call (the local end is determined by the UserInfo identified through the user handle above)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;leg2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The last diverting user (if any)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;leg2orig&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The 1st diverting user (if any, from on v9hf1)&lt;br /&gt;
&lt;br /&gt;
:* &#039;&#039;&#039;leg1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: Indicates a call-forward/blind-xfer(?) to the calling end&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;ct&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The last user having transferred the call (if any)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;parked-to&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The call was parked to the indicated endpoint. This is sent with the &#039;r-rel&#039; message indicating the clearing of this call.&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;picking&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The call was picked by the indicated endpoint. Usually empty because sent with the new call which is created at the picking endpoint, but the fact that it is present indicates that this is a picked up call. The endpoint where this call is picked from is indicated with a &#039;&#039;ct&#039;&#039; No within the same call_info.&lt;br /&gt;
*&#039;&#039;&#039;Info info&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;Info&#039;&#039;&#039; record describing various aspects of the call.  The type of the information described in an individual &#039;&#039;&#039;Info&#039;&#039;&#039; record is determined by the value of its &#039;&#039;type&#039;&#039; member.  Currently defined values for &#039;&#039;type&#039;&#039; are:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;conf&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: A string holding the &#039;&#039;conference id&#039;&#039; (a GUID) of the call the reported call leg (all legs of a certain call share the same &#039;&#039;conference id&#039;&#039;). Also, CDRs for a call show this &#039;&#039;conference id&#039;&#039; (&#039;&#039;ref&#039;&#039; for [[Reference:Call_Detail_Record_CDR|gateway CDRs]], &#039;&#039;conf&#039;&#039; in the &#039;&#039;&amp;lt;event&amp;gt;&#039;&#039; tag for [[Reference10:Concept_Call_Detail_Record_CDR_PBX|PBX CDRs]]).&lt;br /&gt;
:*&#039;&#039;&#039;cause&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The latest [[Reference:ISDN_Cause_Codes | cause code ]] which has been notified on the call&lt;br /&gt;
&lt;br /&gt;
===== CallInfo for Boolean Objects =====&lt;br /&gt;
A &#039;&#039;Boolean&#039;&#039; will send a CallInfo event when it&#039;s status changes.  From the indicated number, you can derive the status as follows:&lt;br /&gt;
&lt;br /&gt;
00 - Auto-Off&lt;br /&gt;
01 - Auto-On&lt;br /&gt;
10 - Manual-Off&lt;br /&gt;
11 - Manual-On&lt;br /&gt;
&lt;br /&gt;
====No Record====&lt;br /&gt;
&lt;br /&gt;
Peer information is stored in a &#039;&#039;&#039;No&#039;&#039;&#039; record with the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the type of the peer described by the record&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string cn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s PBX’s objects common name (if any)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string e164&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s phone number&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string h323&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s h323 alias&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string dn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s display name&lt;br /&gt;
&lt;br /&gt;
====Info record====&lt;br /&gt;
Various information is stored in &#039;&#039;&#039;Info&#039;&#039;&#039; records with the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: the type of the information described by the record. The following values for &#039;&#039;type&#039;&#039; are used (although more may appear at any time):&lt;br /&gt;
:; conf : the call conference guid&lt;br /&gt;
:; cause : a cause code related to the call, see [[Reference:ISDN Cause Codes]]&lt;br /&gt;
:; uui : a user-user-info sent or received on the call. The UUI is conveyed in the &#039;&#039;vals&#039;&#039; member (see below). Note that from 13r3 upwards, the UUI conveyed is url-encoded. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string vals&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
a string value associated with this information (if any, the &#039;&#039;type&#039;&#039; of the element determines if an &#039;&#039;&#039;Info&#039;&#039;&#039; element has a string or an integer value) &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer vali&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
an integer value associated with this information (if any)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the call related functions do not return a meaningful value.  This is because the operations success is reflected in the subsequent CallInfo events.&lt;br /&gt;
&lt;br /&gt;
====integer UserCall(integer user, string cn, string e164, string h323, int reg, InfoArray info, int rc, string srce164)====&lt;br /&gt;
&lt;br /&gt;
Creates an outgoing call from the &#039;&#039;&#039;user&#039;&#039;&#039; (which is a handle obtained by a call to &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;)  to the destination described by &#039;&#039;cn&#039;&#039;, &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039;.  The argument &#039;&#039;&#039;srce164&#039;&#039;&#039; may be used to override the calling party number (note that this overrides the callers extension, not the full calling party number). Arguments &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039; are currently ignored. The argument &#039;&#039;rc&#039;&#039; is usually 0, unless special behavior is required by using other [[Reference8:SOAP_API#Remote_Control_Facilities|Remote Control Facilities]]. Returns a handle to the call (0 on failure).&lt;br /&gt;
&lt;br /&gt;
The called number (&#039;&#039;e164&#039;&#039;) is interpreted in the context of the user object the call is placed for (&#039;&#039;user&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
From V8HF3 on, if the srce164 argument of UserCall starts with &#039;r&#039; or &#039;R&#039;, the call is sent with CLIR (calling line identification restricted).&lt;br /&gt;
&lt;br /&gt;
Depending on the nature of the device the user is registered with, the device may actually place the call or the PBX may place a call and once it is accepted, it places another call to the destination.&lt;br /&gt;
&lt;br /&gt;
====UserConnect(integer call)====&lt;br /&gt;
Connects an existing &#039;&#039;call&#039;&#039;.  This forces the device the user is registered with to accept the call.  It may then go into hands-free mode.  Incapable (i.e. non-innovaphone) devices may simply ignore this call.&lt;br /&gt;
&lt;br /&gt;
====UserTransfer (int acall, integer bcall)====&lt;br /&gt;
&#039;&#039;acall&#039;&#039; and &#039;&#039;bcall&#039;&#039; are both calls a single user currently has active.  This method will connect &#039;&#039;acall&#039;&#039; with &#039;&#039;bcall&#039;&#039;, leaving the user without both calls.&lt;br /&gt;
&lt;br /&gt;
====UserMediaTransfer (integer acall, integer bcall, boolean user, boolean peer)====&lt;br /&gt;
&lt;br /&gt;
This function establishes a media connection between two parties currently active in a call independent of the signalling connection. &#039;&#039;acall&#039;&#039; and &#039;&#039;bcall&#039;&#039; are both active (connected) calls. If &#039;&#039;user&#039;&#039; is true, the user sides of the calls are connected together, if &#039;&#039;peer&#039;&#039; is set to true the peer sides of the calls are connected together. If neither &#039;&#039;user&#039;&#039; nor &#039;&#039;peer&#039;&#039; is set the calls are connected to their respective signalling peers.&lt;br /&gt;
&lt;br /&gt;
====bool UserRedirect(integer call, string cn, string e164, string h323, InfoArray info, int rc)====&lt;br /&gt;
Places a call to the destination described by &#039;&#039;cn&#039;&#039;, &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039; and connects &#039;&#039;call&#039;&#039; to this destination.  Argument &#039;&#039;info&#039;&#039; is currently ignored. &#039;&#039;rc&#039;&#039; can carry one of the remote control facilities listed in [[Reference:Remote Control Facility]] (see also [[{{NAMESPACE}}:Concept_SOAP_API#UserRc(integer_call,_integer_rc)|UserRc]] below).&lt;br /&gt;
&lt;br /&gt;
Any call forwarding configured for the destination will be ignored.  See [[Reference8:SOAP_API#bool_UserReroute.28integer_call.2C_string_cn.2C_string_e164.2C_string_h323.29|UserReroute()]] below.&lt;br /&gt;
&lt;br /&gt;
Note: in 2009, the semantics of UserRedirect has accidentally been changed so that call forwarding will no longer be ignored. From 14r1 Service Release 4, the original behavior can be restored by specifying 999 as &#039;&#039;rc&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====bool UserReroute(integer call, string cn, string e164, string h323)====&lt;br /&gt;
Performs a rerouting of the call.  Call forwardings set for the destination will be obeyed.&lt;br /&gt;
&lt;br /&gt;
Note: rerouting calls on a waiting queue or call broadcast object works only if the &#039;&#039;Execute Operator CFB/CFNR&#039;&#039; or &#039;&#039;Execute Group Member Diversions&#039;&#039; option is turned on.&lt;br /&gt;
&lt;br /&gt;
====integer UserPickup(int user, string cn, integer call, string group, int reg, InfoArray info)====&lt;br /&gt;
Redirects a call such that it appears as a new call at &#039;&#039;user&#039;&#039;. The call to be redirected can be specified by its &#039;&#039;call&#039;&#039; handle.  Alternatively, calls can be picked up by a users &#039;&#039;cn&#039;&#039; or by a &#039;&#039;group&#039;&#039; name.  If all parameters are null, an implicit pickup is done.  The new call handle is returned. Arguments &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039; are currently ignored.&lt;br /&gt;
&lt;br /&gt;
====UserClear(integer call, integer cause, InfoArray info)====&lt;br /&gt;
Disconnects the &#039;&#039;call&#039;&#039; providing &#039;&#039;cause&#039;&#039; as disconnect reason. For example the cause code &#039;&#039;26 non-selected user clearing&#039;&#039; could be used to disconnect the call immediately on local phone, so no disconnect tone is played.&lt;br /&gt;
&lt;br /&gt;
Cause is coded as a 7bit integer according to the table found in [[Reference:ISDN Cause Codes]].&lt;br /&gt;
Argument &#039;&#039;info&#039;&#039; is currently ignored.&lt;br /&gt;
&lt;br /&gt;
====UserCtComplete(integer call, string e164, string h323)====&lt;br /&gt;
&lt;br /&gt;
Sends a notification to the device &#039;&#039;call&#039;&#039; is active on that the remote peer has changed to &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039;.   This resembles the notification a device may receive if its remote peer transfers the call to the new destination.  The device may update its display and/or call data accordingly.  This call is often used to force the devices (i.e. telephones) display to show application specific data.&lt;br /&gt;
&lt;br /&gt;
====UserHold(integer call, bool remote)====&lt;br /&gt;
Sets the call on hold.  The device may or may not display the hold status.  In any case, the media channel is disconnected until a UserRetrieve is called.&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;V8 hotfix23&#039;&#039; an additional parameter &#039;&#039;&#039;remote&#039;&#039;&#039; was added. If set to &#039;&#039;&#039;true&#039;&#039;&#039;, &#039;&#039;&#039;remote&#039;&#039;&#039; will force to play MOH only to remote user (who is being held), set to &#039;&#039;&#039;false&#039;&#039;&#039; maintains the default behaviour (MOH played on remote user and a dialing tone to local user (depending on the pbx firmware, versions prior to v11r2 will play music on hold)). To use this parameter the recent WSDL 8.00 file must be retrieved.&lt;br /&gt;
&lt;br /&gt;
====UserRetrieve(integer call)====&lt;br /&gt;
Retrieves the &#039;&#039;call&#039;&#039; on hold.  The device may or may not display the new status.  In any case, the media channel is reconnected.&lt;br /&gt;
&lt;br /&gt;
====integer UserPark(integer call, string cn, integer position)====&lt;br /&gt;
Parks the call at the PBX object &#039;&#039;&#039;cn&#039;&#039;&#039; and local user on postion &#039;&#039;&#039;position&#039;&#039;&#039;. A position of -1 means any position is allowed. &amp;lt;!-- The parked call will show up as new call at the user in &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records returned by &#039;&#039;&#039;Poll()&#039;&#039;&#039; if the &#039;&#039;&#039;xfer&#039;&#039;&#039; flag of the corresponding &#039;&#039;&#039;UserInitialize()&#039;&#039;&#039; call has been set to true. - no, not ture - ckl -- --&amp;gt;The return value is the handle of the new call.&lt;br /&gt;
&lt;br /&gt;
To unpark calls, use the returned call handle with the &#039;&#039;&#039;UserPickup()&#039;&#039;&#039; function.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;cn&#039;&#039;&#039; argument can be used to identify another object, where the call shall be parked to.&lt;br /&gt;
&lt;br /&gt;
====UserDTMF(integer call, bool recv, string dtmf)====&lt;br /&gt;
Sends DTMF digits on behalf of the user. If &#039;&#039;&#039;recv&#039;&#039;&#039; is set to &#039;&#039;true&#039;&#039; the DTMF is sent to the local user.&lt;br /&gt;
&lt;br /&gt;
====UserUUI(integer call, bool recv, string uui)====&lt;br /&gt;
Sends User-User_information on behalf of the user. If &#039;&#039;&#039;recv&#039;&#039;&#039; is set to &#039;&#039;true&#039;&#039; the uui is sent to the local user.&lt;br /&gt;
&lt;br /&gt;
====UserInfo(integer call, bool recv, string cdpn, string key, string dsp)====&lt;br /&gt;
Sends INFO message on behalf of the user. If &#039;&#039;&#039;recv&#039;&#039;&#039; is set to &#039;&#039;true&#039;&#039; the INFO message is sent to the local user. This function can be used to send overlap dialing information.&lt;br /&gt;
&lt;br /&gt;
====UserRc(integer call, integer rc)====&lt;br /&gt;
Sends remote control facility to an innovaphone IP phone. It will be ignored by 3rd-party endpoints.&lt;br /&gt;
&lt;br /&gt;
A remote control facility can be sent to an innovaphone IP phone to activate additional call handling on the device.&lt;br /&gt;
&lt;br /&gt;
The current set of remote control facility function codes actually depends on the firmware used on the telephone, not the WSDL version used for SOAP.  The current set is documented in [[Reference:Remote Control Facility]].&lt;br /&gt;
&lt;br /&gt;
This function can be used for example to establish a three-party conference on an innovaphone IP phone. For this use the function UserRc on an active call using the &#039;&#039;&#039;rc&#039;&#039;&#039; value 4, while a second call is on hold.  See also the &#039;&#039;rc&#039;&#039; argument to [[#integer_UserCall.28integer_user.2C_string_cn.2C_string_e164.2C_string_h323.2C_int_reg.2C_InfoArray_info.2C_int_rc.2C_string_srce164.29|UserCall()]].&lt;br /&gt;
&lt;br /&gt;
===Messaging===&lt;br /&gt;
&lt;br /&gt;
====integer UserMessage(integer user, string e164, string h323, string msg, string src_e164, string src_h323 )====&lt;br /&gt;
Sends an message from the &#039;&#039;&#039;user&#039;&#039;&#039; (which is a handle obtained by a call to &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;) to the destination described by &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039;.  The parameters &#039;&#039;src_e164&#039;&#039; and &#039;&#039;src_h323&#039;&#039; may be used to override the calling party&#039;s information, in order to present a different callback information to the recipient of the message. Returns a handle to the call (0 on failure), which can be used to track the delivery of the message. A event of type &#039;msg-sent&#039; indicates the delivery of the message.&lt;br /&gt;
&lt;br /&gt;
===Status Retrieval===&lt;br /&gt;
&lt;br /&gt;
Instead of monitoring calls using the &#039;&#039;Poll&#039;&#039; mechanics, there are some functions to retrieve the current at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
====CallInfo[] Calls(integer session, string user)====&lt;br /&gt;
Returns an array of &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records for the calls currently active at the registration defined by &#039;&#039;user&#039;&#039;.  Please note that this function may be called without having called &#039;&#039;&#039;UserInitialize ()&#039;&#039;&#039; before.  Thus, the call handle information in the &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records returned is meaningless.&lt;br /&gt;
&lt;br /&gt;
====UserInfo[] FindUser(string v501, string v700, string v800, string vx1000, string cn, string h323, string e164, integer count, integer next, boolean nohide)====&lt;br /&gt;
Returns an array of at most &#039;&#039;count&#039;&#039; &#039;&#039;&#039;UserInfo&#039;&#039;&#039; records for the users matching &#039;&#039;cn&#039;&#039;, &#039;&#039;h323&#039;&#039; or &#039;&#039;e164&#039;&#039;. Only one of &#039;&#039;cn&#039;&#039;, &#039;&#039;h323&#039;&#039; and &#039;&#039;e164&#039;&#039; may be specified, except that &#039;&#039;e164&#039;&#039; and &#039;&#039;cn&#039;&#039; may be specified. In this case the number in &#039;&#039;e164&#039;&#039; is interpreted in the Node of the user specified with &#039;&#039;cn&#039;&#039;. The search string will be used as a starting point into the alphabetically sorted list of objects, that is, a search for “&#039;&#039;&#039;A&#039;&#039;&#039;” will yield entries starting with “&#039;&#039;&#039;A&#039;&#039;&#039;” but also – depending on &#039;&#039;count&#039;&#039; – the following entries. Neither search string may be empty. &#039;&#039;v501&#039;&#039;, &#039;&#039;v700&#039;&#039;, &#039;&#039;v800&#039;&#039; and &#039;&#039;vx1000&#039;&#039; must be set to a non-empty value. In case &#039;&#039;cn&#039;&#039; is set to the empty value, &#039;&#039;&#039;FindUser&#039;&#039;&#039; returns results starting from the first object in the PBX.&lt;br /&gt;
&lt;br /&gt;
To call &#039;&#039;&#039;FindUser&#039;&#039;&#039;, no session is required, however, you need a valid HTTP authentication.&lt;br /&gt;
&lt;br /&gt;
Be aware that large values for &#039;&#039;count&#039;&#039; may fail and even crash the PBX.  If you need to retrieve the whole user list, you should be using 20 as  &#039;&#039;count&#039;&#039;, provide the last &#039;&#039;cn&#039;&#039; retrieved as new start cn and loop until &#039;&#039;&#039;FindUser&#039;&#039;&#039; returns no more results, passing &#039;&#039;&#039;true&#039;&#039;&#039; as  value for &#039;&#039;next&#039;&#039; for all but the first calls.&lt;br /&gt;
&lt;br /&gt;
If the parameter &#039;&#039;nohide&#039;&#039; is true, all objects regardless if marked as &#039;&#039;Hide from LDAP&#039;&#039; or not are returned by the &#039;&#039;&#039;FindUser&#039;&#039;&#039; function.&lt;br /&gt;
&lt;br /&gt;
====bool UserFindDestination(integer user, string e164, string h323, out UserInfo user)====&lt;br /&gt;
This function checks if a destination can be reached from a given user by either a given number or a given name. &#039;&#039;user&#039;&#039; is the user handle from which PBX user the searching is started through all PBX nodes up and down. &#039;&#039;e164&#039;&#039; is the number, &#039;&#039;h323&#039;&#039; is a name.&lt;br /&gt;
&lt;br /&gt;
The function returns &#039;&#039;&#039;true&#039;&#039;&#039;, if the number or name is incomplete, otherwise &#039;&#039;&#039;false&#039;&#039;&#039;. If a destination is found, a &#039;&#039;&#039;UserInfo&#039;&#039;&#039; &#039;&#039;user&#039;&#039; is delivered.&lt;br /&gt;
&lt;br /&gt;
No session is required to call &#039;&#039;&#039;UserFindDestination&#039;&#039;&#039;, however, you need a valid HTTP authentication.&lt;br /&gt;
&lt;br /&gt;
====string License(integer session, string name)====&lt;br /&gt;
This function is for internal use only.&lt;br /&gt;
&lt;br /&gt;
====string LocationUrl(string v501, string v700, string v800, string vx1000, string location, bool tls)====&lt;br /&gt;
Returns a string with the HTTP URL for the PBX named location to which a SOAP session can be created. Typically, &#039;&#039;location&#039;&#039; is retrieved from the &#039;&#039;vals&#039;&#039; element of an &#039;&#039;&#039;Info&#039;&#039;&#039; record with &#039;&#039;type&#039;&#039; &#039;&#039;&#039;loc&#039;&#039;&#039; in an &#039;&#039;&#039;UserInfo&#039;&#039;&#039; record.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;location&#039;&#039; needs to be specified as the &#039;&#039;&#039;h323&#039;&#039;&#039; attributes value of the PBX node &#039;&#039;&#039;UserInfo&#039;&#039;&#039; data you are interested in.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;tls&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, a HTTPS URL is returned.&lt;br /&gt;
&lt;br /&gt;
====string UserLocalNum(int user, string num)====&lt;br /&gt;
Converts a given number &#039;&#039;&#039;num&#039;&#039;&#039; into a number diallable from the location of a specific &#039;&#039;&#039;user&#039;&#039;&#039;. Useful in inter-node scenarios where a destination node number and -extension are known, but the required escape prefix digits are unknown.&lt;br /&gt;
;user:The id of the specified user&lt;br /&gt;
;num:The number to be localized into the spefified user&#039;s location&lt;br /&gt;
;result:The localized number, including escape prefixes&lt;br /&gt;
&lt;br /&gt;
===Administration===&lt;br /&gt;
The SOAP interface can be used for administrational purposes also.  This is done via the Admin call.  All kinds of PBX objects can be created, read or modified. &lt;br /&gt;
&lt;br /&gt;
====string Admin(string xml)====&lt;br /&gt;
&lt;br /&gt;
Sends the administrational command &#039;&#039;xml&#039;&#039; to the PBX.  The command is executed and any result is returned.  &lt;br /&gt;
&lt;br /&gt;
This command allows you to query and modify the PBX object configuration (e.g. to query and set a users call forwarding).  The scope and format of the commands valid for &#039;&#039;xml&#039;&#039; is beyond the scope of this document, however, there is a [[Howto:Using the SOAP Admin Function | separate article on that ]].&lt;br /&gt;
&lt;br /&gt;
To call &#039;&#039;&#039;Admin&#039;&#039;&#039;, no session is required.  However, you must be authenticated as an admin user on the underlying HTTP layer.&lt;br /&gt;
&lt;br /&gt;
[[Howto:Using the SOAP Admin Function]]&lt;br /&gt;
&lt;br /&gt;
==Typical design of a PBX SOAP Application==&lt;br /&gt;
Please refer to the [[Reference:SOAP_API_%28pbx501.wsdl%29#Typical_design_of_a_PBX_SOAP_Application|pbx501.wsdl]] article for a discussion of the typical design of a SOAP application.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx10_00.wsdl Version10-wsdl].&lt;br /&gt;
&lt;br /&gt;
Applications based on this wsdl will work with V10 PBX firmware (and up) only. &lt;br /&gt;
&lt;br /&gt;
Applications written to the previous pbx501.wsdl, pbx700.wsdl and pbx900.wsdl will continue to work with V10 firmware. &lt;br /&gt;
&lt;br /&gt;
For your reference the old version files are still available:&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx501.wsdl Version5-wsdl]&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx700.wsdl Version7-wsdl]&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx900.wsdl Version9-wsdl]&lt;br /&gt;
&lt;br /&gt;
==Known Problems==&lt;br /&gt;
Please read [[Howto:Authentication in the SOAP interface]] in case you have problems to authenticate SOAP access.&lt;br /&gt;
&lt;br /&gt;
==System Requirements==&lt;br /&gt;
The PBX SOAP API requires a working PBX.&lt;br /&gt;
&lt;br /&gt;
To work with the PBX API in this version, you must run at least version 7.00 software on your PBX.  Also, you must run at least version 5 software on the phones.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
There is no specific installation required, as the PBX API is integral part of the PBX (although licenses are required to operate the PBX).&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
To prepare an PBX for PBX API testing&lt;br /&gt;
*setup a separate PBX&lt;br /&gt;
*install current firmware (at least 8.00)&lt;br /&gt;
*configure the PBX as usually&lt;br /&gt;
*add an user object called &#039;&#039;&#039;API&#039;&#039;&#039; , define a &#039;&#039;password&#039;&#039; for this object&lt;br /&gt;
*create a new group (e.g. called &#039;&#039;&#039;all users&#039;&#039;&#039;), by adding a group tag to &#039;&#039;&#039;API&#039;&#039;&#039;, make it &#039;&#039;active&#039;&#039;&lt;br /&gt;
*add a similar group tag to all other test users&lt;br /&gt;
*call &#039;&#039;&#039;Initialize()&#039;&#039;&#039; and use &#039;&#039;&#039;API&#039;&#039;&#039; as user and &#039;&#039;&#039;API&#039;&#039;&#039; and its &#039;&#039;password&#039;&#039; as http credentials&lt;br /&gt;
&lt;br /&gt;
==Known Issues==&lt;br /&gt;
We have reports that the PBX wsdl is incompatible to some of the contemporary SOAP platforms available in the market.  Most notably, Silverlight and Java seem to be affected.  These problems are fixed in the v11 implementation of the PBX SOAP interface &#039;&#039;pbx11_00.wsdl&#039;&#039; (available at [http://www.innovaphone.com/wsdl/pbx11_00.wsdl www.innovaphone.com/wsdl/pbx11_00.wsdl ]).&lt;br /&gt;
&lt;br /&gt;
Note: This wdsl file is not available directly from the PBX (e.g. at &amp;lt;code&amp;gt;http://xx.xx.xx.xx/pbx11_00.wsdl&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
However, we have had indications that for Java, solutions are possible based on Apache Axis 1.4, Netbeans 6.8 or JAX-RPC.&lt;br /&gt;
&lt;br /&gt;
The PBX does not expect the SOAP client to disconnect the session right after a UserCall.  If this is the case (e.g. in a script which merely creates a call on behalf of a user and then terminates), it might happen that the outgoing call from the device will not be created correctly (a matter of timing).  In this case, just wait for one second.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
:[[Howto:Authentication in the SOAP interface]]&lt;br /&gt;
:[[Howto:Clear a call completely with SOAP using UserClear]]&lt;br /&gt;
:[[Howto:PBX SOAP Api C sample code]]&lt;br /&gt;
:[[Howto:SOAP Api VisualBasic.Net Sample Code]]&lt;br /&gt;
:[[Support:TAPI or other SOAP Application fails to function properly if PBX users have special characters in their long or short user name]]&lt;br /&gt;
:[[Howto:How to monitor configuration changes in the SOAP interface ]]&lt;br /&gt;
:[[Howto:SOAP with PHP5 ]]&lt;br /&gt;
:[[Howto:SOAP API Java Sample Code ]]&lt;br /&gt;
:[[Howto:Using the SOAP Admin Function]]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.innovaphone.com/index.php?search=soap Search for more articles about SOAP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- keywords: sopa soap --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference10:Concept_SOAP_API&amp;diff=73591</id>
		<title>Reference10:Concept SOAP API</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference10:Concept_SOAP_API&amp;diff=73591"/>
		<updated>2024-09-25T08:24:50Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Info record */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;innovaphone®&#039;s PBX web services, also known as SOAP API, while no longer actively extended, remains available and functional. A transition to WebSocket API, specifically the RCC API (https://sdk.innovaphone.com/13r3/doc/appwebsocket/RCC.htm), was introduced with version 13 firmware.&lt;br /&gt;
&lt;br /&gt;
For ongoing development, we recommend utilizing [http://www.innovaphone.com/wsdl/pbx10_00.wsdl WSDL version 10 &#039;&#039;pbx10_00.wsdl&#039;&#039;] (also available on the gateway &amp;lt;code&amp;gt;http://xx.xx.xx.xx/pbx10_00.wsdl&amp;lt;/code&amp;gt;) in conjunction with this Wiki article. It&#039;s advisable to disregard the higher versions of WSDL for your development.&lt;br /&gt;
&lt;br /&gt;
For upcoming developments the WebSocket API should be used, as it represents the current and future direction of our API development.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
For an overview of the basic architecture, see the [[Reference:SOAP_API_%28pbx501.wsdl%29#Overview|corresponding chapter in the pbx501.wsdl related article]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Concept|{{PAGENAME}}]]&lt;br /&gt;
&lt;br /&gt;
== Definition of PBX object (WSDL) == &lt;br /&gt;
Within the SOAP framework there is a mechanism to formally decribe the definition of remote objects. This is done by so called WSDL (Web Service Description Language) files. This [[http://www.innovaphone.com/wsdl/pbx10_00.wsdl wsdl file]] defines the PBX web services  described in this document.&lt;br /&gt;
&lt;br /&gt;
NB: while you can access and retrieve the WSDL file through this URL on runtime of your application, we&#039;d rather recommend to install a local copy with your application and use this on runtime.  This way, your application will be immune against failures of www.innovaphone.com.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;There is also an [[http://www.innovaphone.com/wsdl/pbx900.wsdl old version of the wsdl]] available which has less interface functions.  This interface can still be accessed by legacy applications and is activated on the PBX by calling the &#039;&#039;&#039;Initialize&#039;&#039;&#039; Function with fewer arguments (&#039;&#039;&#039;Integer Initialize(string user, string appl, out key)&#039;&#039;&#039;).  It should not be used for new develoments though.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SOAP URL ===&lt;br /&gt;
The SOAP service URI is &#039;&#039;&#039;/PBX0/user.soap&#039;&#039;&#039; for the standard PBX and &#039;&#039;&#039;/PBX-&#039;&#039;id&#039;&#039;/user.soap&#039;&#039;&#039; for a dynamic PBX (where &#039;&#039;id&#039;&#039; corresponds to the &#039;&#039;Id&#039;&#039; field in the [[Reference10:PBX/Dyn-PBXs]] configuration dialog).  SOAP is accessible via plain HTTP or HTTPS, so valid URLs might be &amp;lt;code&amp;gt;http://172.16.0.1/PBX0/user.soap&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;https://172.16.0.1/PBX0-mydynpbxid/user.soap&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==PBX Objects and Methods==&lt;br /&gt;
&lt;br /&gt;
This section contains a language agnostic description of the PBX API’s object model.  Despite of the fact that we are discussing an object model, the PBX API is in fact not an object oriented API.  This is because SOAP itself is not really object oriented.  In particular, there is no object creation, activation or lifetime concept.  This is left up to the service designer.  SOAP is more a message exchange mechanism than an object method invocation mechanism.  This is reflected in the API structure.&lt;br /&gt;
&lt;br /&gt;
Specifically, objects are represented through handles, which are integers.  Objects are created and destroyed using dedicated methods and it’s the users responsibility to manage the lifetime of all objects.&lt;br /&gt;
&lt;br /&gt;
The syntax shown here actually is no valid syntax in any existing language.  Please refer to the various sample codes for working syntax.&lt;br /&gt;
&lt;br /&gt;
===Session===&lt;br /&gt;
&lt;br /&gt;
All PBX API methods are executed in the context of a session.  A session is created using the &#039;&#039;&#039;initialize&#039;&#039;&#039; method and is identified by a handle.  This handle must be provided to all subsequent method calls.&lt;br /&gt;
&lt;br /&gt;
A session is owned by the PBX API user, i.e. there is no way to have access to a session of another application.  Each session has a scope, which defines the view of the PBX the session user has.  The scope determines the set of PBX registrations seen by the session.&lt;br /&gt;
&lt;br /&gt;
Scopes are defined and configured in the PBX and are bound to particular PBX users. Thus, a session has a user attribute, which defines the scope.   It includes all users which are members of groups &#039;&#039;&#039;user&#039;&#039;&#039; is active member of.  If &#039;&#039;&#039;user&#039;&#039;&#039; is not an active member of any group, the scope is the user itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Initialize(string user, string appl, bool $v, bool $v501, bool v700, bool v800, bool vx1000, out int key)====&lt;br /&gt;
&lt;br /&gt;
To access the current web services implementation, &#039;&#039;&#039;v&#039;&#039;&#039;, &#039;&#039;&#039;v501&#039;&#039;&#039;, &#039;&#039;&#039;v700&#039;&#039;&#039;, &#039;&#039;&#039;v800&#039;&#039;&#039; and &#039;&#039;&#039;vx10000&#039;&#039;&#039; must be present and set to &#039;&#039;&#039;true&#039;&#039;&#039;. &lt;br /&gt;
These parameters actually convey the wsdl version used by the client.  Different versions of the interface use different parameter sets for the Initialize call.  Applications should always use the wsdl version current at the time of writing the application.&lt;br /&gt;
&lt;br /&gt;
The method creates a session.  The session will have the user &#039;&#039;&#039;user&#039;&#039;&#039;’s scope (&#039;&#039;&#039;user&#039;&#039;&#039; is the &#039;&#039;Long Name&#039;&#039; of a PBX user).  The session handle is returned and is 0 for failure and positive for a valid session handle.  &#039;&#039;&#039;appl&#039;&#039;&#039; specifies the name of the calling application and is used for administrative purposes.  The output parameter &#039;&#039;&#039;key&#039;&#039;&#039; is a random number associated to the session.   It may be used in subsequent &#039;&#039;&#039;Echo&#039;&#039;&#039; operations.&lt;br /&gt;
&lt;br /&gt;
When a session is created, &#039;&#039;&#039;UserInfo&#039;&#039;&#039; events for all PBX registrations in the scope can be received by the &#039;&#039;&#039;Poll&#039;&#039;&#039; function.  Initially, one &#039;&#039;&#039;UserInfo&#039;&#039;&#039; per registration within the session’s scope is received (the list is terminated by a &#039;&#039;&#039;UserInfo&#039;&#039;&#039; with empty &#039;&#039;&#039;cn&#039;&#039;&#039; and may require multiple &#039;&#039;&#039;Poll&#039;&#039;&#039; calls to retrieve).  Subsequently, &#039;&#039;&#039;UserInfo&#039;&#039;&#039; events are received when a registrations state changes.&lt;br /&gt;
&lt;br /&gt;
The underlying transport session (HTTP) must authenticate itself  either as &#039;&#039;&#039;user&#039;&#039;&#039;  (using the users long name and PBX password) or as the admin user (using the gateway administrator account name and password) to perform an &#039;&#039;&#039;Initialize&#039;&#039;&#039; and any session related function.   Note that if you use a PBX user account, the user needs to have at least &#039;&#039;Group/Call Forwards&#039;&#039; rights. &lt;br /&gt;
&lt;br /&gt;
Note that the method to force the SOAP system you are using to authenticate to the PBX is entirely up to the system itself.  Some systems even do not support authentication at all.  If your SOAP implementation does not support digest authentication, make sure the gateway accepts basic authentication by setting the “&#039;&#039;allow HTTP basic authentication&#039;&#039;” in the “&#039;&#039;General settings&#039;&#039;”.&lt;br /&gt;
&lt;br /&gt;
Note that although many HTTP connections may be used in a single session, at least one HTTP connection must remain open during the lifetime of the session.  When the last connection disappears, the logical session is terminated after a short timeout. Some SOAP libraries may per default always close the HTTP connection and reconnect on subsequent SOAP calls, which will not work. The SOAP library should either be configured to keep at least one HTTP connection alive or, if this is not an option, the application should take care to always have a an active request pending (such as &#039;&#039;&#039;Poll&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
====Echo(integer session, integer key)====&lt;br /&gt;
&lt;br /&gt;
Verifies a session.  You need to supply the &#039;&#039;session&#039;&#039; identifier and &#039;&#039;key&#039;&#039; returned by a previous call to &#039;&#039;&#039;Initialize&#039;&#039;&#039;.  Returns nonzero if successful.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====End(integer session)====&lt;br /&gt;
&lt;br /&gt;
Terminates the session referenced by &#039;&#039;session&#039;&#039;.  No further events will be received.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Integer Version(out string gkId, out string location, out string firmware, out string serial)====&lt;br /&gt;
&lt;br /&gt;
Returns the version number of the WSDL file the PBX supports.  The first released WSDL file had version number 500.  The version described by this document has version number 501. Also delivers information about the connected PBX (in &#039;&#039;gkId&#039;&#039;, &#039;&#039;location&#039;&#039;, &#039;&#039;firmware&#039;&#039; and &#039;&#039;serial&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====AnyInfo Poll(integer session)====&lt;br /&gt;
&lt;br /&gt;
Returns pending events for the session referenced by &#039;&#039;session&#039;&#039;.  &#039;&#039;AnyInfo&#039;&#039; is a struct with four arrays as members: &#039;&#039;user&#039;&#039;, &#039;&#039;call&#039;&#039;, &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039;. &#039;&#039;user&#039;&#039; is an array of type &#039;&#039;UserInfo&#039;&#039; and call is an array of type CallInfo.  The other two arrays &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039; are currently not used.&lt;br /&gt;
&lt;br /&gt;
After a successful &#039;&#039;&#039;Initialize()&#039;&#039; there will be a &#039;&#039;UserInfo&#039;&#039; event for each defined and visible user in the system.  This allows the application to synchronize on the state of all visible users.  The list will be terminated by an &#039;&#039;UserInfo&#039;&#039; event for a user with an empty &#039;&#039;cn&#039;&#039; which normally cannot happen since a user entry must have a cn.&lt;br /&gt;
&lt;br /&gt;
===User===&lt;br /&gt;
&lt;br /&gt;
A user represents a configured object within the PBX (a “PBX user”). The PBX API provides the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; method to obtain a handle to the user.&lt;br /&gt;
&lt;br /&gt;
====UserInfo====&lt;br /&gt;
The user’s properties are stored in a &#039;&#039;UserInfo&#039;&#039; structure, which has the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;boolean active&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
true if the user exists.  The only case where active can be false is when a user is moved out of the session context. This may happen if the users group assignment is changed or the user is deleted. A single UserInfo event will be posted with active set to false then.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1 if the user is registered, 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer channel&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
number of current calls.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer  alert&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
number of alerting calls&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the type of the users device.  Currently defined are “&#039;&#039;&#039;ep&#039;&#039;&#039;” (it is an endpoint), “&#039;&#039;&#039;gw&#039;&#039;&#039;” (it is a gateway, for example a trunk line), “&#039;&#039;&#039;waiting&#039;&#039;&#039;” (a call queue) or “&#039;&#039;&#039;broadcast&#039;&#039;&#039;” (a group).  Others may be defined over time.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string guid&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the users GUID.  This is a globally unique identifier for the user.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string cn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the common name of the user. This is what the PBX’s LDAP server recognizes as the CN of this user.  The user’s name in the PBX configuration applet.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string e164&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the extension number the user is registered with.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string h323&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the alias the user is registered with.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string dn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the users display name.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string domain&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the PBX domain if the Gatekeeper ID is used as domain&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;boolean h323email&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If true, the h323 name shall be used as primary email address when sending emails to this user.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string email[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
email addresses of the user. If &#039;h323email&#039; is not set, the first address in this list shall be used as primary email address when sending emails to this user.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Group groups&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An array of &#039;&#039;&#039;Group&#039;&#039;&#039; records (see below).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Presence presence&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An array of &#039;&#039;&#039;Presence&#039;&#039;&#039; records (see below).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;boolean cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If set to true indicates that the config of the user has changed&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The type of the user object&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string loc&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If the object described is not local to the PBX the &#039;&#039;&#039;UserInfo&#039;&#039;&#039; is sent from, the name of the location the object is homed in is given in this element.  See &#039;&#039;&#039;LocationUrl&#039;&#039;&#039; to find out how to proceed further.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string node&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The node of the object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string nodenum&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The object nodes node number (prefix).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Info&#039;&#039;&#039;&lt;br /&gt;
An &#039;&#039;&#039;Info&#039;&#039;&#039; record describing various aspects of the user.  The type of the information described in an individual &#039;&#039;&#039;Info&#039;&#039;&#039; record is determined by the value of its &#039;&#039;type&#039;&#039; member.  Currently defined values for &#039;&#039;type&#039;&#039; are:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;fake&#039;&#039;&#039;&lt;br /&gt;
: The value configured as &#039;Send Number&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;groups&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The users group memberships are stored in a &#039;&#039;&#039;Group&#039;&#039;&#039; record which has the following elements:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string group&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: the name of the group the user is a member of&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;bool active&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: true if the user is an active member of the group&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;presence&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The users presence status is stored in a &#039;&#039;&#039;Presence&#039;&#039;&#039; record which has the following elements:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string status&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: either &#039;&#039;&#039;open&#039;&#039;&#039; or &#039;&#039;&#039;closed&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string activity&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The users current activity (optional)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;string note&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The user provided additional note (optional)&lt;br /&gt;
&lt;br /&gt;
====integer UserInitialize(integer session, string user, bool xfer, bool disc, string hw)====&lt;br /&gt;
&lt;br /&gt;
Returns a handle to the named &#039;&#039;user&#039;&#039; (0 on failure). String &amp;lt;code&amp;gt;user&amp;lt;/code&amp;gt; must be a Long Name(cn). Phone number(e164) is not supported. Use FindUser instead, to retrieve cn to specified e164 number.&lt;br /&gt;
&lt;br /&gt;
Once a user handle is obtained with &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;, &#039;&#039;&#039;CallInfo&#039;&#039;&#039; events will be posted and retrieved via &#039;&#039;&#039;Poll&#039;&#039;&#039; for all calls related to the user.  If &#039;&#039;&#039;xfer&#039;&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, &#039;&#039;&#039;CallInfo&#039;&#039;&#039; events will also be posted for calls which are transferred away from &#039;&#039;&#039;user&#039;&#039;&#039;.  Otherwise, such events will be posted only for the user handle which the call has been transferred to. Thus, without setting follow to true, an application will generally not be able to track calls after a transfer unless it has called &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; for any PBX object a call may be transferred to and matches the new call on the transferred-to user via the &#039;&#039;&#039;conf&#039;&#039;&#039; information in the &#039;&#039;&#039;Info&#039;&#039;&#039; record of the new call (which will be identical to the &#039;&#039;&#039;conf&#039;&#039;&#039; information for the transferred call).&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;xfer&#039;&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, transferred calls will show up in the &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records with a &#039;&#039;&#039;No&#039;&#039;&#039; element of type &#039;&#039;&#039;xfer&#039;&#039;&#039; that indicates the number the call has been transferred to.&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;disc&#039;&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, calls to phones of the monitored user are cleared only after the user hangs up the phone. This way it can be avoided that the SOAP application assumes the phone is free but is still off-hook. This only works with innovaphone H.323 endpoints since the Disconnect message used to do this is not defined in the SIP standard.&lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;&#039;hw&#039;&#039;&#039; argument is provided only the device identified by this is monitored. Please note that a valid handle will be returned even if there is no matching device for &#039;&#039;&#039;user&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Also, the user handle can be used to create and control calls on behalf of the user.&lt;br /&gt;
&lt;br /&gt;
====void UserEnd(integer user)====&lt;br /&gt;
&lt;br /&gt;
Frees the handle &#039;&#039;user&#039;&#039; obtained with &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;. No events will be posted for this user anymore.&lt;br /&gt;
&lt;br /&gt;
====int SetPresence(inno:Presence presence, bool im, string contact, string guid, string h323)====&lt;br /&gt;
&lt;br /&gt;
Sets the presence of a PBX user.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;presence&#039;&#039;&#039;: &lt;br /&gt;
:* &#039;&#039;&#039;inno:PresenceStatus&#039;&#039;&#039;: the status &#039;&#039;&#039;closed&#039;&#039;&#039;/&#039;&#039;&#039;open&#039;&#039;&#039; or empty&lt;br /&gt;
:* &#039;&#039;&#039;inno:PresenceActivity&#039;&#039;&#039;: the activity like &#039;&#039;&#039;busy&#039;&#039;&#039;&lt;br /&gt;
:* string &#039;&#039;&#039;note&#039;&#039;&#039;: the presence note&lt;br /&gt;
* &#039;&#039;&#039;im&#039;&#039;&#039;: from im client?&lt;br /&gt;
* &#039;&#039;&#039;contact&#039;&#039;&#039;: the presence contact like &#039;&#039;&#039;tel:&#039;&#039;&#039;, &#039;&#039;&#039;calendar:&#039;&#039;&#039;...&lt;br /&gt;
* &#039;&#039;&#039;guid&#039;&#039;&#039;: the user guid&lt;br /&gt;
* &#039;&#039;&#039;h323&#039;&#039;&#039;: the h323 name of the user&lt;br /&gt;
&lt;br /&gt;
You can use &#039;&#039;&#039;guid&#039;&#039;&#039; or &#039;&#039;&#039;h323&#039;&#039;&#039; to identify the user! If no guid is known, use &#039;&#039;&#039;*&#039;&#039;&#039; as guid value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
If the setting of the presence was ok, the method returns &#039;&#039;&#039;1&#039;&#039;&#039;. Otherwise &#039;&#039;&#039;0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Device===&lt;br /&gt;
&lt;br /&gt;
For each User object multiple devices can be configured within the PBX. A device represents the physical endpoint used for calls (e.g. phones). Any registration to the PBX is associated to a configured device by the name/number used for the registration. Even thou it is possible that one configured device in the PBX accepts multiple registrations, it is recommened to configure the PBX in a way that there is one registration to a device. This way an application can control which physical endpoint is used for a call.&lt;br /&gt;
&lt;br /&gt;
====Device[] Devices(int session, string user)====&lt;br /&gt;
&lt;br /&gt;
This function returns an array of devices configured for a user identified by its cn (long name). The &#039;&#039;&#039;cfg&#039;&#039;&#039; flag in &#039;&#039;&#039;UserInfo&#039;&#039;&#039; is set when this information is changed. The structure &#039;Device&#039; contains the following members:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|valign=top nowrap=true|&#039;&#039;&#039;hw&#039;&#039;&#039;&lt;br /&gt;
|The Hardware Id used to identify the device. This string is used to associate any calls to devices.&lt;br /&gt;
|-&lt;br /&gt;
|valign=top nowrap=true|&#039;&#039;&#039;text&#039;&#039;&#039;&lt;br /&gt;
|A text configured as a description of the device. It can be used to be presented to the user for the user to select a device.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Call===&lt;br /&gt;
A call represents one leg of an existing call in the PBX.  &lt;br /&gt;
&lt;br /&gt;
====CallInfo====&lt;br /&gt;
The calls attributes are stored in a &#039;&#039;&#039;CallInfo&#039;&#039;&#039; structure, which has the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;int user&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the user handle the call belongs to&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;int call&#039;&#039;&#039;&lt;br /&gt;
the call handle&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;int reg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
currently unused&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;bool active&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;true&#039;&#039;&#039; if the call exists, &#039;&#039;&#039;false&#039;&#039;&#039; if not.  The only case where &#039;&#039;active&#039;&#039; can be &#039;&#039;&#039;false&#039;&#039;&#039; is when a call is terminated. A single &#039;&#039;&#039;CallInfo&#039;&#039;&#039; event will be posted with &#039;&#039;active&#039;&#039; set to &#039;&#039;&#039;false&#039;&#039;&#039; then&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A calls state. A bit field made up as follows:&lt;br /&gt;
{|border=&amp;quot;2&amp;quot; cellspacing=&amp;quot;4&amp;quot; cellpadding=&amp;quot;3&amp;quot; rules=&amp;quot;all&amp;quot; style=&amp;quot;margin:1em 1em 1em 0; border:solid 1px #AAAAAA; border-collapse:collapse;empty-cells:show;&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
| Value &lt;br /&gt;
| Mask &lt;br /&gt;
| Meaning&lt;br /&gt;
|-&lt;br /&gt;
| 1 &lt;br /&gt;
| 0xF &lt;br /&gt;
| setup&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 0xF || setup-ack&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 0xF || call-proc&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 0xF || Alert&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 0xF || Connect&lt;br /&gt;
|-&lt;br /&gt;
| 6 || 0xF || disconnect sent&lt;br /&gt;
|-&lt;br /&gt;
| 7 || 0xF || disconnect received&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 0xF || parked&lt;br /&gt;
|-&lt;br /&gt;
| 0 ||	0x80    || inbound  call&lt;br /&gt;
|-&lt;br /&gt;
| 128 ||	0x80    || outbound call&lt;br /&gt;
|-&lt;br /&gt;
| 0 ||	0x100   || active call&lt;br /&gt;
|-&lt;br /&gt;
| 256 ||	0x100   || call on hold&lt;br /&gt;
|-&lt;br /&gt;
| 0 ||	0x200   || active call&lt;br /&gt;
|-&lt;br /&gt;
| 512 ||	0x200   || active call put on hold by peer&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that the PBX API is PBX-centric, not terminal centric.  As such, it considers a call &#039;&#039;from&#039;&#039; the PBX &#039;&#039;to&#039;&#039; the terminal as &#039;&#039;outbound&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Refer to the [[Howto:SOAP API PHP5 Sample Code#Working with Call States from CallInfo]] Article to learn how to work with the call state values.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string msg&#039;&#039;&#039;&lt;br /&gt;
A textual representation of the signalling message causing this event. E.g. “&#039;&#039;&#039;x-setup&#039;&#039;&#039;”.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;No No&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An array of &#039;&#039;&#039;No&#039;&#039;&#039; records (see below).  This can include information about various peers related to the call itself.  The type of the peer described in an individual &#039;&#039;&#039;No&#039;&#039;&#039; record is determined by the value of its &#039;&#039;&#039;type&#039;&#039;&#039; member.  Currently defined values for &#039;&#039;&#039;type&#039;&#039;&#039; are:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;peer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The current remote end of the call (the local end is determined by the UserInfo identified through the user handle above)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;leg2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The last diverting user (if any)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;leg2orig&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The 1st diverting user (if any, from on v9hf1)&lt;br /&gt;
&lt;br /&gt;
:* &#039;&#039;&#039;leg1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: Indicates a call-forward/blind-xfer(?) to the calling end&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;ct&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The last user having transferred the call (if any)&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;parked-to&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The call was parked to the indicated endpoint. This is sent with the &#039;r-rel&#039; message indicating the clearing of this call.&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;picking&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The call was picked by the indicated endpoint. Usually empty because sent with the new call which is created at the picking endpoint, but the fact that it is present indicates that this is a picked up call. The endpoint where this call is picked from is indicated with a &#039;&#039;ct&#039;&#039; No within the same call_info.&lt;br /&gt;
*&#039;&#039;&#039;Info info&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;Info&#039;&#039;&#039; record describing various aspects of the call.  The type of the information described in an individual &#039;&#039;&#039;Info&#039;&#039;&#039; record is determined by the value of its &#039;&#039;type&#039;&#039; member.  Currently defined values for &#039;&#039;type&#039;&#039; are:&lt;br /&gt;
&lt;br /&gt;
:*&#039;&#039;&#039;conf&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: A string holding the &#039;&#039;conference id&#039;&#039; (a GUID) of the call the reported call leg (all legs of a certain call share the same &#039;&#039;conference id&#039;&#039;). Also, CDRs for a call show this &#039;&#039;conference id&#039;&#039; (&#039;&#039;ref&#039;&#039; for [[Reference:Call_Detail_Record_CDR|gateway CDRs]], &#039;&#039;conf&#039;&#039; in the &#039;&#039;&amp;lt;event&amp;gt;&#039;&#039; tag for [[Reference10:Concept_Call_Detail_Record_CDR_PBX|PBX CDRs]]).&lt;br /&gt;
:*&#039;&#039;&#039;cause&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: The latest [[Reference:ISDN_Cause_Codes | cause code ]] which has been notified on the call&lt;br /&gt;
&lt;br /&gt;
===== CallInfo for Boolean Objects =====&lt;br /&gt;
A &#039;&#039;Boolean&#039;&#039; will send a CallInfo event when it&#039;s status changes.  From the indicated number, you can derive the status as follows:&lt;br /&gt;
&lt;br /&gt;
00 - Auto-Off&lt;br /&gt;
01 - Auto-On&lt;br /&gt;
10 - Manual-Off&lt;br /&gt;
11 - Manual-On&lt;br /&gt;
&lt;br /&gt;
====No Record====&lt;br /&gt;
&lt;br /&gt;
Peer information is stored in a &#039;&#039;&#039;No&#039;&#039;&#039; record with the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the type of the peer described by the record&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string cn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s PBX’s objects common name (if any)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string e164&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s phone number&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string h323&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s h323 alias&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string dn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the peer’s display name&lt;br /&gt;
&lt;br /&gt;
====Info record====&lt;br /&gt;
Various information is stored in &#039;&#039;&#039;Info&#039;&#039;&#039; records with the following elements:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: the type of the information described by the record. The following values for &#039;&#039;type&#039;&#039; are used (although more may appear at any time):&lt;br /&gt;
:; conf : the call conference guid&lt;br /&gt;
:; cause : a cause code related to the call, see [[Reference:ISDN Cause Codes]]&lt;br /&gt;
:; uui : a user-user-info sent or received on the call. The UUI is conveyed in the &#039;&#039;vals&#039;&#039; member (see below). Note that form 13r3 upwards, the UUI conveyed is url-encoded. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;string vals&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
a string value associated with this information (if any, the &#039;&#039;type&#039;&#039; of the element determines if an &#039;&#039;&#039;Info&#039;&#039;&#039; element has a string or an integer value) &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;integer vali&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
an integer value associated with this information (if any)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the call related functions do not return a meaningful value.  This is because the operations success is reflected in the subsequent CallInfo events.&lt;br /&gt;
&lt;br /&gt;
====integer UserCall(integer user, string cn, string e164, string h323, int reg, InfoArray info, int rc, string srce164)====&lt;br /&gt;
&lt;br /&gt;
Creates an outgoing call from the &#039;&#039;&#039;user&#039;&#039;&#039; (which is a handle obtained by a call to &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;)  to the destination described by &#039;&#039;cn&#039;&#039;, &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039;.  The argument &#039;&#039;&#039;srce164&#039;&#039;&#039; may be used to override the calling party number (note that this overrides the callers extension, not the full calling party number). Arguments &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039; are currently ignored. The argument &#039;&#039;rc&#039;&#039; is usually 0, unless special behavior is required by using other [[Reference8:SOAP_API#Remote_Control_Facilities|Remote Control Facilities]]. Returns a handle to the call (0 on failure).&lt;br /&gt;
&lt;br /&gt;
The called number (&#039;&#039;e164&#039;&#039;) is interpreted in the context of the user object the call is placed for (&#039;&#039;user&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
From V8HF3 on, if the srce164 argument of UserCall starts with &#039;r&#039; or &#039;R&#039;, the call is sent with CLIR (calling line identification restricted).&lt;br /&gt;
&lt;br /&gt;
Depending on the nature of the device the user is registered with, the device may actually place the call or the PBX may place a call and once it is accepted, it places another call to the destination.&lt;br /&gt;
&lt;br /&gt;
====UserConnect(integer call)====&lt;br /&gt;
Connects an existing &#039;&#039;call&#039;&#039;.  This forces the device the user is registered with to accept the call.  It may then go into hands-free mode.  Incapable (i.e. non-innovaphone) devices may simply ignore this call.&lt;br /&gt;
&lt;br /&gt;
====UserTransfer (int acall, integer bcall)====&lt;br /&gt;
&#039;&#039;acall&#039;&#039; and &#039;&#039;bcall&#039;&#039; are both calls a single user currently has active.  This method will connect &#039;&#039;acall&#039;&#039; with &#039;&#039;bcall&#039;&#039;, leaving the user without both calls.&lt;br /&gt;
&lt;br /&gt;
====UserMediaTransfer (integer acall, integer bcall, boolean user, boolean peer)====&lt;br /&gt;
&lt;br /&gt;
This function establishes a media connection between two parties currently active in a call independent of the signalling connection. &#039;&#039;acall&#039;&#039; and &#039;&#039;bcall&#039;&#039; are both active (connected) calls. If &#039;&#039;user&#039;&#039; is true, the user sides of the calls are connected together, if &#039;&#039;peer&#039;&#039; is set to true the peer sides of the calls are connected together. If neither &#039;&#039;user&#039;&#039; nor &#039;&#039;peer&#039;&#039; is set the calls are connected to their respective signalling peers.&lt;br /&gt;
&lt;br /&gt;
====bool UserRedirect(integer call, string cn, string e164, string h323, InfoArray info, int rc)====&lt;br /&gt;
Places a call to the destination described by &#039;&#039;cn&#039;&#039;, &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039; and connects &#039;&#039;call&#039;&#039; to this destination.  Argument &#039;&#039;info&#039;&#039; is currently ignored. &#039;&#039;rc&#039;&#039; can carry one of the remote control facilities listed in [[Reference:Remote Control Facility]] (see also [[{{NAMESPACE}}:Concept_SOAP_API#UserRc(integer_call,_integer_rc)|UserRc]] below).&lt;br /&gt;
&lt;br /&gt;
Any call forwarding configured for the destination will be ignored.  See [[Reference8:SOAP_API#bool_UserReroute.28integer_call.2C_string_cn.2C_string_e164.2C_string_h323.29|UserReroute()]] below.&lt;br /&gt;
&lt;br /&gt;
Note: in 2009, the semantics of UserRedirect has accidentally been changed so that call forwarding will no longer be ignored. From 14r1 Service Release 4, the original behavior can be restored by specifying 999 as &#039;&#039;rc&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====bool UserReroute(integer call, string cn, string e164, string h323)====&lt;br /&gt;
Performs a rerouting of the call.  Call forwardings set for the destination will be obeyed.&lt;br /&gt;
&lt;br /&gt;
Note: rerouting calls on a waiting queue or call broadcast object works only if the &#039;&#039;Execute Operator CFB/CFNR&#039;&#039; or &#039;&#039;Execute Group Member Diversions&#039;&#039; option is turned on.&lt;br /&gt;
&lt;br /&gt;
====integer UserPickup(int user, string cn, integer call, string group, int reg, InfoArray info)====&lt;br /&gt;
Redirects a call such that it appears as a new call at &#039;&#039;user&#039;&#039;. The call to be redirected can be specified by its &#039;&#039;call&#039;&#039; handle.  Alternatively, calls can be picked up by a users &#039;&#039;cn&#039;&#039; or by a &#039;&#039;group&#039;&#039; name.  If all parameters are null, an implicit pickup is done.  The new call handle is returned. Arguments &#039;&#039;reg&#039;&#039; and &#039;&#039;info&#039;&#039; are currently ignored.&lt;br /&gt;
&lt;br /&gt;
====UserClear(integer call, integer cause, InfoArray info)====&lt;br /&gt;
Disconnects the &#039;&#039;call&#039;&#039; providing &#039;&#039;cause&#039;&#039; as disconnect reason. For example the cause code &#039;&#039;26 non-selected user clearing&#039;&#039; could be used to disconnect the call immediately on local phone, so no disconnect tone is played.&lt;br /&gt;
&lt;br /&gt;
Cause is coded as a 7bit integer according to the table found in [[Reference:ISDN Cause Codes]].&lt;br /&gt;
Argument &#039;&#039;info&#039;&#039; is currently ignored.&lt;br /&gt;
&lt;br /&gt;
====UserCtComplete(integer call, string e164, string h323)====&lt;br /&gt;
&lt;br /&gt;
Sends a notification to the device &#039;&#039;call&#039;&#039; is active on that the remote peer has changed to &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039;.   This resembles the notification a device may receive if its remote peer transfers the call to the new destination.  The device may update its display and/or call data accordingly.  This call is often used to force the devices (i.e. telephones) display to show application specific data.&lt;br /&gt;
&lt;br /&gt;
====UserHold(integer call, bool remote)====&lt;br /&gt;
Sets the call on hold.  The device may or may not display the hold status.  In any case, the media channel is disconnected until a UserRetrieve is called.&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;V8 hotfix23&#039;&#039; an additional parameter &#039;&#039;&#039;remote&#039;&#039;&#039; was added. If set to &#039;&#039;&#039;true&#039;&#039;&#039;, &#039;&#039;&#039;remote&#039;&#039;&#039; will force to play MOH only to remote user (who is being held), set to &#039;&#039;&#039;false&#039;&#039;&#039; maintains the default behaviour (MOH played on remote user and a dialing tone to local user (depending on the pbx firmware, versions prior to v11r2 will play music on hold)). To use this parameter the recent WSDL 8.00 file must be retrieved.&lt;br /&gt;
&lt;br /&gt;
====UserRetrieve(integer call)====&lt;br /&gt;
Retrieves the &#039;&#039;call&#039;&#039; on hold.  The device may or may not display the new status.  In any case, the media channel is reconnected.&lt;br /&gt;
&lt;br /&gt;
====integer UserPark(integer call, string cn, integer position)====&lt;br /&gt;
Parks the call at the PBX object &#039;&#039;&#039;cn&#039;&#039;&#039; and local user on postion &#039;&#039;&#039;position&#039;&#039;&#039;. A position of -1 means any position is allowed. &amp;lt;!-- The parked call will show up as new call at the user in &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records returned by &#039;&#039;&#039;Poll()&#039;&#039;&#039; if the &#039;&#039;&#039;xfer&#039;&#039;&#039; flag of the corresponding &#039;&#039;&#039;UserInitialize()&#039;&#039;&#039; call has been set to true. - no, not ture - ckl -- --&amp;gt;The return value is the handle of the new call.&lt;br /&gt;
&lt;br /&gt;
To unpark calls, use the returned call handle with the &#039;&#039;&#039;UserPickup()&#039;&#039;&#039; function.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;cn&#039;&#039;&#039; argument can be used to identify another object, where the call shall be parked to.&lt;br /&gt;
&lt;br /&gt;
====UserDTMF(integer call, bool recv, string dtmf)====&lt;br /&gt;
Sends DTMF digits on behalf of the user. If &#039;&#039;&#039;recv&#039;&#039;&#039; is set to &#039;&#039;true&#039;&#039; the DTMF is sent to the local user.&lt;br /&gt;
&lt;br /&gt;
====UserUUI(integer call, bool recv, string uui)====&lt;br /&gt;
Sends User-User_information on behalf of the user. If &#039;&#039;&#039;recv&#039;&#039;&#039; is set to &#039;&#039;true&#039;&#039; the uui is sent to the local user.&lt;br /&gt;
&lt;br /&gt;
====UserInfo(integer call, bool recv, string cdpn, string key, string dsp)====&lt;br /&gt;
Sends INFO message on behalf of the user. If &#039;&#039;&#039;recv&#039;&#039;&#039; is set to &#039;&#039;true&#039;&#039; the INFO message is sent to the local user. This function can be used to send overlap dialing information.&lt;br /&gt;
&lt;br /&gt;
====UserRc(integer call, integer rc)====&lt;br /&gt;
Sends remote control facility to an innovaphone IP phone. It will be ignored by 3rd-party endpoints.&lt;br /&gt;
&lt;br /&gt;
A remote control facility can be sent to an innovaphone IP phone to activate additional call handling on the device.&lt;br /&gt;
&lt;br /&gt;
The current set of remote control facility function codes actually depends on the firmware used on the telephone, not the WSDL version used for SOAP.  The current set is documented in [[Reference:Remote Control Facility]].&lt;br /&gt;
&lt;br /&gt;
This function can be used for example to establish a three-party conference on an innovaphone IP phone. For this use the function UserRc on an active call using the &#039;&#039;&#039;rc&#039;&#039;&#039; value 4, while a second call is on hold.  See also the &#039;&#039;rc&#039;&#039; argument to [[#integer_UserCall.28integer_user.2C_string_cn.2C_string_e164.2C_string_h323.2C_int_reg.2C_InfoArray_info.2C_int_rc.2C_string_srce164.29|UserCall()]].&lt;br /&gt;
&lt;br /&gt;
===Messaging===&lt;br /&gt;
&lt;br /&gt;
====integer UserMessage(integer user, string e164, string h323, string msg, string src_e164, string src_h323 )====&lt;br /&gt;
Sends an message from the &#039;&#039;&#039;user&#039;&#039;&#039; (which is a handle obtained by a call to &#039;&#039;&#039;UserInitialize&#039;&#039;&#039;) to the destination described by &#039;&#039;e164&#039;&#039; and &#039;&#039;h323&#039;&#039;.  The parameters &#039;&#039;src_e164&#039;&#039; and &#039;&#039;src_h323&#039;&#039; may be used to override the calling party&#039;s information, in order to present a different callback information to the recipient of the message. Returns a handle to the call (0 on failure), which can be used to track the delivery of the message. A event of type &#039;msg-sent&#039; indicates the delivery of the message.&lt;br /&gt;
&lt;br /&gt;
===Status Retrieval===&lt;br /&gt;
&lt;br /&gt;
Instead of monitoring calls using the &#039;&#039;Poll&#039;&#039; mechanics, there are some functions to retrieve the current at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
====CallInfo[] Calls(integer session, string user)====&lt;br /&gt;
Returns an array of &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records for the calls currently active at the registration defined by &#039;&#039;user&#039;&#039;.  Please note that this function may be called without having called &#039;&#039;&#039;UserInitialize ()&#039;&#039;&#039; before.  Thus, the call handle information in the &#039;&#039;&#039;CallInfo&#039;&#039;&#039; records returned is meaningless.&lt;br /&gt;
&lt;br /&gt;
====UserInfo[] FindUser(string v501, string v700, string v800, string vx1000, string cn, string h323, string e164, integer count, integer next, boolean nohide)====&lt;br /&gt;
Returns an array of at most &#039;&#039;count&#039;&#039; &#039;&#039;&#039;UserInfo&#039;&#039;&#039; records for the users matching &#039;&#039;cn&#039;&#039;, &#039;&#039;h323&#039;&#039; or &#039;&#039;e164&#039;&#039;. Only one of &#039;&#039;cn&#039;&#039;, &#039;&#039;h323&#039;&#039; and &#039;&#039;e164&#039;&#039; may be specified, except that &#039;&#039;e164&#039;&#039; and &#039;&#039;cn&#039;&#039; may be specified. In this case the number in &#039;&#039;e164&#039;&#039; is interpreted in the Node of the user specified with &#039;&#039;cn&#039;&#039;. The search string will be used as a starting point into the alphabetically sorted list of objects, that is, a search for “&#039;&#039;&#039;A&#039;&#039;&#039;” will yield entries starting with “&#039;&#039;&#039;A&#039;&#039;&#039;” but also – depending on &#039;&#039;count&#039;&#039; – the following entries. Neither search string may be empty. &#039;&#039;v501&#039;&#039;, &#039;&#039;v700&#039;&#039;, &#039;&#039;v800&#039;&#039; and &#039;&#039;vx1000&#039;&#039; must be set to a non-empty value. In case &#039;&#039;cn&#039;&#039; is set to the empty value, &#039;&#039;&#039;FindUser&#039;&#039;&#039; returns results starting from the first object in the PBX.&lt;br /&gt;
&lt;br /&gt;
To call &#039;&#039;&#039;FindUser&#039;&#039;&#039;, no session is required, however, you need a valid HTTP authentication.&lt;br /&gt;
&lt;br /&gt;
Be aware that large values for &#039;&#039;count&#039;&#039; may fail and even crash the PBX.  If you need to retrieve the whole user list, you should be using 20 as  &#039;&#039;count&#039;&#039;, provide the last &#039;&#039;cn&#039;&#039; retrieved as new start cn and loop until &#039;&#039;&#039;FindUser&#039;&#039;&#039; returns no more results, passing &#039;&#039;&#039;true&#039;&#039;&#039; as  value for &#039;&#039;next&#039;&#039; for all but the first calls.&lt;br /&gt;
&lt;br /&gt;
If the parameter &#039;&#039;nohide&#039;&#039; is true, all objects regardless if marked as &#039;&#039;Hide from LDAP&#039;&#039; or not are returned by the &#039;&#039;&#039;FindUser&#039;&#039;&#039; function.&lt;br /&gt;
&lt;br /&gt;
====bool UserFindDestination(integer user, string e164, string h323, out UserInfo user)====&lt;br /&gt;
This function checks if a destination can be reached from a given user by either a given number or a given name. &#039;&#039;user&#039;&#039; is the user handle from which PBX user the searching is started through all PBX nodes up and down. &#039;&#039;e164&#039;&#039; is the number, &#039;&#039;h323&#039;&#039; is a name.&lt;br /&gt;
&lt;br /&gt;
The function returns &#039;&#039;&#039;true&#039;&#039;&#039;, if the number or name is incomplete, otherwise &#039;&#039;&#039;false&#039;&#039;&#039;. If a destination is found, a &#039;&#039;&#039;UserInfo&#039;&#039;&#039; &#039;&#039;user&#039;&#039; is delivered.&lt;br /&gt;
&lt;br /&gt;
No session is required to call &#039;&#039;&#039;UserFindDestination&#039;&#039;&#039;, however, you need a valid HTTP authentication.&lt;br /&gt;
&lt;br /&gt;
====string License(integer session, string name)====&lt;br /&gt;
This function is for internal use only.&lt;br /&gt;
&lt;br /&gt;
====string LocationUrl(string v501, string v700, string v800, string vx1000, string location, bool tls)====&lt;br /&gt;
Returns a string with the HTTP URL for the PBX named location to which a SOAP session can be created. Typically, &#039;&#039;location&#039;&#039; is retrieved from the &#039;&#039;vals&#039;&#039; element of an &#039;&#039;&#039;Info&#039;&#039;&#039; record with &#039;&#039;type&#039;&#039; &#039;&#039;&#039;loc&#039;&#039;&#039; in an &#039;&#039;&#039;UserInfo&#039;&#039;&#039; record.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;location&#039;&#039; needs to be specified as the &#039;&#039;&#039;h323&#039;&#039;&#039; attributes value of the PBX node &#039;&#039;&#039;UserInfo&#039;&#039;&#039; data you are interested in.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;tls&#039;&#039; is set to &#039;&#039;&#039;true&#039;&#039;&#039;, a HTTPS URL is returned.&lt;br /&gt;
&lt;br /&gt;
====string UserLocalNum(int user, string num)====&lt;br /&gt;
Converts a given number &#039;&#039;&#039;num&#039;&#039;&#039; into a number diallable from the location of a specific &#039;&#039;&#039;user&#039;&#039;&#039;. Useful in inter-node scenarios where a destination node number and -extension are known, but the required escape prefix digits are unknown.&lt;br /&gt;
;user:The id of the specified user&lt;br /&gt;
;num:The number to be localized into the spefified user&#039;s location&lt;br /&gt;
;result:The localized number, including escape prefixes&lt;br /&gt;
&lt;br /&gt;
===Administration===&lt;br /&gt;
The SOAP interface can be used for administrational purposes also.  This is done via the Admin call.  All kinds of PBX objects can be created, read or modified. &lt;br /&gt;
&lt;br /&gt;
====string Admin(string xml)====&lt;br /&gt;
&lt;br /&gt;
Sends the administrational command &#039;&#039;xml&#039;&#039; to the PBX.  The command is executed and any result is returned.  &lt;br /&gt;
&lt;br /&gt;
This command allows you to query and modify the PBX object configuration (e.g. to query and set a users call forwarding).  The scope and format of the commands valid for &#039;&#039;xml&#039;&#039; is beyond the scope of this document, however, there is a [[Howto:Using the SOAP Admin Function | separate article on that ]].&lt;br /&gt;
&lt;br /&gt;
To call &#039;&#039;&#039;Admin&#039;&#039;&#039;, no session is required.  However, you must be authenticated as an admin user on the underlying HTTP layer.&lt;br /&gt;
&lt;br /&gt;
[[Howto:Using the SOAP Admin Function]]&lt;br /&gt;
&lt;br /&gt;
==Typical design of a PBX SOAP Application==&lt;br /&gt;
Please refer to the [[Reference:SOAP_API_%28pbx501.wsdl%29#Typical_design_of_a_PBX_SOAP_Application|pbx501.wsdl]] article for a discussion of the typical design of a SOAP application.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx10_00.wsdl Version10-wsdl].&lt;br /&gt;
&lt;br /&gt;
Applications based on this wsdl will work with V10 PBX firmware (and up) only. &lt;br /&gt;
&lt;br /&gt;
Applications written to the previous pbx501.wsdl, pbx700.wsdl and pbx900.wsdl will continue to work with V10 firmware. &lt;br /&gt;
&lt;br /&gt;
For your reference the old version files are still available:&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx501.wsdl Version5-wsdl]&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx700.wsdl Version7-wsdl]&lt;br /&gt;
* [http://www.innovaphone.com/wsdl/pbx900.wsdl Version9-wsdl]&lt;br /&gt;
&lt;br /&gt;
==Known Problems==&lt;br /&gt;
Please read [[Howto:Authentication in the SOAP interface]] in case you have problems to authenticate SOAP access.&lt;br /&gt;
&lt;br /&gt;
==System Requirements==&lt;br /&gt;
The PBX SOAP API requires a working PBX.&lt;br /&gt;
&lt;br /&gt;
To work with the PBX API in this version, you must run at least version 7.00 software on your PBX.  Also, you must run at least version 5 software on the phones.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
There is no specific installation required, as the PBX API is integral part of the PBX (although licenses are required to operate the PBX).&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
To prepare an PBX for PBX API testing&lt;br /&gt;
*setup a separate PBX&lt;br /&gt;
*install current firmware (at least 8.00)&lt;br /&gt;
*configure the PBX as usually&lt;br /&gt;
*add an user object called &#039;&#039;&#039;API&#039;&#039;&#039; , define a &#039;&#039;password&#039;&#039; for this object&lt;br /&gt;
*create a new group (e.g. called &#039;&#039;&#039;all users&#039;&#039;&#039;), by adding a group tag to &#039;&#039;&#039;API&#039;&#039;&#039;, make it &#039;&#039;active&#039;&#039;&lt;br /&gt;
*add a similar group tag to all other test users&lt;br /&gt;
*call &#039;&#039;&#039;Initialize()&#039;&#039;&#039; and use &#039;&#039;&#039;API&#039;&#039;&#039; as user and &#039;&#039;&#039;API&#039;&#039;&#039; and its &#039;&#039;password&#039;&#039; as http credentials&lt;br /&gt;
&lt;br /&gt;
==Known Issues==&lt;br /&gt;
We have reports that the PBX wsdl is incompatible to some of the contemporary SOAP platforms available in the market.  Most notably, Silverlight and Java seem to be affected.  These problems are fixed in the v11 implementation of the PBX SOAP interface &#039;&#039;pbx11_00.wsdl&#039;&#039; (available at [http://www.innovaphone.com/wsdl/pbx11_00.wsdl www.innovaphone.com/wsdl/pbx11_00.wsdl ]).&lt;br /&gt;
&lt;br /&gt;
Note: This wdsl file is not available directly from the PBX (e.g. at &amp;lt;code&amp;gt;http://xx.xx.xx.xx/pbx11_00.wsdl&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
However, we have had indications that for Java, solutions are possible based on Apache Axis 1.4, Netbeans 6.8 or JAX-RPC.&lt;br /&gt;
&lt;br /&gt;
The PBX does not expect the SOAP client to disconnect the session right after a UserCall.  If this is the case (e.g. in a script which merely creates a call on behalf of a user and then terminates), it might happen that the outgoing call from the device will not be created correctly (a matter of timing).  In this case, just wait for one second.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
:[[Howto:Authentication in the SOAP interface]]&lt;br /&gt;
:[[Howto:Clear a call completely with SOAP using UserClear]]&lt;br /&gt;
:[[Howto:PBX SOAP Api C sample code]]&lt;br /&gt;
:[[Howto:SOAP Api VisualBasic.Net Sample Code]]&lt;br /&gt;
:[[Support:TAPI or other SOAP Application fails to function properly if PBX users have special characters in their long or short user name]]&lt;br /&gt;
:[[Howto:How to monitor configuration changes in the SOAP interface ]]&lt;br /&gt;
:[[Howto:SOAP with PHP5 ]]&lt;br /&gt;
:[[Howto:SOAP API Java Sample Code ]]&lt;br /&gt;
:[[Howto:Using the SOAP Admin Function]]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.innovaphone.com/index.php?search=soap Search for more articles about SOAP]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- keywords: sopa soap --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
</feed>