Add location support. Fixes #87

This commit is contained in:
Michael Woods 2021-11-16 12:01:29 -05:00
parent 033bc93a80
commit f36e2b0dbc
6 changed files with 62 additions and 3 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
.nyc_output/
node_modules/
onstar2mqtt.env

View File

@ -1,5 +1,29 @@
Sample configs for MQTT Home Assistant integration.
### Location
Unfortunately, the MQTT Device tracker uses a home/not_home state and the MQTT Json device tracker does not support
the discovery schema so a manual entity configuration is required.
device tracker yaml:
```yaml
device_tracker:
- platform: mqtt_json
devices:
your_car_name: homeassistant/device_tracker/YOUR_CAR_VIN/getlocation/state
```
script yaml:
```yaml
alias: Car - Location
sequence:
- service: mqtt.publish
data:
topic: homeassistant/YOUR_CAR_VIN/command
payload: '{"command": "getLocation"}'
mode: single
icon: 'mdi:map-marker'
```
### Lovelace Dashboard
Create a new dashboard, or use the cards in your own view. The `mdi:car-electric` icon works well here.

View File

@ -109,6 +109,10 @@ class Commands {
return this.onstar.setChargingProfile();
}
async getLocation() {
return this.onstar.location();
}
async diagnostics({diagnosticItem = [
Commands.CONSTANTS.DIAGNOSTICS.ODOMETER,
Commands.CONSTANTS.DIAGNOSTICS.TIRE_PRESSURE,

View File

@ -65,10 +65,28 @@ const configureMQTT = async (commands, client, mqttHA) => {
client.on('message', (topic, message) => {
logger.debug('Subscription message', {topic, message});
const {command, options} = JSON.parse(message);
const commandFn = commands[command].bind(commands);
const cmd = commands[command];
if (!cmd) {
logger.error('Command not found', {command});
return;
}
const commandFn = cmd.bind(commands);
logger.info('Command sent', {command});
commandFn(options || {})
.then(() => logger.info('Command completed', {command}))
.then(data => {
// TODO refactor the response handling for commands
logger.info('Command completed', {command});
const location = _.get(data, 'response.data.commandResponse.body.location');
if (data && location) {
logger.info('Command response data', {location});
const topic = mqttHA.getStateTopic({name: command});
// TODO create device_tracker entity. MQTT device tracker doesn't support lat/lon and mqtt_json
// doesn't have discovery
client.publish(topic,
JSON.stringify({latitude: location.lat, longitude: location.long}), {retain: true})
.then(() => logger.info('Published location to topic.', {topic}));
}
})
.catch(err=> logger.error('Command error', {command, err}));
});
const topic = mqttHA.getCommandTopic();

View File

@ -57,13 +57,15 @@ class MQTT {
case 'PRIORITY CHARGE INDICATOR':
case 'PRIORITY CHARGE STATUS':
return 'binary_sensor';
case 'getLocation':
return 'device_tracker';
default:
return 'sensor';
}
}
/**
* @param {'sensor'|'binary_sensor'} type
* @param {'sensor'|'binary_sensor'|'device_tracker'} type
* @returns {string}
*/
getBaseTopic(type = 'sensor') {

View File

@ -28,6 +28,16 @@ describe('MQTT', () => {
assert.strictEqual(MQTT.convertFriendlyName('FOO BAR'), 'Foo Bar');
});
it('should determine sensor types', () => {
assert.strictEqual(MQTT.determineSensorType('EV CHARGE STATE'), 'binary_sensor');
assert.strictEqual(MQTT.determineSensorType('EV PLUG STATE'), 'binary_sensor');
assert.strictEqual(MQTT.determineSensorType('PRIORITY CHARGE INDICATOR'), 'binary_sensor');
assert.strictEqual(MQTT.determineSensorType('PRIORITY CHARGE STATUS'), 'binary_sensor');
assert.strictEqual(MQTT.determineSensorType('getLocation'), 'device_tracker');
assert.strictEqual(MQTT.determineSensorType('foo'), 'sensor');
assert.strictEqual(MQTT.determineSensorType(''), 'sensor');
});
describe('topics', () => {
let d;