Skip to content

Commit b377837

Browse files
galpeteryichoi
authored andcommitted
Add SmartThings Cloud-to-Cloud demo (#14)
IoT.js-Samples-DCO-1.0-Signed-off-by: Peter Gal [email protected]
1 parent 96704c8 commit b377837

File tree

8 files changed

+1145
-0
lines changed

8 files changed

+1145
-0
lines changed

Diff for: cloud-2-cloud/README.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Demo Cloud-to-Cloud connector
2+
3+
The example creates a C2C connector which creates a new device with
4+
`switchLevel` capability and a schedules timer events in every 5 minutes.
5+
6+
## How to use?
7+
8+
1. Create a personal token at the [https://account.smartthings.com/tokens] page.
9+
For this demo you should select all of the scopes. Please note down the
10+
authentication token as it will be required below as the `authToken`.
11+
12+
2. Create an `ngrok` http tunnel for a custom port.
13+
For example:
14+
```
15+
$ ngrok http 8889
16+
```
17+
There will be a `Forwarding https://.....ngrok.io` entry from which the
18+
https url is required, please note this down.
19+
20+
3. Create a JSON file named `local_config.json` with the following contents:
21+
```
22+
{
23+
"appName": "....",
24+
"displayName": "....",
25+
"targetUrl": "https://....",
26+
"localPort": 8889,
27+
"authToken": "..."
28+
}
29+
```
30+
31+
Info about the keys:
32+
* `appName` - the name of the app, must be a globally unique (do *not* use upper case letters!)
33+
* `displayName` - the name which will be displayed.
34+
* `targetUrl` - the publicly accessible url by the ST cloud, must be a https url!
35+
* `localPort` - the local port on which the application should listen,
36+
* `authToken` - the authToken issued by the https://account.smartthings.com/tokens page.
37+
38+
4. Start the `app.js`. This will create a Cloud-to-Cloud connector. Do not close this terminal.
39+
```
40+
$ iotjs app.js
41+
```
42+
43+
5. In another terminal run the `appRegister.js`.
44+
```
45+
$ iotjs appRegister.js
46+
```
47+
This command will register the previously started Cloud-to-Cloud connector. There should be
48+
a PING activity in the previous terminal. Additionally a device profile is also created.
49+
To see what was returned by the Cloud please see the `result_appdeviceprofile.json` and
50+
the `result_appprofile.json` files. Do *not* delete these new files.
51+
52+
6. Install the C2C connector application in the SmartThings Android application.
53+
For this maybe the old Android application should be used.
54+
55+
7. After a successful installation the C2C connector should install its own
56+
device. This device has one capability: `switchLevel`.
57+
58+
8. To send a command to the device please use the `trigger_device.js` application.
59+
This application will send a new random switchLevel value for the installed device.
60+
The new value arrives for the C2C connector as an `EVENT` lifecycle with `DEVICE_EVENT` type.
61+
All events are printed out by the C2C connector.
62+
63+
64+
9. If the application is no longer needed it is possible to uninstall it.
65+
For this please extract the `installedAppId` from the `result_appinstallconfig.json` file and
66+
execute the following command:
67+
```
68+
$ iotjs cmds installedapps_delete <installedAppId>
69+
```
70+
This will remove the registered timer(s) also.

Diff for: cloud-2-cloud/app.js

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
var console = require('console');
17+
18+
var config = require('./config.js');
19+
var st = require('./smartthings.js');
20+
var sthook = require('./stwebhook.js');
21+
var fs = require('fs');
22+
23+
var config_ok = true;
24+
if (!config.authToken) {
25+
console.log('ERROR: No personal authToken specified in the config file');
26+
console.log('Please visit the https://account.smartthings.com/tokens page');
27+
console.log('To generate an authToken');
28+
console.log('');
29+
config_ok = false;
30+
}
31+
32+
if (!config.targetUrl) {
33+
console.log('ERROR: No targetUrl specified in the config file');
34+
console.log('The targetUrl should be a publicly accessible https url');
35+
console.log('');
36+
config_ok = false;
37+
}
38+
39+
if (!config.appName) {
40+
console.log('ERROR: No appName specified in the config file');
41+
console.log('The appName should be a globally unique name');
42+
console.log('');
43+
config_ok = false;
44+
}
45+
46+
if (!config_ok) {
47+
process.exit(-1);
48+
}
49+
50+
var demoApp = new sthook.STWebHook();
51+
52+
demoApp.on('CONFIGURATION', function(message, response) {
53+
console.log(' Got CONFIGURATION lifecycle');
54+
var data = {};
55+
56+
if (message.configurationData.phase === 'INITIALIZE') {
57+
console.log(' Performing SmartApp initialization');
58+
this._installedAppId = message.configurationData.installedAppId;
59+
var initData = {
60+
name: 'Example IoT.js SmartC2C app',
61+
description: data.name,
62+
id: 'demoappc2c',
63+
permissions: [
64+
'l:devices',
65+
'r:devices:*',
66+
'x:devices:*',
67+
'r:schedules',
68+
'w:schedules',
69+
'i:deviceprofiles',
70+
'r:locations:*',
71+
],
72+
firstPageId: '1',
73+
};
74+
75+
data = { initialize: initData };
76+
} else if (message.configurationData.phase === 'PAGE') {
77+
var pageData = {
78+
pageId: '1',
79+
name: 'Example IoT.js SmartC2C app',
80+
nextPageId: null,
81+
previousPageId: null,
82+
complete: true,
83+
sections: [
84+
{
85+
name: 'C-2-C config',
86+
settings: [
87+
{
88+
id: 'magicKeySettings',
89+
name: 'Magic key',
90+
description: 'Magic key to configure something',
91+
type: 'TEXT',
92+
required: false,
93+
defaultValue: '42',
94+
},
95+
{
96+
id: 'debugLogging',
97+
name: 'Use debug logging?',
98+
description: '',
99+
type: 'BOOLEAN',
100+
required: true,
101+
defaultValue: 'true',
102+
},
103+
],
104+
}
105+
],
106+
};
107+
108+
data.page = pageData;
109+
}
110+
111+
return { statusCode: 200, configurationData: data };
112+
});
113+
114+
115+
demoApp.on('INSTALL', function(message, response) {
116+
console.log(' Got INSTALL lifecycle');
117+
console.log(' Got authToken: %s', message.installData.authToken);
118+
119+
this._installData = message.installData;
120+
fs.writeFileSync(config.paths.lastInstall, JSON.stringify(message));
121+
122+
var deviceProfile = JSON.parse(fs.readFileSync(config.paths.deviceProfile));
123+
124+
if (config.schedule) {
125+
var options = {
126+
authToken: message.installData.authToken,
127+
installedAppId: message.installData.installedApp.installedAppId,
128+
}
129+
console.log(' Trying to install a schedule');
130+
st.schedules_add(options, config.schedule, function(data, status_code) {
131+
if (status_code == 200) {
132+
console.log(' Schedule install OK');
133+
} else {
134+
console.log(' Schedule install failed');
135+
}
136+
});
137+
}
138+
139+
var deviceData = {
140+
label: "Test dev",
141+
locationId: this._installData.installedApp.locationId,
142+
app: {
143+
profileId: deviceProfile.id,
144+
installedAppId: this._installData.installedApp.installedAppId,
145+
externalId: 'IOTJSD0001',
146+
}
147+
};
148+
st.device_install({authToken: this._installData.authToken}, deviceData, function(data) {
149+
console.log("Device installed:");
150+
console.log(data);
151+
fs.writeFileSync(config.paths.deviceInstall, JSON.stringify(data));
152+
});
153+
154+
return { statusCode: 200, installData: {} };
155+
});
156+
157+
demoApp.on('UPDATE', function(message, response) {
158+
console.log(' Got UPDATE lifecycle');
159+
160+
fs.writeFileSync(config.path.newConfig, JSON.stringify(message));
161+
162+
return { statusCode: 200, updateData: {} };
163+
});
164+
165+
demoApp.on('EVENT', function(message, response) {
166+
console.log(' Got EVENT lifecycle');
167+
168+
var events = message.eventData.events;
169+
170+
for (var idx = 0; idx < events.length; idx++) {
171+
var event = events[idx];
172+
var eventData = {};
173+
switch (event.eventType) {
174+
case 'DEVICE_COMMANDS_EVENT': {
175+
console.log(' DEVICE Event triggered:')
176+
eventData = event.deviceCommandsEvent;
177+
break;
178+
}
179+
case 'DEVICE_EVENT': {
180+
console.log(' DEVICE Event triggered:')
181+
eventData = event.deviceEvent;
182+
break;
183+
}
184+
case 'TIMER_EVENT': {
185+
console.log(' TIMER Event triggered:')
186+
eventData = event.timerEvent;
187+
break;
188+
}
189+
}
190+
191+
console.log(eventData);
192+
}
193+
194+
return { statusCode: 200, eventData: {} };
195+
});
196+
197+
var server = new sthook.STWebHookServer(config, demoApp);
198+
server.createServer();
199+
server.listen();

Diff for: cloud-2-cloud/appRegister.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
var console = require('console');
17+
var fs = require('fs');
18+
var st = require('./smartthings.js')
19+
20+
var config = require('./config.js');
21+
22+
st.register_webhook(config, function(response, status_code) {
23+
console.log('WebHook Register Response:');
24+
console.log(response);
25+
if (status_code == 200) {
26+
fs.writeFileSync(config.paths.appProfile, JSON.stringify(response));
27+
28+
var options = {
29+
authToken: config.authToken,
30+
appName: response.app.appId,
31+
};
32+
st.app_updateoauth(options, config.appOauth, function(data, status_code) {
33+
console.log('Update oauth response:');
34+
console.log(data);
35+
36+
console.log('');
37+
console.log('Everything should be registered!');
38+
console.log('Please check the Android App');
39+
});
40+
}
41+
});
42+
43+
st.deviceprofile_create(config, config.deviceProfile, function(data, status_code) {
44+
console.log('Device profile install response:');
45+
console.log(data);
46+
if (status_code == 200) {
47+
fs.writeFileSync(config.paths.deviceProfile, JSON.stringify(data));
48+
console.log('Device profile install DONE');
49+
}
50+
});

0 commit comments

Comments
 (0)