@phystack/hub-client 4.4.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +10 -0
- package/.prettierrc +10 -0
- package/CHANGELOG.md +1202 -0
- package/README-MEDIASTREAM.md +124 -0
- package/README.md +302 -0
- package/dist/constants/constants.d.ts +7 -0
- package/dist/constants/constants.d.ts.map +1 -0
- package/dist/constants/constants.js +10 -0
- package/dist/constants/constants.js.map +1 -0
- package/dist/helpers/browser.helper.d.ts +5 -0
- package/dist/helpers/browser.helper.d.ts.map +1 -0
- package/dist/helpers/browser.helper.js +19 -0
- package/dist/helpers/browser.helper.js.map +1 -0
- package/dist/helpers/cache.helper.d.ts +6 -0
- package/dist/helpers/cache.helper.d.ts.map +1 -0
- package/dist/helpers/cache.helper.js +46 -0
- package/dist/helpers/cache.helper.js.map +1 -0
- package/dist/helpers/date.helper.d.ts +4 -0
- package/dist/helpers/date.helper.d.ts.map +1 -0
- package/dist/helpers/date.helper.js +13 -0
- package/dist/helpers/date.helper.js.map +1 -0
- package/dist/helpers/session.helper.d.ts +13 -0
- package/dist/helpers/session.helper.d.ts.map +1 -0
- package/dist/helpers/session.helper.js +88 -0
- package/dist/helpers/session.helper.js.map +1 -0
- package/dist/helpers/shorten-look-ups.helper.d.ts +3 -0
- package/dist/helpers/shorten-look-ups.helper.d.ts.map +1 -0
- package/dist/helpers/shorten-look-ups.helper.js +80 -0
- package/dist/helpers/shorten-look-ups.helper.js.map +1 -0
- package/dist/helpers/signals-client.helper.d.ts +9 -0
- package/dist/helpers/signals-client.helper.d.ts.map +1 -0
- package/dist/helpers/signals-client.helper.js +44 -0
- package/dist/helpers/signals-client.helper.js.map +1 -0
- package/dist/helpers/signals.helper.d.ts +19 -0
- package/dist/helpers/signals.helper.d.ts.map +1 -0
- package/dist/helpers/signals.helper.js +48 -0
- package/dist/helpers/signals.helper.js.map +1 -0
- package/dist/helpers/wrtc/browser.d.ts +3 -0
- package/dist/helpers/wrtc/browser.d.ts.map +1 -0
- package/dist/helpers/wrtc/browser.js +11 -0
- package/dist/helpers/wrtc/browser.js.map +1 -0
- package/dist/helpers/wrtc/index.d.ts +5 -0
- package/dist/helpers/wrtc/index.d.ts.map +1 -0
- package/dist/helpers/wrtc/index.js +30 -0
- package/dist/helpers/wrtc/index.js.map +1 -0
- package/dist/helpers/wrtc/node.d.ts +3 -0
- package/dist/helpers/wrtc/node.d.ts.map +1 -0
- package/dist/helpers/wrtc/node.js +18 -0
- package/dist/helpers/wrtc/node.js.map +1 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1013 -0
- package/dist/index.js.map +1 -0
- package/dist/services/online-status-subscription.service.d.ts +28 -0
- package/dist/services/online-status-subscription.service.d.ts.map +1 -0
- package/dist/services/online-status-subscription.service.js +96 -0
- package/dist/services/online-status-subscription.service.js.map +1 -0
- package/dist/services/phyhub-connection.service.d.ts +20 -0
- package/dist/services/phyhub-connection.service.d.ts.map +1 -0
- package/dist/services/phyhub-connection.service.js +176 -0
- package/dist/services/phyhub-connection.service.js.map +1 -0
- package/dist/services/signals.service.d.ts +97 -0
- package/dist/services/signals.service.d.ts.map +1 -0
- package/dist/services/signals.service.js +536 -0
- package/dist/services/signals.service.js.map +1 -0
- package/dist/services/webrtc/datachannel.d.ts +10 -0
- package/dist/services/webrtc/datachannel.d.ts.map +1 -0
- package/dist/services/webrtc/datachannel.js +290 -0
- package/dist/services/webrtc/datachannel.js.map +1 -0
- package/dist/services/webrtc/mediastream.d.ts +10 -0
- package/dist/services/webrtc/mediastream.d.ts.map +1 -0
- package/dist/services/webrtc/mediastream.js +396 -0
- package/dist/services/webrtc/mediastream.js.map +1 -0
- package/dist/services/webrtc/peer-connection-ice.d.ts +32 -0
- package/dist/services/webrtc/peer-connection-ice.d.ts.map +1 -0
- package/dist/services/webrtc/peer-connection-ice.js +483 -0
- package/dist/services/webrtc/peer-connection-ice.js.map +1 -0
- package/dist/types/signal.types.d.ts +354 -0
- package/dist/types/signal.types.d.ts.map +1 -0
- package/dist/types/signal.types.js +53 -0
- package/dist/types/signal.types.js.map +1 -0
- package/dist/types/twin.types.d.ts +705 -0
- package/dist/types/twin.types.d.ts.map +1 -0
- package/dist/types/twin.types.js +21 -0
- package/dist/types/twin.types.js.map +1 -0
- package/dist/types/webrtc.types.d.ts +41 -0
- package/dist/types/webrtc.types.d.ts.map +1 -0
- package/dist/types/webrtc.types.js +3 -0
- package/dist/types/webrtc.types.js.map +1 -0
- package/package.json +50 -0
- package/src/constants/constants.ts +12 -0
- package/src/helpers/browser.helper.ts +15 -0
- package/src/helpers/cache.helper.ts +52 -0
- package/src/helpers/date.helper.ts +8 -0
- package/src/helpers/session.helper.ts +96 -0
- package/src/helpers/shorten-look-ups.helper.ts +75 -0
- package/src/helpers/signals-client.helper.ts +54 -0
- package/src/helpers/signals.helper.ts +41 -0
- package/src/helpers/wrtc/browser.ts +9 -0
- package/src/helpers/wrtc/index.ts +32 -0
- package/src/helpers/wrtc/node.ts +16 -0
- package/src/index.ts +1429 -0
- package/src/services/online-status-subscription.service.ts +127 -0
- package/src/services/phyhub-connection.service.ts +213 -0
- package/src/services/signals.service.ts +783 -0
- package/src/services/webrtc/datachannel.ts +421 -0
- package/src/services/webrtc/mediastream.ts +602 -0
- package/src/services/webrtc/peer-connection-ice.ts +689 -0
- package/src/types/lodash.d.ts +3 -0
- package/src/types/signal.types.ts +382 -0
- package/src/types/twin.types.ts +803 -0
- package/src/types/webrtc.types.ts +48 -0
- package/tsconfig.json +45 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1013 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectPhyClient = exports.PhyHubClient = void 0;
|
|
4
|
+
const twin_types_1 = require("./types/twin.types");
|
|
5
|
+
const phyhub_connection_service_1 = require("./services/phyhub-connection.service");
|
|
6
|
+
const signals_service_1 = require("./services/signals.service");
|
|
7
|
+
const signal_types_1 = require("./types/signal.types");
|
|
8
|
+
const datachannel_1 = require("./services/webrtc/datachannel");
|
|
9
|
+
const mediastream_1 = require("./services/webrtc/mediastream");
|
|
10
|
+
(async function initializeWebRTCGlobals() {
|
|
11
|
+
if (typeof window !== 'undefined')
|
|
12
|
+
return;
|
|
13
|
+
try {
|
|
14
|
+
const wrtc = require('@roamhq/wrtc');
|
|
15
|
+
if (typeof global.MediaStream === 'undefined' && wrtc.MediaStream) {
|
|
16
|
+
global.MediaStream = wrtc.MediaStream;
|
|
17
|
+
console.log('Global MediaStream initialized');
|
|
18
|
+
}
|
|
19
|
+
if (typeof global.RTCPeerConnection === 'undefined' && wrtc.RTCPeerConnection) {
|
|
20
|
+
global.RTCPeerConnection = wrtc.RTCPeerConnection;
|
|
21
|
+
console.log('Global RTCPeerConnection initialized');
|
|
22
|
+
}
|
|
23
|
+
if (typeof global.RTCSessionDescription === 'undefined' && wrtc.RTCSessionDescription) {
|
|
24
|
+
global.RTCSessionDescription = wrtc.RTCSessionDescription;
|
|
25
|
+
console.log('Global RTCSessionDescription initialized');
|
|
26
|
+
}
|
|
27
|
+
if (typeof global.RTCIceCandidate === 'undefined' && wrtc.RTCIceCandidate) {
|
|
28
|
+
global.RTCIceCandidate = wrtc.RTCIceCandidate;
|
|
29
|
+
console.log('Global RTCIceCandidate initialized');
|
|
30
|
+
}
|
|
31
|
+
if (typeof global.RTCVideoSource === 'undefined' && wrtc.nonstandard.RTCVideoSource) {
|
|
32
|
+
global.RTCVideoSource = wrtc.nonstandard.RTCVideoSource;
|
|
33
|
+
console.log('Global RTCVideoSource initialized');
|
|
34
|
+
}
|
|
35
|
+
console.log('WebRTC globals successfully initialized');
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error('Failed to initialize WebRTC globals:', error);
|
|
39
|
+
}
|
|
40
|
+
})().catch(err => console.error('Error in WebRTC globals initialization:', err));
|
|
41
|
+
class PhyHubClient {
|
|
42
|
+
constructor(params = {}) {
|
|
43
|
+
this.instanceId = undefined;
|
|
44
|
+
this.moduleName = undefined;
|
|
45
|
+
this.socket = null;
|
|
46
|
+
this.socketConnected = false;
|
|
47
|
+
this.emitQueue = [];
|
|
48
|
+
this.lastDeviceStatusCheck = 0;
|
|
49
|
+
this.lastDeviceStatusResponse = undefined;
|
|
50
|
+
this.subscribedTwins = new Set();
|
|
51
|
+
this.twinMessageListeners = {};
|
|
52
|
+
this.instances = new Map();
|
|
53
|
+
this.peripheralInstances = new Map();
|
|
54
|
+
this.twinUpdateListeners = {};
|
|
55
|
+
this.EVENTS = {
|
|
56
|
+
PING: 'ping',
|
|
57
|
+
PONG: 'pong',
|
|
58
|
+
CONNECT: 'connect',
|
|
59
|
+
RECONNECT: 'reconnect',
|
|
60
|
+
RECONNECT_ERROR: 'reconnect_error',
|
|
61
|
+
RECONNECT_FAILED: 'reconnect_failed',
|
|
62
|
+
DISCONNECT: 'disconnect',
|
|
63
|
+
REPORT_SCREEN_INSTANCE_PROPERTIES: 'setScreenInstanceReportedProperties',
|
|
64
|
+
GET_DEVICE_STATUS: 'getDeviceStatus',
|
|
65
|
+
GET_DEVICE_NETWORKS: 'getDeviceNetworks',
|
|
66
|
+
GET_DEVICE_INSTANCE: 'getDeviceInstance',
|
|
67
|
+
GET_INSTANCE: 'getInstance',
|
|
68
|
+
SIGNAL_EVENT: 'sendEventSignal',
|
|
69
|
+
SIGNAL_CHECKOUT: 'sendEventSignal',
|
|
70
|
+
SIGNAL_PURCHASE: 'sendEventSignal',
|
|
71
|
+
SIGNAL_SESSION: 'sendSessionSignal',
|
|
72
|
+
SIGNAL_CLIENT: 'sendClientSignal',
|
|
73
|
+
TWIN_MESSAGE: 'twinMessage',
|
|
74
|
+
TWIN_SUBSCRIBE: 'twinSubscribe',
|
|
75
|
+
TWIN_UNSUBSCRIBE: 'twinUnsubscribe',
|
|
76
|
+
GET_TWIN_BY_ID: 'getTwinById',
|
|
77
|
+
};
|
|
78
|
+
this.getSocket = () => {
|
|
79
|
+
return this.socket;
|
|
80
|
+
};
|
|
81
|
+
this.initializeSignals = async (initParams) => {
|
|
82
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
|
|
83
|
+
let edgeTwin;
|
|
84
|
+
if (!initParams) {
|
|
85
|
+
await this.getDeviceStatus();
|
|
86
|
+
if (!this.lastDeviceStatusResponse) {
|
|
87
|
+
throw new Error('Failed to fetch device settings');
|
|
88
|
+
}
|
|
89
|
+
edgeTwin = (await this.getInstance());
|
|
90
|
+
if (!edgeTwin) {
|
|
91
|
+
throw new Error('Unable to determine app settings');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const initSignalsPayload = {
|
|
95
|
+
deviceId: (_d = (_b = (_a = initParams === null || initParams === void 0 ? void 0 : initParams.deviceId) !== null && _a !== void 0 ? _a : edgeTwin === null || edgeTwin === void 0 ? void 0 : edgeTwin.deviceId) !== null && _b !== void 0 ? _b : (_c = this.lastDeviceStatusResponse) === null || _c === void 0 ? void 0 : _c.deviceId) !== null && _d !== void 0 ? _d : '',
|
|
96
|
+
installationId: (_f = (_e = initParams === null || initParams === void 0 ? void 0 : initParams.installationId) !== null && _e !== void 0 ? _e : edgeTwin === null || edgeTwin === void 0 ? void 0 : edgeTwin.properties.desired.installationId) !== null && _f !== void 0 ? _f : '',
|
|
97
|
+
spaceId: (_j = (_g = initParams === null || initParams === void 0 ? void 0 : initParams.spaceId) !== null && _g !== void 0 ? _g : (_h = this.lastDeviceStatusResponse) === null || _h === void 0 ? void 0 : _h.spaceId) !== null && _j !== void 0 ? _j : '',
|
|
98
|
+
tenantId: (_m = (_k = initParams === null || initParams === void 0 ? void 0 : initParams.tenantId) !== null && _k !== void 0 ? _k : (_l = this.lastDeviceStatusResponse) === null || _l === void 0 ? void 0 : _l.tenantId) !== null && _m !== void 0 ? _m : '',
|
|
99
|
+
appVersion: (_o = initParams === null || initParams === void 0 ? void 0 : initParams.appVersion) !== null && _o !== void 0 ? _o : 'XXXXXXXXXXXXXXXXXXXXXXXX',
|
|
100
|
+
appId: (_p = initParams === null || initParams === void 0 ? void 0 : initParams.appId) !== null && _p !== void 0 ? _p : 'XXXXXXXXXXXXXXXXXXXXXXXX',
|
|
101
|
+
environment: (_s = (_q = initParams === null || initParams === void 0 ? void 0 : initParams.environment) !== null && _q !== void 0 ? _q : (_r = this.lastDeviceStatusResponse) === null || _r === void 0 ? void 0 : _r.gridEnv) !== null && _s !== void 0 ? _s : '',
|
|
102
|
+
dataResidency: ((_v = (_t = initParams === null || initParams === void 0 ? void 0 : initParams.dataResidency) !== null && _t !== void 0 ? _t : (_u = this.lastDeviceStatusResponse) === null || _u === void 0 ? void 0 : _u.dataResidency) !== null && _v !== void 0 ? _v : '').toUpperCase(),
|
|
103
|
+
country: (_w = initParams === null || initParams === void 0 ? void 0 : initParams.country) !== null && _w !== void 0 ? _w : 'SE',
|
|
104
|
+
installationVersion: (_x = initParams === null || initParams === void 0 ? void 0 : initParams.installationVersion) !== null && _x !== void 0 ? _x : 'XXXXXXXXXXXXXXXXXXXXXXXX',
|
|
105
|
+
accessToken: (_y = initParams === null || initParams === void 0 ? void 0 : initParams.accessToken) !== null && _y !== void 0 ? _y : (_z = this.lastDeviceStatusResponse) === null || _z === void 0 ? void 0 : _z.accessKey,
|
|
106
|
+
clientUserAgent: (_0 = initParams === null || initParams === void 0 ? void 0 : initParams.clientUserAgent) !== null && _0 !== void 0 ? _0 : undefined,
|
|
107
|
+
ip: (_5 = (_1 = initParams === null || initParams === void 0 ? void 0 : initParams.ip) !== null && _1 !== void 0 ? _1 : (_4 = (_3 = (_2 = this.lastDeviceStatusResponse) === null || _2 === void 0 ? void 0 : _2.ip) === null || _3 === void 0 ? void 0 : _3[0]) === null || _4 === void 0 ? void 0 : _4.ipv4) !== null && _5 !== void 0 ? _5 : 'N/A',
|
|
108
|
+
};
|
|
109
|
+
this.signals = new signals_service_1.SignalsService(this, initSignalsPayload);
|
|
110
|
+
return this.signals;
|
|
111
|
+
};
|
|
112
|
+
this.getDataChannel = async (targetTwinId) => {
|
|
113
|
+
const options = {
|
|
114
|
+
targetTwinId,
|
|
115
|
+
sendTwinMessage: this.sendTwinMessage.bind(this),
|
|
116
|
+
subscribeTwin: this.subscribeTwin.bind(this),
|
|
117
|
+
onTwinMessage: this.onTwinMessage.bind(this),
|
|
118
|
+
offTwinMessage: this.offTwinMessage.bind(this),
|
|
119
|
+
useStun: true,
|
|
120
|
+
isInitiator: true,
|
|
121
|
+
channelPrefix: 'channel',
|
|
122
|
+
mediaOptions: { isMediaConnection: false },
|
|
123
|
+
};
|
|
124
|
+
const result = (await (0, datachannel_1.createWebRTCDataChannelConnection)(options));
|
|
125
|
+
return result.dataChannel;
|
|
126
|
+
};
|
|
127
|
+
this.onDataChannel = async (sourceTwinId, callback) => {
|
|
128
|
+
const options = {
|
|
129
|
+
targetTwinId: sourceTwinId,
|
|
130
|
+
sendTwinMessage: this.sendTwinMessage.bind(this),
|
|
131
|
+
subscribeTwin: this.subscribeTwin.bind(this),
|
|
132
|
+
onTwinMessage: this.onTwinMessage.bind(this),
|
|
133
|
+
offTwinMessage: this.offTwinMessage.bind(this),
|
|
134
|
+
useStun: true,
|
|
135
|
+
isInitiator: false,
|
|
136
|
+
channelPrefix: 'channel',
|
|
137
|
+
mediaOptions: { isMediaConnection: false },
|
|
138
|
+
};
|
|
139
|
+
const result = (await (0, datachannel_1.createWebRTCDataChannelConnection)(options));
|
|
140
|
+
callback(result.dataChannel);
|
|
141
|
+
};
|
|
142
|
+
this.onMediaStream = async (sourceTwinId, callback) => {
|
|
143
|
+
const options = {
|
|
144
|
+
targetTwinId: sourceTwinId,
|
|
145
|
+
sendTwinMessage: this.sendTwinMessage.bind(this),
|
|
146
|
+
subscribeTwin: this.subscribeTwin.bind(this),
|
|
147
|
+
onTwinMessage: this.onTwinMessage.bind(this),
|
|
148
|
+
offTwinMessage: this.offTwinMessage.bind(this),
|
|
149
|
+
isInitiator: false,
|
|
150
|
+
channelPrefix: 'media',
|
|
151
|
+
mediaOptions: {
|
|
152
|
+
isMediaConnection: true,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
const result = await (0, mediastream_1.createWebRTCMediaStreamConnection)(options);
|
|
156
|
+
callback(result.mediaStream);
|
|
157
|
+
};
|
|
158
|
+
this.instanceId = params.instanceId;
|
|
159
|
+
if (!this.instanceId) {
|
|
160
|
+
if (typeof window !== 'undefined') {
|
|
161
|
+
console.log('Running in browser, looking for instanceId in URL hash', window.location.hash);
|
|
162
|
+
this.instanceId =
|
|
163
|
+
new URLSearchParams(window.location.hash.slice(1)).get('instanceId') || undefined;
|
|
164
|
+
console.log('Found instanceId in URL hash', this.instanceId);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
this.instanceId = process.env.TWIN_ID;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
this.moduleName = params.moduleName;
|
|
171
|
+
}
|
|
172
|
+
async initializeConnection() {
|
|
173
|
+
if (this.socket && this.socketConnected) {
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
console.log('initializeConnection()', JSON.stringify({
|
|
178
|
+
instanceId: this.instanceId,
|
|
179
|
+
moduleName: this.moduleName,
|
|
180
|
+
}, null, 2));
|
|
181
|
+
const phyHubConnection = phyhub_connection_service_1.PhyHubConnection.getInstance({
|
|
182
|
+
instanceId: this.instanceId,
|
|
183
|
+
moduleName: this.moduleName,
|
|
184
|
+
});
|
|
185
|
+
this.socket = await phyHubConnection.getPhyHubSocket();
|
|
186
|
+
await new Promise((resolve, reject) => {
|
|
187
|
+
var _a, _b, _c;
|
|
188
|
+
if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected) {
|
|
189
|
+
this.socketConnected = true;
|
|
190
|
+
resolve();
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
(_b = this.socket) === null || _b === void 0 ? void 0 : _b.once('connect', () => {
|
|
194
|
+
this.socketConnected = true;
|
|
195
|
+
resolve();
|
|
196
|
+
});
|
|
197
|
+
(_c = this.socket) === null || _c === void 0 ? void 0 : _c.once('connect_error', error => {
|
|
198
|
+
reject(error);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
this.setupSocketListeners((value) => value, (reason) => {
|
|
203
|
+
throw reason;
|
|
204
|
+
});
|
|
205
|
+
return this;
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
this.socket = null;
|
|
209
|
+
this.socketConnected = false;
|
|
210
|
+
throw err;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
setupSocketListeners(resolve, _reject) {
|
|
214
|
+
if (!this.socket)
|
|
215
|
+
return;
|
|
216
|
+
this.socket.on(this.EVENTS.PONG, (data) => {
|
|
217
|
+
setTimeout(() => {
|
|
218
|
+
this.emit('ping', { count: data.data.count + 1 });
|
|
219
|
+
}, 30000);
|
|
220
|
+
});
|
|
221
|
+
this.socket.on(this.EVENTS.CONNECT, () => {
|
|
222
|
+
this.socketConnected = true;
|
|
223
|
+
this.emit(this.EVENTS.PING, { count: 1 });
|
|
224
|
+
this.processEmitQueue();
|
|
225
|
+
this.subscribedTwins.forEach(twinId => {
|
|
226
|
+
this.subscribeTwin(twinId).catch(error => {
|
|
227
|
+
console.error(`Failed to re-subscribe to twin ${twinId}:`, error);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
resolve(this);
|
|
231
|
+
});
|
|
232
|
+
this.socket.io.on(this.EVENTS.RECONNECT, () => {
|
|
233
|
+
this.socketConnected = true;
|
|
234
|
+
this.processEmitQueue();
|
|
235
|
+
this.subscribedTwins.forEach(twinId => {
|
|
236
|
+
this.subscribeTwin(twinId).catch(error => {
|
|
237
|
+
console.error(`Failed to re-subscribe to twin ${twinId}:`, error);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
this.socket.io.on(this.EVENTS.RECONNECT_ERROR, () => {
|
|
242
|
+
this.socketConnected = false;
|
|
243
|
+
});
|
|
244
|
+
this.socket.io.on(this.EVENTS.RECONNECT_FAILED, () => {
|
|
245
|
+
this.socketConnected = false;
|
|
246
|
+
});
|
|
247
|
+
this.socket.on(this.EVENTS.DISCONNECT, () => {
|
|
248
|
+
this.socketConnected = false;
|
|
249
|
+
});
|
|
250
|
+
this.socket.on(this.EVENTS.TWIN_MESSAGE, (payload) => {
|
|
251
|
+
if (payload.twinId && payload.data) {
|
|
252
|
+
const listeners = this.twinMessageListeners[payload.twinId];
|
|
253
|
+
if (listeners) {
|
|
254
|
+
listeners.forEach(callback => {
|
|
255
|
+
try {
|
|
256
|
+
callback(payload);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
console.error(`Error in twin message listener for ${payload.twinId}:`, error);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
this.socket.on('twinUpdated', (payload) => {
|
|
270
|
+
console.log('twinUpdated event received', JSON.stringify(payload, null, 2));
|
|
271
|
+
if (payload.data) {
|
|
272
|
+
const twinId = payload.twinId || payload.data.id;
|
|
273
|
+
if (twinId && this.twinUpdateListeners[twinId]) {
|
|
274
|
+
this.twinUpdateListeners[twinId].forEach(cb => {
|
|
275
|
+
try {
|
|
276
|
+
cb(payload.data);
|
|
277
|
+
console.log('twinUpdateListeners[twinId].forEach() callback executed', JSON.stringify(payload.data, null, 2));
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
console.error(`Error in twin update listener for ${twinId}:`, error);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
async assureSocketConnection() {
|
|
288
|
+
if (!this.socket || !this.socketConnected) {
|
|
289
|
+
await this.initializeConnection();
|
|
290
|
+
}
|
|
291
|
+
if (!this.socket) {
|
|
292
|
+
throw new Error('Socket not initialized');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
static async connect(params = {}) {
|
|
296
|
+
console.info(`connect(): Connecting to phyhub`);
|
|
297
|
+
if (!PhyHubClient.instance) {
|
|
298
|
+
PhyHubClient.instance = new PhyHubClient(params);
|
|
299
|
+
await PhyHubClient.instance.initializeConnection();
|
|
300
|
+
console.info(`connect(): Connection to phyhub initialized`);
|
|
301
|
+
}
|
|
302
|
+
return PhyHubClient.instance;
|
|
303
|
+
}
|
|
304
|
+
isConnected() {
|
|
305
|
+
return this.socketConnected;
|
|
306
|
+
}
|
|
307
|
+
async sendSignal(type, data) {
|
|
308
|
+
let eventToEmit = undefined;
|
|
309
|
+
switch (type) {
|
|
310
|
+
case signal_types_1.DataRequestTypeEnum.EVENT:
|
|
311
|
+
eventToEmit = this.EVENTS.SIGNAL_EVENT;
|
|
312
|
+
break;
|
|
313
|
+
case signal_types_1.DataRequestTypeEnum.CHECKOUT:
|
|
314
|
+
eventToEmit = this.EVENTS.SIGNAL_CHECKOUT;
|
|
315
|
+
break;
|
|
316
|
+
case signal_types_1.DataRequestTypeEnum.PURCHASE:
|
|
317
|
+
eventToEmit = this.EVENTS.SIGNAL_PURCHASE;
|
|
318
|
+
break;
|
|
319
|
+
case signal_types_1.DataRequestTypeEnum.SESSION:
|
|
320
|
+
eventToEmit = this.EVENTS.SIGNAL_SESSION;
|
|
321
|
+
break;
|
|
322
|
+
case signal_types_1.DataRequestTypeEnum.CLIENT:
|
|
323
|
+
eventToEmit = this.EVENTS.SIGNAL_CLIENT;
|
|
324
|
+
break;
|
|
325
|
+
default:
|
|
326
|
+
throw new Error(`Unsupported type ${type}`);
|
|
327
|
+
}
|
|
328
|
+
if (!eventToEmit) {
|
|
329
|
+
throw new Error(`Unsupported type ${type}`);
|
|
330
|
+
}
|
|
331
|
+
const payload = {
|
|
332
|
+
data,
|
|
333
|
+
};
|
|
334
|
+
this.emit(eventToEmit, payload);
|
|
335
|
+
}
|
|
336
|
+
async getDeviceStatus() {
|
|
337
|
+
await this.assureSocketConnection();
|
|
338
|
+
const now = Date.now();
|
|
339
|
+
const tenSeconds = 10 * 1000;
|
|
340
|
+
if (now - this.lastDeviceStatusCheck < tenSeconds) {
|
|
341
|
+
return Promise.resolve(this.lastDeviceStatusResponse);
|
|
342
|
+
}
|
|
343
|
+
return new Promise((resolve, reject) => {
|
|
344
|
+
var _a;
|
|
345
|
+
this.lastDeviceStatusCheck = now;
|
|
346
|
+
this.emit(this.EVENTS.GET_DEVICE_STATUS, (response) => {
|
|
347
|
+
this.lastDeviceStatusResponse = response;
|
|
348
|
+
resolve(response);
|
|
349
|
+
});
|
|
350
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
351
|
+
reject(error);
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
async getMediaStream(targetTwinId) {
|
|
356
|
+
const options = {
|
|
357
|
+
targetTwinId,
|
|
358
|
+
sendTwinMessage: this.sendTwinMessage.bind(this),
|
|
359
|
+
subscribeTwin: this.subscribeTwin.bind(this),
|
|
360
|
+
onTwinMessage: this.onTwinMessage.bind(this),
|
|
361
|
+
offTwinMessage: this.offTwinMessage.bind(this),
|
|
362
|
+
isInitiator: true,
|
|
363
|
+
channelPrefix: 'media',
|
|
364
|
+
mediaOptions: {
|
|
365
|
+
isMediaConnection: true,
|
|
366
|
+
mediaDirection: 'recvonly',
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
const result = await (0, mediastream_1.createWebRTCMediaStreamConnection)(options);
|
|
370
|
+
return {
|
|
371
|
+
stream: result.mediaStream,
|
|
372
|
+
close: result.close,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
async getInstance() {
|
|
376
|
+
if (!this.instanceId) {
|
|
377
|
+
throw new Error('Instance ID not set');
|
|
378
|
+
}
|
|
379
|
+
if (this.instances.has(this.instanceId)) {
|
|
380
|
+
return this.instances.get(this.instanceId);
|
|
381
|
+
}
|
|
382
|
+
await this.assureSocketConnection();
|
|
383
|
+
let instance;
|
|
384
|
+
let instanceTwin = await this.getTwinById(this.instanceId);
|
|
385
|
+
const edgeInstanceTypePrefix = 'edgeInstance';
|
|
386
|
+
const edgeTwinEmit = (type, payload) => {
|
|
387
|
+
const { id: twinId } = instanceTwin;
|
|
388
|
+
const edgeTwinMessagePayload = {
|
|
389
|
+
type: `${edgeInstanceTypePrefix}:${type}`,
|
|
390
|
+
sourceTwinId: twinId,
|
|
391
|
+
sourceDeviceId: instanceTwin.deviceId,
|
|
392
|
+
data: payload,
|
|
393
|
+
};
|
|
394
|
+
this.sendTwinMessage(twinId, edgeTwinMessagePayload);
|
|
395
|
+
};
|
|
396
|
+
const edgeTwinOn = (type, callback) => {
|
|
397
|
+
const { id: twinId } = instanceTwin;
|
|
398
|
+
const onEdgeTwinMessage = (payload) => {
|
|
399
|
+
var _a, _b;
|
|
400
|
+
const messageType = ((_a = payload.data) === null || _a === void 0 ? void 0 : _a.type) || payload.type;
|
|
401
|
+
if (messageType === `${edgeInstanceTypePrefix}:${type}`) {
|
|
402
|
+
callback(((_b = payload.data) === null || _b === void 0 ? void 0 : _b.data) || payload.data);
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
this.onTwinMessage(twinId, onEdgeTwinMessage);
|
|
408
|
+
};
|
|
409
|
+
const edgeTwinTo = (targetTwinId) => ({
|
|
410
|
+
emit: (type, payload) => {
|
|
411
|
+
const edgeTwinMessagePayload = {
|
|
412
|
+
type: `${edgeInstanceTypePrefix}:${type}`,
|
|
413
|
+
sourceTwinId: instanceTwin.id,
|
|
414
|
+
sourceDeviceId: instanceTwin.deviceId,
|
|
415
|
+
data: payload,
|
|
416
|
+
};
|
|
417
|
+
this.sendTwinMessage(targetTwinId, edgeTwinMessagePayload);
|
|
418
|
+
},
|
|
419
|
+
});
|
|
420
|
+
const getPeripheralTwins = async () => {
|
|
421
|
+
const payload = {
|
|
422
|
+
data: {
|
|
423
|
+
instanceId: instanceTwin.id,
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
return new Promise((resolve, reject) => {
|
|
427
|
+
var _a;
|
|
428
|
+
this.emit('getPeripheralTwins', payload, (response) => {
|
|
429
|
+
const { twins } = response;
|
|
430
|
+
resolve(twins || []);
|
|
431
|
+
});
|
|
432
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
433
|
+
reject(error);
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
};
|
|
437
|
+
const createPeripheralTwin = async (peripheralName, hardwareId, desiredProperties, descriptors) => {
|
|
438
|
+
const existingTwins = (await getPeripheralTwins());
|
|
439
|
+
const existingTwin = existingTwins.find((twin) => twin.properties.desired.hardwareId === hardwareId);
|
|
440
|
+
if (existingTwin) {
|
|
441
|
+
throw new Error(`Peripheral twin with hardwareId ${hardwareId} already exists`);
|
|
442
|
+
}
|
|
443
|
+
const payload = {
|
|
444
|
+
data: {
|
|
445
|
+
deviceId: instanceTwin.deviceId,
|
|
446
|
+
tenantId: instanceTwin.tenantId,
|
|
447
|
+
instanceId: instanceTwin.id,
|
|
448
|
+
peripheralName,
|
|
449
|
+
hardwareId,
|
|
450
|
+
desiredProperties,
|
|
451
|
+
descriptors,
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
return new Promise((resolve, reject) => {
|
|
455
|
+
var _a;
|
|
456
|
+
this.emit('createPeripheralTwin', payload, (response) => {
|
|
457
|
+
const { twin } = response;
|
|
458
|
+
if (!twin)
|
|
459
|
+
throw new Error('Failed to create peripheral twin');
|
|
460
|
+
resolve(twin);
|
|
461
|
+
});
|
|
462
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
463
|
+
reject(error);
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
};
|
|
467
|
+
const getDataChannel = async () => {
|
|
468
|
+
return await this.getDataChannel(instanceTwin.id);
|
|
469
|
+
};
|
|
470
|
+
const onDataChannel = async (callback) => {
|
|
471
|
+
return await this.onDataChannel(instanceTwin.id, callback);
|
|
472
|
+
};
|
|
473
|
+
const getMediaStream = async () => {
|
|
474
|
+
if (!instance) {
|
|
475
|
+
throw new Error('Instance not initialized');
|
|
476
|
+
}
|
|
477
|
+
return await this.getMediaStream(instance.id);
|
|
478
|
+
};
|
|
479
|
+
const onMediaStream = async (callback) => {
|
|
480
|
+
if (!instance) {
|
|
481
|
+
throw new Error('Instance not initialized');
|
|
482
|
+
}
|
|
483
|
+
await this.onMediaStream(instance.id, callback);
|
|
484
|
+
};
|
|
485
|
+
const updateReported = async (properties) => {
|
|
486
|
+
const newReported = {
|
|
487
|
+
...properties,
|
|
488
|
+
};
|
|
489
|
+
const result = await this.updateReportedProperties(instanceTwin.id, newReported);
|
|
490
|
+
Object.assign(instance, result);
|
|
491
|
+
return result;
|
|
492
|
+
};
|
|
493
|
+
instance = {
|
|
494
|
+
...instanceTwin,
|
|
495
|
+
emit: edgeTwinEmit,
|
|
496
|
+
on: edgeTwinOn,
|
|
497
|
+
to: edgeTwinTo,
|
|
498
|
+
createPeripheralTwin,
|
|
499
|
+
updateReported,
|
|
500
|
+
getPeripheralTwins,
|
|
501
|
+
getDataChannel,
|
|
502
|
+
onDataChannel,
|
|
503
|
+
getMediaStream,
|
|
504
|
+
onMediaStream,
|
|
505
|
+
};
|
|
506
|
+
this.instances.set(this.instanceId, instance);
|
|
507
|
+
return instance;
|
|
508
|
+
}
|
|
509
|
+
async getEdgeInstance() {
|
|
510
|
+
return this.getInstance();
|
|
511
|
+
}
|
|
512
|
+
async getScreenInstance() {
|
|
513
|
+
return this.getInstance();
|
|
514
|
+
}
|
|
515
|
+
async getPeripheralInstance(peripheralTwinId) {
|
|
516
|
+
if (this.peripheralInstances.has(peripheralTwinId)) {
|
|
517
|
+
return this.peripheralInstances.get(peripheralTwinId);
|
|
518
|
+
}
|
|
519
|
+
let peripheralInstance;
|
|
520
|
+
const edgeInstance = await this.getInstance();
|
|
521
|
+
if (!edgeInstance) {
|
|
522
|
+
console.error('Edge instance not found');
|
|
523
|
+
throw new Error('Edge instance not found');
|
|
524
|
+
}
|
|
525
|
+
const peripheralTwin = await this.getTwinById(peripheralTwinId);
|
|
526
|
+
if (!peripheralTwin) {
|
|
527
|
+
console.error(`Peripheral twin with id ${peripheralTwinId} not found`);
|
|
528
|
+
throw new Error(`Peripheral twin with id ${peripheralTwinId} not found`);
|
|
529
|
+
}
|
|
530
|
+
if (peripheralTwin.type !== twin_types_1.TwinTypeEnum.Peripheral) {
|
|
531
|
+
throw new Error(`Twin ${peripheralTwinId} is not a peripheral twin`);
|
|
532
|
+
}
|
|
533
|
+
await this.subscribeTwin(peripheralTwinId);
|
|
534
|
+
const instanceTypePrefix = 'peripheralInstance';
|
|
535
|
+
const peripheralTwinEmit = (type, payload) => {
|
|
536
|
+
const messagePayload = {
|
|
537
|
+
type: `${instanceTypePrefix}:${peripheralTwin.id}:${type}`,
|
|
538
|
+
sourceTwinId: peripheralTwin.id,
|
|
539
|
+
sourceDeviceId: edgeInstance.deviceId,
|
|
540
|
+
data: payload,
|
|
541
|
+
};
|
|
542
|
+
this.sendTwinMessage(peripheralTwin.id, messagePayload);
|
|
543
|
+
};
|
|
544
|
+
const peripheralTwinOn = (type, callback) => {
|
|
545
|
+
console.log(`Setting up listener for peripheral ${peripheralTwinId} event: ${type}`);
|
|
546
|
+
const onMessage = (payload) => {
|
|
547
|
+
var _a, _b;
|
|
548
|
+
const messageType = ((_a = payload.data) === null || _a === void 0 ? void 0 : _a.type) || payload.type;
|
|
549
|
+
if (messageType === `${instanceTypePrefix}:${peripheralTwin.id}:${type}`) {
|
|
550
|
+
callback(((_b = payload.data) === null || _b === void 0 ? void 0 : _b.data) || payload.data);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
this.onTwinMessage(peripheralTwin.id, onMessage);
|
|
556
|
+
};
|
|
557
|
+
const peripheralTwinTo = (targetTwinId) => ({
|
|
558
|
+
emit: (type, payload) => {
|
|
559
|
+
const messagePayload = {
|
|
560
|
+
type: `${instanceTypePrefix}:${peripheralTwin.id}:${type}`,
|
|
561
|
+
sourceTwinId: edgeInstance.id,
|
|
562
|
+
sourceDeviceId: edgeInstance.deviceId,
|
|
563
|
+
data: payload,
|
|
564
|
+
};
|
|
565
|
+
this.sendTwinMessage(targetTwinId, messagePayload);
|
|
566
|
+
},
|
|
567
|
+
});
|
|
568
|
+
const getDataChannel = async () => {
|
|
569
|
+
return await this.getDataChannel(peripheralTwin.id);
|
|
570
|
+
};
|
|
571
|
+
const onDataChannel = async (callback) => {
|
|
572
|
+
return await this.onDataChannel(peripheralTwin.id, callback);
|
|
573
|
+
};
|
|
574
|
+
const getMediaStream = async () => {
|
|
575
|
+
if (!peripheralInstance) {
|
|
576
|
+
throw new Error('Peripheral instance not initialized');
|
|
577
|
+
}
|
|
578
|
+
return await this.getMediaStream(peripheralInstance.id);
|
|
579
|
+
};
|
|
580
|
+
const onMediaStream = async (callback) => {
|
|
581
|
+
if (!peripheralInstance) {
|
|
582
|
+
throw new Error('Peripheral instance not initialized');
|
|
583
|
+
}
|
|
584
|
+
await this.onMediaStream(peripheralInstance.id, callback);
|
|
585
|
+
};
|
|
586
|
+
const updateReported = async (properties) => {
|
|
587
|
+
const newReported = {
|
|
588
|
+
...properties,
|
|
589
|
+
};
|
|
590
|
+
const result = await this.updateReportedProperties(peripheralTwin.id, newReported);
|
|
591
|
+
Object.assign(peripheralInstance, result);
|
|
592
|
+
return result;
|
|
593
|
+
};
|
|
594
|
+
const onUpdateReported = (callback) => {
|
|
595
|
+
let previousProperties = undefined;
|
|
596
|
+
console.log(`[onUpdateReported] Registering handler for all reported properties`);
|
|
597
|
+
this.onTwinUpdate(peripheralTwin.id, (twin) => {
|
|
598
|
+
console.log(`[onUpdateReported] Twin update received for ${peripheralTwin.id}`);
|
|
599
|
+
if (twin.id !== peripheralTwin.id) {
|
|
600
|
+
console.log(`[onUpdateReported] Twin ID mismatch: ${twin.id} !== ${peripheralTwin.id}`);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const reported = twin.properties.reported;
|
|
604
|
+
if (reported) {
|
|
605
|
+
if (previousProperties === undefined) {
|
|
606
|
+
console.log(`[onUpdateReported] First update - calling callback`);
|
|
607
|
+
previousProperties = JSON.parse(JSON.stringify(reported));
|
|
608
|
+
callback(reported);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const currentPropertiesStr = JSON.stringify(reported);
|
|
612
|
+
const previousPropertiesStr = JSON.stringify(previousProperties);
|
|
613
|
+
console.log(`[onUpdateReported] Current (end): ...${currentPropertiesStr.substring(currentPropertiesStr.length - 100)}`);
|
|
614
|
+
console.log(`[onUpdateReported] Previous (end): ...${previousPropertiesStr.substring(previousPropertiesStr.length - 100)}`);
|
|
615
|
+
if (currentPropertiesStr.length !== previousPropertiesStr.length) {
|
|
616
|
+
console.log(`[onUpdateReported] String length changed: ${currentPropertiesStr.length} vs ${previousPropertiesStr.length}`);
|
|
617
|
+
}
|
|
618
|
+
const hasChanged = currentPropertiesStr !== previousPropertiesStr;
|
|
619
|
+
console.log(`[onUpdateReported] Properties comparison:`, hasChanged ? 'CHANGED' : 'UNCHANGED');
|
|
620
|
+
if (hasChanged) {
|
|
621
|
+
previousProperties = JSON.parse(currentPropertiesStr);
|
|
622
|
+
console.log(`[onUpdateReported] Calling callback with updated reported properties`);
|
|
623
|
+
callback(reported);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
console.log(`[onUpdateReported] No change detected in properties`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
console.log(`[onUpdateReported] No reported properties found`);
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
};
|
|
634
|
+
const onUpdateDesired = (callback) => {
|
|
635
|
+
let previousProperties = undefined;
|
|
636
|
+
console.log(`[onUpdateDesired] Registering handler for all desired properties`);
|
|
637
|
+
this.onTwinUpdate(peripheralTwin.id, (twin) => {
|
|
638
|
+
console.log(`[onUpdateDesired] Twin update received for ${peripheralTwin.id}`);
|
|
639
|
+
if (twin.id !== peripheralTwin.id) {
|
|
640
|
+
console.log(`[onUpdateDesired] Twin ID mismatch: ${twin.id} !== ${peripheralTwin.id}`);
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
const desired = twin.properties.desired;
|
|
644
|
+
if (desired) {
|
|
645
|
+
if (previousProperties === undefined) {
|
|
646
|
+
console.log(`[onUpdateDesired] First update - calling callback`);
|
|
647
|
+
previousProperties = JSON.parse(JSON.stringify(desired));
|
|
648
|
+
callback(desired);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
const currentPropertiesStr = JSON.stringify(desired);
|
|
652
|
+
const previousPropertiesStr = JSON.stringify(previousProperties);
|
|
653
|
+
console.log(`[onUpdateDesired] Current (end): ...${currentPropertiesStr.substring(currentPropertiesStr.length - 100)}`);
|
|
654
|
+
console.log(`[onUpdateDesired] Previous (end): ...${previousPropertiesStr.substring(previousPropertiesStr.length - 100)}`);
|
|
655
|
+
if (currentPropertiesStr.length !== previousPropertiesStr.length) {
|
|
656
|
+
console.log(`[onUpdateDesired] String length changed: ${currentPropertiesStr.length} vs ${previousPropertiesStr.length}`);
|
|
657
|
+
}
|
|
658
|
+
const hasChanged = currentPropertiesStr !== previousPropertiesStr;
|
|
659
|
+
console.log(`[onUpdateDesired] Properties comparison:`, hasChanged ? 'CHANGED' : 'UNCHANGED');
|
|
660
|
+
if (hasChanged) {
|
|
661
|
+
previousProperties = JSON.parse(currentPropertiesStr);
|
|
662
|
+
console.log(`[onUpdateDesired] Calling callback with updated desired properties`);
|
|
663
|
+
callback(desired);
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
console.log(`[onUpdateDesired] No change detected in properties`);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
else {
|
|
670
|
+
console.log(`[onUpdateDesired] No desired properties found`);
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
};
|
|
674
|
+
const remove = async () => {
|
|
675
|
+
const payload = {
|
|
676
|
+
data: { twinId: peripheralTwin.id },
|
|
677
|
+
};
|
|
678
|
+
return new Promise((resolve, reject) => {
|
|
679
|
+
var _a;
|
|
680
|
+
this.emit('deletePeripheralTwin', payload, (response) => {
|
|
681
|
+
const { twin } = response;
|
|
682
|
+
resolve(twin);
|
|
683
|
+
});
|
|
684
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
685
|
+
reject(error);
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
};
|
|
689
|
+
const updateDesired = async (properties) => {
|
|
690
|
+
const payload = {
|
|
691
|
+
twinId: peripheralTwin.id,
|
|
692
|
+
data: properties,
|
|
693
|
+
};
|
|
694
|
+
return new Promise((resolve, reject) => {
|
|
695
|
+
var _a;
|
|
696
|
+
this.emit('updatePeripheralTwinDesired', payload, (response) => {
|
|
697
|
+
const { twin } = response;
|
|
698
|
+
resolve(twin || {});
|
|
699
|
+
});
|
|
700
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
701
|
+
reject(error);
|
|
702
|
+
});
|
|
703
|
+
});
|
|
704
|
+
};
|
|
705
|
+
peripheralInstance = {
|
|
706
|
+
...peripheralTwin,
|
|
707
|
+
emit: peripheralTwinEmit,
|
|
708
|
+
on: peripheralTwinOn,
|
|
709
|
+
to: peripheralTwinTo,
|
|
710
|
+
updateReported,
|
|
711
|
+
updateDesired,
|
|
712
|
+
onUpdateReported,
|
|
713
|
+
onUpdateDesired,
|
|
714
|
+
remove,
|
|
715
|
+
getDataChannel,
|
|
716
|
+
onDataChannel,
|
|
717
|
+
getMediaStream,
|
|
718
|
+
onMediaStream,
|
|
719
|
+
};
|
|
720
|
+
this.peripheralInstances.set(peripheralTwinId, peripheralInstance);
|
|
721
|
+
return peripheralInstance;
|
|
722
|
+
}
|
|
723
|
+
getGridApp() {
|
|
724
|
+
let currentWindow = window;
|
|
725
|
+
while (currentWindow) {
|
|
726
|
+
try {
|
|
727
|
+
if (currentWindow.gridapp &&
|
|
728
|
+
typeof currentWindow.gridapp.getSettings === 'function') {
|
|
729
|
+
return currentWindow.gridapp;
|
|
730
|
+
}
|
|
731
|
+
if (currentWindow.parent === currentWindow)
|
|
732
|
+
break;
|
|
733
|
+
currentWindow = currentWindow.parent;
|
|
734
|
+
}
|
|
735
|
+
catch (e) {
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
async getSettings() {
|
|
742
|
+
if (typeof window !== 'undefined') {
|
|
743
|
+
const gridapp = this.getGridApp();
|
|
744
|
+
if (gridapp) {
|
|
745
|
+
return gridapp.getSettings();
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
const edgeInstance = await this.getInstance();
|
|
749
|
+
if (!edgeInstance) {
|
|
750
|
+
throw new Error('Edge instance not found');
|
|
751
|
+
}
|
|
752
|
+
return edgeInstance.properties.desired.settings;
|
|
753
|
+
}
|
|
754
|
+
async getEdgeSettings() {
|
|
755
|
+
return this.getSettings();
|
|
756
|
+
}
|
|
757
|
+
async getScreenSettings() {
|
|
758
|
+
return this.getSettings();
|
|
759
|
+
}
|
|
760
|
+
async getDeviceInstance() {
|
|
761
|
+
await this.assureSocketConnection();
|
|
762
|
+
return new Promise((resolve, reject) => {
|
|
763
|
+
var _a;
|
|
764
|
+
this.emit(this.EVENTS.GET_DEVICE_INSTANCE, (response) => {
|
|
765
|
+
resolve(response);
|
|
766
|
+
});
|
|
767
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
768
|
+
reject(error);
|
|
769
|
+
});
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
async getDeviceNetworks() {
|
|
773
|
+
await this.assureSocketConnection();
|
|
774
|
+
return new Promise((resolve, reject) => {
|
|
775
|
+
var _a;
|
|
776
|
+
this.emit(this.EVENTS.GET_DEVICE_NETWORKS, (response) => {
|
|
777
|
+
resolve(response);
|
|
778
|
+
});
|
|
779
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
780
|
+
reject(error);
|
|
781
|
+
});
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
async setScreenInstanceReportedProperties(payload) {
|
|
785
|
+
await this.assureSocketConnection();
|
|
786
|
+
console.info(`setScreenInstanceReportedProperties(): payload ${JSON.stringify(payload)}`);
|
|
787
|
+
return new Promise((resolve, reject) => {
|
|
788
|
+
var _a;
|
|
789
|
+
this.emit(this.EVENTS.REPORT_SCREEN_INSTANCE_PROPERTIES, payload, (response) => {
|
|
790
|
+
resolve(response);
|
|
791
|
+
});
|
|
792
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
793
|
+
reject(error);
|
|
794
|
+
});
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
emit(method, ...args) {
|
|
798
|
+
if (!this.socket) {
|
|
799
|
+
console.error('emit(): Socket not created');
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
const event = this.instanceId;
|
|
803
|
+
const callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
|
|
804
|
+
const payload = { method, ...args[0] };
|
|
805
|
+
const emitArgs = [event, payload];
|
|
806
|
+
if (callback) {
|
|
807
|
+
emitArgs.push(callback);
|
|
808
|
+
}
|
|
809
|
+
if (!this.socketConnected) {
|
|
810
|
+
console.info('emit(): Socket not connected, adding to emitQueue', emitArgs);
|
|
811
|
+
this.emitQueue.push(emitArgs);
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
this.socket.emit(...emitArgs);
|
|
815
|
+
}
|
|
816
|
+
processEmitQueue() {
|
|
817
|
+
if (!this.socket || !this.socketConnected) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
while (this.emitQueue.length > 0) {
|
|
821
|
+
const args = this.emitQueue.shift();
|
|
822
|
+
if (args) {
|
|
823
|
+
this.socket.emit.apply(this.socket, args);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
onTwinUpdate(targetTwinId, callback) {
|
|
828
|
+
console.log(`onTwinUpdate() called for twin ${targetTwinId}`);
|
|
829
|
+
this.assureSocketConnection();
|
|
830
|
+
if (!this.twinUpdateListeners[targetTwinId]) {
|
|
831
|
+
this.twinUpdateListeners[targetTwinId] = new Set();
|
|
832
|
+
}
|
|
833
|
+
this.twinUpdateListeners[targetTwinId].add(callback);
|
|
834
|
+
console.log(`Added twin update listener for ${targetTwinId}. Total listeners: ${this.twinUpdateListeners[targetTwinId].size}`);
|
|
835
|
+
if (!this.subscribedTwins.has(targetTwinId)) {
|
|
836
|
+
this.subscribeTwin(targetTwinId).catch(error => {
|
|
837
|
+
console.error(`Failed to subscribe to twin ${targetTwinId} for updates:`, error);
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
offTwinUpdate(targetTwinId, callback) {
|
|
842
|
+
console.log(`Removing update listener for twin ${targetTwinId}`);
|
|
843
|
+
if (!this.twinUpdateListeners[targetTwinId]) {
|
|
844
|
+
console.log(`No update listeners found for twin ${targetTwinId}`);
|
|
845
|
+
return false;
|
|
846
|
+
}
|
|
847
|
+
const result = this.twinUpdateListeners[targetTwinId].delete(callback);
|
|
848
|
+
if (this.twinUpdateListeners[targetTwinId].size === 0) {
|
|
849
|
+
delete this.twinUpdateListeners[targetTwinId];
|
|
850
|
+
console.log(`Removed last update listener for twin ${targetTwinId}, cleaning up`);
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
console.log(`Removed update listener. Remaining listeners: ${this.twinUpdateListeners[targetTwinId].size}`);
|
|
854
|
+
}
|
|
855
|
+
return result;
|
|
856
|
+
}
|
|
857
|
+
async sendTwinMessage(targetTwinId, data, callback) {
|
|
858
|
+
const edgeInstance = await this.getInstance();
|
|
859
|
+
if (!edgeInstance) {
|
|
860
|
+
console.error('sendTwinMessage failed: Edge instance not found');
|
|
861
|
+
throw new Error('Edge instance not found');
|
|
862
|
+
}
|
|
863
|
+
const { id: edgeTwinId, deviceId } = edgeInstance;
|
|
864
|
+
if (!deviceId) {
|
|
865
|
+
console.error('sendTwinMessage failed: Device ID not available');
|
|
866
|
+
throw new Error('Device ID not available - ensure device is connected');
|
|
867
|
+
}
|
|
868
|
+
const payload = {
|
|
869
|
+
twinId: targetTwinId,
|
|
870
|
+
sourceTwinId: edgeTwinId,
|
|
871
|
+
sourceDeviceId: deviceId,
|
|
872
|
+
data,
|
|
873
|
+
};
|
|
874
|
+
if (callback) {
|
|
875
|
+
this.emit(this.EVENTS.TWIN_MESSAGE, payload, (response) => {
|
|
876
|
+
callback(response);
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
else {
|
|
880
|
+
return new Promise((resolve, reject) => {
|
|
881
|
+
var _a;
|
|
882
|
+
this.emit(this.EVENTS.TWIN_MESSAGE, payload, (response) => {
|
|
883
|
+
resolve(response);
|
|
884
|
+
});
|
|
885
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
886
|
+
console.error('sendTwinMessage socket error:', error);
|
|
887
|
+
reject(error);
|
|
888
|
+
});
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
async onTwinMessage(targetTwinId, callback) {
|
|
893
|
+
var _a;
|
|
894
|
+
console.log('onTwinMessage called for twin:', {
|
|
895
|
+
targetTwinId,
|
|
896
|
+
existingListeners: ((_a = this.twinMessageListeners[targetTwinId]) === null || _a === void 0 ? void 0 : _a.size) || 0,
|
|
897
|
+
});
|
|
898
|
+
if (!this.twinMessageListeners[targetTwinId]) {
|
|
899
|
+
this.twinMessageListeners[targetTwinId] = new Set();
|
|
900
|
+
}
|
|
901
|
+
this.twinMessageListeners[targetTwinId].add(callback);
|
|
902
|
+
console.log(`Added new callback. Total listeners: ${this.twinMessageListeners[targetTwinId].size}`);
|
|
903
|
+
this.twinMessageListeners[targetTwinId].add(callback);
|
|
904
|
+
}
|
|
905
|
+
offTwinMessage(targetTwinId, callback) {
|
|
906
|
+
console.log(`Removing message listener for twin ${targetTwinId}`);
|
|
907
|
+
if (!this.twinMessageListeners[targetTwinId]) {
|
|
908
|
+
console.log(`No listeners found for twin ${targetTwinId}`);
|
|
909
|
+
return false;
|
|
910
|
+
}
|
|
911
|
+
const result = this.twinMessageListeners[targetTwinId].delete(callback);
|
|
912
|
+
if (this.twinMessageListeners[targetTwinId].size === 0) {
|
|
913
|
+
delete this.twinMessageListeners[targetTwinId];
|
|
914
|
+
console.log(`Removed last listener for twin ${targetTwinId}, cleaning up`);
|
|
915
|
+
}
|
|
916
|
+
else {
|
|
917
|
+
console.log(`Removed listener. Remaining listeners: ${this.twinMessageListeners[targetTwinId].size}`);
|
|
918
|
+
}
|
|
919
|
+
return result;
|
|
920
|
+
}
|
|
921
|
+
removeMessageListener(twinId, callback) {
|
|
922
|
+
const listeners = this.twinMessageListeners[twinId];
|
|
923
|
+
if (listeners) {
|
|
924
|
+
listeners.delete(callback);
|
|
925
|
+
if (listeners.size === 0) {
|
|
926
|
+
delete this.twinMessageListeners[twinId];
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
async subscribeTwin(targetTwinId, callback) {
|
|
931
|
+
console.log(`[subscribeTwin] Starting subscription to twin ${targetTwinId}`);
|
|
932
|
+
console.log(`[subscribeTwin] Current subscribed twins:`, Array.from(this.subscribedTwins));
|
|
933
|
+
console.log(`[subscribeTwin] Current listeners:`, Object.keys(this.twinMessageListeners));
|
|
934
|
+
this.subscribedTwins.add(targetTwinId);
|
|
935
|
+
const edgeInstance = await this.getInstance();
|
|
936
|
+
if (!edgeInstance) {
|
|
937
|
+
throw new Error('Edge instance not found');
|
|
938
|
+
}
|
|
939
|
+
const { id: edgeTwinId, deviceId } = edgeInstance;
|
|
940
|
+
const payload = {
|
|
941
|
+
twinId: targetTwinId,
|
|
942
|
+
sourceTwinId: edgeTwinId,
|
|
943
|
+
sourceDeviceId: deviceId,
|
|
944
|
+
};
|
|
945
|
+
console.log(`[subscribeTwin] Emitting TWIN_SUBSCRIBE with payload:`, payload);
|
|
946
|
+
if (callback) {
|
|
947
|
+
this.emit(this.EVENTS.TWIN_SUBSCRIBE, payload, (response) => {
|
|
948
|
+
console.log(`[subscribeTwin] Subscription callback response:`, response);
|
|
949
|
+
callback(response);
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
return new Promise((resolve, reject) => {
|
|
954
|
+
var _a;
|
|
955
|
+
this.emit(this.EVENTS.TWIN_SUBSCRIBE, payload, (response) => {
|
|
956
|
+
console.log(`[subscribeTwin] Subscription promise response:`, response);
|
|
957
|
+
resolve(response);
|
|
958
|
+
});
|
|
959
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
960
|
+
console.error(`[subscribeTwin] Socket error:`, error);
|
|
961
|
+
reject(error);
|
|
962
|
+
});
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
async getTwinById(twinId) {
|
|
967
|
+
const payload = {
|
|
968
|
+
data: { twinId },
|
|
969
|
+
};
|
|
970
|
+
return new Promise((resolve, reject) => {
|
|
971
|
+
var _a;
|
|
972
|
+
this.emit(this.EVENTS.GET_TWIN_BY_ID, payload, (response) => {
|
|
973
|
+
const { twin } = response;
|
|
974
|
+
if (!twin) {
|
|
975
|
+
reject(new Error(`Twin with id ${twinId} not found`));
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
resolve(twin);
|
|
979
|
+
});
|
|
980
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
981
|
+
reject(error);
|
|
982
|
+
});
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
async updateReportedProperties(twinId, reportedProperties) {
|
|
986
|
+
const payload = {
|
|
987
|
+
twinId,
|
|
988
|
+
data: reportedProperties,
|
|
989
|
+
};
|
|
990
|
+
return new Promise((resolve, reject) => {
|
|
991
|
+
var _a;
|
|
992
|
+
this.emit('reportPeripheralTwinProperties', payload, (response) => {
|
|
993
|
+
const { twin } = response;
|
|
994
|
+
if (!twin) {
|
|
995
|
+
reject(new Error(`Failed to update reported properties for twin ${twinId}`));
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
resolve(twin);
|
|
999
|
+
});
|
|
1000
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.on('error', (error) => {
|
|
1001
|
+
reject(error);
|
|
1002
|
+
});
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
exports.PhyHubClient = PhyHubClient;
|
|
1007
|
+
PhyHubClient.instance = null;
|
|
1008
|
+
const connectPhyClient = (params = {}) => PhyHubClient.connect(params);
|
|
1009
|
+
exports.connectPhyClient = connectPhyClient;
|
|
1010
|
+
exports.default = {
|
|
1011
|
+
connectPhyClient: exports.connectPhyClient,
|
|
1012
|
+
};
|
|
1013
|
+
//# sourceMappingURL=index.js.map
|