Skip to content

Commit

Permalink
Merge pull request #3 from electricimp/develop
Browse files Browse the repository at this point in the history
v1.0.0
  • Loading branch information
Pavel Petroshenko authored Apr 4, 2018
2 parents 7d9421c + 6d49aa0 commit 11f3a6d
Show file tree
Hide file tree
Showing 20 changed files with 1,416 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .impt.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"deviceGroupId": "4e784e30-183f-a3fa-d9b9-6870c4749f6c",
"timeout": 30,
"stopOnFail": false,
"allowDisconnect": false,
"builderCache": false,
"testFiles": [
"*.test.nut",
"tests/**/*.test.nut"
],
"agentFile": "ThingWorx.agent.lib.nut"
}
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
language: node_js

node_js:
- 'node'

before_script:
- npm i -g imp-central-impt@latest
- impt auth login --local --lk ${EI_LOGIN_KEY}

script:
- impt test run
138 changes: 138 additions & 0 deletions Examples/DataSender.agent.nut
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// MIT License
//
// Copyright 2018 Electric Imp
//
// SPDX-License-Identifier: MIT
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#require "ThingWorx.agent.lib.nut:1.0.0"

// ThingWorx library example.
// Creates a ThingWorx Thing with two predefined Properties if it does not exist
// (thing name is specified as constructor argument) and periodically updates the properties values.
// Properties contain integer incremental value, converted to string and data measurement time
// in seconds since the epoch.
// Properties values are updated every 10 seconds.

const UPDATE_DATA_PERIOD = 10.0;

const THING_NAME = "test_thing";
const THING_PROPERTY_DATA_NAME = "data";
const THING_PROPERTY_DATA_TYPE = "STRING";
const THING_PROPERTY_MEASURE_TIME_NAME = "measure_time";
const THING_PROPERTY_MEASURE_TIME_TYPE = "INTEGER";

class DataSender {
_counter = 0;
_thingWorxClient = null;
_thingName = null;

constructor(endpoint, appKey, thingName) {
_thingWorxClient = ThingWorx(endpoint, appKey);
_thingName = thingName;
}

// Creates ThingWorx client, creates Thing if it doesn't exist and starts properties values update
function start() {
_thingWorxClient.existThing(_thingName, function (error, exist) {
if (error) {
server.error("ThingWorx existThing failed: " + error.details);
} else if (!exist) {
createThing(updatePropertiesValues);
} else {
updatePropertiesValues();
}
}.bindenv(this));
}

// Creates ThingWorx Thing
function createThing(callback) {
_thingWorxClient.createThing(_thingName, null, function (error) {
if (error) {
server.error("ThingWorx createThing failed: " + error.details);
} else {
createThingProperties(callback);
}
}.bindenv(this));
}

// Creates ThingWorx Thing Properties
function createThingProperties(callback) {
createThingProperty(THING_PROPERTY_DATA_NAME, THING_PROPERTY_DATA_TYPE, function () {
createThingProperty(THING_PROPERTY_MEASURE_TIME_NAME, THING_PROPERTY_MEASURE_TIME_TYPE, callback);
}.bindenv(this));
}

function createThingProperty(propertyName, propertyType, callback) {
_thingWorxClient.createThingProperty(_thingName, propertyName, propertyType, function (error) {
if (error) {
server.error("ThingWorx createThingProperty failed: " + error.details);
} else {
callback();
}
}.bindenv(this));
}

// Returns a data to be set for ThingWorx Properties
function getData() {
_counter++;
local result = {};
result[THING_PROPERTY_DATA_NAME] <- _counter.tostring();
result[THING_PROPERTY_MEASURE_TIME_NAME] <- time();
return result;
}

// Periodically updates Properties values
function updatePropertiesValues() {
local values = getData();
setPropertyValue(THING_PROPERTY_DATA_NAME, values[THING_PROPERTY_DATA_NAME], function() {
setPropertyValue(THING_PROPERTY_MEASURE_TIME_NAME, values[THING_PROPERTY_MEASURE_TIME_NAME], function() {
server.log("Property values updated successfully: " + http.jsonencode(values));
}.bindenv(this));
}.bindenv(this));

imp.wakeup(UPDATE_DATA_PERIOD, function () {
updatePropertiesValues();
}.bindenv(this));
}

// Updates value of the specified ThingWorx property
function setPropertyValue(propertyName, propertyValue, callback) {
_thingWorxClient.setPropertyValue(_thingName, propertyName, propertyValue, function (error) {
if (error) {
server.error("ThingWorx setPropertyValue failed: " + error.details);
} else {
callback();
}
}.bindenv(this));
}
}

// RUNTIME
// ---------------------------------------------------------------------------------

// ThingWorx constants
// ---------------------------------------------------------------------------------
const THING_WORX_ENDPOINT = "<YOUR_THING_WORX_ENDPOINT>";
const THING_WORX_APPLICATION_KEY = "<YOUR_THING_WORX_APPLICATION_KEY>";

// Start application
dataSender <- DataSender(THING_WORX_ENDPOINT, THING_WORX_APPLICATION_KEY, THING_NAME);
dataSender.start();
61 changes: 61 additions & 0 deletions Examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# ThingWorx Examples #

This document describes the example application provided with the [ThingWorx library](../README.md).

## DataSender Example ##

This example creates a ThingWorx Thing named `test_thing` (if it does not exist already) with two predefined Properties:

- *data* &mdash; An integer value, converted to string, which starts at 1 and increases by 1 with every update. It restarts from 1 every time the example is restarted.
- *measure_time* &mdash; An integer value, which is the time in seconds since the epoch.

The application updates the Properties values every 10 seconds.

## Setup and Run ##

### ThingWorx Evaluation Server Configuration ###

- Login to the [ThingWorx Developer Portal](https://developer.thingworx.com/login) in your web browser.
- Click the **Evaluation Server** icon in the top right corner. **Note** The initial provisioning of Evaluation Server for a new account usually takes between 3-5 minutes.
- Copy the **Hostname** value from the pop-up and paste it into a plain text document or equivalent. This will be used as the value of the *THING_WORX_ENDPOINT* constant in the imp agent code:
![LaunchThingWorx](../png/LaunchThingWorx.png?raw=true)
- Click **Launch**. You will be redirected to the ThingWorx Composer page (usually a new browser tab)
- In the **ThingWorx Composer** page’s **Home** tab, click **+** under **Application Keys** in the **SECURITY** section:
![AddAppKey](../png/AddAppKey.png?raw=true)
- Enter any Application Key **Name**, eg. `testAppKey`.
- Click **Search** in the **User Name Reference** field under **General Information**, and choose the **Administrator** user:
![AppKeyUser](../png/AppKeyUser.png?raw=true)
- Choose a date and time for **Expiration Date** field.
- Click **Done** then click **Save**:
![AppKeyExpirationDate](../png/AppKeyExpirationDate.png?raw=true)
- On the **General Information** page select and copy the **keyId** field and paste into a plain text document or equivalent. This will be used as the value of the *THING_WORX_APPLICATION_KEY* constant in the imp agent code:
![AppKeyId](../png/AppKeyId.png?raw=true)

### Setting Up and Running the Application ###

- In [Electric Imp’s impCentral™](https://impcentral.electricimp.com) create a Product and Development Device Group.
- Assign a development device to the newly created Device Group.
- Open the code editor for the newly created Device Group.
- Copy the [DataSender source code](./DataSender.agent.nut) and paste it into the code editor as the agent code.
- Set the *THING_WORX_ENDPOINT* constant in the agent example code to the value of Evaluation Server Hostname you retrieved and saved above. Ensure it is prefixed with `https://`. The value should look like `"https://PP-1802281448E8.Devportal.Ptc.Io"`.
- Set the *THING_WORX_APPLICATION_KEY* constant in the agent example code to the value of the Application Key ID you retrieved and saved above:
![SetThingWorxConsts](../png/SetThingWorxConsts.png?raw=true)
- Click **Build and Force Restart**.
- Use the code editor’s log pane to confirm that data is being sent successfully:
![DataSenderLogs](../png/DataSenderLogs.png?raw=true)

### Notes ###

- The hosted ThingWorx Evaluation Server is stopped after three hours of inactivity and, typically, it takes about one minute to start it again.
- You need to ensure the Server is started before running the example. To start the Server:
- Click the **Evaluation Server** icon in the top right corner of the ThingWorx Developer Portal.
- Check the Server status in the pop-up. If it is **Stopped**, click **Start**.

### Monitor the Properties Values in ThingWorx ###

- In the **ThingWorx Composer** page’s **Home** tab, click **Things** in the **MODELING** section.
- Click *test_thing* in the **Things** table:
![ThingsTable](../png/Things.png?raw=true)
- In the **test_thing** tab, click **Properties** in the **ENTITY INFORMATION** section.
- Ensure the Properties table contains **data** and **measure_time** Properties, and that their values are updated periodically if **Values** column’s refresh button is clicked:
![ThingProperties](../png/ThingProperties.png?raw=true)
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 Electric Imp

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading

0 comments on commit 11f3a6d

Please sign in to comment.