Skip to content

v3.0.1 #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
01aa69f
Wrap message handler in try/catch block to catch all errors that are …
LeLunZ Sep 3, 2024
0de516b
log error if we want to publish a message if client is disconnected
LeLunZ Sep 3, 2024
4f0d1b5
Bumped version to 3.0.1-beta1
LeLunZ Sep 3, 2024
72eded9
Add more information to error message in setup scripts
LeLunZ Sep 3, 2024
b244c71
Added sendCommand script
LeLunZ Sep 3, 2024
8cbe4a4
Merge pull request #69 from MrAsterisco/handle-error-in-mqtt-callback
LeLunZ Sep 3, 2024
63c9be6
Fix error logging in bin-scripts
LeLunZ Sep 3, 2024
89418b7
Added longer error message to mqtt error
LeLunZ Sep 3, 2024
4ef1d8a
included --help flag for scripts and added stack to error message
LeLunZ Sep 4, 2024
785c71f
Added line breaks
LeLunZ Sep 4, 2024
d284d31
Replace \t with \'
LeLunZ Sep 4, 2024
1734a00
fixed default ssl mode
LeLunZ Sep 4, 2024
bfd86ad
bumped version to 3.0.1-beta.2
LeLunZ Sep 4, 2024
fcc4507
Refactored scripts into a single script
LeLunZ Sep 7, 2024
7282cf4
Changed log message
LeLunZ Sep 7, 2024
a069323
Bumped version to 3.0.1-beta.3
LeLunZ Sep 7, 2024
90777ad
Fix help message
LeLunZ Sep 7, 2024
2c36d7e
Fix exit and timeout problems
LeLunZ Sep 7, 2024
4bff26b
bumped version to 3.0.1-beta.4
LeLunZ Sep 7, 2024
4e2035f
Added line break
LeLunZ Sep 7, 2024
ed54ff1
fix alwaysOnTest script && bumped version to 3.0.1-beta.5
LeLunZ Sep 8, 2024
3e6d3ff
Fix subscribing to wrong topic
LeLunZ Sep 8, 2024
4eff9c4
Bumped to version v3.0.1-beta.6
LeLunZ Sep 8, 2024
e587d5a
Fix script optional args
LeLunZ Sep 8, 2024
ab6655f
bumped version to v3.0.1-beta.7
LeLunZ Sep 8, 2024
c738c2c
Fix max listener error
LeLunZ Sep 8, 2024
273ccd4
Bumped to v3.0.1-beta.8
LeLunZ Sep 8, 2024
f985918
Added message if no picture settings changes are detected
LeLunZ Sep 11, 2024
f29ac02
Bumped version to 3.0.1
LeLunZ Sep 11, 2024
cef6797
Add Logs/Debugging mqtt section to README
LeLunZ Sep 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE/bug-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ assignees: ''
**Logs:**

```
Show the Homebridge logs here, remove any sensitive information.
Show the Homebridge logs/protocol here, remove any sensitive information.
In case of a crash or error, please try enabling debug mode and provide the full log output.
```

**Plugin Config:**
Expand Down
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE/support-request.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ assignees: ''
**Logs:**

```
Show the Homebridge logs here, remove any sensitive information.
Show the Homebridge logs/protocol here, remove any sensitive information.
In case of a crash or error, please try enabling debug mode and provide the full log output.
```

**Plugin Config:**
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# 3.0.1

Please checkout the 3.0.0 release notes for the changes in this major version.

### Changes
- **IMPORTANT** Combined `hisense-tv-authorize` and `hisense-tv-always-on-test` into one script `hisense-tv`
- The script is now just `hisense-tv`
- Authorize can be done with `hisense-tv authorize`
- Always on test can be done with `hisense-tv always-on-test`
- `hisense-tv listen-to-mqtt` is now available to listen to mqtt messages and debug the plugin

### Fixed
- Fixed an issue where the plugin crashes if malformed mqtt data is send
- Disabled sending mqtt data if the mqtt connection is down

# 3.0.0

This release has **braking changes**.
Expand Down
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ The mac address is needed in the next step and in the config.json file.
### Continue the Setup
For this plugin to work correctly, you need to configure your TV to use a static ip address (or configure a static DHCP reservation on your router).

To connect to your TV, you need to pair the machine where you're running Homebridge with your TV. This is done in the command line, by manually running the bundled `hisense-tv-authorize` command. To do this, open the homebridge UI and go to Terminal.
To connect to your TV, you need to pair the machine where you're running Homebridge with your TV. This is done in the command line, by manually running the bundled `hisense-tv authorize` command. To do this, open the homebridge UI and go to Terminal.

![terminal](images/terminal-location.png)

Expand All @@ -64,19 +64,19 @@ If this one fails, try the other commands.

SSLMode: default (most common)
```bash
hisense-tv-authorize --hostname <TV_IP_ADDRESS> --mac <HOMEBRIDGE_MAC_ADDRESS>
hisense-tv authorize --hostname <TV_IP_ADDRESS> --mac <HOMEBRIDGE_MAC_ADDRESS>
```

SSLMode: disabled (no SSL)
```bash
hisense-tv-authorize --hostname <TV_IP_ADDRESS> --mac <HOMEBRIDGE_MAC_ADDRESS> --no-ssl
hisense-tv authorize --hostname <TV_IP_ADDRESS> --mac <HOMEBRIDGE_MAC_ADDRESS> --no-ssl
```

SSLMode: custom (use cert and key below)
Replace `<CERTFILE>` and `<KEYFILE>` with the path to the certificate and key files you want to use.
The certificate and key files most used can be found [here](https://github.com/MrAsterisco/hisensetv/tree/master/cert)
```bash
hisense-tv-authorize --hostname <TV_IP_ADDRESS> --mac <HOMEBRIDGE_MAC_ADDRESS> --certfile <CERTFILE> --keyfile <KEYFILE>
hisense-tv authorize --hostname <TV_IP_ADDRESS> --mac <HOMEBRIDGE_MAC_ADDRESS> --certfile <CERTFILE> --keyfile <KEYFILE>
```

Your TV, if compatible, will display a PIN code: insert it in the command line and confirm. Your device is now paired with your TV and they can communicate when the TV is on. Repeat this step for all the TVs you want to use via HomeKit.
Expand Down Expand Up @@ -170,7 +170,7 @@ Some TVs may be shown as "On" even when you turn them off. If you have a TV that
- pictureSettings

This can be different for each TV, because the behavior is not consistent across all models.
To find out which one works for you, you can try running the `hisense-tv-always-on-test` command. (From the Homebridge Terminal)
To find out which one works for you, you can try running the `hisense-tv always-on-test` command. (From the Homebridge Terminal)
The script will guide you through the process of finding the correct `tvType` for your TV.
If you find any issues with the script, please open an issue on GitHub, as I couldn't test that script with my TV.

Expand Down Expand Up @@ -218,11 +218,24 @@ Take a note of the Setup Code and open your Home app on your iPhone, iPad or Mac

**Done**! As always, you can repeat the steps above if you have multiple TVs to add. Please note that each TV will have a different Setup Code logged in Homebridge.

## Issues
## Issues/Bugs
This plugin has been developed and tested running Homebridge on Ubuntu Linux 20.04 and macOS Monterey with a Hisense 50AE7010F. If your configuration differs, the steps below may not be a 100% accurate: even if the general idea is the same *(pair the TV, add it to Home, use it)*, your mileage may vary.

**If you find anything that is not correct, please open an issue (or even better: a PR changing this file) explaining what you're doing differently to make this plugin work with different TV models and/or on different operating systems.**

**Also check your Homebridge protocol/log if there are any errors and add them to the issue.**

### Logs

If you have any error in your homebridge logs, please open an issue on GitHub and provide the logs.

If you have an issue but no error, you can enable debug logs in the settings of homebridge by activating Homebridge Debug Mode.

### Debugging MQTT Issues

If there are problems regarding the MQTT communications, you can run the `hisense-tv listen-to-mqtt` command to see all mqtt messages.
These can be helpful to debug issues with the plugin.

### Known Issues
- The input list might not be fetched correctly if the TV is turned off while adding the accessory or after restarting Homebridge.
- FIX: force close your Home app and open it again a few times.
Expand All @@ -231,6 +244,7 @@ This plugin has been developed and tested running Homebridge on Ubuntu Linux 20.
- Some TVs have inconsistent data regarding apps
- Due to the inconsistent data, the current selected app on the tv may not be shown correctly in homekit (will be "Unknown")


# Contributions
All contributions to expand the library are welcome. Fork the repo, make the changes you want, and open a Pull Request.

Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"displayName": "HiSense TV",
"name": "homebridge-hisense-tv-remotenow",
"version": "3.0.0",
"version": "3.0.1",
"description": "Control RemoteNow-enabled HiSense TVs.",
"main": "dist/index.js",
"license": "MIT",
Expand All @@ -21,13 +21,12 @@
"url": "https://github.com/MrAsterisco/homebridge-hisense-tv/issues"
},
"bin": {
"hisense-tv-authorize": "dist/scripts/authorize.js",
"hisense-tv-always-on-test": "dist/scripts/alwaysOnTest.js"
"hisense-tv": "dist/scripts/hisenseTV.js"
},
"scripts": {
"lint": "eslint src/**.ts --max-warnings=5 --fix",
"watch": "npm run build && npm link && nodemon",
"build": "rimraf ./dist && tsc && chmod +x dist/scripts/authorize.js && chmod +x dist/scripts/alwaysOnTest.js",
"build": "rimraf ./dist && tsc && chmod +x dist/scripts/hisenseTV.js",
"prepublishOnly": "npm run lint && npm run build",
"prepare": "husky"
},
Expand Down
24 changes: 20 additions & 4 deletions src/hisenseMQTTClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,33 @@ export class HisenseMQTTClient {
public _SOURCE_LIST_TOPIC : string;
public _APP_LIST_TOPIC : string;
public _PICTURE_SETTINGS_TOPIC : string;
public _DEVICE_PICTURE_SETTINGS_TOPIC : string;

public mqttClient: mqtt.MqttClient;

constructor(public deviceConfig: Pick<DeviceConfig, 'sslmode' | 'ipaddress' | 'sslcertificate' | 'sslprivatekey'>, macaddress: string) {
constructor(public deviceConfig: Pick<DeviceConfig, 'sslmode' | 'ipaddress' | 'sslcertificate' | 'sslprivatekey'>,
macaddress: string, private log: {error: (message: string) => void}, connectionTimeout?: number) {

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`;
this._COMMUNICATION_TOPIC = path.join(this._BASE_TOPIC, this._DEVICE_TOPIC, 'ui_service', 'data');
this._APP_LIST_TOPIC = path.join(this._COMMUNICATION_TOPIC, 'applist');
this._SOURCE_LIST_TOPIC = path.join(this._COMMUNICATION_TOPIC, 'sourcelist');
this._PICTURE_SETTINGS_TOPIC = path.join(this._BASE_TOPIC, 'broadcast', 'platform_service', 'data', 'picturesetting');
this._DEVICE_PICTURE_SETTINGS_TOPIC = path.join(this._BASE_TOPIC, this._DEVICE_TOPIC, 'platform_service', 'data', 'picturesetting');

let key: Buffer|null = null;
let cert: Buffer|null = null;

if(this.deviceConfig.sslmode === 'custom') {
key = fs.readFileSync(this.deviceConfig.sslprivatekey);
cert = fs.readFileSync(this.deviceConfig.sslcertificate);
try{
key = fs.readFileSync(this.deviceConfig.sslprivatekey);
cert = fs.readFileSync(this.deviceConfig.sslcertificate);
}catch (e){
this.log.error('Could not read certificate or key file');
this.log.error('Continuing with SSL but no certificate or key');
}
}

this.mqttClient = mqtt.connect({
Expand All @@ -44,6 +53,7 @@ export class HisenseMQTTClient {
cert: cert,
username: 'hisenseservice',
password: 'multimqttservice',
connectTimeout: connectionTimeout,
rejectUnauthorized: false,
queueQoSZero: false,
protocol: this.deviceConfig.sslmode === 'disabled' ? 'mqtt' : 'mqtts',
Expand All @@ -52,7 +62,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) {
Expand Down
4 changes: 3 additions & 1 deletion src/interfaces/device-config.interface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {SSLMode} from '../types/ssl-mode.type';

export interface DeviceConfig {
id: string;
tvType: 'default' | 'fakeSleep' | 'pictureSettings';
Expand All @@ -11,7 +13,7 @@ export interface DeviceConfig {
wolRetries: number;
ipaddress: string;
macaddress: string;
sslmode: 'disabled' | 'custom';
sslmode: SSLMode;
sslcertificate: string;
sslprivatekey: string;
showApps: boolean;
Expand Down
55 changes: 30 additions & 25 deletions src/platformAccessory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
constructor(private readonly platform: HiSenseTVPlatform, private readonly accessory: PlatformAccessory) {
this.log = platform.log;

if (accessory.context.macaddress == null || accessory.context.macaddress == '') {

Check warning on line 67 in src/platformAccessory.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

Expected '===' and instead saw '=='

Check warning on line 67 in src/platformAccessory.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

Expected '===' and instead saw '=='

Check warning on line 67 in src/platformAccessory.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Expected '===' and instead saw '=='

Check warning on line 67 in src/platformAccessory.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Expected '===' and instead saw '=='
this.log.warn('Config not up to date, please check the README on https://github.com/MrAsterisco/homebridge-hisense-tv' +
' for the latest configuration options or use the homebridge UI to update the configuration.');
this.log.error('Homebridge MAC address is required for the TV accessory.');
Expand Down Expand Up @@ -127,7 +127,7 @@
// 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
Expand Down Expand Up @@ -163,32 +163,36 @@
});


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

Expand All @@ -210,6 +214,7 @@

this.mqttHelper.mqttClient.on('error', (err) => {
this.log.error('An error occurred while connecting to MQTT service: ' + JSON.stringify(err));
this.log.error('This usually means the TV is off/the IP address is incorrect or you configured the wrong ssl options.');
this.setTVPowerStateOff();
});
}
Expand Down
Loading