<?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-07-28T17:27:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference16r1:Concept_myApps&amp;diff=80051</id>
		<title>Reference16r1:Concept myApps</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference16r1:Concept_myApps&amp;diff=80051"/>
		<updated>2026-06-29T09:01:53Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Storage and format */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|myApps]]&lt;br /&gt;
[[Category:Concept_myApps]]&lt;br /&gt;
==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
* innovaphone PBX from version 16r1&lt;br /&gt;
= Overview =&lt;br /&gt;
innovaphone myApps is the client software for innovaphone users and administrators. The base functionality is provided by a web application that is loaded from the PBX. Additionally there are [[{{NAMESPACE}}:Concept_myApps_platform_services|installable versions for Windows, Android, macOS and iOS]] that come with an integrated browser and implement adaptations to the local operating system.&lt;br /&gt;
&lt;br /&gt;
The purpose of myApps is to organize and run apps. All productive functionality is provided by additional apps that run inside myApps.&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== Web version ===&lt;br /&gt;
For opening myApps in the web browser you need the most recent version of one of the following browsers:&lt;br /&gt;
* Chrome&lt;br /&gt;
* Firefox&lt;br /&gt;
* Safari&lt;br /&gt;
* or Edge&lt;br /&gt;
The following browser features are required and must not be disabled:&lt;br /&gt;
* JavaScript&lt;br /&gt;
* HTML5 Local Storage&lt;br /&gt;
&lt;br /&gt;
=== Native versions ===&lt;br /&gt;
myApps can also run as native executables on Windows (myApps for Windows), iOS (myApps for iOS), macOS (myApps for macOS) and Android (myApps for Android).  In this case, myApps platform services are available and provide additional features. The myApps Web version then runs in a web view window embedded in this native client.  See [[{{NAMESPACE}}:Concept myApps platform services|myApps platform services overview]] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Licenses ===&lt;br /&gt;
* No license needed for myApps itself&lt;br /&gt;
* Apps might require licenses&lt;br /&gt;
&lt;br /&gt;
=== Account ===&lt;br /&gt;
* A user account (user object) on the PBX is needed in order to use myApps.&lt;br /&gt;
&lt;br /&gt;
=== Reverse proxy ===&lt;br /&gt;
For access from the public internet, the reverse proxy must be configured to allow access to the following paths on the PBX.&lt;br /&gt;
; /PBX0/APPCLIENT/appclient.htm&lt;br /&gt;
: The myApps client itself&lt;br /&gt;
; /PBX0/session&lt;br /&gt;
: Needed for two-factor authentication using email&lt;br /&gt;
; /PBX0/APPS&lt;br /&gt;
: Needed for apps loaded from the PBX (e.g. softphone and chat) and for apps that use PBX APIs&lt;br /&gt;
; /OAUTH2/oauth2_login&lt;br /&gt;
: Needed for OAuth2 authentication&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
myApps comes with the following features:&lt;br /&gt;
* User login including two-factor authentication.&lt;br /&gt;
* Display and set the own presence (on the home screen and when the focus app is shown).&lt;br /&gt;
* List of all available apps including search functionality.&lt;br /&gt;
* Running apps (inside an iframe).&lt;br /&gt;
* Apps can be pinned to the main window. Pinned apps are always running and can&#039;t be closed. They are also started automatically when the myApps client is loaded.&lt;br /&gt;
* The &amp;quot;app focus&amp;quot; can be used to define a default app for the user. It is started and shown automatically when myApps is loaded. When closing other apps the app is shown instead of the home screen.&lt;br /&gt;
* Detaching apps in myApps for Windows and myApps for macOS. Detached apps are opened in a separate window.&lt;br /&gt;
* Home screen with user-selected apps and app items that can be organized in collapsible groups.&lt;br /&gt;
* Push notifications sent by app services.&lt;br /&gt;
* List of all myApps-Logins. Unused or suspicious sessions can be logged out remotely.&lt;br /&gt;
* Color scheme selection (light, dark).&lt;br /&gt;
* Configuration of standard apps for certain functions (like phone calls or chat).&lt;br /&gt;
* Link to account specific settings provided by a separate app (profile).&lt;br /&gt;
* Dialogue guidance in following languages: Català, Ceština, Deutsch, English, Español, Euskara, Français, Italiano, Nederlands, Polski, Português, Româna, ??????? ????, Slovenšcina, Türkçe&lt;br /&gt;
* Screen reader compatiblity and keyboard control &lt;br /&gt;
* Interactive, clickable onboarding tour to guide users through the client&#039;s structure and key features.&lt;br /&gt;
&lt;br /&gt;
All other functionality is provided by apps. For example phone calls require a phone app. Chats require a chat app.&lt;br /&gt;
&lt;br /&gt;
= Details =&lt;br /&gt;
== Connecting to the PBX ==&lt;br /&gt;
The myApps web application is loaded from the PBX. The corresponding URL for opening myApps in a browser is&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm&lt;br /&gt;
The installable versions ask for the &amp;quot;server name&amp;quot; on the first startup. Enter the host name of the PBX to proceed to the login screen.&lt;br /&gt;
You can change the server afterwards by logging out and clicking the &amp;quot;Change server&amp;quot; link on the login screen.&lt;br /&gt;
&lt;br /&gt;
== Supported URL Parameters ==&lt;br /&gt;
Some parameters can be specified with the URL in both the query string or fragment identifier. Those parameters are intended for internal use in the myApps launcher and automated testing. However they could be useful for special applications.&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm?lang=de&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm#lang=it&lt;br /&gt;
&lt;br /&gt;
Supported parameters:&lt;br /&gt;
&lt;br /&gt;
;lang:The two-letter code of the desired myApps language (&amp;quot;en&amp;quot;, &amp;quot;it&amp;quot;, &amp;quot;fr&amp;quot;, &amp;quot;de&amp;quot;, ...)&lt;br /&gt;
;scheme:The color scheme (&amp;quot;light&amp;quot;, &amp;quot;dark&amp;quot;).&lt;br /&gt;
;app:An app link to be started (e.g. &amp;quot;chat&amp;quot;).&lt;br /&gt;
;usr:The user name for login. Note that this will create a new permanent session at the user object. Should only be used in the fragment identifier.&lt;br /&gt;
;pwd:The password for login. Note that this will create a new permanent session at the user object. Should only be used in the fragment identifier.&lt;br /&gt;
;inactiveTimeout:Overrides the general timeout for the &amp;quot;auto appear offline&amp;quot; feature in browsers. Sets a timeout in milliseconds that shall be used before the user goes offline. Setting it to 0 disables the &amp;quot;auto appear offline&amp;quot;. Browser version only. Available from 13r2 SR11.&lt;br /&gt;
;phys: User defined physical location for Softphone Apps&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm?lang=de&amp;amp;scheme=light&amp;amp;app=chat#usr=john.doe&amp;amp;pwd=secret&lt;br /&gt;
&lt;br /&gt;
== Redirect to the user&#039;s PBX==&lt;br /&gt;
If the logged-in user is not on the current PBX, myApps will be redirected to the user&#039;s PBX (as configured in the pbx attribute of the user). The following rules apply:&lt;br /&gt;
===Master-Slave scenario===&lt;br /&gt;
* Slave PBXes redirect to the master PBX.&lt;br /&gt;
* The master PBX redirects to the correct slave PBX.&lt;br /&gt;
&lt;br /&gt;
Note: If the current PBX has no registration to the redirect target PBX but knows the user, it will act as a standby and keep the connection, until the registration is up gain.&lt;br /&gt;
&lt;br /&gt;
===Standby scenario===&lt;br /&gt;
See [[Reference16r1:Concept_myApps_Redundancy]]&lt;br /&gt;
&lt;br /&gt;
== Deployment of settings ==&lt;br /&gt;
The administrator can deploy some general settings to be used as a default by all myApps clients. This can be done in the admin UI on page PBX/Config/myApps. See [[Reference13r1:PBX/Config/myApps]] for details.&lt;br /&gt;
&lt;br /&gt;
== Authentication and security ==&lt;br /&gt;
For using myApps you need an account (user object) on the pbx with a password. For logging-in you need to enter the username (SIP-URI) or email address and the password.&lt;br /&gt;
&lt;br /&gt;
=== Permanent sessions ===&lt;br /&gt;
On each successful login on a new browser or new device a permanent session is created that is defined by a session id and a session password. Those are stored both in the local storage of the browser and at the user object in the PBX. If the user closes myApps and opens it again, the stored session is used. Only when logging-out the session is deleted in both places and the login screen is shown again.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The user password is never transmitted over the network or permanently stored in the browser.&lt;br /&gt;
* The PBX stores up to 12 persistent sessions per user. When the limit is reached, creating a new session removes the session with the oldest login timestamp.&lt;br /&gt;
&lt;br /&gt;
The user can keep track of all his permanent sessions in the myApps menu under &amp;quot;Account security&amp;quot;. Sessions that are not needed anymore can be deleted here. The corresponding browser or device is logged out on-the-fly.&lt;br /&gt;
&lt;br /&gt;
=== Two-factor authentication ===&lt;br /&gt;
The purpose of two-factor authentication is to maintain an additional level of security that prevents attackers form logging-in even if they compromised a users password. Therefore we strongly recommend to use it.&lt;br /&gt;
&lt;br /&gt;
It can be activated during installation of the PBX or in the admin UI under PBX/Config/Authentication. If activated, the password alone is not sufficient for logging-in but the user must also verify the new session by&lt;br /&gt;
* Confirming it in a dialog displayed on any existing myApps session.&lt;br /&gt;
* Clicking a link that is sent to the email address configured at the user object.&lt;br /&gt;
&lt;br /&gt;
In both cases a security code is displayed that should be compared to the one that is shown on the login screen of the new session. If it is the same the user can be sure that he is confirming his own login but not the possible concurrent login of an attacker.&lt;br /&gt;
&lt;br /&gt;
The email account for sending the verification emails can be configured during installation of the PBX, in the PBX Manager plugin &amp;quot;Email&amp;quot; or in the admin UI under PBX/Config/Authentication.&lt;br /&gt;
&lt;br /&gt;
If a user is notified about a login attempt he did not do, it means that the user password is compromised. The following should be done in such cases:&lt;br /&gt;
* Reject the session (email link or displayed dialog)&lt;br /&gt;
* Inform the administrator&lt;br /&gt;
* Change the user password&lt;br /&gt;
&lt;br /&gt;
=== Using Windows passwords ===&lt;br /&gt;
Instead of using the passwords configured at the user object, the Windows account can be used.&lt;br /&gt;
; OAuth2 (recommended) : See [[Reference16r1:Concept_OAuth2_Windows_Authentication]] for details.&lt;br /&gt;
; NTLM : See [[Reference16r1:Concept_Netlogon_and_myPBX_Windows_Authentication]] for details.&lt;br /&gt;
&lt;br /&gt;
=== Logging out ===&lt;br /&gt;
A logout can be done in the myApps menu at &amp;quot;Account security&amp;quot; / &amp;quot;Current session&amp;quot; (all versions).&lt;br /&gt;
In the browser version there is also separate menu item &amp;quot;Logout&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Resetting passwords ===&lt;br /&gt;
If the user has forgotten the password, he or she can set a new one by clicking the &amp;quot;Forgot password?&amp;quot; link on the login screen and completing an email verification process. This function can be activated or deactivated by the admin by configuring the link at &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Reset Password Page&amp;quot; or - more conveniently - using the PBX manager plugin of the innovaphone Users App that provides the functionality to change the configuration by pressing OK and then Enable or Disable various options like the password reset option.&lt;br /&gt;
&lt;br /&gt;
=== Brute force protection ===&lt;br /&gt;
myApps does several things to mitigate and detect brute force attacks on user accounts.&lt;br /&gt;
* After an attempt to log-in using a wrong password, the corresponding user account is locked for 0, 0, 8, 16, 32, 64, 128, 256, 512, 1024 seconds. In that time no more user logins with that account are possible. Logins using sessions that have been established before, are not affected.&lt;br /&gt;
* If there is a login attempt with a wrong password, the user is notified inside all existing myApps sessions. There the user can tell that it was him in order to reset the counters and unlock the account.&lt;br /&gt;
* From the third login attempt with a wrong password, events are generated to notify the administrator.&lt;br /&gt;
** Event Code 0x0002000b&lt;br /&gt;
** Severity Major&lt;br /&gt;
** Example Text: 3 rejected login attempts for user johndoe from 192.168.0.53&lt;br /&gt;
== Syslog ==&lt;br /&gt;
The log flag &#039;&#039;&#039;Maintenance / Diagnostics / Logging / myApps&#039;&#039;&#039; can be used to write information about the myApps connections to the syslog.&lt;br /&gt;
=== Example ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
A               B              C D        E   F               G                    H                                I                    J&lt;br /&gt;
&lt;br /&gt;
20250113-165252 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   -                    -                                -                    Connect&lt;br /&gt;
20250113-165256 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      -                                -                    Login FAILED &amp;quot;admin&amp;quot; (Authentication failed)&lt;br /&gt;
20250113-165301 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      -                                -                    Login FAILED &amp;quot;admin&amp;quot; (Authentication failed)&lt;br /&gt;
20250113-165303 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                Login OK &amp;quot;admin&amp;quot;&lt;br /&gt;
20250113-165308 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                AppGetLogin OK &amp;quot;chat&amp;quot;&lt;br /&gt;
20250113-165311 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                AppGetLogin OK &amp;quot;calllist&amp;quot;&lt;br /&gt;
20250113-165318 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                Logout OK&lt;br /&gt;
20250113-165914 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   -                    -                                -                    Disconnect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logging format ===&lt;br /&gt;
;A:Date and time&lt;br /&gt;
;B:PBX module name&lt;br /&gt;
;C:Serial number of connection object&lt;br /&gt;
;D:Memory address of connection object&lt;br /&gt;
;E:Transport protocol of the connection&lt;br /&gt;
;F:IP address of the client&lt;br /&gt;
;G:User agent of the client&lt;br /&gt;
;H:Session ID&lt;br /&gt;
;I:User name&lt;br /&gt;
;J:Action&lt;br /&gt;
&lt;br /&gt;
=== Logged actions ===&lt;br /&gt;
;Connect: A new connection has been established.&lt;br /&gt;
;Disconnect: The connection was closed.&lt;br /&gt;
;Login FAILED &amp;quot;username&amp;quot; (error): A user login failed.&lt;br /&gt;
;Login FAILED &amp;quot;sessionid&amp;quot; (error): A session login for a resumed session failed.&lt;br /&gt;
;Login AUTHORIZE &amp;quot;username&amp;quot;: The user was asked to authorize a login over another channel (2FA).&lt;br /&gt;
;Login REDIRECT &amp;quot;username&amp;quot;: Redirect to another PBX.&lt;br /&gt;
;Login REDIRECT &amp;quot;sessionid&amp;quot;: Redirect to another PBX.&lt;br /&gt;
;Login OK &amp;quot;username&amp;quot;: A user login was successful.&lt;br /&gt;
;Login OK &amp;quot;sessionid&amp;quot;: A session login was successful for a resumed session.&lt;br /&gt;
;Logout OK: The user has logged-out and the session is deleted.&lt;br /&gt;
;StandbyBack: Redirected from the standby PBX to the actual PBX.&lt;br /&gt;
;AuthorizeSession OK &amp;quot;sessionid&amp;quot;: The user authorized a login for another session (2FA).&lt;br /&gt;
;AuthorizeSession FAILED &amp;quot;sessionid&amp;quot;: The user rejected a login for another session (2FA).&lt;br /&gt;
;ResetInvalidLogins OK&amp;quot;: The user told that a failed login attempt was done by himself (2FA).&lt;br /&gt;
;DeleteSession OK &amp;quot;sessionid&amp;quot;: The user deleted the access for another session.&lt;br /&gt;
;DeleteSession FAILED &amp;quot;sessionid&amp;quot;: Deleting another session failed.&lt;br /&gt;
;AppGetLogin OK &amp;quot;appname&amp;quot;: Access to an app was granted.&lt;br /&gt;
;AppGetLogin FAILED &amp;quot;appname&amp;quot;: Access to an app was denied.&lt;br /&gt;
&lt;br /&gt;
== Apps ==&lt;br /&gt;
=== App runtime ===&lt;br /&gt;
All apps are web applications that consist of&lt;br /&gt;
* An HTML page&lt;br /&gt;
* Javascript files&lt;br /&gt;
* An app icon&lt;br /&gt;
myApps starts apps by opening the HTML page in an iframe. All communication between the apps and the myApps client is done using HTML5 window messaging. For example if the user changes the color scheme, myApps sends a window message to all open apps, so they can also switch colors.&lt;br /&gt;
&lt;br /&gt;
=== App objects ===&lt;br /&gt;
All apps that appear in the myApps client must be configured in the PBX. For apps that are loaded from the innovaphone App Platform or any other external server an App object is used that contains all the needed parameters.&lt;br /&gt;
&lt;br /&gt;
;Name:An ID that must be unique per PBX domain. The ID is only used internally to reference that app and is not shown to the user.&lt;br /&gt;
;Long Name:The display name of the app.&lt;br /&gt;
;Password:The shared secret between the app instance and the PBX. It corresponds to the password configured at the app instance. This secret is used when a user is authenticated against the app.&lt;br /&gt;
;URL:The base URL of the app. myApps appends .htm to get the URL of the HTML page and .png to get the URL of the app icon.&lt;br /&gt;
;Icon URL:If configured this URL is used for the app icon, instead of deriving it from the URL.&lt;br /&gt;
;Hidden:Some apps don&#039;t have a user interface. Their only purpose is to provide functionality (Client APIs) for myApps or other apps using window messaging. They have the &amp;quot;Hidden&amp;quot; flag checked at the app object and are not shown to the user.&lt;br /&gt;
&lt;br /&gt;
;Plain website&lt;br /&gt;
:Checked if the HTML page is not an actual app that requires login and processes the window messages used for apps, but if it is just a regular website. This flag can be used to integrate websites into myApps via iframe.&lt;br /&gt;
:Please note that this feature is meant for having a possibility to create simple content pages and integrate them into myApps without the need to develop a full-fledged app.&lt;br /&gt;
:&#039;&#039;Note: Most existing websites cannot be integrated in this way because they do not allow you to load them into an iframe. Check [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing Cross-origin resource sharing] and [https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1 Cookies SameSite] settings with the owner of the website. If you miss some configuration, you should see an error message in your browser console.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;Websocket:Some apps need a websocket connection from the PBX. This can be used to exchange additional information or to use APIs on the PBX. Those apps need the Websocket flag checked.&lt;br /&gt;
&lt;br /&gt;
Some other PBX objects also provide apps, like the Boolean object.&lt;br /&gt;
&lt;br /&gt;
=== App permissions ===&lt;br /&gt;
In order to use an app the administrator must grant the permission to the user. This can be done using templates of at the specific user object (&amp;quot;Edit Object&amp;quot;/&amp;quot;Apps&amp;quot;). The same setting can be done in the PBX manager plugin &amp;quot;Templates&amp;quot;. The user will find the apps he has access to in the &amp;quot;All apps&amp;quot; view in myApps.&lt;br /&gt;
&lt;br /&gt;
==== Special case: phone apps ====&lt;br /&gt;
If a user has access to the &amp;quot;phone&amp;quot; or &amp;quot;softphone&amp;quot; app, it will not automatically appear in &amp;quot;All apps&amp;quot;. Those apps need to be assigned to a device at the user object and will then be used for the registration on those devices. The admin  can configure the app name at the individual devices in the admin UI. The user can assign the app during provisioning of phones in &amp;quot;Edit profile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Client APIs and default apps ===&lt;br /&gt;
Some apps provide APIs that allow communication with other apps. An app providing an API is called an API provider. Communication is done using HTML5 window messages sent to the myApps client that dispatches them to the right app.&lt;br /&gt;
&lt;br /&gt;
If there are many providers for the same API, the app can send messages to specific provider, to all providers or let the user decide. In the latter case, myApps displays a selection dialog to the user. The user can also mark an app as the default app for an API that will then be used without asking again.&lt;br /&gt;
&lt;br /&gt;
Additionally the user can configure the standard apps in the myApps menu.&lt;br /&gt;
&lt;br /&gt;
The default apps are stored locally on each browser / device. So the user can have a different setting on each device.&lt;br /&gt;
&lt;br /&gt;
==== Special case: phone API (com.innovaphone.phone) ====&lt;br /&gt;
The phone apps provide a phone API that can be used by other apps to start calls. If a phone app is selected as the default phone app it has the following effects:&lt;br /&gt;
* When dialing a phone number (in a contacts app) the default phone app will be used for the call.&lt;br /&gt;
* On incoming calls the phone app is started and displayed automatically, to handle the call.&lt;br /&gt;
&lt;br /&gt;
If no default phone app is selected on a device&lt;br /&gt;
* The user will be asked what phone app shall be used when dialing (in a contacts app)&lt;br /&gt;
* On incoming calls no phone app will be started&lt;br /&gt;
&lt;br /&gt;
Regardless of the setting, the user can open any phone to start or receive calls.&lt;br /&gt;
&lt;br /&gt;
The standard phone app can be also selected by longpressing the app tile on the home screen.&lt;br /&gt;
&lt;br /&gt;
== Home screen ==&lt;br /&gt;
The home screen contains tiles that represent apps or items from apps - generally speaking links to apps. For example the user can place his phone app next to a contact from a contact app. Those tiles can be organized in named groups that can be collapsed, if they are currently not needed.&lt;br /&gt;
&lt;br /&gt;
The presentation of a tile contains an icon, the name of the app or item and optionally a presence and a badge count provided by the app.&lt;br /&gt;
&lt;br /&gt;
There are two ways for the user to add new items to the home screen:&lt;br /&gt;
* Click the home symbol at an app in the &amp;quot;All apps&amp;quot; view.&lt;br /&gt;
* Click an attach icon at an item inside an app.&lt;br /&gt;
&lt;br /&gt;
Apps can be removed again the same way or by longpressing the tile and clicking &amp;quot;Remove from home&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Storage and format ===&lt;br /&gt;
The home screen is stored at the user object in the PBX and is synchronized over all sessions of the user.&lt;br /&gt;
&lt;br /&gt;
The admin can see and configure it in the admin UI at &amp;quot;Edit User&amp;quot;/&amp;quot;User&amp;quot;/&amp;quot;Home Screen Apps&amp;quot;. It is a comma-separated string of app links.&lt;br /&gt;
&lt;br /&gt;
The string is limited to 8KB. If the limit is reached no more items or groups can be added to the home screen.&lt;br /&gt;
&lt;br /&gt;
Format: Items starting with a colon are groups. Items starting with two colons are collapsed groups.&lt;br /&gt;
&lt;br /&gt;
For example &amp;lt;code&amp;gt;:Apps,chat,users,::Contacts,users?id=jdo#d=John%20Doe&amp;amp;s=jdo&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
corresponds to&lt;br /&gt;
* Apps (group)&lt;br /&gt;
** Chat&lt;br /&gt;
** Users&lt;br /&gt;
* Contacts (collapsed group)&lt;br /&gt;
** &amp;quot;John Doe&amp;quot; from the app &amp;quot;users&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Individual app links are URL-encoded. An App link must not appear twice.&lt;br /&gt;
&lt;br /&gt;
== All apps ==&lt;br /&gt;
This page in myApps shows all apps that the user has access to (see: [[#App permissions|App permissions]]). Apps that are often used can be attached to the home screen.&lt;br /&gt;
&lt;br /&gt;
== App Notifications ==&lt;br /&gt;
From version 14r1 app services can send notifications to users. Those notifications will be transmitted to and displayed by all myApps sessions of the user that have app notifications enabled. Clicking the notification will open the app with optional parameters.&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
Launcher&lt;br /&gt;
* myApps for Windows from version 14r1&lt;br /&gt;
* myApps for macOS from version 14r1&lt;br /&gt;
* myApps Android from version 14r1&lt;br /&gt;
* myApps for iOS from version 14r1&lt;br /&gt;
&lt;br /&gt;
Browser&lt;br /&gt;
* Supported browser with the following features enabled:&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Push_API Push API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API Notifications API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API Service Worker API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Client Client API]&lt;br /&gt;
* myApps opened using https:&lt;br /&gt;
&lt;br /&gt;
PBX&lt;br /&gt;
* Trusted certificate with a valid DNS name. Self-signed certificates don&#039;t work.&lt;br /&gt;
* Push enabled, otherwise notifications will only be sent to connected myApps sesssions.&lt;br /&gt;
&lt;br /&gt;
Reverse Proxy &lt;br /&gt;
* Trusted certificate with a valid DNS name. Self-signed certificates don&#039;t work.&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
* If the feature is supported, the user can enable / disable app notifications in the hamburger menu of the myApps home screen (&amp;quot;App notifications&amp;quot;).&lt;br /&gt;
* The setting is per device. So the user can choose on which devices he or she likes to receive notifications.&lt;br /&gt;
* By default app notifications are enabled in the launcher and disabled in browser sessions.&lt;br /&gt;
* For enabling app notifications in the browser the user needs to grant the permission for Web Notifications.&lt;br /&gt;
&lt;br /&gt;
=== Some examples for apps supporting app notifications ===&lt;br /&gt;
* The Chat App in 14r1 uses app notifications for incoming chat messages.&lt;br /&gt;
* The Working App in 14r1 uses app notifications for warnings.&lt;br /&gt;
&lt;br /&gt;
=== Documentation for app developers ===&lt;br /&gt;
[https://sdk.innovaphone.com/16r1/doc/appwebsocket/PbxApi.htm#AppNotify https://sdk.innovaphone.com/16r1/doc/appwebsocket/PbxApi.htm#AppNotify]&lt;br /&gt;
&lt;br /&gt;
== Accessibility ==&lt;br /&gt;
For information regarding accessibility see following Article: https://wiki.innovaphone.com/index.php?title=Reference:Concept_Accessibility&lt;br /&gt;
&lt;br /&gt;
== Edit profile ==&lt;br /&gt;
An app for managing the user profile can be configured in the admin UI at &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Edit Profile App&amp;quot;. Typically the profile app provided by the innovaphone Users app is used for that. If configured, a menu item &amp;quot;Edit profile&amp;quot; appears in the myApps menu.&lt;br /&gt;
&lt;br /&gt;
== Onboarding ==&lt;br /&gt;
The administrator can configure a web page that shall be displayed as an intro when a user opens myApps for the first time. The user can see the intro again by clicking &amp;quot;Intro&amp;quot; in the hamburger menu of myApps.&lt;br /&gt;
&lt;br /&gt;
Configuration:&lt;br /&gt;
* The URL of the onboarding page can be configured at: PBX / Config / myApps / Onboarding URL. The corresponding command line attribute is &amp;lt;code&amp;gt;PBX0 /onboarding&amp;lt;/code&amp;gt;. The default URL configured during install is: https://www.innovaphone.com/en/services/intro-video.html?embedded=1&lt;br /&gt;
* The information whether a user has already seen the onboarding is stored at the user object or template (User / Onboarding seen). The corresponding LDAP attribute is &amp;lt;code&amp;gt;onboarded&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following parameters are passed to the page using URL parameters:&lt;br /&gt;
;name: &amp;quot;onboarding&amp;quot;&lt;br /&gt;
;title: The title as shown in the hamburger menu of myApps (depending on the e.g. &amp;quot;Intro&amp;quot;)&lt;br /&gt;
;scheme:The color scheme (&amp;quot;light&amp;quot; or &amp;quot;dark&amp;quot;)&lt;br /&gt;
;size:The size setting of the home screen items (&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot; or &amp;quot;2&amp;quot;)&lt;br /&gt;
;lang: The myApps language (e.g. &amp;quot;de&amp;quot; or &amp;quot;en&amp;quot;)&lt;br /&gt;
;ver: The version of the PBX (e.g. &amp;quot;16r1&amp;quot;)&lt;br /&gt;
;build: The build of the PBX (e.g. &amp;quot;1510335)&lt;br /&gt;
&lt;br /&gt;
Requirements for the configured page:&lt;br /&gt;
* Must work inside an IFrame.&lt;br /&gt;
* Should follow the language given in the URL parameters, defaulting to &amp;quot;en&amp;quot; if no contents are available for the language.&lt;br /&gt;
* Should follow the collor scheme (&amp;quot;dark&amp;quot; or &amp;quot;light&amp;quot;) given in the URL parameters. &lt;br /&gt;
* Must be responsive to work in different orientations (landscape or portrait) and on different screen sizes (Desktop and Smartphone).&lt;br /&gt;
* Must reserve a space (width 306px, height 102px) for an overlay button that is displayed by myApps in the bottom right corner.&lt;br /&gt;
&lt;br /&gt;
== Tutorials app ==&lt;br /&gt;
The administrator can define an app providing tutorials or other help for end users. That app will appear in the hamburger menu of myApps as &amp;quot;Tutorials&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Requirements:&lt;br /&gt;
* Create an app object pointing to the corresponding web page (eg. https://www.innovaphone.com/myapps/tutorial.htm) via the Adv.GUI, PBX, Objects, create new App Object with a name (eg. Tutorials)&lt;br /&gt;
* Give users access to that app, preferably using templates (eg. Conf Users).&lt;br /&gt;
* Configure the app name in the admin UI &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Tutorial App&amp;quot; with the previous created name (eg. Tutorials).&lt;br /&gt;
&lt;br /&gt;
Note: This configuration is synchronized with the client when the connection is established. So a restart of myApps is needed for the tutorials app to appear in the hamburger menu.&lt;br /&gt;
&lt;br /&gt;
When installing a new PBX, a tutorial app provided by innovaphone is configured by default. It points to https://www.innovaphone.com/myapps/tutorial.htm and shows videos about the usage of myApps.&lt;br /&gt;
&lt;br /&gt;
== Privacy and Datastorage ==&lt;br /&gt;
&lt;br /&gt;
myApps will store the following data on your local device:&lt;br /&gt;
&lt;br /&gt;
* appclient-username / appclient-password&lt;br /&gt;
: Auth token from the user session on this device (This is not the password itself, only a random token).&lt;br /&gt;
* appclient-model&lt;br /&gt;
: Offline-files from myApps which contains the personal user data (eg. Home screen configuration and Push tokens).&lt;br /&gt;
* appclient-config&lt;br /&gt;
: URLs and credentials for local services (credentials will be new generated randomly on every startup)&lt;br /&gt;
* appclient-usr-XXXXXXXXXXXXXXXXXXX&lt;br /&gt;
: anonymized environment settings of all historical user sessions (eg. theme, element size of home screen elements, language)&lt;br /&gt;
&lt;br /&gt;
Additionally, it is allowed to every App to create own offline files or create local settings which will be stored also.&lt;br /&gt;
&lt;br /&gt;
The Chromium Cache and DOM Storage (myApps for Windows) will be stored in &amp;lt;code&amp;gt;%appdata%\innovaphone\myApps\chromium\cache&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Idle Bandwidth =&lt;br /&gt;
== myApps ==&lt;br /&gt;
The myApps client opens a single Websocket connection to the PBX. When the connection is idle, the PBX sends just a Websocket PING/PONG every 60s. Note that the PING/PONG exchange prevents TCP KeepAlive Messages, so there is no additional load for it.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  PING        20 bytes    20 bytes      31 bytes      71 bytes       &lt;br /&gt;
  PONG        20 bytes    20 bytes      35 bytes      75 bytes&lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     186 bytes / min&lt;br /&gt;
                                                  11.160 bytes / h&lt;br /&gt;
                                                 267.840 bytes / d&lt;br /&gt;
&lt;br /&gt;
== Apps ==&lt;br /&gt;
Most apps also open a Websocket connection to the PBX or App Platform and also use the PING/PONG mechanism. So the idle load is identical to myApps.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  PING        20 bytes    20 bytes      31 bytes      71 bytes       &lt;br /&gt;
  PONG        20 bytes    20 bytes      35 bytes      75 bytes&lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     186 bytes / min&lt;br /&gt;
                                                  11.160 bytes / h&lt;br /&gt;
                                                 267.840 bytes / d&lt;br /&gt;
&lt;br /&gt;
There are some apps - like the phone apps - send a Websocket message {&amp;quot;mt&amp;quot;:&amp;quot;KeepAlive&amp;quot;} on application layer every 60s to the PBX to dectect connection problems faster. Note that sending the message both prevents PING/PONG by the server and TCP KeepAlive, so there is no additonal load for it. In that case the idle bandwith can be calculated like follows.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  KeepAlive   20 bytes    20 bytes      53 bytes      93 bytes       &lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     133 bytes / min&lt;br /&gt;
                                                   7.980 bytes / h&lt;br /&gt;
                                                 191.520 bytes / d&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting =&lt;br /&gt;
&lt;br /&gt;
Client-side&lt;br /&gt;
*The myApps web uses the logging facilities provided by the browser it runs in (i.e. JavaScript function &amp;lt;code&amp;gt;console.log&amp;lt;/code&amp;gt;).  In most browser this is available as &#039;&#039;Console&#039;&#039; after pressing F12.&lt;br /&gt;
*The myApps platform services provide more elaborate tracing mechanisms. See &#039;&#039;Troubleshooting&#039;&#039; in [[{{NAMESPACE}}:Concept_myApps_platform_services#Troubleshooting|Concept myApps platform services]].&lt;br /&gt;
&lt;br /&gt;
PBX-side&lt;br /&gt;
*The Syslog can be used to log all connections to the PBX. See [[Reference16r1:Concept_myApps#Syslog]].&lt;br /&gt;
*You can activate the trace flag Servlets to see all websocket messages from and to the PBX. &amp;lt;code&amp;gt;!config add HTTP0 /servlet-trace on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Related Articles =&lt;br /&gt;
* [[{{NAMESPACE}}:Concept myApps platform services]]&lt;br /&gt;
&lt;br /&gt;
= Known Problems =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Problem_myApps|Known Problems]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference16r1:Concept_myApps&amp;diff=80050</id>
		<title>Reference16r1:Concept myApps</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference16r1:Concept_myApps&amp;diff=80050"/>
		<updated>2026-06-29T09:01:30Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Storage and format */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|myApps]]&lt;br /&gt;
[[Category:Concept_myApps]]&lt;br /&gt;
==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
* innovaphone PBX from version 16r1&lt;br /&gt;
= Overview =&lt;br /&gt;
innovaphone myApps is the client software for innovaphone users and administrators. The base functionality is provided by a web application that is loaded from the PBX. Additionally there are [[{{NAMESPACE}}:Concept_myApps_platform_services|installable versions for Windows, Android, macOS and iOS]] that come with an integrated browser and implement adaptations to the local operating system.&lt;br /&gt;
&lt;br /&gt;
The purpose of myApps is to organize and run apps. All productive functionality is provided by additional apps that run inside myApps.&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== Web version ===&lt;br /&gt;
For opening myApps in the web browser you need the most recent version of one of the following browsers:&lt;br /&gt;
* Chrome&lt;br /&gt;
* Firefox&lt;br /&gt;
* Safari&lt;br /&gt;
* or Edge&lt;br /&gt;
The following browser features are required and must not be disabled:&lt;br /&gt;
* JavaScript&lt;br /&gt;
* HTML5 Local Storage&lt;br /&gt;
&lt;br /&gt;
=== Native versions ===&lt;br /&gt;
myApps can also run as native executables on Windows (myApps for Windows), iOS (myApps for iOS), macOS (myApps for macOS) and Android (myApps for Android).  In this case, myApps platform services are available and provide additional features. The myApps Web version then runs in a web view window embedded in this native client.  See [[{{NAMESPACE}}:Concept myApps platform services|myApps platform services overview]] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Licenses ===&lt;br /&gt;
* No license needed for myApps itself&lt;br /&gt;
* Apps might require licenses&lt;br /&gt;
&lt;br /&gt;
=== Account ===&lt;br /&gt;
* A user account (user object) on the PBX is needed in order to use myApps.&lt;br /&gt;
&lt;br /&gt;
=== Reverse proxy ===&lt;br /&gt;
For access from the public internet, the reverse proxy must be configured to allow access to the following paths on the PBX.&lt;br /&gt;
; /PBX0/APPCLIENT/appclient.htm&lt;br /&gt;
: The myApps client itself&lt;br /&gt;
; /PBX0/session&lt;br /&gt;
: Needed for two-factor authentication using email&lt;br /&gt;
; /PBX0/APPS&lt;br /&gt;
: Needed for apps loaded from the PBX (e.g. softphone and chat) and for apps that use PBX APIs&lt;br /&gt;
; /OAUTH2/oauth2_login&lt;br /&gt;
: Needed for OAuth2 authentication&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
myApps comes with the following features:&lt;br /&gt;
* User login including two-factor authentication.&lt;br /&gt;
* Display and set the own presence (on the home screen and when the focus app is shown).&lt;br /&gt;
* List of all available apps including search functionality.&lt;br /&gt;
* Running apps (inside an iframe).&lt;br /&gt;
* Apps can be pinned to the main window. Pinned apps are always running and can&#039;t be closed. They are also started automatically when the myApps client is loaded.&lt;br /&gt;
* The &amp;quot;app focus&amp;quot; can be used to define a default app for the user. It is started and shown automatically when myApps is loaded. When closing other apps the app is shown instead of the home screen.&lt;br /&gt;
* Detaching apps in myApps for Windows and myApps for macOS. Detached apps are opened in a separate window.&lt;br /&gt;
* Home screen with user-selected apps and app items that can be organized in collapsible groups.&lt;br /&gt;
* Push notifications sent by app services.&lt;br /&gt;
* List of all myApps-Logins. Unused or suspicious sessions can be logged out remotely.&lt;br /&gt;
* Color scheme selection (light, dark).&lt;br /&gt;
* Configuration of standard apps for certain functions (like phone calls or chat).&lt;br /&gt;
* Link to account specific settings provided by a separate app (profile).&lt;br /&gt;
* Dialogue guidance in following languages: Català, Ceština, Deutsch, English, Español, Euskara, Français, Italiano, Nederlands, Polski, Português, Româna, ??????? ????, Slovenšcina, Türkçe&lt;br /&gt;
* Screen reader compatiblity and keyboard control &lt;br /&gt;
* Interactive, clickable onboarding tour to guide users through the client&#039;s structure and key features.&lt;br /&gt;
&lt;br /&gt;
All other functionality is provided by apps. For example phone calls require a phone app. Chats require a chat app.&lt;br /&gt;
&lt;br /&gt;
= Details =&lt;br /&gt;
== Connecting to the PBX ==&lt;br /&gt;
The myApps web application is loaded from the PBX. The corresponding URL for opening myApps in a browser is&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm&lt;br /&gt;
The installable versions ask for the &amp;quot;server name&amp;quot; on the first startup. Enter the host name of the PBX to proceed to the login screen.&lt;br /&gt;
You can change the server afterwards by logging out and clicking the &amp;quot;Change server&amp;quot; link on the login screen.&lt;br /&gt;
&lt;br /&gt;
== Supported URL Parameters ==&lt;br /&gt;
Some parameters can be specified with the URL in both the query string or fragment identifier. Those parameters are intended for internal use in the myApps launcher and automated testing. However they could be useful for special applications.&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm?lang=de&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm#lang=it&lt;br /&gt;
&lt;br /&gt;
Supported parameters:&lt;br /&gt;
&lt;br /&gt;
;lang:The two-letter code of the desired myApps language (&amp;quot;en&amp;quot;, &amp;quot;it&amp;quot;, &amp;quot;fr&amp;quot;, &amp;quot;de&amp;quot;, ...)&lt;br /&gt;
;scheme:The color scheme (&amp;quot;light&amp;quot;, &amp;quot;dark&amp;quot;).&lt;br /&gt;
;app:An app link to be started (e.g. &amp;quot;chat&amp;quot;).&lt;br /&gt;
;usr:The user name for login. Note that this will create a new permanent session at the user object. Should only be used in the fragment identifier.&lt;br /&gt;
;pwd:The password for login. Note that this will create a new permanent session at the user object. Should only be used in the fragment identifier.&lt;br /&gt;
;inactiveTimeout:Overrides the general timeout for the &amp;quot;auto appear offline&amp;quot; feature in browsers. Sets a timeout in milliseconds that shall be used before the user goes offline. Setting it to 0 disables the &amp;quot;auto appear offline&amp;quot;. Browser version only. Available from 13r2 SR11.&lt;br /&gt;
;phys: User defined physical location for Softphone Apps&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm?lang=de&amp;amp;scheme=light&amp;amp;app=chat#usr=john.doe&amp;amp;pwd=secret&lt;br /&gt;
&lt;br /&gt;
== Redirect to the user&#039;s PBX==&lt;br /&gt;
If the logged-in user is not on the current PBX, myApps will be redirected to the user&#039;s PBX (as configured in the pbx attribute of the user). The following rules apply:&lt;br /&gt;
===Master-Slave scenario===&lt;br /&gt;
* Slave PBXes redirect to the master PBX.&lt;br /&gt;
* The master PBX redirects to the correct slave PBX.&lt;br /&gt;
&lt;br /&gt;
Note: If the current PBX has no registration to the redirect target PBX but knows the user, it will act as a standby and keep the connection, until the registration is up gain.&lt;br /&gt;
&lt;br /&gt;
===Standby scenario===&lt;br /&gt;
See [[Reference16r1:Concept_myApps_Redundancy]]&lt;br /&gt;
&lt;br /&gt;
== Deployment of settings ==&lt;br /&gt;
The administrator can deploy some general settings to be used as a default by all myApps clients. This can be done in the admin UI on page PBX/Config/myApps. See [[Reference13r1:PBX/Config/myApps]] for details.&lt;br /&gt;
&lt;br /&gt;
== Authentication and security ==&lt;br /&gt;
For using myApps you need an account (user object) on the pbx with a password. For logging-in you need to enter the username (SIP-URI) or email address and the password.&lt;br /&gt;
&lt;br /&gt;
=== Permanent sessions ===&lt;br /&gt;
On each successful login on a new browser or new device a permanent session is created that is defined by a session id and a session password. Those are stored both in the local storage of the browser and at the user object in the PBX. If the user closes myApps and opens it again, the stored session is used. Only when logging-out the session is deleted in both places and the login screen is shown again.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The user password is never transmitted over the network or permanently stored in the browser.&lt;br /&gt;
* The PBX stores up to 12 persistent sessions per user. When the limit is reached, creating a new session removes the session with the oldest login timestamp.&lt;br /&gt;
&lt;br /&gt;
The user can keep track of all his permanent sessions in the myApps menu under &amp;quot;Account security&amp;quot;. Sessions that are not needed anymore can be deleted here. The corresponding browser or device is logged out on-the-fly.&lt;br /&gt;
&lt;br /&gt;
=== Two-factor authentication ===&lt;br /&gt;
The purpose of two-factor authentication is to maintain an additional level of security that prevents attackers form logging-in even if they compromised a users password. Therefore we strongly recommend to use it.&lt;br /&gt;
&lt;br /&gt;
It can be activated during installation of the PBX or in the admin UI under PBX/Config/Authentication. If activated, the password alone is not sufficient for logging-in but the user must also verify the new session by&lt;br /&gt;
* Confirming it in a dialog displayed on any existing myApps session.&lt;br /&gt;
* Clicking a link that is sent to the email address configured at the user object.&lt;br /&gt;
&lt;br /&gt;
In both cases a security code is displayed that should be compared to the one that is shown on the login screen of the new session. If it is the same the user can be sure that he is confirming his own login but not the possible concurrent login of an attacker.&lt;br /&gt;
&lt;br /&gt;
The email account for sending the verification emails can be configured during installation of the PBX, in the PBX Manager plugin &amp;quot;Email&amp;quot; or in the admin UI under PBX/Config/Authentication.&lt;br /&gt;
&lt;br /&gt;
If a user is notified about a login attempt he did not do, it means that the user password is compromised. The following should be done in such cases:&lt;br /&gt;
* Reject the session (email link or displayed dialog)&lt;br /&gt;
* Inform the administrator&lt;br /&gt;
* Change the user password&lt;br /&gt;
&lt;br /&gt;
=== Using Windows passwords ===&lt;br /&gt;
Instead of using the passwords configured at the user object, the Windows account can be used.&lt;br /&gt;
; OAuth2 (recommended) : See [[Reference16r1:Concept_OAuth2_Windows_Authentication]] for details.&lt;br /&gt;
; NTLM : See [[Reference16r1:Concept_Netlogon_and_myPBX_Windows_Authentication]] for details.&lt;br /&gt;
&lt;br /&gt;
=== Logging out ===&lt;br /&gt;
A logout can be done in the myApps menu at &amp;quot;Account security&amp;quot; / &amp;quot;Current session&amp;quot; (all versions).&lt;br /&gt;
In the browser version there is also separate menu item &amp;quot;Logout&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Resetting passwords ===&lt;br /&gt;
If the user has forgotten the password, he or she can set a new one by clicking the &amp;quot;Forgot password?&amp;quot; link on the login screen and completing an email verification process. This function can be activated or deactivated by the admin by configuring the link at &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Reset Password Page&amp;quot; or - more conveniently - using the PBX manager plugin of the innovaphone Users App that provides the functionality to change the configuration by pressing OK and then Enable or Disable various options like the password reset option.&lt;br /&gt;
&lt;br /&gt;
=== Brute force protection ===&lt;br /&gt;
myApps does several things to mitigate and detect brute force attacks on user accounts.&lt;br /&gt;
* After an attempt to log-in using a wrong password, the corresponding user account is locked for 0, 0, 8, 16, 32, 64, 128, 256, 512, 1024 seconds. In that time no more user logins with that account are possible. Logins using sessions that have been established before, are not affected.&lt;br /&gt;
* If there is a login attempt with a wrong password, the user is notified inside all existing myApps sessions. There the user can tell that it was him in order to reset the counters and unlock the account.&lt;br /&gt;
* From the third login attempt with a wrong password, events are generated to notify the administrator.&lt;br /&gt;
** Event Code 0x0002000b&lt;br /&gt;
** Severity Major&lt;br /&gt;
** Example Text: 3 rejected login attempts for user johndoe from 192.168.0.53&lt;br /&gt;
== Syslog ==&lt;br /&gt;
The log flag &#039;&#039;&#039;Maintenance / Diagnostics / Logging / myApps&#039;&#039;&#039; can be used to write information about the myApps connections to the syslog.&lt;br /&gt;
=== Example ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
A               B              C D        E   F               G                    H                                I                    J&lt;br /&gt;
&lt;br /&gt;
20250113-165252 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   -                    -                                -                    Connect&lt;br /&gt;
20250113-165256 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      -                                -                    Login FAILED &amp;quot;admin&amp;quot; (Authentication failed)&lt;br /&gt;
20250113-165301 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      -                                -                    Login FAILED &amp;quot;admin&amp;quot; (Authentication failed)&lt;br /&gt;
20250113-165303 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                Login OK &amp;quot;admin&amp;quot;&lt;br /&gt;
20250113-165308 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                AppGetLogin OK &amp;quot;chat&amp;quot;&lt;br /&gt;
20250113-165311 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                AppGetLogin OK &amp;quot;calllist&amp;quot;&lt;br /&gt;
20250113-165318 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                Logout OK&lt;br /&gt;
20250113-165914 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   -                    -                                -                    Disconnect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logging format ===&lt;br /&gt;
;A:Date and time&lt;br /&gt;
;B:PBX module name&lt;br /&gt;
;C:Serial number of connection object&lt;br /&gt;
;D:Memory address of connection object&lt;br /&gt;
;E:Transport protocol of the connection&lt;br /&gt;
;F:IP address of the client&lt;br /&gt;
;G:User agent of the client&lt;br /&gt;
;H:Session ID&lt;br /&gt;
;I:User name&lt;br /&gt;
;J:Action&lt;br /&gt;
&lt;br /&gt;
=== Logged actions ===&lt;br /&gt;
;Connect: A new connection has been established.&lt;br /&gt;
;Disconnect: The connection was closed.&lt;br /&gt;
;Login FAILED &amp;quot;username&amp;quot; (error): A user login failed.&lt;br /&gt;
;Login FAILED &amp;quot;sessionid&amp;quot; (error): A session login for a resumed session failed.&lt;br /&gt;
;Login AUTHORIZE &amp;quot;username&amp;quot;: The user was asked to authorize a login over another channel (2FA).&lt;br /&gt;
;Login REDIRECT &amp;quot;username&amp;quot;: Redirect to another PBX.&lt;br /&gt;
;Login REDIRECT &amp;quot;sessionid&amp;quot;: Redirect to another PBX.&lt;br /&gt;
;Login OK &amp;quot;username&amp;quot;: A user login was successful.&lt;br /&gt;
;Login OK &amp;quot;sessionid&amp;quot;: A session login was successful for a resumed session.&lt;br /&gt;
;Logout OK: The user has logged-out and the session is deleted.&lt;br /&gt;
;StandbyBack: Redirected from the standby PBX to the actual PBX.&lt;br /&gt;
;AuthorizeSession OK &amp;quot;sessionid&amp;quot;: The user authorized a login for another session (2FA).&lt;br /&gt;
;AuthorizeSession FAILED &amp;quot;sessionid&amp;quot;: The user rejected a login for another session (2FA).&lt;br /&gt;
;ResetInvalidLogins OK&amp;quot;: The user told that a failed login attempt was done by himself (2FA).&lt;br /&gt;
;DeleteSession OK &amp;quot;sessionid&amp;quot;: The user deleted the access for another session.&lt;br /&gt;
;DeleteSession FAILED &amp;quot;sessionid&amp;quot;: Deleting another session failed.&lt;br /&gt;
;AppGetLogin OK &amp;quot;appname&amp;quot;: Access to an app was granted.&lt;br /&gt;
;AppGetLogin FAILED &amp;quot;appname&amp;quot;: Access to an app was denied.&lt;br /&gt;
&lt;br /&gt;
== Apps ==&lt;br /&gt;
=== App runtime ===&lt;br /&gt;
All apps are web applications that consist of&lt;br /&gt;
* An HTML page&lt;br /&gt;
* Javascript files&lt;br /&gt;
* An app icon&lt;br /&gt;
myApps starts apps by opening the HTML page in an iframe. All communication between the apps and the myApps client is done using HTML5 window messaging. For example if the user changes the color scheme, myApps sends a window message to all open apps, so they can also switch colors.&lt;br /&gt;
&lt;br /&gt;
=== App objects ===&lt;br /&gt;
All apps that appear in the myApps client must be configured in the PBX. For apps that are loaded from the innovaphone App Platform or any other external server an App object is used that contains all the needed parameters.&lt;br /&gt;
&lt;br /&gt;
;Name:An ID that must be unique per PBX domain. The ID is only used internally to reference that app and is not shown to the user.&lt;br /&gt;
;Long Name:The display name of the app.&lt;br /&gt;
;Password:The shared secret between the app instance and the PBX. It corresponds to the password configured at the app instance. This secret is used when a user is authenticated against the app.&lt;br /&gt;
;URL:The base URL of the app. myApps appends .htm to get the URL of the HTML page and .png to get the URL of the app icon.&lt;br /&gt;
;Icon URL:If configured this URL is used for the app icon, instead of deriving it from the URL.&lt;br /&gt;
;Hidden:Some apps don&#039;t have a user interface. Their only purpose is to provide functionality (Client APIs) for myApps or other apps using window messaging. They have the &amp;quot;Hidden&amp;quot; flag checked at the app object and are not shown to the user.&lt;br /&gt;
&lt;br /&gt;
;Plain website&lt;br /&gt;
:Checked if the HTML page is not an actual app that requires login and processes the window messages used for apps, but if it is just a regular website. This flag can be used to integrate websites into myApps via iframe.&lt;br /&gt;
:Please note that this feature is meant for having a possibility to create simple content pages and integrate them into myApps without the need to develop a full-fledged app.&lt;br /&gt;
:&#039;&#039;Note: Most existing websites cannot be integrated in this way because they do not allow you to load them into an iframe. Check [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing Cross-origin resource sharing] and [https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1 Cookies SameSite] settings with the owner of the website. If you miss some configuration, you should see an error message in your browser console.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;Websocket:Some apps need a websocket connection from the PBX. This can be used to exchange additional information or to use APIs on the PBX. Those apps need the Websocket flag checked.&lt;br /&gt;
&lt;br /&gt;
Some other PBX objects also provide apps, like the Boolean object.&lt;br /&gt;
&lt;br /&gt;
=== App permissions ===&lt;br /&gt;
In order to use an app the administrator must grant the permission to the user. This can be done using templates of at the specific user object (&amp;quot;Edit Object&amp;quot;/&amp;quot;Apps&amp;quot;). The same setting can be done in the PBX manager plugin &amp;quot;Templates&amp;quot;. The user will find the apps he has access to in the &amp;quot;All apps&amp;quot; view in myApps.&lt;br /&gt;
&lt;br /&gt;
==== Special case: phone apps ====&lt;br /&gt;
If a user has access to the &amp;quot;phone&amp;quot; or &amp;quot;softphone&amp;quot; app, it will not automatically appear in &amp;quot;All apps&amp;quot;. Those apps need to be assigned to a device at the user object and will then be used for the registration on those devices. The admin  can configure the app name at the individual devices in the admin UI. The user can assign the app during provisioning of phones in &amp;quot;Edit profile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Client APIs and default apps ===&lt;br /&gt;
Some apps provide APIs that allow communication with other apps. An app providing an API is called an API provider. Communication is done using HTML5 window messages sent to the myApps client that dispatches them to the right app.&lt;br /&gt;
&lt;br /&gt;
If there are many providers for the same API, the app can send messages to specific provider, to all providers or let the user decide. In the latter case, myApps displays a selection dialog to the user. The user can also mark an app as the default app for an API that will then be used without asking again.&lt;br /&gt;
&lt;br /&gt;
Additionally the user can configure the standard apps in the myApps menu.&lt;br /&gt;
&lt;br /&gt;
The default apps are stored locally on each browser / device. So the user can have a different setting on each device.&lt;br /&gt;
&lt;br /&gt;
==== Special case: phone API (com.innovaphone.phone) ====&lt;br /&gt;
The phone apps provide a phone API that can be used by other apps to start calls. If a phone app is selected as the default phone app it has the following effects:&lt;br /&gt;
* When dialing a phone number (in a contacts app) the default phone app will be used for the call.&lt;br /&gt;
* On incoming calls the phone app is started and displayed automatically, to handle the call.&lt;br /&gt;
&lt;br /&gt;
If no default phone app is selected on a device&lt;br /&gt;
* The user will be asked what phone app shall be used when dialing (in a contacts app)&lt;br /&gt;
* On incoming calls no phone app will be started&lt;br /&gt;
&lt;br /&gt;
Regardless of the setting, the user can open any phone to start or receive calls.&lt;br /&gt;
&lt;br /&gt;
The standard phone app can be also selected by longpressing the app tile on the home screen.&lt;br /&gt;
&lt;br /&gt;
== Home screen ==&lt;br /&gt;
The home screen contains tiles that represent apps or items from apps - generally speaking links to apps. For example the user can place his phone app next to a contact from a contact app. Those tiles can be organized in named groups that can be collapsed, if they are currently not needed.&lt;br /&gt;
&lt;br /&gt;
The presentation of a tile contains an icon, the name of the app or item and optionally a presence and a badge count provided by the app.&lt;br /&gt;
&lt;br /&gt;
There are two ways for the user to add new items to the home screen:&lt;br /&gt;
* Click the home symbol at an app in the &amp;quot;All apps&amp;quot; view.&lt;br /&gt;
* Click an attach icon at an item inside an app.&lt;br /&gt;
&lt;br /&gt;
Apps can be removed again the same way or by longpressing the tile and clicking &amp;quot;Remove from home&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Storage and format ===&lt;br /&gt;
The home screen is stored at the user object in the PBX and is synchronized over all sessions of the user.&lt;br /&gt;
&lt;br /&gt;
The admin can see and configure it in the admin UI at &amp;quot;Edit User&amp;quot;/&amp;quot;User&amp;quot;/&amp;quot;Home Screen Apps&amp;quot;. It is a comma-separated string of app links.&lt;br /&gt;
&lt;br /&gt;
The string is limited to 8KB. If the limit is reached no more items or groups can be added to the home screen.&lt;br /&gt;
&lt;br /&gt;
Format: Items starting with a colon are groups. Items starting with two colons are collapsed groups.&lt;br /&gt;
&lt;br /&gt;
For example &amp;lt;code&amp;gt;:Apps,chat,users,::Contacts,users?id=jdo#d=John%20Doe&amp;amp;s=jdo&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
corresponds to&lt;br /&gt;
* Apps (group)&lt;br /&gt;
** Chat&lt;br /&gt;
** Users&lt;br /&gt;
* Contacts (collapsed group)&lt;br /&gt;
** &amp;quot;John Doe&amp;quot; from the app &amp;quot;users&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Indivisual App links are URL-encoded. An App link must not appear twice.&lt;br /&gt;
&lt;br /&gt;
== All apps ==&lt;br /&gt;
This page in myApps shows all apps that the user has access to (see: [[#App permissions|App permissions]]). Apps that are often used can be attached to the home screen.&lt;br /&gt;
&lt;br /&gt;
== App Notifications ==&lt;br /&gt;
From version 14r1 app services can send notifications to users. Those notifications will be transmitted to and displayed by all myApps sessions of the user that have app notifications enabled. Clicking the notification will open the app with optional parameters.&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
Launcher&lt;br /&gt;
* myApps for Windows from version 14r1&lt;br /&gt;
* myApps for macOS from version 14r1&lt;br /&gt;
* myApps Android from version 14r1&lt;br /&gt;
* myApps for iOS from version 14r1&lt;br /&gt;
&lt;br /&gt;
Browser&lt;br /&gt;
* Supported browser with the following features enabled:&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Push_API Push API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API Notifications API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API Service Worker API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Client Client API]&lt;br /&gt;
* myApps opened using https:&lt;br /&gt;
&lt;br /&gt;
PBX&lt;br /&gt;
* Trusted certificate with a valid DNS name. Self-signed certificates don&#039;t work.&lt;br /&gt;
* Push enabled, otherwise notifications will only be sent to connected myApps sesssions.&lt;br /&gt;
&lt;br /&gt;
Reverse Proxy &lt;br /&gt;
* Trusted certificate with a valid DNS name. Self-signed certificates don&#039;t work.&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
* If the feature is supported, the user can enable / disable app notifications in the hamburger menu of the myApps home screen (&amp;quot;App notifications&amp;quot;).&lt;br /&gt;
* The setting is per device. So the user can choose on which devices he or she likes to receive notifications.&lt;br /&gt;
* By default app notifications are enabled in the launcher and disabled in browser sessions.&lt;br /&gt;
* For enabling app notifications in the browser the user needs to grant the permission for Web Notifications.&lt;br /&gt;
&lt;br /&gt;
=== Some examples for apps supporting app notifications ===&lt;br /&gt;
* The Chat App in 14r1 uses app notifications for incoming chat messages.&lt;br /&gt;
* The Working App in 14r1 uses app notifications for warnings.&lt;br /&gt;
&lt;br /&gt;
=== Documentation for app developers ===&lt;br /&gt;
[https://sdk.innovaphone.com/16r1/doc/appwebsocket/PbxApi.htm#AppNotify https://sdk.innovaphone.com/16r1/doc/appwebsocket/PbxApi.htm#AppNotify]&lt;br /&gt;
&lt;br /&gt;
== Accessibility ==&lt;br /&gt;
For information regarding accessibility see following Article: https://wiki.innovaphone.com/index.php?title=Reference:Concept_Accessibility&lt;br /&gt;
&lt;br /&gt;
== Edit profile ==&lt;br /&gt;
An app for managing the user profile can be configured in the admin UI at &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Edit Profile App&amp;quot;. Typically the profile app provided by the innovaphone Users app is used for that. If configured, a menu item &amp;quot;Edit profile&amp;quot; appears in the myApps menu.&lt;br /&gt;
&lt;br /&gt;
== Onboarding ==&lt;br /&gt;
The administrator can configure a web page that shall be displayed as an intro when a user opens myApps for the first time. The user can see the intro again by clicking &amp;quot;Intro&amp;quot; in the hamburger menu of myApps.&lt;br /&gt;
&lt;br /&gt;
Configuration:&lt;br /&gt;
* The URL of the onboarding page can be configured at: PBX / Config / myApps / Onboarding URL. The corresponding command line attribute is &amp;lt;code&amp;gt;PBX0 /onboarding&amp;lt;/code&amp;gt;. The default URL configured during install is: https://www.innovaphone.com/en/services/intro-video.html?embedded=1&lt;br /&gt;
* The information whether a user has already seen the onboarding is stored at the user object or template (User / Onboarding seen). The corresponding LDAP attribute is &amp;lt;code&amp;gt;onboarded&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following parameters are passed to the page using URL parameters:&lt;br /&gt;
;name: &amp;quot;onboarding&amp;quot;&lt;br /&gt;
;title: The title as shown in the hamburger menu of myApps (depending on the e.g. &amp;quot;Intro&amp;quot;)&lt;br /&gt;
;scheme:The color scheme (&amp;quot;light&amp;quot; or &amp;quot;dark&amp;quot;)&lt;br /&gt;
;size:The size setting of the home screen items (&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot; or &amp;quot;2&amp;quot;)&lt;br /&gt;
;lang: The myApps language (e.g. &amp;quot;de&amp;quot; or &amp;quot;en&amp;quot;)&lt;br /&gt;
;ver: The version of the PBX (e.g. &amp;quot;16r1&amp;quot;)&lt;br /&gt;
;build: The build of the PBX (e.g. &amp;quot;1510335)&lt;br /&gt;
&lt;br /&gt;
Requirements for the configured page:&lt;br /&gt;
* Must work inside an IFrame.&lt;br /&gt;
* Should follow the language given in the URL parameters, defaulting to &amp;quot;en&amp;quot; if no contents are available for the language.&lt;br /&gt;
* Should follow the collor scheme (&amp;quot;dark&amp;quot; or &amp;quot;light&amp;quot;) given in the URL parameters. &lt;br /&gt;
* Must be responsive to work in different orientations (landscape or portrait) and on different screen sizes (Desktop and Smartphone).&lt;br /&gt;
* Must reserve a space (width 306px, height 102px) for an overlay button that is displayed by myApps in the bottom right corner.&lt;br /&gt;
&lt;br /&gt;
== Tutorials app ==&lt;br /&gt;
The administrator can define an app providing tutorials or other help for end users. That app will appear in the hamburger menu of myApps as &amp;quot;Tutorials&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Requirements:&lt;br /&gt;
* Create an app object pointing to the corresponding web page (eg. https://www.innovaphone.com/myapps/tutorial.htm) via the Adv.GUI, PBX, Objects, create new App Object with a name (eg. Tutorials)&lt;br /&gt;
* Give users access to that app, preferably using templates (eg. Conf Users).&lt;br /&gt;
* Configure the app name in the admin UI &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Tutorial App&amp;quot; with the previous created name (eg. Tutorials).&lt;br /&gt;
&lt;br /&gt;
Note: This configuration is synchronized with the client when the connection is established. So a restart of myApps is needed for the tutorials app to appear in the hamburger menu.&lt;br /&gt;
&lt;br /&gt;
When installing a new PBX, a tutorial app provided by innovaphone is configured by default. It points to https://www.innovaphone.com/myapps/tutorial.htm and shows videos about the usage of myApps.&lt;br /&gt;
&lt;br /&gt;
== Privacy and Datastorage ==&lt;br /&gt;
&lt;br /&gt;
myApps will store the following data on your local device:&lt;br /&gt;
&lt;br /&gt;
* appclient-username / appclient-password&lt;br /&gt;
: Auth token from the user session on this device (This is not the password itself, only a random token).&lt;br /&gt;
* appclient-model&lt;br /&gt;
: Offline-files from myApps which contains the personal user data (eg. Home screen configuration and Push tokens).&lt;br /&gt;
* appclient-config&lt;br /&gt;
: URLs and credentials for local services (credentials will be new generated randomly on every startup)&lt;br /&gt;
* appclient-usr-XXXXXXXXXXXXXXXXXXX&lt;br /&gt;
: anonymized environment settings of all historical user sessions (eg. theme, element size of home screen elements, language)&lt;br /&gt;
&lt;br /&gt;
Additionally, it is allowed to every App to create own offline files or create local settings which will be stored also.&lt;br /&gt;
&lt;br /&gt;
The Chromium Cache and DOM Storage (myApps for Windows) will be stored in &amp;lt;code&amp;gt;%appdata%\innovaphone\myApps\chromium\cache&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Idle Bandwidth =&lt;br /&gt;
== myApps ==&lt;br /&gt;
The myApps client opens a single Websocket connection to the PBX. When the connection is idle, the PBX sends just a Websocket PING/PONG every 60s. Note that the PING/PONG exchange prevents TCP KeepAlive Messages, so there is no additional load for it.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  PING        20 bytes    20 bytes      31 bytes      71 bytes       &lt;br /&gt;
  PONG        20 bytes    20 bytes      35 bytes      75 bytes&lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     186 bytes / min&lt;br /&gt;
                                                  11.160 bytes / h&lt;br /&gt;
                                                 267.840 bytes / d&lt;br /&gt;
&lt;br /&gt;
== Apps ==&lt;br /&gt;
Most apps also open a Websocket connection to the PBX or App Platform and also use the PING/PONG mechanism. So the idle load is identical to myApps.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  PING        20 bytes    20 bytes      31 bytes      71 bytes       &lt;br /&gt;
  PONG        20 bytes    20 bytes      35 bytes      75 bytes&lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     186 bytes / min&lt;br /&gt;
                                                  11.160 bytes / h&lt;br /&gt;
                                                 267.840 bytes / d&lt;br /&gt;
&lt;br /&gt;
There are some apps - like the phone apps - send a Websocket message {&amp;quot;mt&amp;quot;:&amp;quot;KeepAlive&amp;quot;} on application layer every 60s to the PBX to dectect connection problems faster. Note that sending the message both prevents PING/PONG by the server and TCP KeepAlive, so there is no additonal load for it. In that case the idle bandwith can be calculated like follows.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  KeepAlive   20 bytes    20 bytes      53 bytes      93 bytes       &lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     133 bytes / min&lt;br /&gt;
                                                   7.980 bytes / h&lt;br /&gt;
                                                 191.520 bytes / d&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting =&lt;br /&gt;
&lt;br /&gt;
Client-side&lt;br /&gt;
*The myApps web uses the logging facilities provided by the browser it runs in (i.e. JavaScript function &amp;lt;code&amp;gt;console.log&amp;lt;/code&amp;gt;).  In most browser this is available as &#039;&#039;Console&#039;&#039; after pressing F12.&lt;br /&gt;
*The myApps platform services provide more elaborate tracing mechanisms. See &#039;&#039;Troubleshooting&#039;&#039; in [[{{NAMESPACE}}:Concept_myApps_platform_services#Troubleshooting|Concept myApps platform services]].&lt;br /&gt;
&lt;br /&gt;
PBX-side&lt;br /&gt;
*The Syslog can be used to log all connections to the PBX. See [[Reference16r1:Concept_myApps#Syslog]].&lt;br /&gt;
*You can activate the trace flag Servlets to see all websocket messages from and to the PBX. &amp;lt;code&amp;gt;!config add HTTP0 /servlet-trace on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Related Articles =&lt;br /&gt;
* [[{{NAMESPACE}}:Concept myApps platform services]]&lt;br /&gt;
&lt;br /&gt;
= Known Problems =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Problem_myApps|Known Problems]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference16r1:Concept_myApps&amp;diff=80049</id>
		<title>Reference16r1:Concept myApps</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference16r1:Concept_myApps&amp;diff=80049"/>
		<updated>2026-06-29T09:01:00Z</updated>

		<summary type="html">&lt;p&gt;Ckl: /* Storage and format */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Concept|myApps]]&lt;br /&gt;
[[Category:Concept_myApps]]&lt;br /&gt;
==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
* innovaphone PBX from version 16r1&lt;br /&gt;
= Overview =&lt;br /&gt;
innovaphone myApps is the client software for innovaphone users and administrators. The base functionality is provided by a web application that is loaded from the PBX. Additionally there are [[{{NAMESPACE}}:Concept_myApps_platform_services|installable versions for Windows, Android, macOS and iOS]] that come with an integrated browser and implement adaptations to the local operating system.&lt;br /&gt;
&lt;br /&gt;
The purpose of myApps is to organize and run apps. All productive functionality is provided by additional apps that run inside myApps.&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== Web version ===&lt;br /&gt;
For opening myApps in the web browser you need the most recent version of one of the following browsers:&lt;br /&gt;
* Chrome&lt;br /&gt;
* Firefox&lt;br /&gt;
* Safari&lt;br /&gt;
* or Edge&lt;br /&gt;
The following browser features are required and must not be disabled:&lt;br /&gt;
* JavaScript&lt;br /&gt;
* HTML5 Local Storage&lt;br /&gt;
&lt;br /&gt;
=== Native versions ===&lt;br /&gt;
myApps can also run as native executables on Windows (myApps for Windows), iOS (myApps for iOS), macOS (myApps for macOS) and Android (myApps for Android).  In this case, myApps platform services are available and provide additional features. The myApps Web version then runs in a web view window embedded in this native client.  See [[{{NAMESPACE}}:Concept myApps platform services|myApps platform services overview]] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Licenses ===&lt;br /&gt;
* No license needed for myApps itself&lt;br /&gt;
* Apps might require licenses&lt;br /&gt;
&lt;br /&gt;
=== Account ===&lt;br /&gt;
* A user account (user object) on the PBX is needed in order to use myApps.&lt;br /&gt;
&lt;br /&gt;
=== Reverse proxy ===&lt;br /&gt;
For access from the public internet, the reverse proxy must be configured to allow access to the following paths on the PBX.&lt;br /&gt;
; /PBX0/APPCLIENT/appclient.htm&lt;br /&gt;
: The myApps client itself&lt;br /&gt;
; /PBX0/session&lt;br /&gt;
: Needed for two-factor authentication using email&lt;br /&gt;
; /PBX0/APPS&lt;br /&gt;
: Needed for apps loaded from the PBX (e.g. softphone and chat) and for apps that use PBX APIs&lt;br /&gt;
; /OAUTH2/oauth2_login&lt;br /&gt;
: Needed for OAuth2 authentication&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
myApps comes with the following features:&lt;br /&gt;
* User login including two-factor authentication.&lt;br /&gt;
* Display and set the own presence (on the home screen and when the focus app is shown).&lt;br /&gt;
* List of all available apps including search functionality.&lt;br /&gt;
* Running apps (inside an iframe).&lt;br /&gt;
* Apps can be pinned to the main window. Pinned apps are always running and can&#039;t be closed. They are also started automatically when the myApps client is loaded.&lt;br /&gt;
* The &amp;quot;app focus&amp;quot; can be used to define a default app for the user. It is started and shown automatically when myApps is loaded. When closing other apps the app is shown instead of the home screen.&lt;br /&gt;
* Detaching apps in myApps for Windows and myApps for macOS. Detached apps are opened in a separate window.&lt;br /&gt;
* Home screen with user-selected apps and app items that can be organized in collapsible groups.&lt;br /&gt;
* Push notifications sent by app services.&lt;br /&gt;
* List of all myApps-Logins. Unused or suspicious sessions can be logged out remotely.&lt;br /&gt;
* Color scheme selection (light, dark).&lt;br /&gt;
* Configuration of standard apps for certain functions (like phone calls or chat).&lt;br /&gt;
* Link to account specific settings provided by a separate app (profile).&lt;br /&gt;
* Dialogue guidance in following languages: Català, Ceština, Deutsch, English, Español, Euskara, Français, Italiano, Nederlands, Polski, Português, Româna, ??????? ????, Slovenšcina, Türkçe&lt;br /&gt;
* Screen reader compatiblity and keyboard control &lt;br /&gt;
* Interactive, clickable onboarding tour to guide users through the client&#039;s structure and key features.&lt;br /&gt;
&lt;br /&gt;
All other functionality is provided by apps. For example phone calls require a phone app. Chats require a chat app.&lt;br /&gt;
&lt;br /&gt;
= Details =&lt;br /&gt;
== Connecting to the PBX ==&lt;br /&gt;
The myApps web application is loaded from the PBX. The corresponding URL for opening myApps in a browser is&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm&lt;br /&gt;
The installable versions ask for the &amp;quot;server name&amp;quot; on the first startup. Enter the host name of the PBX to proceed to the login screen.&lt;br /&gt;
You can change the server afterwards by logging out and clicking the &amp;quot;Change server&amp;quot; link on the login screen.&lt;br /&gt;
&lt;br /&gt;
== Supported URL Parameters ==&lt;br /&gt;
Some parameters can be specified with the URL in both the query string or fragment identifier. Those parameters are intended for internal use in the myApps launcher and automated testing. However they could be useful for special applications.&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm?lang=de&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm#lang=it&lt;br /&gt;
&lt;br /&gt;
Supported parameters:&lt;br /&gt;
&lt;br /&gt;
;lang:The two-letter code of the desired myApps language (&amp;quot;en&amp;quot;, &amp;quot;it&amp;quot;, &amp;quot;fr&amp;quot;, &amp;quot;de&amp;quot;, ...)&lt;br /&gt;
;scheme:The color scheme (&amp;quot;light&amp;quot;, &amp;quot;dark&amp;quot;).&lt;br /&gt;
;app:An app link to be started (e.g. &amp;quot;chat&amp;quot;).&lt;br /&gt;
;usr:The user name for login. Note that this will create a new permanent session at the user object. Should only be used in the fragment identifier.&lt;br /&gt;
;pwd:The password for login. Note that this will create a new permanent session at the user object. Should only be used in the fragment identifier.&lt;br /&gt;
;inactiveTimeout:Overrides the general timeout for the &amp;quot;auto appear offline&amp;quot; feature in browsers. Sets a timeout in milliseconds that shall be used before the user goes offline. Setting it to 0 disables the &amp;quot;auto appear offline&amp;quot;. Browser version only. Available from 13r2 SR11.&lt;br /&gt;
;phys: User defined physical location for Softphone Apps&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  https://&amp;lt;pbx-hostname&amp;gt;/PBX0/APPCLIENT/appclient.htm?lang=de&amp;amp;scheme=light&amp;amp;app=chat#usr=john.doe&amp;amp;pwd=secret&lt;br /&gt;
&lt;br /&gt;
== Redirect to the user&#039;s PBX==&lt;br /&gt;
If the logged-in user is not on the current PBX, myApps will be redirected to the user&#039;s PBX (as configured in the pbx attribute of the user). The following rules apply:&lt;br /&gt;
===Master-Slave scenario===&lt;br /&gt;
* Slave PBXes redirect to the master PBX.&lt;br /&gt;
* The master PBX redirects to the correct slave PBX.&lt;br /&gt;
&lt;br /&gt;
Note: If the current PBX has no registration to the redirect target PBX but knows the user, it will act as a standby and keep the connection, until the registration is up gain.&lt;br /&gt;
&lt;br /&gt;
===Standby scenario===&lt;br /&gt;
See [[Reference16r1:Concept_myApps_Redundancy]]&lt;br /&gt;
&lt;br /&gt;
== Deployment of settings ==&lt;br /&gt;
The administrator can deploy some general settings to be used as a default by all myApps clients. This can be done in the admin UI on page PBX/Config/myApps. See [[Reference13r1:PBX/Config/myApps]] for details.&lt;br /&gt;
&lt;br /&gt;
== Authentication and security ==&lt;br /&gt;
For using myApps you need an account (user object) on the pbx with a password. For logging-in you need to enter the username (SIP-URI) or email address and the password.&lt;br /&gt;
&lt;br /&gt;
=== Permanent sessions ===&lt;br /&gt;
On each successful login on a new browser or new device a permanent session is created that is defined by a session id and a session password. Those are stored both in the local storage of the browser and at the user object in the PBX. If the user closes myApps and opens it again, the stored session is used. Only when logging-out the session is deleted in both places and the login screen is shown again.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The user password is never transmitted over the network or permanently stored in the browser.&lt;br /&gt;
* The PBX stores up to 12 persistent sessions per user. When the limit is reached, creating a new session removes the session with the oldest login timestamp.&lt;br /&gt;
&lt;br /&gt;
The user can keep track of all his permanent sessions in the myApps menu under &amp;quot;Account security&amp;quot;. Sessions that are not needed anymore can be deleted here. The corresponding browser or device is logged out on-the-fly.&lt;br /&gt;
&lt;br /&gt;
=== Two-factor authentication ===&lt;br /&gt;
The purpose of two-factor authentication is to maintain an additional level of security that prevents attackers form logging-in even if they compromised a users password. Therefore we strongly recommend to use it.&lt;br /&gt;
&lt;br /&gt;
It can be activated during installation of the PBX or in the admin UI under PBX/Config/Authentication. If activated, the password alone is not sufficient for logging-in but the user must also verify the new session by&lt;br /&gt;
* Confirming it in a dialog displayed on any existing myApps session.&lt;br /&gt;
* Clicking a link that is sent to the email address configured at the user object.&lt;br /&gt;
&lt;br /&gt;
In both cases a security code is displayed that should be compared to the one that is shown on the login screen of the new session. If it is the same the user can be sure that he is confirming his own login but not the possible concurrent login of an attacker.&lt;br /&gt;
&lt;br /&gt;
The email account for sending the verification emails can be configured during installation of the PBX, in the PBX Manager plugin &amp;quot;Email&amp;quot; or in the admin UI under PBX/Config/Authentication.&lt;br /&gt;
&lt;br /&gt;
If a user is notified about a login attempt he did not do, it means that the user password is compromised. The following should be done in such cases:&lt;br /&gt;
* Reject the session (email link or displayed dialog)&lt;br /&gt;
* Inform the administrator&lt;br /&gt;
* Change the user password&lt;br /&gt;
&lt;br /&gt;
=== Using Windows passwords ===&lt;br /&gt;
Instead of using the passwords configured at the user object, the Windows account can be used.&lt;br /&gt;
; OAuth2 (recommended) : See [[Reference16r1:Concept_OAuth2_Windows_Authentication]] for details.&lt;br /&gt;
; NTLM : See [[Reference16r1:Concept_Netlogon_and_myPBX_Windows_Authentication]] for details.&lt;br /&gt;
&lt;br /&gt;
=== Logging out ===&lt;br /&gt;
A logout can be done in the myApps menu at &amp;quot;Account security&amp;quot; / &amp;quot;Current session&amp;quot; (all versions).&lt;br /&gt;
In the browser version there is also separate menu item &amp;quot;Logout&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Resetting passwords ===&lt;br /&gt;
If the user has forgotten the password, he or she can set a new one by clicking the &amp;quot;Forgot password?&amp;quot; link on the login screen and completing an email verification process. This function can be activated or deactivated by the admin by configuring the link at &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Reset Password Page&amp;quot; or - more conveniently - using the PBX manager plugin of the innovaphone Users App that provides the functionality to change the configuration by pressing OK and then Enable or Disable various options like the password reset option.&lt;br /&gt;
&lt;br /&gt;
=== Brute force protection ===&lt;br /&gt;
myApps does several things to mitigate and detect brute force attacks on user accounts.&lt;br /&gt;
* After an attempt to log-in using a wrong password, the corresponding user account is locked for 0, 0, 8, 16, 32, 64, 128, 256, 512, 1024 seconds. In that time no more user logins with that account are possible. Logins using sessions that have been established before, are not affected.&lt;br /&gt;
* If there is a login attempt with a wrong password, the user is notified inside all existing myApps sessions. There the user can tell that it was him in order to reset the counters and unlock the account.&lt;br /&gt;
* From the third login attempt with a wrong password, events are generated to notify the administrator.&lt;br /&gt;
** Event Code 0x0002000b&lt;br /&gt;
** Severity Major&lt;br /&gt;
** Example Text: 3 rejected login attempts for user johndoe from 192.168.0.53&lt;br /&gt;
== Syslog ==&lt;br /&gt;
The log flag &#039;&#039;&#039;Maintenance / Diagnostics / Logging / myApps&#039;&#039;&#039; can be used to write information about the myApps connections to the syslog.&lt;br /&gt;
=== Example ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
A               B              C D        E   F               G                    H                                I                    J&lt;br /&gt;
&lt;br /&gt;
20250113-165252 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   -                    -                                -                    Connect&lt;br /&gt;
20250113-165256 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      -                                -                    Login FAILED &amp;quot;admin&amp;quot; (Authentication failed)&lt;br /&gt;
20250113-165301 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      -                                -                    Login FAILED &amp;quot;admin&amp;quot; (Authentication failed)&lt;br /&gt;
20250113-165303 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                Login OK &amp;quot;admin&amp;quot;&lt;br /&gt;
20250113-165308 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                AppGetLogin OK &amp;quot;chat&amp;quot;&lt;br /&gt;
20250113-165311 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                AppGetLogin OK &amp;quot;calllist&amp;quot;&lt;br /&gt;
20250113-165318 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   myApps (Chrome)      2dc5f5df36856701b333009033410fcb admin                Logout OK&lt;br /&gt;
20250113-165914 PBX0 APPCLIENT 0 1699138  tcp 192.168.0.200   -                    -                                -                    Disconnect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logging format ===&lt;br /&gt;
;A:Date and time&lt;br /&gt;
;B:PBX module name&lt;br /&gt;
;C:Serial number of connection object&lt;br /&gt;
;D:Memory address of connection object&lt;br /&gt;
;E:Transport protocol of the connection&lt;br /&gt;
;F:IP address of the client&lt;br /&gt;
;G:User agent of the client&lt;br /&gt;
;H:Session ID&lt;br /&gt;
;I:User name&lt;br /&gt;
;J:Action&lt;br /&gt;
&lt;br /&gt;
=== Logged actions ===&lt;br /&gt;
;Connect: A new connection has been established.&lt;br /&gt;
;Disconnect: The connection was closed.&lt;br /&gt;
;Login FAILED &amp;quot;username&amp;quot; (error): A user login failed.&lt;br /&gt;
;Login FAILED &amp;quot;sessionid&amp;quot; (error): A session login for a resumed session failed.&lt;br /&gt;
;Login AUTHORIZE &amp;quot;username&amp;quot;: The user was asked to authorize a login over another channel (2FA).&lt;br /&gt;
;Login REDIRECT &amp;quot;username&amp;quot;: Redirect to another PBX.&lt;br /&gt;
;Login REDIRECT &amp;quot;sessionid&amp;quot;: Redirect to another PBX.&lt;br /&gt;
;Login OK &amp;quot;username&amp;quot;: A user login was successful.&lt;br /&gt;
;Login OK &amp;quot;sessionid&amp;quot;: A session login was successful for a resumed session.&lt;br /&gt;
;Logout OK: The user has logged-out and the session is deleted.&lt;br /&gt;
;StandbyBack: Redirected from the standby PBX to the actual PBX.&lt;br /&gt;
;AuthorizeSession OK &amp;quot;sessionid&amp;quot;: The user authorized a login for another session (2FA).&lt;br /&gt;
;AuthorizeSession FAILED &amp;quot;sessionid&amp;quot;: The user rejected a login for another session (2FA).&lt;br /&gt;
;ResetInvalidLogins OK&amp;quot;: The user told that a failed login attempt was done by himself (2FA).&lt;br /&gt;
;DeleteSession OK &amp;quot;sessionid&amp;quot;: The user deleted the access for another session.&lt;br /&gt;
;DeleteSession FAILED &amp;quot;sessionid&amp;quot;: Deleting another session failed.&lt;br /&gt;
;AppGetLogin OK &amp;quot;appname&amp;quot;: Access to an app was granted.&lt;br /&gt;
;AppGetLogin FAILED &amp;quot;appname&amp;quot;: Access to an app was denied.&lt;br /&gt;
&lt;br /&gt;
== Apps ==&lt;br /&gt;
=== App runtime ===&lt;br /&gt;
All apps are web applications that consist of&lt;br /&gt;
* An HTML page&lt;br /&gt;
* Javascript files&lt;br /&gt;
* An app icon&lt;br /&gt;
myApps starts apps by opening the HTML page in an iframe. All communication between the apps and the myApps client is done using HTML5 window messaging. For example if the user changes the color scheme, myApps sends a window message to all open apps, so they can also switch colors.&lt;br /&gt;
&lt;br /&gt;
=== App objects ===&lt;br /&gt;
All apps that appear in the myApps client must be configured in the PBX. For apps that are loaded from the innovaphone App Platform or any other external server an App object is used that contains all the needed parameters.&lt;br /&gt;
&lt;br /&gt;
;Name:An ID that must be unique per PBX domain. The ID is only used internally to reference that app and is not shown to the user.&lt;br /&gt;
;Long Name:The display name of the app.&lt;br /&gt;
;Password:The shared secret between the app instance and the PBX. It corresponds to the password configured at the app instance. This secret is used when a user is authenticated against the app.&lt;br /&gt;
;URL:The base URL of the app. myApps appends .htm to get the URL of the HTML page and .png to get the URL of the app icon.&lt;br /&gt;
;Icon URL:If configured this URL is used for the app icon, instead of deriving it from the URL.&lt;br /&gt;
;Hidden:Some apps don&#039;t have a user interface. Their only purpose is to provide functionality (Client APIs) for myApps or other apps using window messaging. They have the &amp;quot;Hidden&amp;quot; flag checked at the app object and are not shown to the user.&lt;br /&gt;
&lt;br /&gt;
;Plain website&lt;br /&gt;
:Checked if the HTML page is not an actual app that requires login and processes the window messages used for apps, but if it is just a regular website. This flag can be used to integrate websites into myApps via iframe.&lt;br /&gt;
:Please note that this feature is meant for having a possibility to create simple content pages and integrate them into myApps without the need to develop a full-fledged app.&lt;br /&gt;
:&#039;&#039;Note: Most existing websites cannot be integrated in this way because they do not allow you to load them into an iframe. Check [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing Cross-origin resource sharing] and [https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1 Cookies SameSite] settings with the owner of the website. If you miss some configuration, you should see an error message in your browser console.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;Websocket:Some apps need a websocket connection from the PBX. This can be used to exchange additional information or to use APIs on the PBX. Those apps need the Websocket flag checked.&lt;br /&gt;
&lt;br /&gt;
Some other PBX objects also provide apps, like the Boolean object.&lt;br /&gt;
&lt;br /&gt;
=== App permissions ===&lt;br /&gt;
In order to use an app the administrator must grant the permission to the user. This can be done using templates of at the specific user object (&amp;quot;Edit Object&amp;quot;/&amp;quot;Apps&amp;quot;). The same setting can be done in the PBX manager plugin &amp;quot;Templates&amp;quot;. The user will find the apps he has access to in the &amp;quot;All apps&amp;quot; view in myApps.&lt;br /&gt;
&lt;br /&gt;
==== Special case: phone apps ====&lt;br /&gt;
If a user has access to the &amp;quot;phone&amp;quot; or &amp;quot;softphone&amp;quot; app, it will not automatically appear in &amp;quot;All apps&amp;quot;. Those apps need to be assigned to a device at the user object and will then be used for the registration on those devices. The admin  can configure the app name at the individual devices in the admin UI. The user can assign the app during provisioning of phones in &amp;quot;Edit profile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Client APIs and default apps ===&lt;br /&gt;
Some apps provide APIs that allow communication with other apps. An app providing an API is called an API provider. Communication is done using HTML5 window messages sent to the myApps client that dispatches them to the right app.&lt;br /&gt;
&lt;br /&gt;
If there are many providers for the same API, the app can send messages to specific provider, to all providers or let the user decide. In the latter case, myApps displays a selection dialog to the user. The user can also mark an app as the default app for an API that will then be used without asking again.&lt;br /&gt;
&lt;br /&gt;
Additionally the user can configure the standard apps in the myApps menu.&lt;br /&gt;
&lt;br /&gt;
The default apps are stored locally on each browser / device. So the user can have a different setting on each device.&lt;br /&gt;
&lt;br /&gt;
==== Special case: phone API (com.innovaphone.phone) ====&lt;br /&gt;
The phone apps provide a phone API that can be used by other apps to start calls. If a phone app is selected as the default phone app it has the following effects:&lt;br /&gt;
* When dialing a phone number (in a contacts app) the default phone app will be used for the call.&lt;br /&gt;
* On incoming calls the phone app is started and displayed automatically, to handle the call.&lt;br /&gt;
&lt;br /&gt;
If no default phone app is selected on a device&lt;br /&gt;
* The user will be asked what phone app shall be used when dialing (in a contacts app)&lt;br /&gt;
* On incoming calls no phone app will be started&lt;br /&gt;
&lt;br /&gt;
Regardless of the setting, the user can open any phone to start or receive calls.&lt;br /&gt;
&lt;br /&gt;
The standard phone app can be also selected by longpressing the app tile on the home screen.&lt;br /&gt;
&lt;br /&gt;
== Home screen ==&lt;br /&gt;
The home screen contains tiles that represent apps or items from apps - generally speaking links to apps. For example the user can place his phone app next to a contact from a contact app. Those tiles can be organized in named groups that can be collapsed, if they are currently not needed.&lt;br /&gt;
&lt;br /&gt;
The presentation of a tile contains an icon, the name of the app or item and optionally a presence and a badge count provided by the app.&lt;br /&gt;
&lt;br /&gt;
There are two ways for the user to add new items to the home screen:&lt;br /&gt;
* Click the home symbol at an app in the &amp;quot;All apps&amp;quot; view.&lt;br /&gt;
* Click an attach icon at an item inside an app.&lt;br /&gt;
&lt;br /&gt;
Apps can be removed again the same way or by longpressing the tile and clicking &amp;quot;Remove from home&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Storage and format ===&lt;br /&gt;
The home screen is stored at the user object in the PBX and is synchronized over all sessions of the user.&lt;br /&gt;
&lt;br /&gt;
The admin can see and configure it in the admin UI at &amp;quot;Edit User&amp;quot;/&amp;quot;User&amp;quot;/&amp;quot;Home Screen Apps&amp;quot;. It is a comma-separated string of app links.&lt;br /&gt;
&lt;br /&gt;
The string is limited to 8KB. If the limit is reached no more items or groups can be added to the home screen.&lt;br /&gt;
&lt;br /&gt;
Format: Items starting with a colon are groups. Items starting with two colons are collapsed groups.&lt;br /&gt;
&lt;br /&gt;
For example &amp;lt;code&amp;gt;:Apps,chat,users,::Contacts,users?id=jdo#d=John%20Doe&amp;amp;s=jdo&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
corresponds to&lt;br /&gt;
* Apps (group)&lt;br /&gt;
** Chat&lt;br /&gt;
** Users&lt;br /&gt;
* Contacts (collapsed group)&lt;br /&gt;
** &amp;quot;John Doe&amp;quot; from the app &amp;quot;users&amp;quot;&lt;br /&gt;
&lt;br /&gt;
App links are URL-encoded. An App link must not appear twice.&lt;br /&gt;
&lt;br /&gt;
== All apps ==&lt;br /&gt;
This page in myApps shows all apps that the user has access to (see: [[#App permissions|App permissions]]). Apps that are often used can be attached to the home screen.&lt;br /&gt;
&lt;br /&gt;
== App Notifications ==&lt;br /&gt;
From version 14r1 app services can send notifications to users. Those notifications will be transmitted to and displayed by all myApps sessions of the user that have app notifications enabled. Clicking the notification will open the app with optional parameters.&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
Launcher&lt;br /&gt;
* myApps for Windows from version 14r1&lt;br /&gt;
* myApps for macOS from version 14r1&lt;br /&gt;
* myApps Android from version 14r1&lt;br /&gt;
* myApps for iOS from version 14r1&lt;br /&gt;
&lt;br /&gt;
Browser&lt;br /&gt;
* Supported browser with the following features enabled:&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Push_API Push API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API Notifications API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API Service Worker API]&lt;br /&gt;
** [https://developer.mozilla.org/en-US/docs/Web/API/Client Client API]&lt;br /&gt;
* myApps opened using https:&lt;br /&gt;
&lt;br /&gt;
PBX&lt;br /&gt;
* Trusted certificate with a valid DNS name. Self-signed certificates don&#039;t work.&lt;br /&gt;
* Push enabled, otherwise notifications will only be sent to connected myApps sesssions.&lt;br /&gt;
&lt;br /&gt;
Reverse Proxy &lt;br /&gt;
* Trusted certificate with a valid DNS name. Self-signed certificates don&#039;t work.&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
* If the feature is supported, the user can enable / disable app notifications in the hamburger menu of the myApps home screen (&amp;quot;App notifications&amp;quot;).&lt;br /&gt;
* The setting is per device. So the user can choose on which devices he or she likes to receive notifications.&lt;br /&gt;
* By default app notifications are enabled in the launcher and disabled in browser sessions.&lt;br /&gt;
* For enabling app notifications in the browser the user needs to grant the permission for Web Notifications.&lt;br /&gt;
&lt;br /&gt;
=== Some examples for apps supporting app notifications ===&lt;br /&gt;
* The Chat App in 14r1 uses app notifications for incoming chat messages.&lt;br /&gt;
* The Working App in 14r1 uses app notifications for warnings.&lt;br /&gt;
&lt;br /&gt;
=== Documentation for app developers ===&lt;br /&gt;
[https://sdk.innovaphone.com/16r1/doc/appwebsocket/PbxApi.htm#AppNotify https://sdk.innovaphone.com/16r1/doc/appwebsocket/PbxApi.htm#AppNotify]&lt;br /&gt;
&lt;br /&gt;
== Accessibility ==&lt;br /&gt;
For information regarding accessibility see following Article: https://wiki.innovaphone.com/index.php?title=Reference:Concept_Accessibility&lt;br /&gt;
&lt;br /&gt;
== Edit profile ==&lt;br /&gt;
An app for managing the user profile can be configured in the admin UI at &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Edit Profile App&amp;quot;. Typically the profile app provided by the innovaphone Users app is used for that. If configured, a menu item &amp;quot;Edit profile&amp;quot; appears in the myApps menu.&lt;br /&gt;
&lt;br /&gt;
== Onboarding ==&lt;br /&gt;
The administrator can configure a web page that shall be displayed as an intro when a user opens myApps for the first time. The user can see the intro again by clicking &amp;quot;Intro&amp;quot; in the hamburger menu of myApps.&lt;br /&gt;
&lt;br /&gt;
Configuration:&lt;br /&gt;
* The URL of the onboarding page can be configured at: PBX / Config / myApps / Onboarding URL. The corresponding command line attribute is &amp;lt;code&amp;gt;PBX0 /onboarding&amp;lt;/code&amp;gt;. The default URL configured during install is: https://www.innovaphone.com/en/services/intro-video.html?embedded=1&lt;br /&gt;
* The information whether a user has already seen the onboarding is stored at the user object or template (User / Onboarding seen). The corresponding LDAP attribute is &amp;lt;code&amp;gt;onboarded&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following parameters are passed to the page using URL parameters:&lt;br /&gt;
;name: &amp;quot;onboarding&amp;quot;&lt;br /&gt;
;title: The title as shown in the hamburger menu of myApps (depending on the e.g. &amp;quot;Intro&amp;quot;)&lt;br /&gt;
;scheme:The color scheme (&amp;quot;light&amp;quot; or &amp;quot;dark&amp;quot;)&lt;br /&gt;
;size:The size setting of the home screen items (&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot; or &amp;quot;2&amp;quot;)&lt;br /&gt;
;lang: The myApps language (e.g. &amp;quot;de&amp;quot; or &amp;quot;en&amp;quot;)&lt;br /&gt;
;ver: The version of the PBX (e.g. &amp;quot;16r1&amp;quot;)&lt;br /&gt;
;build: The build of the PBX (e.g. &amp;quot;1510335)&lt;br /&gt;
&lt;br /&gt;
Requirements for the configured page:&lt;br /&gt;
* Must work inside an IFrame.&lt;br /&gt;
* Should follow the language given in the URL parameters, defaulting to &amp;quot;en&amp;quot; if no contents are available for the language.&lt;br /&gt;
* Should follow the collor scheme (&amp;quot;dark&amp;quot; or &amp;quot;light&amp;quot;) given in the URL parameters. &lt;br /&gt;
* Must be responsive to work in different orientations (landscape or portrait) and on different screen sizes (Desktop and Smartphone).&lt;br /&gt;
* Must reserve a space (width 306px, height 102px) for an overlay button that is displayed by myApps in the bottom right corner.&lt;br /&gt;
&lt;br /&gt;
== Tutorials app ==&lt;br /&gt;
The administrator can define an app providing tutorials or other help for end users. That app will appear in the hamburger menu of myApps as &amp;quot;Tutorials&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Requirements:&lt;br /&gt;
* Create an app object pointing to the corresponding web page (eg. https://www.innovaphone.com/myapps/tutorial.htm) via the Adv.GUI, PBX, Objects, create new App Object with a name (eg. Tutorials)&lt;br /&gt;
* Give users access to that app, preferably using templates (eg. Conf Users).&lt;br /&gt;
* Configure the app name in the admin UI &amp;quot;PBX&amp;quot;/&amp;quot;Config&amp;quot;/&amp;quot;myApps&amp;quot;/&amp;quot;Tutorial App&amp;quot; with the previous created name (eg. Tutorials).&lt;br /&gt;
&lt;br /&gt;
Note: This configuration is synchronized with the client when the connection is established. So a restart of myApps is needed for the tutorials app to appear in the hamburger menu.&lt;br /&gt;
&lt;br /&gt;
When installing a new PBX, a tutorial app provided by innovaphone is configured by default. It points to https://www.innovaphone.com/myapps/tutorial.htm and shows videos about the usage of myApps.&lt;br /&gt;
&lt;br /&gt;
== Privacy and Datastorage ==&lt;br /&gt;
&lt;br /&gt;
myApps will store the following data on your local device:&lt;br /&gt;
&lt;br /&gt;
* appclient-username / appclient-password&lt;br /&gt;
: Auth token from the user session on this device (This is not the password itself, only a random token).&lt;br /&gt;
* appclient-model&lt;br /&gt;
: Offline-files from myApps which contains the personal user data (eg. Home screen configuration and Push tokens).&lt;br /&gt;
* appclient-config&lt;br /&gt;
: URLs and credentials for local services (credentials will be new generated randomly on every startup)&lt;br /&gt;
* appclient-usr-XXXXXXXXXXXXXXXXXXX&lt;br /&gt;
: anonymized environment settings of all historical user sessions (eg. theme, element size of home screen elements, language)&lt;br /&gt;
&lt;br /&gt;
Additionally, it is allowed to every App to create own offline files or create local settings which will be stored also.&lt;br /&gt;
&lt;br /&gt;
The Chromium Cache and DOM Storage (myApps for Windows) will be stored in &amp;lt;code&amp;gt;%appdata%\innovaphone\myApps\chromium\cache&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Idle Bandwidth =&lt;br /&gt;
== myApps ==&lt;br /&gt;
The myApps client opens a single Websocket connection to the PBX. When the connection is idle, the PBX sends just a Websocket PING/PONG every 60s. Note that the PING/PONG exchange prevents TCP KeepAlive Messages, so there is no additional load for it.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  PING        20 bytes    20 bytes      31 bytes      71 bytes       &lt;br /&gt;
  PONG        20 bytes    20 bytes      35 bytes      75 bytes&lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     186 bytes / min&lt;br /&gt;
                                                  11.160 bytes / h&lt;br /&gt;
                                                 267.840 bytes / d&lt;br /&gt;
&lt;br /&gt;
== Apps ==&lt;br /&gt;
Most apps also open a Websocket connection to the PBX or App Platform and also use the PING/PONG mechanism. So the idle load is identical to myApps.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  PING        20 bytes    20 bytes      31 bytes      71 bytes       &lt;br /&gt;
  PONG        20 bytes    20 bytes      35 bytes      75 bytes&lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     186 bytes / min&lt;br /&gt;
                                                  11.160 bytes / h&lt;br /&gt;
                                                 267.840 bytes / d&lt;br /&gt;
&lt;br /&gt;
There are some apps - like the phone apps - send a Websocket message {&amp;quot;mt&amp;quot;:&amp;quot;KeepAlive&amp;quot;} on application layer every 60s to the PBX to dectect connection problems faster. Note that sending the message both prevents PING/PONG by the server and TCP KeepAlive, so there is no additonal load for it. In that case the idle bandwith can be calculated like follows.&lt;br /&gt;
&lt;br /&gt;
  Message     IP header   TCP header    TLS payload   Total bytes&lt;br /&gt;
  KeepAlive   20 bytes    20 bytes      53 bytes      93 bytes       &lt;br /&gt;
  ACK         20 bytes    20 bytes      -             40 bytes&lt;br /&gt;
  ------------------------------------------------------------------&lt;br /&gt;
                                                     133 bytes / min&lt;br /&gt;
                                                   7.980 bytes / h&lt;br /&gt;
                                                 191.520 bytes / d&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting =&lt;br /&gt;
&lt;br /&gt;
Client-side&lt;br /&gt;
*The myApps web uses the logging facilities provided by the browser it runs in (i.e. JavaScript function &amp;lt;code&amp;gt;console.log&amp;lt;/code&amp;gt;).  In most browser this is available as &#039;&#039;Console&#039;&#039; after pressing F12.&lt;br /&gt;
*The myApps platform services provide more elaborate tracing mechanisms. See &#039;&#039;Troubleshooting&#039;&#039; in [[{{NAMESPACE}}:Concept_myApps_platform_services#Troubleshooting|Concept myApps platform services]].&lt;br /&gt;
&lt;br /&gt;
PBX-side&lt;br /&gt;
*The Syslog can be used to log all connections to the PBX. See [[Reference16r1:Concept_myApps#Syslog]].&lt;br /&gt;
*You can activate the trace flag Servlets to see all websocket messages from and to the PBX. &amp;lt;code&amp;gt;!config add HTTP0 /servlet-trace on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Related Articles =&lt;br /&gt;
* [[{{NAMESPACE}}:Concept myApps platform services]]&lt;br /&gt;
&lt;br /&gt;
= Known Problems =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Problem_myApps|Known Problems]]&lt;/div&gt;</summary>
		<author><name>Ckl</name></author>
	</entry>
	<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>
</feed>