in device/core/src/device_client.ts [46:126]
constructor(transport: DeviceTransport, connStr?: string, blobUploadClient?: BlobUploadClient, fileUploadApi?: FileUploadInterface) {
super(transport, connStr);
this._blobUploadClient = blobUploadClient;
this._userRegisteredC2dListener = false;
this._fileUploadApi = fileUploadApi;
this.on('removeListener', () => {
if (this.listenerCount('message') === 0) {
this._userRegisteredC2dListener = false;
/*Codes_SRS_NODE_DEVICE_CLIENT_16_005: [The client shall stop listening for messages from the service whenever the last listener unsubscribes from the `message` event.]*/
debug('in removeListener, disabling C2D.');
this._disableC2D((err) => {
if (err) {
debugErrors('in removeListener, error disabling C2D: ' + err);
this.emit('error', err);
} else {
debug('removeListener successfully disabled C2D.');
}
});
}
});
this.on('newListener', (eventName) => {
if (eventName === 'message') {
//
// We want to always retain that the we want to have this feature enabled because the API (.on) doesn't really
// provide for the capability to say it failed. It can certainly fail because a network operation is required to
// enable.
// By saving this off, we are strictly honoring that the feature is enabled. If it doesn't turn on we signal via
// the emitted 'error' that something bad happened.
// But if we ever again attain a connected state, this feature will be operational.
//
this._userRegisteredC2dListener = true;
/*Codes_SRS_NODE_DEVICE_CLIENT_16_004: [The client shall start listening for messages from the service whenever there is a listener subscribed to the `message` event.]*/
debug('in newListener, enabling C2D.');
this._enableC2D((err) => {
if (err) {
debugErrors('in newListener, error enabling C2D: ' + err);
this.emit('error', err);
} else {
debug('in newListener, successfully enabled C2D');
}
});
}
});
/*Codes_SRS_NODE_DEVICE_CLIENT_16_002: [The `message` event shall be emitted when a cloud-to-device message is received from the IoT Hub service.]*/
/*Codes_SRS_NODE_DEVICE_CLIENT_16_003: [The `message` event parameter shall be a `message` object.]*/
this._transport.on('message', (msg) => {
this.emit('message', msg);
});
this._deviceDisconnectHandler = (err) => {
if (err) {
debugErrors('transport disconnect event: ' + err);
} else {
debug('transport disconnect event: no error');
}
if (err && this._retryPolicy.shouldRetry(err)) {
debugErrors('reconnect policy specifies a reconnect on error');
/*Codes_SRS_NODE_DEVICE_CLIENT_16_097: [If the transport emits a `disconnect` event while the client is subscribed to c2d messages the retry policy shall be used to reconnect and re-enable the feature using the transport `enableC2D` method.]*/
if (this._userRegisteredC2dListener) {
// turn on C2D
debug('disconnectHandler re-enabling C2D');
this._enableC2D((err) => {
if (err) {
/*Codes_SRS_NODE_DEVICE_CLIENT_16_102: [If the retry policy fails to reestablish the C2D functionality a `disconnect` event shall be emitted with a `results.Disconnected` object.]*/
debugErrors('error on _enableC2D in _deviceDisconnectHandler. Failed to reestablish C2D functionality: ' + err);
this.emit('disconnect', new results.Disconnected(err));
} else {
debug('_deviceDisconnectHandler has enabled C2D');
}
});
} else {
debug('C2D has not been enabled on the device');
}
}
};
this._transport.on('disconnect', this._deviceDisconnectHandler);
}