Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 0 additions & 31 deletions .eslintrc.js

This file was deleted.

93 changes: 57 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,56 @@
# SmartThings Javascript SDK
# SmartThings SmartApp NodeJS SDK (preview)

<p align="center">
<a href="https://www.npmjs.com/package/@smartthings/smartapp"><img src="https://badgen.net/npm/v/@smartthings/smartapp" /></a>
<a href="https://www.npmjs.com/package/@smartthings/smartapp"><img src="https://badgen.net/npm/license/@smartthings/smartapp" /></a>
<a href="https://status.badgen.net/"><img src="https://badgen.net/xo/status/@smartthings/smartapp" /></a>
<a href="https://lgtm.com/projects/g/SmartThingsCommunity/smartapp-sdk-nodejs/context:javascript"><img alt="Language grade: JavaScript" src="https://img.shields.io/lgtm/grade/javascript/g/SmartThingsCommunity/smartapp-sdk-nodejs.svg?logo=lgtm&logoWidth=18"/></a>
<a href="https://lgtm.com/projects/g/SmartThingsCommunity/smartapp-sdk-nodejs/alerts/"><img alt="Total alerts" src="https://img.shields.io/lgtm/alerts/g/SmartThingsCommunity/smartapp-sdk-nodejs.svg?logo=lgtm&logoWidth=18"/></a>
<a href="https://snyk.io/test/github/SmartThingsCommunity/smartapp-sdk-nodejs?targetFile=package.json"><img src="https://snyk.io/test/github/SmartThingsCommunity/smartapp-sdk-nodejs/badge.svg?targetFile=package.json" alt="Known Vulnerabilities" data-canonical-src="https://snyk.io/test/github/SmartThingsCommunity/smartapp-sdk-nodejs?targetFile=package.json" style="max-width:100%;"></a>
<a href="https://smartthingsdev.slack.com/messages/CG595N08N"><img src="https://badgen.net/badge//smartthingsdev?icon=slack" /></a>
</p>

[Reference Documentation](doc/index.md)

SDK that wraps the SmartThings REST API and reduces the amount of code necessary
to write a SmartApp app. Supports both web-hook and AWS Lambda implementations.
This is a pre-release version of the API and may change over
time time.
SDK that wraps the SmartThings REST API and reduces the amount of code necessary to write a SmartApp app. It supports both webhook and AWS Lambda implementations. This is a preview version of the API and will change over time time.

## Installation

```bash
npm i @smartthings/smartapp --save
```

## Importing

`NodeJS`:

## Installation:
```javascript
const smartapp = require('@smartthings/smartapp')
```
npm install @smartthings/smartapp --save

Or, if you're transpiling to `ES6`/`ES2015`+:

```javascript
import smartapp from '@smartthings/smartapp'
```

## Key Features
* Javascript API hides details of REST calls and authentication.
* Event handler framework dispatches lifecycle evebnts to named event handlers.
* Configuration page API simplifies page definition.
* Integrated [i18n](https://www.npmjs.com/package/i18n) framework provides configuration page localization.
* [Winston](https://www.npmjs.com/package/winston) framework manges log messages.
## Highlights

- [x] Javascript API hides details of REST calls and authentication.
- [x] Event handler framework dispatches lifecycle evebnts to named event handlers.
- [x] Configuration page API simplifies page definition.
- [x] Integrated [i18n](https://www.npmjs.com/package/i18n) framework provides configuration page localization.
- [x] [Winston](https://www.npmjs.com/package/winston) framework manges log messages.

## Example

### Run as an AWS Lambda function
Here's the equivalent of the origial SmartThings Groovy _Let There Be Light_ app that
turns on and off a light when a door opens and closes, set up to run as a Lambda.

```
require('@smartthings/smartapp');
app.configureI18n()
Here's the equivalent of the original SmartThings Groovy _Let There Be Light_ app that turns on and off a light when a door opens and closes, set up to run as a Lambda.

```javascript
const smartapp = require('@smartthings/smartapp')
smartapp.configureI18n()
.page('mainPage', (page) => {
page.section('sensors', (section) => {
section.deviceSetting('contactSensor').capabilities(['contactSensor']);
Expand All @@ -37,26 +60,24 @@ app.configureI18n()
});
})
.updated(() => {
app.api.devices.unsubscribeAll().then(() => {
app.api.devices.subscribe(app.config.contactSensor, 'contactSensor', 'contact', 'openCloseHandler');
smartapp.api.devices.unsubscribeAll().then(() => {
smartapp.api.devices.subscribe(smartapp.config.contactSensor, 'contactSensor', 'contact', 'openCloseHandler');
});
})
.subscribedEventHandler('openCloseHandler', (event) => {
const value = event.value === 'open' ? 'on' : 'off';
app.api.devices.sendCommands(app.config.lights, 'switch', value);
smartapp.api.devices.sendCommands(smartapp.config.lights, 'switch', value);
});

exports.handle = (evt, context, callback) => {
app.handleLambdaCallback(evt, context, callback);
smartapp.handleLambdaCallback(evt, context, callback);
};
```

### Localization

Configuration page strings are specified in a separate locales/en.json file, which
can be automatically created the first time you run the app. Here's a completed English localization file
for the previous example:
```
Configuration page strings are specified in a separate `locales/en.json` file, which can be automatically created the first time you run the app. Here's a completed English localization file for the previous example:

```json
{
"pages.mainPage.name": "Let There Be Light",
"pages.mainPage.sections.sensors.name": "When this door or window opens or closes",
Expand All @@ -71,12 +92,13 @@ for the previous example:

To run the app in a webserver rather than a lambda replace the `exports.handle = ...` function with an HTTP server
with the public key file specified:
```

```javascript
const express = require('express');
const bodyParser = require('body-parser');
const server = module.exports = express();
require('@smartthings/smartapp');
app.publicKey(`@${process.env.HOME}/smartthings_rsa.pub`)
const smartapp = require('@smartthings/smartapp');
smartapp.publicKey(`@${process.env.HOME}/smartthings_rsa.pub`)
.configureI18n()
.page('mainPage', (page) => {
page.section('sensors', (section) => {
Expand All @@ -87,17 +109,16 @@ app.publicKey(`@${process.env.HOME}/smartthings_rsa.pub`)
});
})
.updated(() => {
app.api.devices.unsubscribeAll().then(() => {
app.api.devices.subscribe(app.config.contactSensor, 'contactSensor', 'contact', 'openCloseHandler');
smartapp.api.devices.unsubscribeAll().then(() => {
smartapp.api.devices.subscribe(smartapp.config.contactSensor, 'contactSensor', 'contact', 'openCloseHandler');
});
})
.subscribedEventHandler('openCloseHandler', (event) => {
const value = event.value === 'open' ? 'on' : 'off';
app.api.devices.sendCommands(app.config.lights, 'switch', value);
smartapp.api.devices.sendCommands(smartapp.config.lights, 'switch', value);
});

server.use(bodyParser.json());
server.post('/', function(req, response) {
app.handleHttpCallback(req, response);
smartapp.handleHttpCallback(req, response);
});
```
```
10 changes: 5 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use strict';
'use strict'

const SmartApp = require('./lib/smart-app');
const SmartApp = require('./lib/smart-app')

module.exports = (function (options = {}) {
return new SmartApp(options);
})();
return new SmartApp(options)
})()

module.exports.default = Object.assign({}, module.exports);
module.exports.default = Object.assign({}, module.exports)
53 changes: 26 additions & 27 deletions lib/api.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
'use strict';
'use strict'

const Client = require('./platform/client');
const Apps = require('./platform/apps');
const DeviceProfiles = require('./platform/deviceprofiles');
const Devices = require('./platform/devices');
const InstalledApps = require('./platform/installedapps');
const Locations = require('./platform/locations');
const Modes = require('./platform/modes');
const Scenes = require('./platform/scenes');
const Schedules = require('./platform/schedules');
const Subscriptions = require('./platform/subscriptions');
const Client = require('./platform/client')
const Apps = require('./platform/apps')
const DeviceProfiles = require('./platform/deviceprofiles')
const Devices = require('./platform/devices')
const InstalledApps = require('./platform/installedapps')
const Locations = require('./platform/locations')
const Modes = require('./platform/modes')
const Scenes = require('./platform/scenes')
const Schedules = require('./platform/schedules')
const Subscriptions = require('./platform/subscriptions')

module.exports = class SmartThingsApi {

constructor(options) {
this.client = new Client(options);
this.apps = new Apps(this);
this.deviceProfiles = new DeviceProfiles(this);
this.devices = new Devices(this);
this.installedApps = new InstalledApps(this);
this.locations = new Locations(this);
this.modes = new Modes(this);
this.scenes = new Scenes(this);
this.schedules = new Schedules(this);
this.subscriptions = new Subscriptions(this);
this.installedAppId = options.installedAppId;
this.locationId = options.locationId;
}
};
constructor(options) {
this.client = new Client(options)
this.apps = new Apps(this)
this.deviceProfiles = new DeviceProfiles(this)
this.devices = new Devices(this)
this.installedApps = new InstalledApps(this)
this.locations = new Locations(this)
this.modes = new Modes(this)
this.scenes = new Scenes(this)
this.schedules = new Schedules(this)
this.subscriptions = new Subscriptions(this)
this.installedAppId = options.installedAppId
this.locationId = options.locationId
}
}
64 changes: 33 additions & 31 deletions lib/pages/boolean-setting.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
'use strict';
'use strict'

const SectionSetting = require('./section-setting.js');
const SectionSetting = require('./section-setting.js')

module.exports = class BooleanSetting extends SectionSetting {
constructor(section, id) {
super(section, id)
this._type = 'BOOLEAN'
}

constructor(section, id) {
super(section, id);
this._type = 'BOOLEAN';
}

image(value) {
this._image = value;
return this;
}

submitOnChange(value) {
this._submitOnChange = value;
return this;
}

toJson() {
let result = super.toJson();
if (result.defaultValue === undefined && result.required) {
result.defaultValue = 'false';
}
if (this._image) {
result.image = this._image;
}
if (this._submitOnChange) {
result.submitOnChange = this._submitOnChange;
}
return result;
}
};
image(value) {
this._image = value
return this
}

submitOnChange(value) {
this._submitOnChange = value
return this
}

toJson() {
const result = super.toJson()
if (result.defaultValue === undefined && result.required) {
result.defaultValue = 'false'
}

if (this._image) {
result.image = this._image
}

if (this._submitOnChange) {
result.submitOnChange = this._submitOnChange
}

return result
}
}
Loading