Add XPanel to Custom (Non‑Template) Project
The Crestron Template Project provides complete integration with the HTML5 Web XPanel library. For developers that choose to use custom (non-template) projects, the following sections describe how to interface with the HTMl5 Web XPanel library.
Install the Library
The HTML5 Web XPanel library (WebXPanel) is distributed on NPM similar to the CH5 Component library. Use the following commands to install the library.
# NPM
npm install @crestron/ch5-webxpanel
# Yarn
yarn add @crestron/ch5-webxpanel
Access the Library
The WebXPanel library is provided in ES6 format.
If your project uses ES6 import statements, you can use a WebXPanel.default as a global module.
Access the Version and Build Date
TypeScript and JavaScript examples are provided below for accessing the WebXPanel library version and build date.
TypeScript Example
import {getVersion, getBuildDate} from "@crestron/ch5-webxpanel";
console.log(`WebXPanel version: ${getVersion()}`);
console.log(`WebXPanel build date: ${getBuildDate()}`);
JavaScript Example
console.log(`WebXPanel version: ${WebXPanel.getVersion()}`);
console.log(`WebXPanel build date: ${WebXPanel.getBuildDate()}`);
Configuration and Initialization
NOTE: Ensure that WebXPanel is the first library that is initialized in your custom project.
All configuration parameters are optional. Only the parameters that need to be overwritten should be defined. Do not pass empty string values for parameters that should not be defined.
Your project should not initialize the WebXPanel library if it is running on a Crestron touch screen or other device with native support to communicate to the control system. For these devices, the WebXPanel library will not be active; a property called ‘isActive’ is provided to indicate that it will not communicate with the control system.
The WebXPanel library also provides an ‘initialize’ function to provide configuration for the control system IP address/hostname, IP ID, and Room ID (for VC-4).
The port defaults to the WebSocket port used to communicate with the control system. Do not supply this value unless the port has been changed from default on the control system.
The other two parameters (tokenUrl and tokenSource) should not be changed. They are for future integrations.
Refer to the following example code (app.module.ts):
import WebXPanel, {WebXPanelConfigParams, isActive} from "@crestron/ch5-webxpanel";
const configuration: Partial<WebXPanelConfigParams> = {
host: 'ip_address | hostname', // defaults to window.location.host
ipId: '3|0x03', // string representing a hex value. Might contain "0x" or not. Defaults to "0x03"
roomId: 'virtual_control_room_id', // defaults to empty string
};
// other rarely used options
// port: 49200, // port for Secure WebSocket connection. Defaults to 49200
// tokenUrl: 'https://url/cws/websocket/getWebSocketToken', // defaults to `${location.origin}/cws/websocket/getWebSocketToken`,
// tokenSource: 'CSSelf|Fusion', // defaults to CSSelf
const webXPanelFactory = () => () => {
if (isActive) {
WebXPanel.initialize(configuration);
}
}
// ...
@NgModule({
// ...
providers: [
{ provide: APP_INITIALIZER, useFactory: webXPanelFactory, multi: true },
// ...
],
// ...
})
// ...
Simple JavaScript Example
const configuration = {
host: 'ip_address | hostname', // defaults to window.location.host
ipId: '3|0x03', // string representing a hex value. Might contain "0x" or not. Defaults to "0x03"
roomId: 'virtual_control_room_id', // defaults to empty string
};
if (WebXPanel.isActive){
WebXPanel.default.initialize(configuration);
}
Listen to WebXPanel Events
All events dispatched by WebXPanel are CustomEvents. The relevant data within each event can be found in the detail property.
Many of these events are also available as Reserve Join state messages. Refer to Reserve Joins for more information.
The following events are available for listening:
Event | Dispatch Reason | Notes |
---|---|---|
CONNECT_WS | A successful WebSocket connection has been established | Similar to WebSocket.onopen |
DISCONNECT_WS | The WebSocket connection was disconnected | Similar to WebSocket.onclose |
ERROR_WS | A error occurred over the WebSocket connection | Similar to WebSocket.onerror |
WEB_WORKER_FAILED | Worker is not supported in the current browser | |
CONNECT_CIP | Successfully connected to the control system over CIP protocol | Provides information about the current connection. Not the same as CONNECT_WS |
DISCONNECT_CIP | Disconnected from the control system over CIP protocol | Not the same as DISCONNECT_WS |
AUTHENTICATION_FAILED | Failed to authenticate to the control system | |
AUTHENTICATION_REQUIRED | Authentication token is required by the control system | |
LICENSE_WS | A change occurred in the license (such as a received license or a license/trial period update) | |
NOT_AUTHORIZED | The /cws/websocket/getWebSocketToken endpoint response is a redirect |
Refer to the following sample code showing how to listen to the LICENSE_WS event from a custom project.
TypeScript Example
import WebXPanel, {WebXPanelEvents} from "@crestron/ch5-webxpanel";
WebXPanel.addEventListener(WebXPanelEvents.LICENSE_WS, ({detail}) => {
const {
resourceAvailable,
controlSystemSupportsLicense,
licenseApplied,
licenseHasExpiry,
licenseDaysRemaining,
trialPeriod,
trialPeriodDaysRemaining,
} = detail;
// other callback code
});
JavaScript Example
// Display License errors
WebXPanel.default.addEventListener(WebXPanel.WebXPanelEvents.LICENSE_WS, ({ detail }) => {
updateDialogLicenseInfo(detail);
});
function updateDialogLicenseInfo(detail) {
const controlSystemSupportsLicense = detail.controlSystemSupportsLicense; // boolean
const licenseApplied = detail.licenseApplied; // optional boolean
const licenseDaysRemaining = detail.licenseDaysRemaining; // optional number
const licenseHasExpiry = detail.licenseHasExpiry; // optional boolean
const trialPeriod = detail.trialPeriod; // optional boolean
const trialPeriodDaysRemaining = detail.trialPeriodDaysRemaining; // optional number
const resourceAvailable = detail.resourceAvailable; // boolean
const licenseText = document.getElementById("webXPnlLicense");
if (!controlSystemSupportsLicense) {
licenseText.textContent = "Control system does not support Mobility license";
} else if (!resourceAvailable) {
licenseText.textContent = "Mobility license is required (expired or never applied)";
} else if (licenseApplied) {
if (!licenseHasExpiry) {
licenseText.textContent = "Mobility license is valid";
} else {
// Display warning
licenseText.textContent = `Mobility license expires in ${licenseDaysRemaining} day(s)`;
}
} else if (trialPeriod) {
licenseText.textContent = ` Trial period expires in ${trialPeriodDaysRemaining} day(s)`;
}
}
Refer to the following sample code showing how to listen to the CONNECT_CIP event from a custom project.
TypeScript Example
import WebXPanel, {WebXPanelEvents} from "@crestron/ch5-webxpanel";
WebXPanel.addEventListener(WebXPanelEvents.CONNECT_CIP, ({detail}) => {
const {url, ipId, roomId} = detail;
console.log(`Connected to ${url}, 0x${ ipId.toString(16)}, ${roomId}`);
});
JavaScript Example
WebXPanel.default.addEventListener(WebXPanel.WebXPanelEvents.CONNECT_CIP, ({detail}) => {
const {url, ipId, roomId} = detail;
console.log(`Connected to ${url}, 0x${ ipId.toString(16)}, ${roomId}`);
});
Refer to the following sample code showing how to listen to the DISCONNECT_CIP event from a custom project.
TypeScript Example
import WebXPanel, {WebXPanelEvents} from "@crestron/ch5-webxpanel";
WebXPanel.addEventListener(WebXPanelEvents.DISCONNECT_CIP, ({detail}) => {
const {reason} = detail;
console.log(`Disconnected from CIP. Reason: ${reason}`);
});
JavaScript Example
WebXPanel.default.addEventListener(WebXPanel.WebXPanelEvents.DISCONNECT_CIP, ({detail}) => {
const {reason} = detail;
console.log(`Disconnected from CIP. Reason: ${reason}`);
});