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.

Copy
# 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.

Copy

TypeScript Example

import {getVersion, getBuildDate} from "@crestron/ch5-webxpanel"

console.log(`WebXPanel version: ${getVersion()}`); 
console.log(`WebXPanel build date: ${getBuildDate()}`); 

 

Copy

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):

Copy
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 },
    // ... 
  ], 
  // ... 
}) 

// ... 

 

Copy

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.

Copy

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 
}); 

 

Copy

JavaScript Example

    // Display License errors 
    WebXPanel.default.addEventListener(WebXPanel.WebXPanelEvents.LICENSE_WS, ({ detail }) => { 
      updateDialogLicenseInfo(detail); 
    }); 

    functionupdateDialogLicenseInfo(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"
      } elseif (!resourceAvailable) { 
        licenseText.textContent = "Mobility license is required (expired or never applied)"
      } elseif (licenseApplied) { 
        if (!licenseHasExpiry) { 
          licenseText.textContent = "Mobility license is valid"
        } else { 
          // Display warning 
          licenseText.textContent = `Mobility license expires in ${licenseDaysRemaining} day(s)`
        } 
      } elseif (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.

Copy

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}`); 
  }); 

 

Copy

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.

Copy

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}`); 
  }); 

 

Copy

JavaScript Example

  WebXPanel.default.addEventListener(WebXPanel.WebXPanelEvents.DISCONNECT_CIP, ({detail}) => { 
    const {reason} = detail; 
    console.log(`Disconnected from CIP. Reason: ${reason}`); 
  });