"use strict"; // Convert querystring name/value pairs into dictionary. const QUERY_STRING = (function (a) { if (a == '') return {}; const b = {}; for (let i = 0; i < a.length; ++i) { const p = a[i].split('=', 2); if (p.length == 1) b[p[0]] = ''; else b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, ' ')); } return b; })(window.location.search.substr(1).split('&')); function onReaderDataReceived(deviceType, data) { console.log(data + '\n' + hexView(data)); } // Name of group that the client will join on connection const QSS_GROUP_NAME = 'DeviceUsers'; const SIGNALR_CONNECTION_STATE_LABEL = { 0: 'Connecting', 1: 'Connected', 2: 'Reconnecting', 4: 'Disconnected' }; // A unified wrapper to handle both Framework and Core SignalR APIs. const QSS_API_WRAPPER = { connection: null, type: null, // 'framework' or 'core' deviceHubProxy: null, // only populated in 'framework' // Map a server-side call invokeServerMethod: function (methodName, ...args) { if (this.type === 'framework') { // Framework API call return this.deviceHubProxy.invoke(methodName, ...args); } else { // Core API call return this.connection.invoke(methodName, ...args); } }, // Map a client-side listener onClientMethod: function (methodName, callback) { if (this.type === 'framework') { // Framework client-side listener this.deviceHubProxy.on(methodName, callback); } else { // Core client-side listener this.connection.on(methodName, callback); } } }; function isNullEmptyOrWhitespace(value) { if (value == null) { return true; } if (typeof value === 'string') { return value.trim().length === 0; } return false; } async function startSignalR(callback) { if (!('qssUrl' in QUERY_STRING) || isNullEmptyOrWhitespace(QUERY_STRING['qssUrl'])) { console.warn('Missing "qssUrl" in query string'); return; } console.log('Attempting SignalR ASP.NET Framework connection...'); // // ASP.NET Framework // QSS_API_WRAPPER.connection = $.hubConnection(QUERY_STRING['qssUrl'], { useDefaultPath: false }); QSS_API_WRAPPER.deviceHubProxy = QSS_API_WRAPPER.connection.createHubProxy('deviceHub'); // Redirect Framework events to event handlers provided in callback class QSS_API_WRAPPER.connection.starting(function () { callback.framework_starting(); }); QSS_API_WRAPPER.connection.received(function (data) { callback.framework_received(data); }); QSS_API_WRAPPER.connection.connectionSlow(function () { callback.framework_connectionSlow(); }); QSS_API_WRAPPER.connection.reconnecting(function () { callback.framework_reconnecting(); }); QSS_API_WRAPPER.connection.reconnected(function () { callback.framework_reconnected(); }); QSS_API_WRAPPER.connection.stateChanged(function (change) { callback.framework_stateChanged(change); }); QSS_API_WRAPPER.connection.disconnected(function () { callback.framework_disconnected(); }); try { await new Promise((resolve, reject) => { QSS_API_WRAPPER.connection.start() .done(() => { console.log("Connected to ASP.NET Framework SignalR!"); QSS_API_WRAPPER.deviceHubProxy.invoke('JoinGroup', QSS_GROUP_NAME) .done(function () { console.log('Joined group: ' + QSS_GROUP_NAME); }) .fail(function (error) { console.error('Invocation of JoinGroup failed. Error:', error); }); resolve(); }) .fail((err) => { reject(err); }); }); QSS_API_WRAPPER.type = 'framework'; } catch (frameworkErr) { console.warn("Framework connection failed. Trying ASP.NET Core...", frameworkErr); // // ASP.NET Core // QSS_API_WRAPPER.connection = new signalR.HubConnectionBuilder() .withUrl(QUERY_STRING['qssUrl']) .withAutomaticReconnect() // Required to perform automatic reconnects .build(); // Redirect Core events to event handlers provided in callback class QSS_API_WRAPPER.connection.onreconnecting(function (error) { console.log('onreconnecting'); callback.core_onreconnecting(error); }); QSS_API_WRAPPER.connection.onreconnected(function (connectionId) { console.log('onreconnected'); callback.core_onreconnected(connectionId); }); QSS_API_WRAPPER.connection.onclose(function (error) { console.log('onclose'); callback.core_onclose(error); }); try {