summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorC.J. Collier <cjcollier@linuxfoundation.org>2017-12-20 06:30:11 +0000
committerGerrit Code Review <gerrit@iotivity.org>2017-12-20 06:30:11 +0000
commit12295f918f5bee283fb858fe5bbb0ceba417c62a (patch)
treed0b0cda7567e52e5a9782f86b558597701785ec9
parent324c70971e7dacdb378c82aa9c9c6b7e257e4e69 (diff)
parenta85c59dbe486d7bf44c3a4e36808cc58f9a7ad90 (diff)
Merge "Alexa code related to RT#50059"
-rw-r--r--alexa-bridge-skill-lambda/index.js366
-rwxr-xr-xalexa-iotivity-bridge-demo/build.sh10
-rwxr-xr-xalexa-iotivity-bridge-demo/run.sh3
-rwxr-xr-xalexa-iotivity-bridge-demo/runscanner.sh3
-rw-r--r--alexa-smart-home-skill-lambda/index.js547
-rw-r--r--ocf-light-server/LICENSE.md195
-rw-r--r--ocf-light-server/README.md51
-rwxr-xr-xocf-light-server/build.sh12
-rw-r--r--ocf-light-server/options.txt2
-rw-r--r--ocf-light-server/res/bulb-icon-32x32.pngbin0 -> 1556 bytes
-rw-r--r--ocf-light-server/res/light-off.pngbin0 -> 36254 bytes
-rw-r--r--ocf-light-server/res/light-on.pngbin0 -> 40066 bytes
-rwxr-xr-xocf-light-server/run.sh1
-rw-r--r--ocf-light-server/sourcefiles.txt13
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/Brightness.java103
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/Light.java259
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/LightConfig.java86
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/LightImageObserver.java31
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/LightPanel.java213
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/Link.java90
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/Links.java82
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/NamesPropertyFile.java115
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/OcfLightDevice.java203
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/Resource.java240
-rw-r--r--ocf-light-server/src/main/java/org/iotivity/base/examples/Switch.java97
25 files changed, 2722 insertions, 0 deletions
diff --git a/alexa-bridge-skill-lambda/index.js b/alexa-bridge-skill-lambda/index.js
new file mode 100644
index 0000000..4e1c5c9
--- /dev/null
+++ b/alexa-bridge-skill-lambda/index.js
@@ -0,0 +1,366 @@
+"use strict";
+var config = {};
+
+var AWS = require("aws-sdk");
+var Alexa = require("alexa-sdk");
+
+// replace with endpoint from AWS IoT Device
+var iotData = new AWS.IotData({endpoint:"a2a16j9xf0mmy6.iot.us-east-1.amazonaws.com", region:"us-east-1"});
+// replace with Thing Name for AWS IoT Device
+var thingName = "larryslinuxbox";
+
+var APP_ID = "amzn1.ask.skill.04c3ebae-673e-48ed-8892-bb58feb3eb54";
+var SKILL_NAME = "AlexaIotivityBridgeSkill";
+
+exports.handler = function(event, context, callback) {
+ console.log("Received event:", JSON.stringify(event, null, 2));
+ var alexa = Alexa.handler(event, context);
+ alexa.appId = APP_ID;
+ alexa.registerHandlers(handlers);
+ alexa.execute();
+};
+
+var handlers = {
+ "LaunchRequest": function() {
+ this.emit(":tell", "Bridge Operational");
+ },
+
+ "ListLightsIntent": function() {
+ awsIot.getLights(this);
+ },
+
+ "AllLightsStateIntent": function() {
+ var itemSlot = this.event.request.intent.slots.lightState;
+ var requestedLightState;
+ if (itemSlot && itemSlot.value) {
+ var itemSlotValue = itemSlot.value.toLowerCase();
+ console.log("itemSlotValue: " + itemSlotValue);
+ if (itemSlotValue == "on" || itemSlotValue == "off") {
+ requestedLightState = itemSlotValue;
+ }
+ }
+ console.log("requestedLightState: " + requestedLightState);
+
+ if (!requestedLightState) {
+ this.emit(":tell", "Sorry, I didn't get that");
+ } else {
+ var speechOutput = "All lights " + requestedLightState;
+ awsIot.allLightsStateChange(this, requestedLightState, speechOutput);
+ }
+ },
+
+ "LightBrightnessIntent": function() {
+ var lightName = this.event.request.intent.slots.lightName.value;
+ var lightBrightness = this.event.request.intent.slots.lightBrightness.value;
+ console.log("lightName: " + lightName);
+ console.log("lightBrightness: " + lightBrightness);
+
+ if (!lightName || !lightBrightness) {
+ this.emit(":tell", "Sorry, I didn't get that");
+ } else {
+ awsIot.updateLight(this, postGetLights.updateBrightness, lightName, lightBrightness);
+ }
+ },
+
+ "LightStateIntent": function() {
+ var lightName = this.event.request.intent.slots.lightName.value;
+ var lightState = this.event.request.intent.slots.lightState.value;
+ console.log("lightName: " + lightName);
+ console.log("lightState: " + lightState);
+
+ if (!lightName || !lightState) {
+ this.emit(":tell", "Sorry, I didn't get that");
+ } else {
+ awsIot.updateLight(this, postGetLights.updateOnOff, lightName, lightState);
+ }
+ },
+
+ "LightRenameIntent": function() {
+ var lightName = this.event.request.intent.slots.lightName.value;
+ var newLightName = this.event.request.intent.slots.newLightName.value;
+ console.log("lightName: " + lightName);
+ console.log("newLightName: " + newLightName);
+
+ if (!lightName || !newLightName) {
+ this.emit(":tell", "Sorry, I didn't get that");
+ } else {
+ awsIot.updateLight(this, postGetLights.updateName, lightName, newLightName);
+ }
+ },
+
+ "AMAZON.HelpIntent": function() {
+ this.attributes["speechOutput"] = "You can ask questions such as, 'List Lights', or you can say 'exit'... " +
+ "Now, what can I help you with?";
+ this.attributes["repromptSpeech"] = "You can say things like, 'List Lights', or you can say 'exit'... " +
+ "Now, what can I help you with?";
+ this.emit(":ask", this.attributes["speechOutput"], this.attributes["repromptSpeech"]);
+ },
+
+ "AMAZON.RepeatIntent": function() {
+ this.emit(":ask", this.attributes["speechOutput"], this.attributes["repromptSpeech"]);
+ },
+
+ "AMAZON.StopIntent": function() {
+ this.emit("SessionEndedRequest");
+ },
+
+ "AMAZON.CancelIntent": function() {
+ this.emit("SessionEndedRequest");
+ },
+
+ "SessionEndedRequest":function() {
+ this.emit(":tell", "Goodbye!");
+ }
+};
+
+var awsIot = {
+ postSendMessage: function(thisOfCaller, speechOutput) {
+ console.log("post send message: " + speechOutput);
+ thisOfCaller.emit(":tell", speechOutput);
+ },
+
+ allLightsStateChange: function(thisOfCaller, requestedStateForEachLight, speechOutput) {
+ // update the state for each light
+ var thingNameParam = {
+ thingName: thingName
+ };
+
+ iotData.getThingShadow(thingNameParam, function(err, data) {
+ console.log("get thing shadow (in sendAllOnOff)")
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (err) {
+ speechOutput = "Sorry, no lights found."
+ awsIot.postSendMessage(thisOfCaller, speechOutput);
+ }
+ else {
+ var jsonPayload = JSON.parse(data.payload);
+ var lightDevices = jsonPayload.state.reported.lightDevices;
+ if (lightDevices.length > 0) {
+ lightDevices.forEach((item, index, array) => {
+ console.log("lightDevices["+index+"]: "+JSON.stringify(item));
+ });
+ } else {
+ console.log("no lights found");
+ speechOutput = "Sorry, no lights found.";
+ }
+
+ postGetLights.updateOnOff(thisOfCaller, lightDevices, null, requestedStateForEachLight, speechOutput);
+ }
+ });
+ },
+
+ getLights: function(thisOfCaller) {
+ var speechOutput = "";
+ var thingNameParam = {
+ thingName: thingName
+ };
+
+ iotData.getThingShadow(thingNameParam, function(err, data) {
+ console.log("get thing shadow")
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (err) {
+ speechOutput += " - Error getting device list: " + err + " ";
+ speechOutput += thingNameParam.thingName;
+ } else {
+ var jsonPayload = JSON.parse(data.payload);
+ var lightDevices = jsonPayload.state.reported.lightDevices;
+ if (lightDevices.length > 0) {
+ jsonPayload.state.reported.lightDevices.forEach((item, index, array) => {
+ console.log("lightDevices["+index+"]: "+JSON.stringify(item));
+ if (index > 0) {
+ speechOutput += ", ";
+ }
+ speechOutput += item.name + " is " + (item.powerOn ? "on" : "off");
+ });
+ } else {
+ speechOutput = "Sorry, no lights found."
+ }
+ }
+
+ awsIot.postSendMessage(thisOfCaller, speechOutput);
+ });
+ },
+
+ updateLight: function(thisOfCaller, postGetLights, lightName, lightParam) {
+ var speechOutput = "";
+ var thingNameParam = {
+ thingName: thingName
+ };
+
+ iotData.getThingShadow(thingNameParam, function(err, data) {
+ console.log("get thing shadow (in updateLights)")
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (err) {
+ speechOutput = "Sorry, no lights found."
+ awsIot.postSendMessage(thisOfCaller, speechOutput);
+ }
+ else {
+ var foundLightName = false;
+ var jsonPayload = JSON.parse(data.payload);
+ var lightDevices = jsonPayload.state.reported.lightDevices;
+ if (lightDevices.length > 0) {
+ lightDevices.forEach((item, index, array) => {
+ console.log("lightDevices["+index+"]: "+JSON.stringify(item));
+ if (item.name.toLowerCase() == lightName.toLowerCase()) {
+ console.log("light found -- lightDevices["+index+"]: "+JSON.stringify(item));
+ foundLightName = true;
+ }
+ });
+ } else {
+ console.log("no lights found");
+ }
+ if (foundLightName) {
+ postGetLights(thisOfCaller, lightDevices, lightName, lightParam, speechOutput);
+ } else {
+ speechOutput = "Sorry, I can't find " + lightName;
+ awsIot.postSendMessage(thisOfCaller, speechOutput);
+ }
+ }
+ });
+ }
+};
+
+var postGetLights = {
+ updateBrightness: function(thisOfCaller, lightDevices, lightName, lightParam, speechOutput) {
+ // Set the desired brightness of the light
+ var newLightBrightness;
+ if (lightParam < 0) {
+ newLightBrightness = 0;
+ } else if (lightParam > 100) {
+ newLightBrightness = 100;
+ } else {
+ newLightBrightness = lightParam * 1; // make it a number
+ }
+
+ lightDevices.forEach((item, index, array) => {
+ console.log("lightDevices["+index+"]: "+JSON.stringify(item));
+ if (item.name.toLowerCase() == lightName.toLowerCase()) {
+ lightDevices[index].brightness = newLightBrightness;
+ }
+ console.log("desired lightDevices["+index+"]: "+JSON.stringify(lightDevices[index]));
+ });
+ var desiredLightState =
+ {"state":{"desired":{"device":thingName,"lightDevices":lightDevices}}};
+
+ var thingNameAndPayload = {
+ thingName: thingName,
+ payload: JSON.stringify(desiredLightState)
+ };
+ console.log("payload:", JSON.stringify(desiredLightState, null, 2));
+
+ iotData.updateThingShadow(thingNameAndPayload, function(err, data) {
+ console.log("updateBrightness update thing shadow")
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (err) {
+ speechOutput += " - Error updating light: " + err + " ";
+ speechOutput += thingNameAndPayload.thingName + " ";
+ speechOutput += thingNameAndPayload.payload;
+ } else {
+ speechOutput = lightName + " brightness " + newLightBrightness;
+ }
+ awsIot.postSendMessage(thisOfCaller, speechOutput);
+ });
+ },
+
+ updateOnOff: function(thisOfCaller, lightDevices, lightName, lightParam, speechOutput) {
+ // Set the desired state of the light
+ // lightName of null means all lights
+ console.log("lightName = "+lightName+", !lightName="+(!lightName));
+ var newLightState = (lightParam.toLowerCase() == "on");
+ lightDevices.forEach((item, index, array) => {
+ console.log("lightDevices["+index+"]: "+JSON.stringify(item));
+ if ((! lightName) || (item.name.toLowerCase() == lightName.toLowerCase())) {
+ lightDevices[index].powerOn = newLightState;
+ }
+ console.log("desired lightDevices["+index+"]: "+JSON.stringify(lightDevices[index]));
+ });
+ var desiredLightState =
+ {"state":{"desired":{"device":thingName,"lightDevices":lightDevices}}};
+
+ var thingNameAndPayload = {
+ thingName: thingName,
+ payload: JSON.stringify(desiredLightState)
+ };
+ console.log("payload:", JSON.stringify(desiredLightState, null, 2));
+
+ iotData.updateThingShadow(thingNameAndPayload, function(err, data) {
+ console.log("updateOnOff update thing shadow")
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (err) {
+ speechOutput += " - Error updating light: " + err + " ";
+ speechOutput += thingNameAndPayload.thingName + " ";
+ speechOutput += thingNameAndPayload.payload;
+ } else {
+ if (lightName) {
+ speechOutput = lightName + " " + (newLightState ? "on" : "off");
+ }
+ }
+ awsIot.postSendMessage(thisOfCaller, speechOutput);
+ });
+ },
+
+ updateName: function(thisOfCaller, lightDevices, lightName, lightParam, speechOutput) {
+ // Set the desired name of the light
+ var newLightName = lightParam;
+
+ lightDevices.forEach((item, index, array) => {
+ console.log("lightDevices["+index+"]: "+JSON.stringify(item));
+ if (item.name.toLowerCase() == lightName.toLowerCase()) {
+ lightDevices[index].name = newLightName;
+ }
+ console.log("desired lightDevices["+index+"]: "+JSON.stringify(lightDevices[index]));
+ });
+
+ // sort desired light devices by name (ignoring case)
+ lightDevices.sort((lhs, rhs) => {
+ var lhsName = lhs.name.toLowerCase();
+ var rhsName = rhs.name.toLowerCase();
+
+ if (lhsName < rhsName) {
+ return -1;
+ }
+ if (lhsName > rhsName) {
+ return 1;
+ }
+ // names must be equal
+ return 0;
+ });
+ lightDevices.forEach((item, index, array) => {
+ console.log("sorted desired lightDevices["+index+"]: "+JSON.stringify(item));
+ });
+
+ var desiredLightState =
+ {"state":{"desired":{"device":thingName,"lightDevices":lightDevices}}};
+
+ var thingNameAndPayload = {
+ thingName: thingName,
+ payload: JSON.stringify(desiredLightState)
+ };
+ console.log("payload:", JSON.stringify(desiredLightState, null, 2));
+
+ iotData.updateThingShadow(thingNameAndPayload, function(err, data) {
+ console.log("updateName update thing shadow")
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (err) {
+ speechOutput += " - Error updating light: " + err + " ";
+ speechOutput += thingNameAndPayload.thingName + " ";
+ speechOutput += thingNameAndPayload.payload;
+ } else {
+ speechOutput = lightName + " renamed as " + newLightName;
+ }
+ awsIot.postSendMessage(thisOfCaller, speechOutput);
+ });
+ }
+};
diff --git a/alexa-iotivity-bridge-demo/build.sh b/alexa-iotivity-bridge-demo/build.sh
new file mode 100755
index 0000000..5c78ab3
--- /dev/null
+++ b/alexa-iotivity-bridge-demo/build.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+#find ./out -type f -name '*.class' -delete
+rm -rf ./out
+mkdir out
+javac @options.txt @sourcefiles.txt
+
+#jar -cfv AlexaIotivityBridgeDemo.jar -C out/ .
+jar -cf AlexaIotivityBridgeDemo.jar -C out/ .
+
diff --git a/alexa-iotivity-bridge-demo/run.sh b/alexa-iotivity-bridge-demo/run.sh
new file mode 100755
index 0000000..e14441a
--- /dev/null
+++ b/alexa-iotivity-bridge-demo/run.sh
@@ -0,0 +1,3 @@
+# -cp assumes iotivity.jar has been copied into ./lib/
+
+java -Djava.library.path=/home/larrys/work/iotivity-1.3-rel/iotivity/out/linux/x86_64/release -cp AlexaIotivityBridgeDemo.jar:./lib/iotivity.jar:./lib/aws-iot-device-sdk-java-1.1.1.jar:./lib/jackson-core-2.9.0.jar:./lib/jackson-annotations-2.9.0.jar:./lib/jackson-databind-2.9.0.jar:./lib/org.eclipse.paho.client.mqttv3-1.2.0.jar org.iotivity.base.examples.AlexaIotivityBridgeDemo -clientEndpoint a2a16j9xf0mmy6.iot.us-east-1.amazonaws.com -clientId arn:aws:iot:us-east-1:834884142022:thing/larryslinuxbox -certificateFile /home/larrys/work/connect_device_package/larryslinuxbox.cert.pem -privateKeyFile /home/larrys/work/connect_device_package/larryslinuxbox.private.key -thingName larryslinuxbox
diff --git a/alexa-iotivity-bridge-demo/runscanner.sh b/alexa-iotivity-bridge-demo/runscanner.sh
new file mode 100755
index 0000000..3bb2327
--- /dev/null
+++ b/alexa-iotivity-bridge-demo/runscanner.sh
@@ -0,0 +1,3 @@
+# -cp assumes iotivity.jar has been copied into ./lib/
+
+java -Djava.library.path=/home/larrys/work/iotivity-1.3-rel/iotivity/out/linux/x86_64/release -cp AlexaIotivityBridgeDemo.jar:./lib/iotivity.jar org.iotivity.base.examples.IotivityScanner $1 \ No newline at end of file
diff --git a/alexa-smart-home-skill-lambda/index.js b/alexa-smart-home-skill-lambda/index.js
new file mode 100644
index 0000000..ced7734
--- /dev/null
+++ b/alexa-smart-home-skill-lambda/index.js
@@ -0,0 +1,547 @@
+"use strict";
+
+const AWS = require("aws-sdk");
+const uuidV4 = require("uuid/v4");
+
+// replace with endpoint from AWS IoT Device
+const iotData = new AWS.IotData({endpoint:"a2a16j9xf0mmy6.iot.us-east-1.amazonaws.com", region:"us-east-1"});
+// replace with Thing Name for AWS IoT Device
+const thingName = "LeetoniaLinuxSystem";
+// replace with skill's Application Id
+const APP_ID = "amzn1.ask.skill.26df3d97-ba4d-44c4-aee5-0f20cce5375b";
+const SKILL_NAME = "AlexaIotivityHomeSkill";
+
+function generateMessageId() {
+ return uuidV4();
+}
+
+function generateDevice(endpointId, friendlyName, uri) {
+ return {
+ endpointId: endpointId,
+ manufacturerName: "Intel",
+ friendlyName: friendlyName,
+ description: uri,
+ displayCategories: [ "LIGHT" ],
+ cookie: {},
+ capabilities: [
+ {
+ type: "AlexaInterface",
+ interface: "Alexa",
+ version: "3"
+ },
+ {
+ type: "AlexaInterface",
+ interface: "Alexa.EndpointHealth",
+ version: "3",
+ properties: {
+ supported: [
+ {
+ name: "connectivity"
+ }
+ ],
+ proactivelyReported: true,
+ retrievable: true
+ }
+ },
+ {
+ type: "AlexaInterface",
+ interface: "Alexa.PowerController",
+ version: "3",
+ properties: {
+ supported: [
+ {
+ name: "powerState"
+ }
+ ],
+ proactivelyReported: true,
+ retrievable: true
+ }
+ },
+ {
+ type: "AlexaInterface",
+ interface: "Alexa.BrightnessController",
+ version: "3",
+ properties: {
+ supported: [
+ {
+ name: "brightness"
+ }
+ ],
+ proactivelyReported: true,
+ retrievable: true
+ }
+ }
+ ]
+ };
+}
+
+function generateStateResponse(endpointId, correlationToken, powerOn, brightness) {
+ const currentTime = new Date().toISOString();
+ return {
+ context: {
+ properties: [
+ {
+ namespace: "Alexa.EndpointHealth",
+ name: "connectivity",
+ value: {
+ value: "OK"
+ },
+ timeOfSample: currentTime,
+ uncertaintyInMilliseconds: 1000
+ },
+ {
+ namespace: "Alexa.PowerController",
+ name: "powerState",
+ value: powerOn ? "ON" : "OFF",
+ timeOfSample: currentTime,
+ uncertaintyInMilliseconds: 1000
+ },
+ {
+ namespace: "Alexa.BrightnessController",
+ name: "brightness",
+ value: brightness,
+ timeOfSample: currentTime,
+ uncertaintyInMilliseconds: 1000
+ }
+ ]
+ },
+ event: {
+ header: {
+ namespace: "Alexa",
+ name: "StateReport",
+ payloadVersion: "3",
+ messageId: generateMessageId(),
+ correlationToken: correlationToken
+ },
+ endpoint: {
+ scope: {
+ type: "BearerToken",
+ token: "access-token-from-Amazon"
+ },
+ endpointId: endpointId
+ },
+ payload: {}
+ }
+ };
+}
+
+function generateResponse(namespace, name, value, endpointId, correlationToken) {
+ return {
+ context: {
+ properties: [
+ {
+ namespace: namespace,
+ name: name,
+ value: value,
+ timeOfSample: new Date().toISOString(),
+ uncertaintyInMilliseconds: 1000
+ }
+ ]
+ },
+ event: {
+ header: {
+ namespace: "Alexa",
+ name: "Response",
+ payloadVersion: "3",
+ messageId: generateMessageId(),
+ correlationToken: correlationToken
+ },
+ endpoint: {
+ scope: {
+ type: "BearerToken",
+ token: "access-token-from-Amazon"
+ },
+ endpointId: endpointId
+ },
+ payload: {}
+ }
+ };
+}
+
+function generateErrorResponse(type, message, endpointId, correlationToken) {
+ return {
+ event: {
+ header: {
+ namespace: "Alexa",
+ name: "ErrorResponse",
+ payloadVersion: "3",
+ messageId: generateMessageId(),
+ correlationToken: correlationToken
+ },
+ endpoint: {
+ scope: {
+ type: "BearerToken",
+ token: "access-token-from-Amazon"
+ },
+ endpointId: endpointId
+ },
+ payload: {
+ type: type,
+ message: message
+ }
+ }
+ };
+}
+
+function isValidToken(userAccessToken) {
+ // TODO:
+ return true;
+}
+
+function isDeviceOnline(endpointId, userAccessToken) {
+ // TODO:
+ console.log("DEBUG", "isDeviceOnline -- endpointId: " + endpointId);
+ return true;
+}
+
+function getDevicesFromAwsIot(userAccessToken, callback) {
+ var devices = [];
+ const thingNameParam = {
+ thingName: thingName
+ };
+
+ iotData.getThingShadow(thingNameParam, function(err, data) {
+ console.log("DEBUG", "get thing shadow");
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (!err) {
+ const jsonPayload = JSON.parse(data.payload);
+ const lightDevices = jsonPayload.state.reported.lightDevices;
+ if (lightDevices.length > 0) {
+ jsonPayload.state.reported.lightDevices.forEach((item, index, array) => {
+ console.log("DEBUG", "lightDevices["+index+"]: "+JSON.stringify(item, null, 2));
+ const uriParts = item.uri.split("/");
+ const endpointId = uriParts[uriParts.length-1];
+ devices.push(generateDevice(endpointId, item.name, item.uri));
+ });
+ }
+ }
+
+ const response = {
+ event: {
+ header: {
+ namespace: "Alexa.Discovery",
+ name: "Discover.Response",
+ payloadVersion: "3",
+ messageId: generateMessageId()
+ },
+ payload: {
+ endpoints: devices
+ }
+ }
+ };
+
+ console.log("DEBUG", "Discovery Response: " + JSON.stringify(response, null, 2));
+ callback(null, response);
+ });
+}
+
+function getDeviceStateFromAwsIot(userAccessToken, endpointId, correlationToken, callback) {
+ var deviceFound = false;
+ const thingNameParam = {
+ thingName: thingName
+ };
+
+ iotData.getThingShadow(thingNameParam, function(err, data) {
+ console.log("DEBUG", "get thing shadow");
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (!err) {
+ const jsonPayload = JSON.parse(data.payload);
+ const lightDevices = jsonPayload.state.reported.lightDevices;
+ if (lightDevices.length > 0) {
+ deviceFound = jsonPayload.state.reported.lightDevices.some((item, index, array) => {
+ console.log("DEBUG", "lightDevices["+index+"]: "+JSON.stringify(item, null, 2));
+ const uriParts = item.uri.split("/");
+ const endpointIdFromUri = uriParts[uriParts.length-1];
+ if (endpointId == endpointIdFromUri) {
+ const response = generateStateResponse(endpointId, correlationToken, item.powerOn, item.brightness);
+ console.log("DEBUG", "StateReport Response: " + JSON.stringify(response, null, 2));
+
+ callback(null, response);
+ return true;
+ }
+ });
+ }
+ }
+ if (!deviceFound) {
+ const message = "EndpointId not found in device list";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("ENDPOINT_UNREACHABLE", message, endpointId, correlationToken));
+ }
+ });
+}
+
+function setAwsIotDeviceState(userAccessToken, endpointId, correlationToken, powerState, brightness, delta, callback) {
+ var deviceFound = false;
+ const thingNameParam = {
+ thingName: thingName
+ };
+
+ iotData.getThingShadow(thingNameParam, function(err, data) {
+ console.log("DEBUG", "get thing shadow");
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (!err) {
+ const jsonPayload = JSON.parse(data.payload);
+ const lightDevices = jsonPayload.state.reported.lightDevices;
+ var response;
+ if (lightDevices.length > 0) {
+ jsonPayload.state.reported.lightDevices.forEach((item, index, array) => {
+ console.log("DEBUG", "lightDevices["+index+"]: "+JSON.stringify(item, null, 2));
+ const uriParts = item.uri.split("/");
+ const endpointIdFromUri = uriParts[uriParts.length-1];
+ if (endpointId == endpointIdFromUri) {
+ deviceFound = true;
+ // Set the desired state of the found light
+ if (powerState) {
+ const powerOn = (powerState == "ON") ? true : false;
+ lightDevices[index].powerOn = powerOn;
+ response = generateResponse("Alexa.PowerController", "powerState", powerState, endpointId, correlationToken);
+ }
+ else if (brightness) {
+ brightness = Math.min(brightness, 100);
+ brightness = Math.max(brightness, 0);
+ lightDevices[index].brightness = brightness;
+ response = generateResponse("Alexa.BrightnessController", "brightness", brightness, endpointId, correlationToken);
+ }
+ else if (delta) {
+ lightDevices[index].brightness += delta;
+ lightDevices[index].brightness = Math.min(lightDevices[index].brightness, 100);
+ lightDevices[index].brightness = Math.max(lightDevices[index].brightness, 0);
+ response = generateResponse("Alexa.BrightnessController", "brightness", lightDevices[index].brightness, endpointId, correlationToken);
+ } else {
+ console.log("DEBUG", "no state change requested? for endpointId " + endpointId);
+ }
+ console.log("DEBUG", "desired lightDevices["+index+"]: "+JSON.stringify(lightDevices[index], null, 2));
+ }
+ });
+ }
+
+ if (deviceFound) {
+ const desiredLightState = {"state":{"desired":{"lightDevices":lightDevices}}};
+ const thingNameAndPayload = {
+ thingName: thingName,
+ payload: JSON.stringify(desiredLightState)
+ };
+ console.log("DEBUG", "payload: " + JSON.stringify(desiredLightState, null, 2));
+
+ iotData.updateThingShadow(thingNameAndPayload, function(err, data) {
+ console.log("DEBUG", "update thing shadow");
+ if (err) console.log(err, err.stack); // an error occurred
+ else console.log(data); // successful response
+
+ if (!err) {
+ console.log("DEBUG", "Response: " + JSON.stringify(response, null, 2));
+ callback(null, response);
+
+ } else {
+ const message = "Unable to set device state";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INTERNAL_ERROR", message, endpointId, correlationToken));
+ }
+ });
+
+ } else {
+ const message = "EndpointId not found in device list";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("ENDPOINT_UNREACHABLE", message, endpointId, correlationToken));
+ }
+ }
+ });
+}
+
+function handleDiscovery(request, callback) {
+ console.log("DEBUG", "Discovery Request: " + JSON.stringify(request, null, 2));
+
+ /**
+ * Get the OAuth token from the request.
+ */
+ const userAccessToken = request.directive.payload.scope.token;
+ console.log("DEBUG", "userAccessToken: " + userAccessToken);
+
+ if (!userAccessToken || !isValidToken(userAccessToken)) {
+ const message = "Invalid access token: " + userAccessToken;
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_AUTHORIZATION_CREDENTIAL", message, "", ""));
+ return;
+ }
+
+ /**
+ * Retrieve list of devices from cloud based on token.
+ */
+ getDevicesFromAwsIot(userAccessToken, callback);
+}
+
+function handleReportState(request, callback) {
+ console.log("DEBUG", "ReportState Request: " + JSON.stringify(request, null, 2));
+
+ const correlationToken = request.directive.header.correlationToken;
+ console.log("DEBUG", "correlationToken: " + correlationToken);
+
+ const endpointId = request.directive.endpoint.endpointId;
+
+ /**
+ * Get the OAuth token from the request.
+ */
+ const userAccessToken = request.directive.endpoint.scope.token;
+ console.log("DEBUG", "userAccessToken: " + userAccessToken);
+
+ if (!userAccessToken || !isValidToken(userAccessToken)) {
+ const message = "Invalid access token: " + userAccessToken;
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_AUTHORIZATION_CREDENTIAL", message, endpointId, correlationToken));
+ return;
+ }
+
+ if (!endpointId) {
+ const message = "No endpointId provided in request";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("NO_SUCH_ENDPOINT", message, endpointId, correlationToken));
+ return;
+ }
+
+ /**
+ * At this point the endpointId and accessToken are present in the request.
+ */
+ if (!isDeviceOnline(endpointId, userAccessToken)) {
+ const message = "Target is offline";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("ENDPOINT_UNREACHABLE", message, endpointId, correlationToken));
+ return;
+ }
+
+ /**
+ * Retrieve device state from cloud.
+ */
+ getDeviceStateFromAwsIot(userAccessToken, endpointId, correlationToken, callback);
+}
+
+function handleControl(request, callback) {
+ console.log("DEBUG", "Control Request: " + JSON.stringify(request, null, 2));
+
+ const correlationToken = request.directive.header.correlationToken;
+ const endpointId = request.directive.endpoint.endpointId;
+
+ /**
+ * Get the access token from the request.
+ */
+ const userAccessToken = request.directive.endpoint.scope.token;
+ console.log("DEBUG", "userAccessToken: " + userAccessToken);
+
+ if (!userAccessToken || !isValidToken(userAccessToken)) {
+ const message = "Invalid access token: " + userAccessToken;
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_AUTHORIZATION_CREDENTIAL", message, endpointId, correlationToken));
+ return;
+ }
+
+ if (!endpointId) {
+ const message = "No endpointId provided in request";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("NO_SUCH_ENDPOINT", message, endpointId, correlationToken));
+ return;
+ }
+
+ /**
+ * At this point the endpointId and accessToken are present in the request.
+ */
+ if (!isDeviceOnline(endpointId, userAccessToken)) {
+ const message = "Target is offline";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("ENDPOINT_UNREACHABLE", message, endpointId, correlationToken));
+ return;
+ }
+
+ switch (request.directive.header.name) {
+ case "TurnOn":
+ setAwsIotDeviceState(userAccessToken, endpointId, correlationToken, "ON", null, null, callback);
+ break;
+
+ case "TurnOff":
+ setAwsIotDeviceState(userAccessToken, endpointId, correlationToken, "OFF", null, null, callback);
+ break;
+
+ case "SetBrightness": {
+ const brightness = request.directive.payload.brightness;
+ if (!brightness) {
+ const message = "No brightness provided in request";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_VALUE", message, endpointId, correlationToken));
+ return;
+ }
+ setAwsIotDeviceState(userAccessToken, endpointId, correlationToken, null, brightness, null, callback);
+ break;
+ }
+
+ case "AdjustBrightness": {
+ const delta = request.directive.payload.brightnessDelta;
+ if (!delta) {
+ const message = "No brightness delta provided in request";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_VALUE", message, endpointId, correlationToken));
+ return;
+ }
+ setAwsIotDeviceState(userAccessToken, endpointId, correlationToken, null, null, delta, callback);
+ break;
+ }
+
+ default: {
+ const message = "Directive not supported";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_DIRECTIVE", message, endpointId, correlationToken));
+ }
+ }
+}
+
+/**
+ * Main entry point.
+ * Incoming events from Alexa service through Smart Home API are all handled by this function.
+ */
+exports.handler = (request, context, callback) => {
+ console.log("DEBUG", "Request: " + JSON.stringify(request, null, 2));
+
+ switch (request.directive.header.namespace) {
+ /**
+ * The namespace of 'Alexa.Discovery' indicates a request is being made to the Lambda for
+ * discovering all endpoints associated with the customer's endpoint cloud account.
+ */
+ case "Alexa.Discovery":
+ handleDiscovery(request, callback);
+ break;
+
+ /**
+ * The namespace of "Alexa.PowerController" and "Alexa.BrightnessController" indicates control request
+ */
+ case "Alexa.PowerController":
+ case "Alexa.BrightnessController":
+ handleControl(request, callback);
+ break;
+
+ /**
+ * The namespace of "Alexa" with a name of "ReportState" indicates state request
+ */
+ case "Alexa":
+ if (request.directive.header.name === "ReportState") {
+ handleReportState(request, callback);
+
+ } else {
+ const message = "Directive not supported";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_DIRECTIVE", message, "", ""));
+ }
+ break;
+
+ /**
+ * Received an unexpected message
+ */
+ default: {
+ const message = "Namespace not supported";
+ console.log("ERROR", message);
+ callback(null, generateErrorResponse("INVALID_DIRECTIVE", message, "", ""));
+ }
+ }
+};
diff --git a/ocf-light-server/LICENSE.md b/ocf-light-server/LICENSE.md
new file mode 100644
index 0000000..b786745
--- /dev/null
+++ b/ocf-light-server/LICENSE.md
@@ -0,0 +1,195 @@
+Copyright (c) 2017 IoTivity
+<http://www.iotivity.org/>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+<http://www.apache.org/licenses/LICENSE-2.0>
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+```
+-------------------------------------------------------------------------
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+```
diff --git a/ocf-light-server/README.md b/ocf-light-server/README.md
new file mode 100644
index 0000000..bc1dc66
--- /dev/null
+++ b/ocf-light-server/README.md
@@ -0,0 +1,51 @@
+<!---
+ ~ //******************************************************************
+ ~ //
+ ~ // Copyright 2107 Intel Corporation All Rights Reserved.
+ ~ //
+ ~ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ ~ //
+ ~ // Licensed under the Apache License, Version 2.0 (the "License");
+ ~ // you may not use this file except in compliance with the License.
+ ~ // You may obtain a copy of the License at
+ ~ //
+ ~ // http://www.apache.org/licenses/LICENSE-2.0
+ ~ //
+ ~ // Unless required by applicable law or agreed to in writing, software
+ ~ // distributed under the License is distributed on an "AS IS" BASIS,
+ ~ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ // See the License for the specific language governing permissions and
+ ~ // limitations under the License.
+ ~ //
+ ~ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ --->
+
+## Install required build libraries
+
+You will need to build IoTivity prior to use.
+
+ $ scons TARGET_TRANSPORT=IP SECURED=0 BUILD_JAVA=ON
+
+Once built, the build.sh and run.sh scripts expect iotivity.jar to be copied to ./lib directory.
+
+ $ cp <iotivity>/out/linux/x86_64/release/java/iotivity.jar lib/.
+
+## Build
+
+ $ ./build.sh
+
+## Run Command line parameters
+
+You can optionally set the name of the light and its inital on/off state and brightness.
+
+ $ ./run.sh [ lightName [ on | off [ 0 - 100 ] ] ]
+
+For example:
+
+ $ ./run.sh "My Favorite Light" on 75
+
+If no parameters are given, a random light name is generated with power on and brightness 100.
+
+Any OCF client should be able to interact with the light. For example, the Client Controller of the IoTivity Simulator. See https://wiki.iotivity.org/iotivity_tool_guide
+
+
diff --git a/ocf-light-server/build.sh b/ocf-light-server/build.sh
new file mode 100755
index 0000000..25e8464
--- /dev/null
+++ b/ocf-light-server/build.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+#find ./out -type f -name '*.class' -delete
+rm -rf ./out
+mkdir out
+javac @options.txt @sourcefiles.txt
+
+#jar -cfv OcfLightDevice.jar -C out/ .
+#jar -ufv OcfLightDevice.jar res/
+jar -cf OcfLightDevice.jar -C out/ .
+jar -uf OcfLightDevice.jar res/
+
diff --git a/ocf-light-server/options.txt b/ocf-light-server/options.txt
new file mode 100644
index 0000000..ef39293
--- /dev/null
+++ b/ocf-light-server/options.txt
@@ -0,0 +1,2 @@
+-cp ./lib/iotivity.jar
+-d ./out/
diff --git a/ocf-light-server/res/bulb-icon-32x32.png b/ocf-light-server/res/bulb-icon-32x32.png
new file mode 100644
index 0000000..b35091d
--- /dev/null
+++ b/ocf-light-server/res/bulb-icon-32x32.png
Binary files differ
diff --git a/ocf-light-server/res/light-off.png b/ocf-light-server/res/light-off.png
new file mode 100644
index 0000000..2ca1f68
--- /dev/null
+++ b/ocf-light-server/res/light-off.png
Binary files differ
diff --git a/ocf-light-server/res/light-on.png b/ocf-light-server/res/light-on.png
new file mode 100644
index 0000000..5ea4a8e
--- /dev/null
+++ b/ocf-light-server/res/light-on.png
Binary files differ
diff --git a/ocf-light-server/run.sh b/ocf-light-server/run.sh
new file mode 100755
index 0000000..517a993
--- /dev/null
+++ b/ocf-light-server/run.sh
@@ -0,0 +1 @@
+java -Djava.library.path=/home/larrys/work/iotivity-1.3-rel/iotivity/out/linux/x86_64/release -cp OcfLightDevice.jar:./lib/iotivity.jar org.iotivity.base.examples.OcfLightDevice "$1" "$2" $3 $4
diff --git a/ocf-light-server/sourcefiles.txt b/ocf-light-server/sourcefiles.txt
new file mode 100644
index 0000000..6ea9ca4
--- /dev/null
+++ b/ocf-light-server/sourcefiles.txt
@@ -0,0 +1,13 @@
+./src/main/java/org/iotivity/base/examples/OcfLightDevice.java
+./src/main/java/org/iotivity/base/examples/Light.java
+./src/main/java/org/iotivity/base/examples/LightConfig.java
+./src/main/java/org/iotivity/base/examples/Brightness.java
+./src/main/java/org/iotivity/base/examples/Switch.java
+./src/main/java/org/iotivity/base/examples/Resource.java
+./src/main/java/org/iotivity/base/examples/Links.java
+./src/main/java/org/iotivity/base/examples/Link.java
+./src/main/java/org/iotivity/base/examples/LightPanel.java
+./src/main/java/org/iotivity/base/examples/LightImageObserver.java
+./src/main/java/org/iotivity/base/examples/NamesPropertyFile.java
+
+
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/Brightness.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/Brightness.java
new file mode 100644
index 0000000..765cca3
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/Brightness.java
@@ -0,0 +1,103 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.ErrorCode;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.OcRepresentation;
+
+/**
+ * Brightness
+ *
+ * This class represents a rightness resource
+ */
+public class Brightness extends Resource implements LightImageObserver {
+ static public final String RES_TYPE = "oic.r.light.brightness";
+ static public final String RES_IF = "oic.if.a";
+
+ static public final String BRIGHTNESS_KEY = "brightness";
+
+ private int brightness;
+
+ public Brightness(String uuid) {
+ super("/ocf/brightness/" + uuid, RES_TYPE, RES_IF);
+ }
+
+ public void setOcRepresentation(OcRepresentation rep) {
+ try {
+ if (rep.hasAttribute(BRIGHTNESS_KEY)) {
+ brightness = rep.getValue(BRIGHTNESS_KEY);
+ brightness = Math.max(0, brightness);
+ brightness = Math.min(100, brightness);
+ }
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to get representation values");
+ }
+ }
+
+ public OcRepresentation getOcRepresentation() {
+ OcRepresentation rep = new OcRepresentation();
+ try {
+ brightness = Math.max(0, brightness);
+ brightness = Math.min(100, brightness);
+ rep.setValue(BRIGHTNESS_KEY, brightness);
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to set representation values");
+ }
+ return rep;
+ }
+
+ public int getBrightness() {
+ return brightness;
+ }
+
+ public void setBrightness(int brightness) {
+ brightness = Math.max(0, brightness);
+ brightness = Math.min(100, brightness);
+ this.brightness = brightness;
+ }
+
+ @Override
+ public void update(boolean powerOn, int brightness) {
+ setBrightness(brightness);
+ try {
+ OcPlatform.notifyAllObservers(getResourceHandle());
+ } catch (OcException e) {
+ ErrorCode errorCode = e.getErrorCode();
+ if (ErrorCode.NO_OBSERVERS == errorCode) {
+// OcfLightDevice.msg("No observers found");
+ } else {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to notify observers");
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[" + super.toString() + ", " + BRIGHTNESS_KEY + ": " + brightness + "]";
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/Light.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/Light.java
new file mode 100644
index 0000000..1926420
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/Light.java
@@ -0,0 +1,259 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.ErrorCode;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.PayloadType;
+
+/**
+ * Light
+ *
+ * This class represents a light resource
+ */
+public class Light extends Resource implements LightImageObserver {
+ static private final String RES_TYPE = "oic.d.light";
+
+ static private final String LINKS_KEY = "links";
+
+ private Links resourceLinks;
+
+ private LightConfig lightConfigRes;
+ private Switch switchRes;
+ private Brightness brightnessRes;
+
+ private String deviceName;
+ private boolean powerOn;
+ private int brightness;
+
+ public Light(boolean useLinks, String name, String uuid, boolean powerOn, int brightness, LightPanel ui) {
+ super("/ocf/light/" + uuid, RES_TYPE, OcPlatform.DEFAULT_INTERFACE);
+
+ if (useLinks) {
+ lightConfigRes = new LightConfig(name, uuid, this);
+ lightConfigRes.addObserver(ui);
+ OcfLightDevice.msg("Created config resource: " + lightConfigRes);
+
+ switchRes = new Switch(uuid);
+ switchRes.setValue(powerOn);
+ switchRes.addObserver(ui);
+ ui.addObserver(switchRes);
+ OcfLightDevice.msg("Created switch resource: " + switchRes);
+
+ brightnessRes = new Brightness(uuid);
+ brightnessRes.setBrightness(brightness);
+ brightnessRes.addObserver(ui);
+ ui.addObserver(brightnessRes);
+ OcfLightDevice.msg("Created brightness resource: " + brightnessRes);
+
+ } else {
+ deviceName = name;
+ this.powerOn = powerOn;
+ this.brightness = brightness;
+ addObserver(ui);
+ ui.addObserver(this);
+ }
+
+ try {
+ OcPlatform.setPropertyValue(PayloadType.PLATFORM.getValue(), "mnmn", "Intel");
+
+ setDeviceName(name);
+ OcPlatform.setPropertyValue(PayloadType.DEVICE.getValue(), "icv", "ocf.1.0.0");
+ OcPlatform.setPropertyValue(PayloadType.DEVICE.getValue(), "dmv", "ocf.res.1.0.0,ocf.sh.1.0.0");
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to create properties for " + getResourceUri());
+ e.printStackTrace();
+ }
+
+ if (useLinks) {
+ Link[] links = new Link[3];
+ links[0] = new Link(lightConfigRes.getResourceUri(), new String[] { LightConfig.RES_TYPE });
+ links[1] = new Link(switchRes.getResourceUri(), new String[] { Switch.RES_TYPE });
+ links[2] = new Link(brightnessRes.getResourceUri(), new String[] { Brightness.RES_TYPE });
+ resourceLinks = new Links(links);
+
+ try {
+ OcPlatform.bindInterfaceToResource(getResourceHandle(), OcPlatform.LINK_INTERFACE);
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to bind link interface for " + getResourceUri());
+ e.printStackTrace();
+ }
+
+ } else {
+ try {
+ OcPlatform.bindInterfaceToResource(getResourceHandle(), LightConfig.RES_IF);
+ OcPlatform.bindTypeToResource(getResourceHandle(), LightConfig.RES_TYPE);
+
+ OcPlatform.bindInterfaceToResource(getResourceHandle(), Switch.RES_IF);
+ OcPlatform.bindTypeToResource(getResourceHandle(), Switch.RES_TYPE);
+
+ OcPlatform.bindInterfaceToResource(getResourceHandle(), Brightness.RES_IF);
+ OcPlatform.bindTypeToResource(getResourceHandle(), Brightness.RES_TYPE);
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to bind interface or type for " + getResourceUri());
+ e.printStackTrace();
+ }
+
+ }
+
+ OcfLightDevice.msg("Created light resource: " + this);
+ }
+
+ public void unregister() {
+ try {
+ lightConfigRes.unregisterResource();
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to unregister " + lightConfigRes.getResourceUri());
+ e.printStackTrace();
+ }
+ try {
+ switchRes.unregisterResource();
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to unregister " + switchRes.getResourceUri());
+ e.printStackTrace();
+ }
+ try {
+ brightnessRes.unregisterResource();
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to unregister " + brightnessRes.getResourceUri());
+ e.printStackTrace();
+ }
+ try {
+ unregisterResource();
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to unregister " + getResourceUri());
+ e.printStackTrace();
+ }
+ }
+
+ public void setDeviceName(String name) {
+ try {
+ OcPlatform.setPropertyValue(PayloadType.DEVICE.getValue(), "n", name);
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to set device name to " + name);
+ e.printStackTrace();
+ }
+ }
+
+ public void setOcRepresentation(OcRepresentation rep) {
+ try {
+ if (rep.hasAttribute(LINKS_KEY)) {
+ OcRepresentation[] links = rep.getValue(LINKS_KEY);
+ resourceLinks.setOcRepresentation(links);
+ }
+ if (rep.hasAttribute(LightConfig.NAME_KEY_SIM)) {
+ deviceName = rep.getValue(LightConfig.NAME_KEY_SIM);
+ setDeviceName(deviceName);
+ }
+ if (rep.hasAttribute(LightConfig.NAME_KEY)) {
+ deviceName = rep.getValue(LightConfig.NAME_KEY);
+ setDeviceName(deviceName);
+ }
+ if (rep.hasAttribute(Switch.VALUE_KEY)) {
+ powerOn = rep.getValue(Switch.VALUE_KEY);
+ }
+ if (rep.hasAttribute(Brightness.BRIGHTNESS_KEY)) {
+ brightness = rep.getValue(Brightness.BRIGHTNESS_KEY);
+ brightness = Math.max(0, brightness);
+ brightness = Math.min(100, brightness);
+ }
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to get representation values");
+ }
+ }
+
+ public OcRepresentation getOcRepresentation() {
+ OcRepresentation rep = new OcRepresentation();
+ try {
+ if (resourceLinks != null) {
+ OcRepresentation[] links = resourceLinks.getOcRepresentation();
+ rep.setValue(LINKS_KEY, links);
+
+ } else {
+ rep.setValue(LightConfig.NAME_KEY, deviceName);
+ rep.setValue(LightConfig.NAME_KEY_SIM, deviceName);
+
+ rep.setValue(Switch.VALUE_KEY, powerOn);
+
+ brightness = Math.max(0, brightness);
+ brightness = Math.min(100, brightness);
+ rep.setValue(Brightness.BRIGHTNESS_KEY, brightness);
+ }
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to set representation values");
+ }
+
+ return rep;
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ public boolean getPowerOn() {
+ return powerOn;
+ }
+
+ public int getBrightness() {
+ return brightness;
+ }
+
+ @Override
+ public void update(boolean powerOn, int brightness) {
+ this.powerOn = powerOn;
+ this.brightness = brightness;
+
+ try {
+ OcPlatform.notifyAllObservers(getResourceHandle());
+ } catch (OcException e) {
+ ErrorCode errorCode = e.getErrorCode();
+ if (ErrorCode.NO_OBSERVERS == errorCode) {
+// OcfLightDevice.msg("No observers found");
+ } else {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to notify observers");
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (resourceLinks != null) {
+ return "[" + super.toString() + ", " + resourceLinks + "]";
+
+ } else {
+ return "[" + super.toString() + ", " + LightConfig.NAME_KEY + ": " + deviceName + ", "
+ + Switch.VALUE_KEY + ": " + powerOn + ", " + Brightness.BRIGHTNESS_KEY + ": " + brightness + "]";
+ }
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/LightConfig.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/LightConfig.java
new file mode 100644
index 0000000..3758dfd
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/LightConfig.java
@@ -0,0 +1,86 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcRepresentation;
+
+/**
+ * LightConfig
+ *
+ * This class represents a light configuration resource
+ */
+public class LightConfig extends Resource {
+ static public final String RES_TYPE = "oic.wk.con";
+ static public final String RES_IF = "oic.if.rw";
+
+ static public final String NAME_KEY = "n";
+ static public final String NAME_KEY_SIM = "nn"; // using 'nn' so it can be used in the simulator
+
+ private String deviceName;
+ private Light lightToConfig; // the light to be configured
+
+ public LightConfig(String name, String uuid, Light light) {
+ super("/ocf/light-config/" + uuid, RES_TYPE, RES_IF);
+ deviceName = name;
+ lightToConfig = light;
+ }
+
+ public void setOcRepresentation(OcRepresentation rep) {
+ try {
+ if (rep.hasAttribute(NAME_KEY_SIM)) {
+ deviceName = rep.getValue(NAME_KEY_SIM);
+ lightToConfig.setDeviceName(deviceName);
+ }
+ if (rep.hasAttribute(NAME_KEY)) {
+ deviceName = rep.getValue(NAME_KEY);
+ lightToConfig.setDeviceName(deviceName);
+ }
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to get representation values");
+ }
+ }
+
+ public OcRepresentation getOcRepresentation() {
+ OcRepresentation rep = new OcRepresentation();
+ try {
+ rep.setValue(NAME_KEY, deviceName);
+ rep.setValue(NAME_KEY_SIM, deviceName);
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to set representation values");
+ }
+ return rep;
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + super.toString() + ", " + NAME_KEY + ": " + deviceName + "]";
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/LightImageObserver.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/LightImageObserver.java
new file mode 100644
index 0000000..125b716
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/LightImageObserver.java
@@ -0,0 +1,31 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2017 Intel Corporation All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+/**
+ * LightImageObserver
+ */
+public interface LightImageObserver {
+
+ void update(boolean powerOn, int brightness);
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/LightPanel.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/LightPanel.java
new file mode 100644
index 0000000..6c52de8
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/LightPanel.java
@@ -0,0 +1,213 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Observable;
+import java.util.Observer;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.imageio.ImageIO;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+/**
+ * LightPanel
+ */
+public class LightPanel extends JLabel implements Observer {
+
+ private boolean powerOn;
+ private int brightness;
+
+ private BufferedImage imageOn;
+ private BufferedImage imageOff;
+ private BufferedImage composite;
+
+ public LightPanel(boolean powerOn, int brightness) {
+
+ this.powerOn = powerOn;
+ this.brightness = brightness;
+
+ try {
+ imageOn = ImageIO.read(LightPanel.class.getResource("/res/light-on.png"));
+ imageOff = ImageIO.read(LightPanel.class.getResource("/res/light-off.png"));
+
+ composite = new BufferedImage(imageOff.getWidth(), imageOff.getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+ Graphics g = composite.getGraphics();
+ g.drawImage(imageOff, 0, 0, null);
+
+ float alpha = powerOn ? ((float) brightness / 100.0f) : 0.0f;
+ AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
+ ((Graphics2D) g).setComposite(ac);
+ g.drawImage(imageOn, 0, 0, null);
+
+ ImageIcon imageIcon = new ImageIcon(composite);
+ setIcon(imageIcon);
+
+ setComponentPopupMenu(new SettingsPopupMenu(this));
+
+ } catch (IOException e) {
+ OcfLightDevice.msgError("Error creating light image: " + e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ g.drawImage(imageOff, 0, 0, null);
+
+ float alpha = powerOn ? ((float) brightness / 100.0f) : 0.0f;
+ AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
+ ((Graphics2D) g).setComposite(ac);
+ g.drawImage(imageOn, 0, 0, null);
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ boolean repaintRequired = false;
+ if (o instanceof Switch) {
+ powerOn = ((Switch) o).getValue();
+ SettingsPopupMenu popupMenu = (SettingsPopupMenu) getComponentPopupMenu();
+ popupMenu.setPowerOn(powerOn);
+ repaintRequired = true;
+
+ } else if (o instanceof Brightness) {
+ brightness = ((Brightness) o).getBrightness();
+ SettingsPopupMenu popupMenu = (SettingsPopupMenu) getComponentPopupMenu();
+ popupMenu.setBrightness(brightness);
+ repaintRequired = true;
+
+ } else if (o instanceof LightConfig) {
+ String deviceName = ((LightConfig) o).getDeviceName();
+ JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(this);
+ frame.setTitle(deviceName);
+
+ } else if (o instanceof Light) {
+ String deviceName = ((Light) o).getDeviceName();
+ powerOn = ((Light) o).getPowerOn();
+ brightness = ((Light) o).getBrightness();
+
+ JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(this);
+ frame.setTitle(deviceName);
+
+ SettingsPopupMenu popupMenu = (SettingsPopupMenu) getComponentPopupMenu();
+ popupMenu.setPowerOn(powerOn);
+ popupMenu.setBrightness(brightness);
+ repaintRequired = true;
+
+ } else {
+ // ignore
+ }
+
+ if (repaintRequired) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ repaint();
+ }
+ });
+ }
+ }
+
+ // LightImageObservable implementation
+ private Map<Integer, LightImageObserver> observers = new ConcurrentHashMap<Integer, LightImageObserver>();
+
+ public void addObserver(LightImageObserver observer) {
+ observers.put(observer.hashCode(), observer);
+ }
+
+ public void notifyObservers() {
+ Thread observerNotifier = new Thread(new Runnable() {
+ public void run() {
+ for (LightImageObserver observer : observers.values()) {
+ observer.update(powerOn, brightness);
+ }
+ }
+ });
+ observerNotifier.setDaemon(true);
+ observerNotifier.start();
+ }
+
+ private class SettingsPopupMenu extends JPopupMenu {
+ private JCheckBoxMenuItem powerItem;
+ private JMenuItem brightnessItem;
+ private SpinnerNumberModel model;
+
+ public SettingsPopupMenu(final LightPanel lightPanel) {
+ powerItem = new JCheckBoxMenuItem("On");
+ powerItem.setSelected(lightPanel.powerOn);
+ powerItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ lightPanel.powerOn = powerItem.isSelected();
+ lightPanel.repaint();
+ lightPanel.notifyObservers();
+ }
+ });
+ add(powerItem);
+
+ brightnessItem = new JMenuItem();
+ model = new SpinnerNumberModel(lightPanel.brightness, 0, 100, 1);
+ JSpinner spinner = new JSpinner(model);
+ brightnessItem.add(spinner);
+
+ brightnessItem.setPreferredSize(powerItem.getPreferredSize());
+ spinner.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ lightPanel.brightness = (int) model.getValue();
+ lightPanel.repaint();
+ lightPanel.notifyObservers();
+ }
+ });
+ add(brightnessItem);
+ }
+
+ public void setPowerOn(boolean powerOn) {
+ powerItem.setSelected(powerOn);
+ }
+
+ public void setBrightness(int brightness) {
+ model.setValue(brightness);
+ }
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/Link.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/Link.java
new file mode 100644
index 0000000..aa36586
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/Link.java
@@ -0,0 +1,90 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2017 Intel Corporation All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcRepresentation;
+
+/**
+ * Link
+ */
+public class Link {
+
+ static private final String HREF_KEY = "href";
+ static private final String REL_KEY = "rel";
+ static private final String RT_KEY = "rt";
+ static private final String DEFAULT_REL = "contains";
+
+ private String href;
+ private String rel;
+ private String[] rt;
+
+ public Link(String href, String[] rt) {
+ this(href, DEFAULT_REL, rt);
+ }
+
+ public Link(String href, String rel, String[] rt) {
+ this.href = href;
+ this.rel = rel;
+ this.rt = rt;
+ }
+
+ public void setOcRepresentation(OcRepresentation ocRep) throws OcException {
+ if (ocRep.hasAttribute(HREF_KEY)) {
+ href = ocRep.getValue(HREF_KEY);
+ }
+ if (ocRep.hasAttribute(REL_KEY)) {
+ rel = ocRep.getValue(REL_KEY);
+ }
+ if (ocRep.hasAttribute(RT_KEY)) {
+ rt = ocRep.getValue(RT_KEY);
+ }
+ }
+
+ public OcRepresentation getOcRepresentation() throws OcException {
+ OcRepresentation ocRep = new OcRepresentation();
+ ocRep.setValue(HREF_KEY, href);
+ ocRep.setValue(REL_KEY, rel);
+ ocRep.setValue(RT_KEY, rt);
+ return ocRep;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ boolean first = true;
+ for (String type : rt) {
+ if (!first) {
+ sb.append(", ");
+ }
+ if (type != null) {
+ sb.append(type.toString());
+ }
+ first = false;
+ }
+ sb.append("]");
+
+ return "[" + HREF_KEY + ": " + href + ", " + REL_KEY + ": " + rel + ", " + RT_KEY + ": " + sb + "]";
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/Links.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/Links.java
new file mode 100644
index 0000000..7891a9a
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/Links.java
@@ -0,0 +1,82 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2017 Intel Corporation All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcRepresentation;
+
+/**
+ * Links
+ */
+public class Links {
+
+ public static final String LINKS_KEY = "links";
+
+ private Link[] links;
+
+ public Links(Link[] links) {
+ this.links = (links != null) ? links : new Link[0];
+ }
+
+ public void setOcRepresentation(OcRepresentation[] ocRepLinks) throws OcException {
+ if ((ocRepLinks != null) && (ocRepLinks.length > 0)) {
+ links = new Link[ocRepLinks.length];
+ int index = 0;
+ for (OcRepresentation ocRepLink : ocRepLinks) {
+ links[index] = new Link("", new String[0]);
+ links[index].setOcRepresentation(ocRepLink);
+ ++index;
+ }
+ }
+ }
+
+ public OcRepresentation[] getOcRepresentation() throws OcException {
+ OcRepresentation[] ocRepLinks = new OcRepresentation[links.length];
+ int index = 0;
+ for (Link link : links) {
+ OcRepresentation ocRepLink = link.getOcRepresentation();
+ ocRepLinks[index] = ocRepLink;
+ ++index;
+ }
+ return ocRepLinks;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ boolean first = true;
+ for (Link link : links) {
+ if (!first) {
+ sb.append(", ");
+ }
+ if (link != null) {
+ sb.append(link.toString());
+ }
+ first = false;
+ }
+ sb.append("]");
+
+ return sb.toString();
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/NamesPropertyFile.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/NamesPropertyFile.java
new file mode 100644
index 0000000..174fddb
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/NamesPropertyFile.java
@@ -0,0 +1,115 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * This class encapsulates the names property file. The names property file is
+ * used for obtaining the uuid for previously used light names.
+ */
+public class NamesPropertyFile {
+
+ static private Properties namesProperties;
+ static private File namesPropertyFile;
+
+ static private NamesPropertyFile instance;
+
+ static {
+ try {
+ namesProperties = new Properties();
+ namesPropertyFile = new File("names.prop");
+ instance = new NamesPropertyFile();
+
+ } catch (Exception e) {
+ OcfLightDevice.msgError("Error creating names property file instance.");
+ }
+ }
+
+ private NamesPropertyFile() {
+ // read the names property file
+ FileInputStream inStream = null;
+ try {
+ if (namesPropertyFile.exists() && namesPropertyFile.length() > 0) {
+ inStream = new FileInputStream(namesPropertyFile);
+ namesProperties.loadFromXML(inStream);
+ namesProperties.list(System.out);
+ }
+
+ } catch (IOException e) {
+ OcfLightDevice.msgError("Error loading name properties: " + e.toString());
+ e.printStackTrace();
+
+ } finally {
+ if (inStream != null) {
+ try {
+ inStream.close();
+ } catch (IOException e) {
+ OcfLightDevice.msgError("Error closing name properties file: " + e.toString());
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static NamesPropertyFile getInstance() {
+ return instance;
+ }
+
+ public boolean hasName(String name) {
+ return namesProperties.containsKey(name);
+ }
+
+ public String getUuidForName(String name) {
+ return (String) namesProperties.get(name);
+ }
+
+ public void updateNamesProperty(String name, String uuid) {
+ // update names property file
+ namesProperties.put(name, uuid);
+ FileOutputStream outStream = null;
+ try {
+ outStream = new FileOutputStream(namesPropertyFile);
+ namesProperties.storeToXML(outStream, null);
+
+ } catch (IOException e) {
+ OcfLightDevice.msgError("Error storing name properties: " + e.toString());
+ e.printStackTrace();
+ }
+
+ finally {
+ if (outStream != null) {
+ try {
+ outStream.close();
+ } catch (IOException e) {
+ OcfLightDevice.msgError("Error closing name properties file: " + e.toString());
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/OcfLightDevice.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/OcfLightDevice.java
new file mode 100644
index 0000000..0c05b26
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/OcfLightDevice.java
@@ -0,0 +1,203 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.ModeType;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.PlatformConfig;
+import org.iotivity.base.QualityOfService;
+import org.iotivity.base.ServiceType;
+
+import java.awt.FlowLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.UUID;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
+import javax.swing.WindowConstants;
+
+/**
+ * OcfLightDevice
+ */
+public class OcfLightDevice {
+
+ static Light light;
+
+ static boolean isTest;
+ static int testFrequency = 3;
+
+ static boolean useLinks;
+ static String name;
+ static boolean powerOn = true;
+ static int brightness = 100;
+
+ public static void main(String args[]) throws IOException, InterruptedException {
+
+ if ((args.length > 0) && (args[0].startsWith("-"))) {
+ if (args[0].startsWith("-t")) {
+ isTest = true;
+ try {
+ testFrequency = Integer.valueOf(args[0].substring(2));
+ } catch (NumberFormatException e) {
+ msg("Frequency must be an integer in the range (1, 60), using default 3.");
+ }
+ testFrequency = Math.max(1, testFrequency);
+ testFrequency = Math.min(60, testFrequency);
+ msg("Server in test mode with frequecy of " + testFrequency);
+ } else if (args[0].equalsIgnoreCase("-l")) {
+ useLinks = true;
+ msg("Server using links");
+ } else {
+ msg("Unknown runtime parameter: " + args[0]);
+ }
+ parseNameAndInitialSettings(args, 1);
+
+ } else {
+ parseNameAndInitialSettings(args, 0);
+ }
+
+ PlatformConfig platformConfig = new PlatformConfig(ServiceType.IN_PROC, ModeType.SERVER, "0.0.0.0", 0,
+ QualityOfService.LOW);
+
+ OcPlatform.Configure(platformConfig);
+ msg("Platform configured");
+
+ String uuid = null;
+ if (NamesPropertyFile.getInstance().hasName(name)) {
+ uuid = NamesPropertyFile.getInstance().getUuidForName(name);
+ } else {
+ uuid = UUID.randomUUID().toString();
+ NamesPropertyFile.getInstance().updateNamesProperty(name, uuid);
+ }
+
+ JFrame frame = new JFrame(name);
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ try {
+ frame.setIconImage(ImageIO.read(OcfLightDevice.class.getResource("/res/bulb-icon-32x32.png")));
+ } catch (IOException ioe) {
+ msgError("Error loading application icon: " + ioe.toString());
+ ioe.printStackTrace();
+ }
+
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ if (light != null) {
+// light.unregister();
+ }
+ msg("Shutdown");
+ e.getWindow().dispose();
+ System.exit(0);
+ }
+ });
+
+ frame.setResizable(false);
+ frame.setLayout(new FlowLayout());
+
+ LightPanel lightPanel = new LightPanel(powerOn, brightness);
+ light = new Light(useLinks, name, uuid, powerOn, brightness, lightPanel);
+
+ frame.setContentPane(lightPanel);
+ frame.pack();
+ frame.setVisible(true);
+
+ if (isTest) {
+ // Start running a task to toggle the light and change its brightness
+ Timer timer = new Timer();
+ timer.schedule(new ToggleTask(lightPanel), testFrequency * 1000, testFrequency * 1000);
+ }
+ }
+
+ private static void parseNameAndInitialSettings(String args[], int index) {
+ if (args.length > index) {
+ name = args[index];
+ }
+
+ if (args.length > index + 1) {
+ String arg = args[index + 1];
+ if (!arg.isEmpty()) {
+ powerOn = arg.equalsIgnoreCase("true") || arg.equalsIgnoreCase("on") || arg.equalsIgnoreCase("yes")
+ || arg.equals("1");
+ }
+ }
+
+ if (args.length > index + 2) {
+ try {
+ brightness = Integer.valueOf(args[index + 2]);
+ } catch (NumberFormatException e) {
+ msg("Brightness must be an integer in the range (0, 100), using default 100.");
+ }
+
+ brightness = Math.max(0, brightness);
+ brightness = Math.min(100, brightness);
+ }
+
+ if (name == null || name.isEmpty()) {
+ name = "Light " + (System.currentTimeMillis() % 10000);
+ }
+ }
+
+ private static void sleep(int seconds) {
+ try {
+ Thread.sleep(seconds * 1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ msgError(e.toString());
+ }
+ }
+
+ public static void msg(final String text) {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+ Date date = new Date();
+ System.out.println(dateFormat.format(date) + " " + text);
+ }
+
+ public static void msgError(final String text) {
+ msg("[Error] " + text);
+ }
+
+ public static class ToggleTask extends TimerTask {
+ LightPanel lightPanel;
+
+ public ToggleTask(LightPanel lightPanel) {
+ this.lightPanel = lightPanel;
+ }
+
+ @Override
+ public void run() {
+ boolean powerOn = ! light.getPowerOn();
+ int brightness = (light.getBrightness() + 10) % 101;
+ OcfLightDevice.msg("Notifying observers for resource " + light.toString());
+ light.update(powerOn, brightness);
+ lightPanel.update(light, null);
+ }
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/Resource.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/Resource.java
new file mode 100644
index 0000000..8262c94
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/Resource.java
@@ -0,0 +1,240 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.EntityHandlerResult;
+import org.iotivity.base.ErrorCode;
+import org.iotivity.base.ObservationInfo;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.OcResourceHandle;
+import org.iotivity.base.OcResourceRequest;
+import org.iotivity.base.OcResourceResponse;
+import org.iotivity.base.RequestHandlerFlag;
+import org.iotivity.base.RequestType;
+import org.iotivity.base.ResourceProperty;
+
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Observable;
+
+/**
+ * Resource
+ *
+ * This is the base class for all resources
+ */
+
+abstract public class Resource extends Observable implements OcPlatform.EntityHandler {
+
+ private String resUri;
+ private OcResourceHandle resHandle;
+
+ public Resource(String uri, String resType, String resIf) {
+ resUri = uri;
+
+ try {
+ resHandle = OcPlatform.registerResource(resUri, resType, resIf, this,
+ EnumSet.of(ResourceProperty.DISCOVERABLE, ResourceProperty.OBSERVABLE, ResourceProperty.SECURE));
+
+ } catch (OcException e) {
+ OcfLightDevice.msgError("Failed to create resource " + resUri);
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public synchronized EntityHandlerResult handleEntity(final OcResourceRequest request) {
+ EntityHandlerResult ehResult = EntityHandlerResult.ERROR;
+ if (null == request) {
+ OcfLightDevice.msg("Server request is invalid");
+ return ehResult;
+ }
+ // Get the request flags
+ EnumSet<RequestHandlerFlag> requestFlags = request.getRequestHandlerFlagSet();
+ if (requestFlags.contains(RequestHandlerFlag.INIT)) {
+ OcfLightDevice.msg("Request Flag: Init for " + request.getResourceUri());
+ ehResult = EntityHandlerResult.OK;
+ }
+ if (requestFlags.contains(RequestHandlerFlag.REQUEST)) {
+// OcfLightDevice.msg("Request Flag: Request for " + request.getResourceUri());
+ ehResult = handleRequest(request);
+ }
+ if (requestFlags.contains(RequestHandlerFlag.OBSERVER)) {
+// OcfLightDevice.msg("Request Flag: Observer for " + request.getResourceUri());
+ ehResult = handleObserver(request);
+ }
+ return ehResult;
+ }
+
+ private EntityHandlerResult handleRequest(OcResourceRequest request) {
+ EntityHandlerResult ehResult = EntityHandlerResult.ERROR;
+ // Check for query params (if any)
+ Map<String, String> queries = request.getQueryParameters();
+// if (!queries.isEmpty()) {
+// OcfLightDevice.msg("Query processing is up to entityHandler");
+// } else {
+// OcfLightDevice.msg("No query parameters in this request");
+// }
+
+ for (Map.Entry<String, String> entry : queries.entrySet()) {
+// OcfLightDevice.msg("Query key: " + entry.getKey() + " value: " + entry.getValue());
+ }
+
+ // Get the request type
+ RequestType requestType = request.getRequestType();
+ switch (requestType) {
+ case GET:
+// OcfLightDevice.msg("Request Type is GET for " + request.getResourceUri());
+ ehResult = handleGetRequest(request);
+ break;
+ case PUT:
+// OcfLightDevice.msg("Request Type is PUT for " + request.getResourceUri());
+ ehResult = handlePutRequest(request);
+ break;
+ case POST:
+// OcfLightDevice.msg("Request Type is POST for " + request.getResourceUri());
+ ehResult = handlePutRequest(request); // same as put
+ break;
+ case DELETE:
+ OcfLightDevice.msg("Request Type is DELETE for " + request.getResourceUri());
+ ehResult = handleDeleteRequest();
+ break;
+ }
+ return ehResult;
+ }
+
+ private EntityHandlerResult handleGetRequest(final OcResourceRequest request) {
+ OcResourceResponse response = new OcResourceResponse();
+ response.setRequestHandle(request.getRequestHandle());
+ response.setResourceHandle(request.getResourceHandle());
+ response.setResponseResult(EntityHandlerResult.OK);
+ response.setResourceRepresentation(getOcRepresentation());
+ return sendResponse(response);
+ }
+
+ private EntityHandlerResult handlePutRequest(final OcResourceRequest request) {
+ OcResourceResponse response = new OcResourceResponse();
+ response.setRequestHandle(request.getRequestHandle());
+ response.setResourceHandle(request.getResourceHandle());
+
+ setOcRepresentation(request.getResourceRepresentation());
+ response.setResourceRepresentation(getOcRepresentation());
+ response.setResponseResult(EntityHandlerResult.OK);
+
+ // notify on separate thread
+ Thread observerNotifier = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+
+ notifyObservers(request);
+
+ // notify observers (ie implementors of Observer)
+ setChanged();
+ notifyObservers();
+ }
+ });
+ observerNotifier.setDaemon(true);
+ observerNotifier.start();
+
+ return sendResponse(response);
+ }
+
+ private EntityHandlerResult handleDeleteRequest() {
+ try {
+ unregisterResource();
+ return EntityHandlerResult.RESOURCE_DELETED;
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to unregister resource " + resUri);
+ return EntityHandlerResult.ERROR;
+ }
+ }
+
+ private EntityHandlerResult handleObserver(final OcResourceRequest request) {
+ ObservationInfo observationInfo = request.getObservationInfo();
+ switch (observationInfo.getObserveAction()) {
+ case REGISTER:
+// OcfLightDevice.msg("handleObserver register observer " + String.format("%02x", observationInfo.getOcObservationId()));
+ break;
+ case UNREGISTER:
+// OcfLightDevice.msg("handleObserver unregister observer " + String.format("%02x", observationInfo.getOcObservationId()));
+ break;
+ }
+ return EntityHandlerResult.OK;
+ }
+
+ private void notifyObservers(OcResourceRequest request) {
+ OcfLightDevice.msg("Notifying observers for resource " + this);
+ try {
+ OcPlatform.notifyAllObservers(getResourceHandle());
+ } catch (OcException e) {
+ ErrorCode errorCode = e.getErrorCode();
+ if (ErrorCode.NO_OBSERVERS == errorCode) {
+// OcfLightDevice.msg("No observers found");
+ } else {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to notify observers");
+ }
+ }
+ }
+
+ private EntityHandlerResult sendResponse(OcResourceResponse response) {
+ try {
+ OcPlatform.sendResponse(response);
+ return EntityHandlerResult.OK;
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to send response");
+ return EntityHandlerResult.ERROR;
+ }
+ }
+
+ public synchronized void unregisterResource() throws OcException {
+ if (null != resHandle) {
+ OcPlatform.unregisterResource(resHandle);
+ OcfLightDevice.msg("Unregistered resource " + resUri);
+ }
+ }
+
+ public abstract void setOcRepresentation(OcRepresentation rep);
+
+ public abstract OcRepresentation getOcRepresentation();
+
+ public String getResourceUri() {
+ return resUri;
+ }
+
+ public OcResourceHandle getResourceHandle() {
+ return resHandle;
+ }
+
+ @Override
+ public String toString() {
+ return resUri;
+ }
+}
diff --git a/ocf-light-server/src/main/java/org/iotivity/base/examples/Switch.java b/ocf-light-server/src/main/java/org/iotivity/base/examples/Switch.java
new file mode 100644
index 0000000..c2adcbe
--- /dev/null
+++ b/ocf-light-server/src/main/java/org/iotivity/base/examples/Switch.java
@@ -0,0 +1,97 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base.examples;
+
+import org.iotivity.base.ErrorCode;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.OcRepresentation;
+
+/**
+ * Switch
+ *
+ * This class represents a binary switch resource
+ */
+public class Switch extends Resource implements LightImageObserver {
+ static public final String RES_TYPE = "oic.r.switch.binary";
+ static public final String RES_IF = "oic.if.a";
+
+ static public final String VALUE_KEY = "value";
+
+ private boolean powerOn;
+
+ public Switch(String uuid) {
+ super("/ocf/switch/" + uuid, RES_TYPE, RES_IF);
+ }
+
+ public void setOcRepresentation(OcRepresentation rep) {
+ try {
+ if (rep.hasAttribute(VALUE_KEY)) {
+ powerOn = rep.getValue(VALUE_KEY);
+ }
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to get representation values");
+ }
+ }
+
+ public OcRepresentation getOcRepresentation() {
+ OcRepresentation rep = new OcRepresentation();
+ try {
+ rep.setValue(VALUE_KEY, powerOn);
+ } catch (OcException e) {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to set representation values");
+ }
+ return rep;
+ }
+
+ public boolean getValue() {
+ return powerOn;
+ }
+
+ public void setValue(boolean value) {
+ powerOn = value;
+ }
+
+ @Override
+ public void update(boolean powerOn, int brightness) {
+ setValue(powerOn);
+ try {
+ OcPlatform.notifyAllObservers(getResourceHandle());
+ } catch (OcException e) {
+ ErrorCode errorCode = e.getErrorCode();
+ if (ErrorCode.NO_OBSERVERS == errorCode) {
+// OcfLightDevice.msg("No observers found");
+ } else {
+ OcfLightDevice.msgError(e.toString());
+ OcfLightDevice.msgError("Failed to notify observers");
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[" + super.toString() + ", " + VALUE_KEY + ": " + powerOn + "]";
+ }
+}