Commit 803e842d authored by George Nash's avatar George Nash

Merge remote-tracking branch 'origin/1.3-rel'

Change-Id: Ie5fe691024e7023b89d3a8b465172b56c26bd63f
Signed-off-by: George Nash's avatarGeorge Nash <george.nash@intel.com>
parents f0d7677d cc2fca24
......@@ -29,37 +29,24 @@
### Fedora
$ sudo dnf install gssdp-devel gupnp-devel
$ sudo dnf install gupnp-tools #optional but recommended
## Update IoTivity
There is currently a [bug reported for IoTivity](https://jira.iotivity.org/browse/IOT-963)
This can be worked around by changing the following line in iotivity project and
rebuilding iotivity.
Find the file
<iotivity>/resource/csdk/stack/include/ocstackconfig.h
change
#define MAX_URI_LENGTH(64)
to
#define MAX_URI_LENGTH(256)
## Build
You will need to copy the setenv.sh.example to setenv.sh then setup the setenv.sh
file to reflect your environment. You can then source the setenv.sh to setup the
enviroment.
$ cp setenv.sh.example setenv.sh
$ cp setenv.sh.example setenv.sh
$ vi setenv.sh
$ source setenv.sh
To build you will need to copy the BuildOptions.txt.example to BuildOptions.txt
Open the files and update the change the build variables to reflect your
environment.
To build you copy the BuildOptions.txt.example to BuildOptions.txt. Open the
files and update the change the build variables to reflect your environment.
$ cp BuildOptions.txt.example BuildOptions.txt
$ vi BuildOptions.txt
To build run 'scons'. Variables specified in the BuildOptions.txt can be
overwriten by adding them to the scons command at runtime.
overwritten by adding them to the scons command at run-time.
$ scons BUILD_TYPE=release
......@@ -71,6 +58,34 @@ The ObserveClient runs until Control-C, it writes OBSERVE messages to the
console when the state of a light changes.
## Testing
The iotivity-upnp-bridge is in the process of transitioning from the IoTivity
resource container for bridging to the new bridging code found in IoTivity. Also
known as the mini-plugin-manager or MPM. Eventualy the older version of the upnp
bridge that used the resource container will depricated. Until that time both
version of the code can be used.
### Testing MPM version of the bridge
For the time being the MPM version of the bridge relies on the mpm_sample_client
to launch run the bridging plugin. The mpm_sample_client can be found in the
out folder of the IoTivity build.
Run the following:
$ gupnp-network-light #requires gupnp-tools be installed
$ ./mpm_sample_client -a -n /<path_to>/libupnpplugin.so
$ # mpm_sample_client does not automatically detect new devices
$ # type 0 0 to scan for new upnp devices.
$ ./Observer
$ ./SimpleClient
The `gupnp-network-light` is a virtual gupnp light that will only respond to
UPnP. The `mpm_sample_client` is sample program designed to load a bridging
plugin. The `libupnpplugin.so` is the plugin code responsible for discovering
and controlling UPnP devices. The `Observer` finds the UPnP light using IoTivity
and observes any changes in the current lights attributes and reports the
change. The `SimpleClient` will find the light and will toggle the light state.
### Testing resource container version of the bridge
Navigate to the `out/linux/x86_64/<build_type>/bin` directory.
Run the following:
......@@ -117,5 +132,5 @@ The UPnP AV Client Demo Android App, 'upnpavclient-debug.apk' is in the 'java/ex
Follow IoTivity instructions for installing Andriod example apps.
## Testing
Caveat: This currently requires the UpnpBridge running on a Linux system with UPnP Client Demo Android App
Caveat: This currently requires the UpnpBridge running on a Linux system with
UPnP Client Demo Android App
......@@ -259,8 +259,8 @@ public class OnOffCycleIntentService extends IntentService implements
try {
// Read attribute values into local representation of resource
if (ocRepresentation.hasAttribute(Device.URI_KEY)) {
final String ocRepUri = ocRepresentation.getValue(Device.URI_KEY);
final String ocRepUri = ocRepresentation.getUri();
if (ocRepUri != null && !ocRepUri.isEmpty()) {
Log.i(TAG, "Resource URI: " + ocRepUri);
Resource resource = mResourceLookup.get(ocRepUri);
......@@ -427,8 +427,8 @@ public class OnOffCycleIntentService extends IntentService implements
try {
// Read attribute values into local representation of resource
if (ocRepresentation.hasAttribute(Device.URI_KEY)) {
final String ocRepUri = ocRepresentation.getValue(Device.URI_KEY);
final String ocRepUri = ocRepresentation.getUri();
if (ocRepUri != null && !ocRepUri.isEmpty()) {
Log.i(TAG, "Resource URI: " + ocRepUri);
Resource resource = mResourceLookup.get(ocRepUri);
......
......@@ -299,8 +299,8 @@ public class UpnpClientActivity extends Activity implements
try {
// Read attribute values into local representation of resource
if (ocRepresentation.hasAttribute(Device.URI_KEY)) {
final String ocRepUri = ocRepresentation.getValue(Device.URI_KEY);
final String ocRepUri = ocRepresentation.getUri();
if (ocRepUri != null && !ocRepUri.isEmpty()) {
Log.i(TAG, "Resource URI: " + ocRepUri);
Resource resource = mResourceLookup.get(ocRepUri);
......@@ -483,8 +483,8 @@ public class UpnpClientActivity extends Activity implements
try {
// Read attribute values into local representation of resource
if (ocRepresentation.hasAttribute(Device.URI_KEY)) {
final String ocRepUri = ocRepresentation.getValue(Device.URI_KEY);
final String ocRepUri = ocRepresentation.getUri();
if (ocRepUri != null && !ocRepUri.isEmpty()) {
Log.i(TAG, "Resource URI: " + ocRepUri);
Resource resource = mResourceLookup.get(ocRepUri);
......@@ -566,8 +566,8 @@ public class UpnpClientActivity extends Activity implements
try {
// Read attribute values into local representation of resource
if (ocRepresentation.hasAttribute(Device.URI_KEY)) {
final String ocRepUri = ocRepresentation.getValue(Device.URI_KEY);
final String ocRepUri = ocRepresentation.getUri();
if (ocRepUri != null && !ocRepUri.isEmpty()) {
Log.i(TAG, "Resource URI: " + ocRepUri);
Resource resource = mResourceLookup.get(ocRepUri);
......
......@@ -28,9 +28,7 @@ using namespace OC;
class Light
{
public:
std::string m_uri; // need to keep uri here, due to OCRepresentation bug
Light() :
m_uri("")
Light()
{
}
};
......@@ -38,10 +36,9 @@ class Light
class PowerSwitch
{
public:
std::string m_uri; // need to keep uri here, due to OCRepresentation bug
bool m_state;
PowerSwitch() :
m_uri(""), m_state(false)
m_state(false)
{
}
};
......@@ -49,10 +46,9 @@ class PowerSwitch
class Brightness
{
public:
std::string m_uri; // need to keep uri here, due to OCRepresentation bug
int m_loadlevel;
Brightness() :
m_uri(""), m_loadlevel(100)
m_loadlevel(100)
{
}
};
......@@ -94,20 +90,17 @@ void OnPostBrightness(const HeaderOptions &headerOptions, const OCRepresentation
const int eCode)
{
(void) headerOptions;
(void) rep;
try
{
if (eCode == OC_STACK_OK)
{
std::cout << "POST Brightness request successful" << std::endl;
std::string repUri;
rep.getValue("uri", repUri);
std::string repUri = rep.getUri();
Brightness brightness = s_brightnessLookup[repUri];
rep.getValue("uri", brightness.m_uri);
rep.getValue("brightness", brightness.m_loadlevel);
std::cout << "\turi: " << brightness.m_uri << std::endl;
std::cout << "\turi: " << repUri << std::endl;
std::cout << "\tbrightness: " << brightness.m_loadlevel << std::endl;
s_brightnessLookup[repUri] = brightness; // save new copy
}
......@@ -116,26 +109,21 @@ void OnPostBrightness(const HeaderOptions &headerOptions, const OCRepresentation
{
std::cout << "Caught exception: " << e.what() << " in onPostBrightness" << std::endl;
}
}
void OnPostLight(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int eCode)
{
(void) headerOptions;
(void) rep;
try
{
if (eCode == OC_STACK_OK)
{
std::cout << "POST request successful" << std::endl;
std::string repUri;
rep.getValue("uri", repUri);
std::string repUri = rep.getUri();
Light light = s_lightLookup[repUri];
rep.getValue("uri", light.m_uri);
std::cout << "\turi: " << light.m_uri << std::endl;
std::cout << "\turi: " << repUri << std::endl;
s_lightLookup[repUri] = light; // save new copy
}
else
......@@ -157,14 +145,12 @@ void OnGetLight(const HeaderOptions &headerOptions, const OCRepresentation &rep,
if (eCode == OC_STACK_OK)
{
std::cout << "GET response" << std::endl;
std::string repUri;
rep.getValue("uri", repUri);
std::string repUri = rep.getUri();
std::shared_ptr< OCResource > lightResource = s_resourceLookup[repUri];
Light light = s_lightLookup[repUri];
rep.getValue("uri", light.m_uri);
std::cout << "\turi: " << light.m_uri << std::endl;
std::cout << "\turi: " << repUri << std::endl;
s_lightLookup[repUri] = light; // save new copy
PostLightRepresentation(lightResource);
......@@ -189,15 +175,13 @@ void OnGetPowerSwitch(const HeaderOptions &headerOptions, const OCRepresentation
if (eCode == OC_STACK_OK)
{
std::cout << "GET response" << std::endl;
std::string repUri;
rep.getValue("uri", repUri);
std::string repUri = rep.getUri();
std::shared_ptr< OCResource > powerSwitchResource = s_resourceLookup[repUri];
PowerSwitch powerSwitch = s_powerSwitchLookup[repUri];
rep.getValue("uri", powerSwitch.m_uri);
rep.getValue("value", powerSwitch.m_state);
std::cout << "\turi: " << powerSwitch.m_uri << std::endl;
std::cout << "\turi: " << repUri << std::endl;
std::cout << "\tstate: " << powerSwitch.m_state << std::endl;
s_powerSwitchLookup[repUri] = powerSwitch; // save new copy
......@@ -224,15 +208,13 @@ void OnGetBrightness(const HeaderOptions &headerOptions, const OCRepresentation
if (eCode == OC_STACK_OK)
{
std::cout << "GET Brightness response" << std::endl;
std::string repUri;
rep.getValue("uri", repUri);
std::string repUri = rep.getUri();
std::shared_ptr< OCResource > brightnessResource = s_resourceLookup[repUri];
Brightness brightness = s_brightnessLookup[repUri];
rep.getValue("uri", brightness.m_uri);
rep.getValue("brightness", brightness.m_loadlevel);
std::cout << "\turi: " << brightness.m_uri << std::endl;
std::cout << "\turi: " << repUri << std::endl;
std::cout << "\tbrightness: " << brightness.m_loadlevel << std::endl;
s_brightnessLookup[repUri] = brightness; // save new copy
......@@ -255,9 +237,7 @@ void PostLightRepresentation(std::shared_ptr< OCResource > resource)
OCRepresentation rep;
std::cout << "Sending POST request to: " << resource->uri() << std::endl;
Light light = s_lightLookup[resource->uri()];
rep.setValue("uri", light.m_uri); // must be set to be available in OnLight()
rep.setUri(resource->uri()); // must be set to be available in OnLight()
resource->post(rep, QueryParamsMap(), &OnPostLight);
}
......@@ -268,7 +248,7 @@ void PostPowerSwitchRepresentation(std::shared_ptr< OCResource > resource)
PowerSwitch powerSwitch = s_powerSwitchLookup[resource->uri()];
rep.setValue("uri", powerSwitch.m_uri); // must be set to be available in OnLight()
rep.setUri(resource->uri()); // must be set to be available in OnPowerSwitch()
rep.setValue("value", !powerSwitch.m_state);
......@@ -282,7 +262,7 @@ void PostBrightnessRepresentation(std::shared_ptr< OCResource > resource)
Brightness brightness = s_brightnessLookup[resource->uri()];
rep.setValue("uri", brightness.m_uri); // must be set to be available in OnLight()
rep.setUri(resource->uri()); // must be set to be available in OnBrightness()
std::cout << "Current brightness level " << brightness.m_loadlevel << std::endl;
int loadlevel = brightness.m_loadlevel - 20;
......@@ -343,7 +323,6 @@ void foundResource(std::shared_ptr< OCResource > resource)
if (s_lightLookup.find(resourceUri) == s_lightLookup.end())
{
Light light = Light();
light.m_uri = resourceUri;
s_lightLookup[resourceUri] = light;
std::shared_ptr< OCResource > lightResource = resource;
......@@ -362,7 +341,6 @@ void foundResource(std::shared_ptr< OCResource > resource)
if (s_powerSwitchLookup.find(resourceUri) == s_powerSwitchLookup.end())
{
PowerSwitch powerSwitch = PowerSwitch();
powerSwitch.m_uri = resourceUri;
s_powerSwitchLookup[resourceUri] = powerSwitch;
std::shared_ptr< OCResource > powerSwitchResource = resource;
......@@ -383,7 +361,6 @@ void foundResource(std::shared_ptr< OCResource > resource)
{
std::cout << "adding Brightness resouce." << std::endl;
Brightness brightness = Brightness();
brightness.m_uri = resourceUri;
s_brightnessLookup[resourceUri] = brightness;
std::shared_ptr< OCResource > brightnessResource = resource;
......
......@@ -96,6 +96,7 @@ upnp_env.PrependUnique(LIBS = ['m',
######################################################################
upnp_src = [
'upnp_plugin.cpp',
'UpnpBridgeDevice.cpp',
'UpnpConnector.cpp',
'UpnpDevice.cpp',
'UpnpDimmingService.cpp',
......
......@@ -21,43 +21,6 @@ using namespace std;
static const string MODULE = "UpnpAttribute";
//UpnpAttributeInfo *UpnpAttribute::getAttributeInfo(std::vector <UpnpAttributeInfo>
// *serviceAttributes,
// std::string attrName)
//{
// vector<UpnpAttributeInfo>::iterator attrInfo;
// for (attrInfo = serviceAttributes->begin() ; attrInfo != serviceAttributes->end() ; ++attrInfo)
// {
// if (attrInfo->name == attrName)
// {
// return &(*attrInfo);
// }
// }
// return nullptr;
//}
//
//bool UpnpAttribute::isValidRequest(map <string, pair <UpnpAttributeInfo *, int>> *attrMap,
// string attrName,
// UpnpActionType actionType)
//
//{
// // Check if the attribute is present
// map <string, pair< UpnpAttributeInfo *, int>>::iterator attr = attrMap->find(attrName);
// if (attr == attrMap->end())
// {
// return false;
// }
//
// // Check that expected action for the attribute has been found
// if ((attr->second.second) & (int) actionType)
// {
// return true;
// }
//
// return false;
//}
void UpnpAttribute::getCb(GUPnPServiceProxy *proxy,
GUPnPServiceProxyAction *actionProxy,
gpointer userData)
......@@ -185,90 +148,3 @@ void UpnpAttribute::setCb(GUPnPServiceProxy *proxy,
UpnpRequest::requestDone(request, status);
}
//bool UpnpAttribute::set(GUPnPServiceProxy *serviceProxy,
// UpnpRequest *request,
// UpnpAttributeInfo *attrInfo,
// RCSResourceAttributes::Value *attrValue)
//{
// GUPnPServiceProxyAction *actionProxy;
// UpnpVar value;
//
// if (attrValue != NULL)
// {
// // Type of the value to be stored can be derived either from
// // input variable type or from state variable type
// GType type = (attrInfo->actions[1].varType != G_TYPE_NONE) ?
// attrInfo->actions[1].varType : attrInfo->type;
//
// switch (type)
// {
// case G_TYPE_STRING:
// {
// const char *sValue = (attrValue->get< string >()).c_str();
// DEBUG_PRINT("resource: " << request->resource->m_uri << ", (string) " << sValue);
// value.var_pchar = (char *) sValue;
// break;
// }
// case G_TYPE_BOOLEAN:
// {
// value.var_boolean = attrValue->get< bool >();
// DEBUG_PRINT("resource: " << request->resource->m_uri << ", (bool) " << value.var_boolean);
// break;
// }
// case G_TYPE_INT:
// case G_TYPE_UINT:
// {
// value.var_int = attrValue->get< int >();
// DEBUG_PRINT("resource: " << request->resource->m_uri << ", (int) " << value.var_int);
// break;
// }
// case G_TYPE_INT64:
// case G_TYPE_UINT64:
// {
// value.var_int64 = attrValue->get< double >();
// DEBUG_PRINT("resource: " << request->resource->m_uri << ", (int64) " << value.var_int64);
// break;
// }
// default:
// {
// //TODO: handle additional types?
// ERROR_PRINT("Type handling not implemented!");
// assert(0);
// }
// }
// }
//
// if (string(attrInfo->actions[1].varName) == "")
// {
// DEBUG_PRINT("action (no args): " << attrInfo->actions[1].name);
// actionProxy = gupnp_service_proxy_begin_action (serviceProxy,
// attrInfo->actions[1].name,
// setCb,
// (gpointer *) request,
// NULL);
// }
// else
// {
// DEBUG_PRINT("action: " << attrInfo->actions[1].name << "( " << attrInfo->actions[1].varName <<
// " )");
// actionProxy = gupnp_service_proxy_begin_action (serviceProxy,
// attrInfo->actions[1].name,
// setCb,
// (gpointer *) request,
// attrInfo->actions[1].varName,
// attrInfo->actions[1].varType,
// value.var_int64,
// NULL);
// }
//
// if (NULL == actionProxy)
// {
// return false;
// }
//
// // Hold on to the attribute info
// request->proxyMap[actionProxy] = attrInfo;
//
// return true;
//}
......@@ -24,14 +24,6 @@
class UpnpAttribute
{
public:
// static UpnpAttributeInfo *getAttributeInfo(std::vector <UpnpAttributeInfo> *serviceAttributes,
// std::string attrName);
//
// static bool isValidRequest(std::map <std::string, std::pair <UpnpAttributeInfo *, int>> *attrMap,
// std::string,
// UpnpActionType actionType);
static void getCb(GUPnPServiceProxy *proxy,
GUPnPServiceProxyAction *action,
gpointer userData);
......@@ -43,12 +35,6 @@ class UpnpAttribute
static void setCb(GUPnPServiceProxy *proxy,
GUPnPServiceProxyAction *action,
gpointer userData);
// static bool set(GUPnPServiceProxy *serviceProxy,
// UpnpRequest *request,
// UpnpAttributeInfo *attrInfo,
// RCSResourceAttributes::Value *attrValue);
};
#endif
//******************************************************************
//
// 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.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <iostream>
#include <ocrandom.h>
#include <ocstack.h>
#include <octypes.h>
#include <oic_string.h>
#include <oic_malloc.h>
#include <pluginServer.h>
#include <ConcurrentIotivityUtils.h>
#include "UpnpBridgeDevice.h"
#include "UpnpException.h"
#include "UpnpInternal.h"
using namespace std;
using namespace OC::Bridging;
static const string MODULE = "UpnpBridgeDevice";
static const string BRIDGE_RESOURCE_TYPE = "oic.d.bridge";
static const string SECUREMODE_RESOURCE_TYPE = "oic.r.securemode";
const uint SECUREMODE_CALLBACK = 0;
const uint COLLECTION_CALLBACK = 1;
static const string SECUREMODE_PROPERTY_KEY = "secureMode";
static const string SECUREMODE_RESOURCE_URI = "/securemode";
static const string BRIDGE_RESOURCE_URI_PREFIX = "/upnp-bridge/";
static string s_bridgeUri = BRIDGE_RESOURCE_URI_PREFIX + "0";
static vector<_link> s_links;
static UpnpManager *s_upnpManager;
OCStackResult createResource(const string uri, const string resourceTypeName,
const char *resourceInterfaceName, OCEntityHandler resourceEntityHandler,
void* callbackParam, uint8_t resourceProperties)
{
OCStackResult result = OC_STACK_ERROR;
OCResourceHandle handle = OCGetResourceHandleAtUri(uri.c_str());
if (!handle)
{
result = OCCreateResource(&handle, resourceTypeName.c_str(), resourceInterfaceName,
uri.c_str(), resourceEntityHandler, callbackParam, resourceProperties);
if (result == OC_STACK_OK)
{
DEBUG_PRINT("Created resource " << uri);
}
else
{
DEBUG_PRINT("Failed to create resource " << uri);
}
}
else
{
DEBUG_PRINT("Not creating resource " << uri << " (already exists)");
result = OC_STACK_OK;
}
return result;
}
UpnpBridgeDevice::UpnpBridgeDevice()
{
OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
if (!handle)
{
DEBUG_PRINT("OCGetResourceHandleAtUri(" << OC_RSRVD_DEVICE_URI << ") failed");
}
DEBUG_PRINT("OCGetResourceHandleAtUri(" << OC_RSRVD_DEVICE_URI << ") " << handle);
uint8_t resourceProperties = (OC_OBSERVABLE | OC_DISCOVERABLE);
// Generate a UUID for the Protocol Independent ID
uint8_t uuid[UUID_SIZE] = {0};
if (!OCGenerateUuid(uuid))
{
// TODO: throw error on failure ?
DEBUG_PRINT("Generate UUID for Upnp Bridge Device failed");
}
char uuidString[UUID_STRING_SIZE] = {0};
if (!OCConvertUuidToString(uuid, uuidString)) {
// TODO: throw error on failure ?
DEBUG_PRINT("Convert UUID to string for Upnp Bridge Device failed");
}
s_bridgeUri = BRIDGE_RESOURCE_URI_PREFIX + string(uuidString);
OCStackResult result = OCBindResourceTypeToResource(handle, BRIDGE_RESOURCE_TYPE.c_str());
if (result != OC_STACK_OK)
{
DEBUG_PRINT("OCBindResourceTypeToResource() = " << result);
}
handle = OCGetResourceHandleAtUri(OC_RSRVD_WELL_KNOWN_URI);
if (!handle)
{
DEBUG_PRINT("OCGetResourceHandleAtUri(" << OC_RSRVD_DEVICE_URI << ") failed");
}
result = OCSetResourceProperties(handle, OC_DISCOVERABLE | OC_OBSERVABLE);
if (result != OC_STACK_OK)
{
DEBUG_PRINT("OCSetResourceProperties() = " << result);
}
result = createResource(SECUREMODE_RESOURCE_URI, SECUREMODE_RESOURCE_TYPE.c_str(),
OC_RSRVD_INTERFACE_READ, entityHandler, (void *) SECUREMODE_CALLBACK, resourceProperties);
if (result != OC_STACK_OK)
{
DEBUG_PRINT("CreateResource() = " << result);
}
result = createResource(s_bridgeUri, BRIDGE_RESOURCE_TYPE.c_str(),
OC_RSRVD_INTERFACE_READ, entityHandler, (void *) COLLECTION_CALLBACK, resourceProperties);