From 01aa69f1f4495283b7816fa5f835925fd0cf6c68 Mon Sep 17 00:00:00 2001 From: LeLunZ <31982496+LeLunZ@users.noreply.github.com> Date: Tue, 3 Sep 2024 18:43:46 +0200 Subject: [PATCH 1/2] Wrap message handler in try/catch block to catch all errors that are caused by malformed messages --- src/platformAccessory.ts | 52 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/platformAccessory.ts b/src/platformAccessory.ts index 7029b6c..bd07a81 100644 --- a/src/platformAccessory.ts +++ b/src/platformAccessory.ts @@ -163,32 +163,36 @@ export class HiSenseTVAccessory { }); - // this.mqttHelper.mqttClient.on('message', (topic, message) => { this.log.debug(`Received message from TV (${topic}):` + message.toString()); - const parsedMessage = JSON.parse(message.toString()); - switch (topic) { - case this.mqttHelper._STATE_TOPIC: - // handle tvType fakeSleep differently as it has a different state - if (this.deviceConfig.tvType === 'fakeSleep') { - // setCurrentInput will be called in setAlwaysOnFakeSleepState - this.setAlwaysOnFakeSleepState(parsedMessage); - } else { - this.setCurrentInput(parsedMessage); - } - break; - case this.mqttHelper._SOURCE_LIST_TOPIC: - this.createSources(parsedMessage, this.availableApps); - break; - case this.mqttHelper._PICTURE_SETTINGS_TOPIC: - this.setAlwaysOnPictureSettingsPowerState(parsedMessage); - break; - case this.mqttHelper._APP_LIST_TOPIC: - this.createSources(this.inputSources, parsedMessage); - break; - default: - this.log.debug('Received unknown message from TV. Topic: ' + topic + ' Message: ' + message.toString()); - break; + try{ + const parsedMessage = JSON.parse(message.toString()); + switch (topic) { + case this.mqttHelper._STATE_TOPIC: + // handle tvType fakeSleep differently as it has a different state + if (this.deviceConfig.tvType === 'fakeSleep') { + // setCurrentInput will be called in setAlwaysOnFakeSleepState + this.setAlwaysOnFakeSleepState(parsedMessage); + } else { + this.setCurrentInput(parsedMessage); + } + break; + case this.mqttHelper._SOURCE_LIST_TOPIC: + this.createSources(parsedMessage, this.availableApps); + break; + case this.mqttHelper._PICTURE_SETTINGS_TOPIC: + this.setAlwaysOnPictureSettingsPowerState(parsedMessage); + break; + case this.mqttHelper._APP_LIST_TOPIC: + this.createSources(this.inputSources, parsedMessage); + break; + default: + this.log.debug('Received unknown message from TV. Topic: ' + topic + ' Message: ' + message.toString()); + break; + } + }catch(e: unknown){ + this.log.error('Error occurred while handling new message from TV: ' + message.toString()); + this.log.error((e as Error).stack ?? (e as Error).toString()); } }); From 0de516b0ff9a0e936c179262bedad727f0798ed6 Mon Sep 17 00:00:00 2001 From: LeLunZ <31982496+LeLunZ@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:01:13 +0200 Subject: [PATCH 2/2] log error if we want to publish a message if client is disconnected --- src/hisenseMQTTClient.ts | 10 ++++++++-- src/platformAccessory.ts | 2 +- src/scripts/alwaysOnTest.ts | 2 +- src/scripts/authorize.ts | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/hisenseMQTTClient.ts b/src/hisenseMQTTClient.ts index c678946..a5dbe1c 100644 --- a/src/hisenseMQTTClient.ts +++ b/src/hisenseMQTTClient.ts @@ -20,7 +20,7 @@ export class HisenseMQTTClient { public mqttClient: mqtt.MqttClient; - constructor(public deviceConfig: Pick, macaddress: string) { + constructor(public deviceConfig: Pick, macaddress: string, private log: {error: (message: string) => void}) { this._BASE_TOPIC = path.join('/', 'remoteapp', 'mobile'); this._STATE_TOPIC = path.join(this._BASE_TOPIC, 'broadcast', 'ui_service', 'state'); this._DEVICE_TOPIC = `${macaddress.toUpperCase()}$normal`; @@ -52,7 +52,13 @@ export class HisenseMQTTClient { public callService(service: string, action: string, payload?: string) { const topic = path.join('/', 'remoteapp', 'tv', service, this._DEVICE_TOPIC, 'actions', action); - this.mqttClient.publish(topic, payload ?? ''); + if(this.mqttClient.disconnected || this.mqttClient.disconnecting) { + this.log.error('Sending message to TV failed - MQTT client is disconnected'); + this.log.error(Error().stack ?? ''); + return; + }else { + this.mqttClient.publish(topic, payload ?? ''); + } } public changeSource(sourceId: string) { diff --git a/src/platformAccessory.ts b/src/platformAccessory.ts index bd07a81..f5fffbb 100644 --- a/src/platformAccessory.ts +++ b/src/platformAccessory.ts @@ -127,7 +127,7 @@ export class HiSenseTVAccessory { // Create "Unknown" source. this.createHomeSource(); - this.mqttHelper = new HisenseMQTTClient(this.deviceConfig, accessory.context.macaddress); + this.mqttHelper = new HisenseMQTTClient(this.deviceConfig, accessory.context.macaddress, this.log); this.setupMqtt(); // set the counter threshold based on the polling interval diff --git a/src/scripts/alwaysOnTest.ts b/src/scripts/alwaysOnTest.ts index f9da3cc..d55df13 100644 --- a/src/scripts/alwaysOnTest.ts +++ b/src/scripts/alwaysOnTest.ts @@ -47,7 +47,7 @@ let pictureSettingsOff: null|PictureSetting = null; await rl.question('Turn your TV off now and press enter when ready: '); rl.write('Wait for a few seconds...'); try { - const mqttHelper = new HisenseMQTTClient({sslmode: sslMode, ipaddress: hostname, sslcertificate: sslCertificate, sslprivatekey: sslPrivateKey}, macaddress); + const mqttHelper = new HisenseMQTTClient({sslmode: sslMode, ipaddress: hostname, sslcertificate: sslCertificate, sslprivatekey: sslPrivateKey}, macaddress, console); const timeout = setTimeout(() => { mqttHelper.mqttClient.end(true); rl.write('Could not detect always on TV'); diff --git a/src/scripts/authorize.ts b/src/scripts/authorize.ts index 6999cc8..d5c8a86 100644 --- a/src/scripts/authorize.ts +++ b/src/scripts/authorize.ts @@ -40,7 +40,7 @@ const macaddress = values['mac'] as string; const hostname = values['hostname'] as string; try { - const mqttHelper = new HisenseMQTTClient({sslmode: sslMode, ipaddress: hostname, sslcertificate: sslCertificate, sslprivatekey: sslPrivateKey}, macaddress); + const mqttHelper = new HisenseMQTTClient({sslmode: sslMode, ipaddress: hostname, sslcertificate: sslCertificate, sslprivatekey: sslPrivateKey}, macaddress, console); mqttHelper.mqttClient.on('connect', () => { mqttHelper.callService('ui_service', 'gettvstate');