diff --git a/.gitignore b/.gitignore index d4bf01a..ebed9e9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .nyc_output/ node_modules/ +onstar2mqtt.env diff --git a/HA-MQTT.md b/HA-MQTT.md index 2590863..423d52c 100644 --- a/HA-MQTT.md +++ b/HA-MQTT.md @@ -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. diff --git a/src/commands.js b/src/commands.js index 2cf979b..5ebc230 100644 --- a/src/commands.js +++ b/src/commands.js @@ -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, diff --git a/src/index.js b/src/index.js index ebc429b..e583001 100644 --- a/src/index.js +++ b/src/index.js @@ -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(); diff --git a/src/mqtt.js b/src/mqtt.js index 5c86be4..8432800 100644 --- a/src/mqtt.js +++ b/src/mqtt.js @@ -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') { diff --git a/test/mqtt.spec.js b/test/mqtt.spec.js index 78ae3a6..92a2885 100644 --- a/test/mqtt.spec.js +++ b/test/mqtt.spec.js @@ -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;