From 6846319df801d40a9cc7facb243b0d41101ffcd7 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Jimenez Date: Wed, 6 Sep 2023 08:21:59 -0700 Subject: [PATCH] feat(lock): Add lock status (#166) This commit will add all the changes to add lock status into the Node SDK Co-authored-by: Adrian Garcia --- doc/readme.md | 100 +++++++++++++++++++++++++++++++++++++ lib/smartcar-service.js | 1 + lib/vehicle.js | 93 ++++++++++++++++++++++++++++++++++ test/end-to-end/vehicle.js | 37 ++++++++++++++ test/unit/lib/vehicle.js | 26 ++++++++++ 5 files changed, 257 insertions(+) diff --git a/doc/readme.md b/doc/readme.md index 0c988bc..434cfe0 100644 --- a/doc/readme.md +++ b/doc/readme.md @@ -74,6 +74,8 @@ the following fields :

Odometer : Object
+
SecurityResponse : Object
+
Location : Object
Attributes : Object
@@ -626,6 +628,7 @@ Initializes a new Service object to make requests to the Smartcar API. * [.startCharge()](#Vehicle+startCharge) ⇒ [ActionResponse](#ActionResponse) * [.stopCharge()](#Vehicle+stopCharge) ⇒ [ActionResponse](#ActionResponse) * [.disconnect()](#Vehicle+disconnect) ⇒ [ActionResponse](#ActionResponse) + * [.lockStatus()](#Vehicle+lockStatus) ⇒ LockStatus @@ -980,6 +983,19 @@ to make requests to it again. for all possible errors. **See**: [Smartcar API Doc - Disconnect](https://smartcar.com/docs/api#delete-disconnect) + + +### vehicle.lockStatus() ⇒ LockStatus +Returns the lock status of the vehicle. + +**Kind**: instance method of [Vehicle](#Vehicle) +**Throws**: + +- [SmartcarError](#SmartcarError) - an instance of SmartcarError. + See the [errors section](https://github.com/smartcar/node-sdk/tree/master/doc#errors) + for all possible errors. + +**See**: [Smartcar API Doc - Lock Status](https://smartcar.com/docs/api#get-security) ## METHODS\_MAP : object.<String, Object> @@ -1317,6 +1333,90 @@ the following fields : } } ``` + + +## SecurityResponse : Object +**Kind**: global typedef +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| isLocked | Boolean | Whether the vehicle is locked or not. | +| doors | Array | The status of each of the vehicle's doors. | +| windows | Array | The status of each of the vehicle's windows. | +| sunroof | Array | The status of each of the vehicle's sunroof. | +| storage | Array | The status of each of the vehicle's storage. | +| chargingPort | Array | The status of each of the vehicle's chargingPort. | +| meta | [Meta](#Meta) | | + +**Example** +```js +{ + isLocked: true, + doors: [ + { + type: 'frontLeft', + status: 'LOCKED', + }, + { + type: 'frontRight', + status: 'LOCKED', + }, + { + type: 'backLeft', + status: 'LOCKED', + }, + { + type: 'backRight', + status: 'LOCKED', + }, + ], + windows: [ + { + type: 'frontLeft', + status: 'CLOSED', + }, + { + type: 'frontRight', + status: 'CLOSED', + }, + { + type: 'backLeft', + status: 'CLOSED', + }, + { + type: 'backRight', + status: 'CLOSED', + }, + ], + sunroof: [ + { + type: 'sunroof', + status: 'CLOSED', + }, + ], + storage: [ + { + type: 'rear', + status: 'CLOSED', + }, + { + type: 'front', + status: 'CLOSED', + }, + ], + chargingPort: [ + { + type: 'chargingPort', + status: 'CLOSED', + }, + ], + meta: { + dataAge: new Date('2018-05-04T07:20:50.844Z'), + requestId: '26c14915-0c26-43c5-8e42-9edfc2a66a0f', + }, +} +``` ## Location : Object diff --git a/lib/smartcar-service.js b/lib/smartcar-service.js index 206d917..7e91b14 100644 --- a/lib/smartcar-service.js +++ b/lib/smartcar-service.js @@ -35,6 +35,7 @@ const getNameFromPath = (path) => { // '/' should have a method name of 'attributes' // '/tires/pressure' should be tirePressure and NOT tiresPressure const BATCH_PATH_TO_ATTRIBUTE = { + '/security': 'lockStatus', '/tires/pressure': 'tirePressure', '/': 'attributes', }; diff --git a/lib/vehicle.js b/lib/vehicle.js index ddeb2e4..6cad6ad 100644 --- a/lib/vehicle.js +++ b/lib/vehicle.js @@ -31,6 +31,7 @@ const METHODS_MAP = { startCharge: {requestType: 'post', path: 'charge', body: {action: 'START'}}, stopCharge: {requestType: 'post', path: 'charge', body: {action: 'STOP'}}, disconnect: {requestType: 'delete', path: 'application'}, + lockStatus: {path: 'security'}, }; /** @exports Vehicle */ @@ -595,6 +596,86 @@ Vehicle.prototype.request = async function( * } * } */ + +/** + * @type {Object} + * @typedef SecurityResponse + * @property {Boolean} isLocked - Whether the vehicle is locked or not. + * @property {Array} doors - The status of each of the vehicle's doors. + * @property {Array} windows - The status of each of the vehicle's windows. + * @property {Array} sunroof - The status of each of the vehicle's sunroof. + * @property {Array} storage - The status of each of the vehicle's storage. + * @property {Array} chargingPort - The status of each of the vehicle's chargingPort. + * @property {Meta} meta + * + * @example + * { + * isLocked: true, + * doors: [ + * { + * type: 'frontLeft', + * status: 'LOCKED', + * }, + * { + * type: 'frontRight', + * status: 'LOCKED', + * }, + * { + * type: 'backLeft', + * status: 'LOCKED', + * }, + * { + * type: 'backRight', + * status: 'LOCKED', + * }, + * ], + * windows: [ + * { + * type: 'frontLeft', + * status: 'CLOSED', + * }, + * { + * type: 'frontRight', + * status: 'CLOSED', + * }, + * { + * type: 'backLeft', + * status: 'CLOSED', + * }, + * { + * type: 'backRight', + * status: 'CLOSED', + * }, + * ], + * sunroof: [ + * { + * type: 'sunroof', + * status: 'CLOSED', + * }, + * ], + * storage: [ + * { + * type: 'rear', + * status: 'CLOSED', + * }, + * { + * type: 'front', + * status: 'CLOSED', + * }, + * ], + * chargingPort: [ + * { + * type: 'chargingPort', + * status: 'CLOSED', + * }, + * ], + * meta: { + * dataAge: new Date('2018-05-04T07:20:50.844Z'), + * requestId: '26c14915-0c26-43c5-8e42-9edfc2a66a0f', + * }, + * } + */ + /** * @name Vehicle#odometer * @function @@ -747,4 +828,16 @@ Vehicle.prototype.request = async function( * for all possible errors. */ +/** + * @name Vehicle#lockStatus + * @function + * @memberof Vehicle + * @description Returns the lock status of the vehicle. + * @see {@link https://smartcar.com/docs/api#get-security|Smartcar API Doc - Lock Status} + * @return {LockStatus} + * @throws {SmartcarError} - an instance of SmartcarError. + * See the [errors section](https://github.com/smartcar/node-sdk/tree/master/doc#errors) + * for all possible errors. + */ + module.exports = Vehicle; diff --git a/test/end-to-end/vehicle.js b/test/end-to-end/vehicle.js index 925cc2f..deb2036 100644 --- a/test/end-to-end/vehicle.js +++ b/test/end-to-end/vehicle.js @@ -25,6 +25,7 @@ test.before(async(t) => { getVehicle('FORD', [ 'required:control_charge', 'required:control_security', + 'required:read_security', ]), getVehicle('KIA', [ 'required:read_charge', @@ -312,6 +313,22 @@ test('vehicle unlock', async(t) => { t.is(response.meta.requestId.length, 36); }); +test('vehicle read security', async(t) => { + const response = await t.context.ford.lockStatus(); + t.deepEqual( + _.xor(_.keys(response), [ + 'isLocked', + 'doors', + 'windows', + 'sunroof', + 'storage', + 'chargingPort', + 'meta', + ]), + [], + ); +}); + test('vehicle startCharge', async(t) => { const response = await t.context.ford.startCharge(); t.deepEqual( @@ -377,6 +394,26 @@ test('vehicle batch', async(t) => { t.is(location.meta.requestId.length, 36); }); +test('vehicle batch - security', async(t) => { + const response = await t.context.ford.batch([ + '/security', + ]); + + const lockStatus = response.lockStatus(); + t.deepEqual( + _.xor(_.keys(lockStatus), [ + 'isLocked', + 'doors', + 'windows', + 'sunroof', + 'storage', + 'chargingPort', + 'meta', + ]), + [], + ); +}); + test('vehicle request - odometer', async(t) => { const response = await t.context.volt.request( 'get', diff --git a/test/unit/lib/vehicle.js b/test/unit/lib/vehicle.js index ddf38c4..cd9ed0c 100644 --- a/test/unit/lib/vehicle.js +++ b/test/unit/lib/vehicle.js @@ -350,3 +350,29 @@ test('request - set charge limit', async function(t) { ); t.true(t.context.n.isDone()); }); + +test('request - security', async function(t) { + sinon.restore(); // clear all spys + + t.context.n = nocks + .base() + .get('/security') + .reply(200, + { + isLocked: true, + doors: [], + windows: [], + storage: [], + sunroof: [], + chargingPort: [], + }, {'sc-request-id': 'requestId'}); + + const serviceRequestSpy = sinon.spy(vehicle.service, 'request'); + + const response = await vehicle.lockStatus(); + + t.true(serviceRequestSpy.calledOnceWith('get', 'security')); + t.is(response.meta.requestId, 'requestId'); + t.is(response.isLocked, true); + t.true(t.context.n.isDone()); +});