Commit 6448b4a4 authored by Larry Sachs's avatar Larry Sachs Committed by Rick Bell

Add Resource Attrs for Actions/State Variables

Attributes added are aligned with current upnp generic
data models.

Change-Id: I20c14667a3ef4a460bbcc19ca1349b8ccbf8de67
Signed-off-by: Larry Sachs's avatarLarry Sachs <larry.j.sachs@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/21155Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: George Nash's avatarGeorge Nash <george.nash@intel.com>
Reviewed-by: default avatarRick Bell <richard.s.bell@intel.com>
parent bfd5bed0
......@@ -587,9 +587,9 @@ OCRepPayload* getCommonPayload(const char *uri, char *interfaceQuery, string res
// If the interface filter is explicitly oic.if.baseline, include all properties.
if (interfaceQuery && string(interfaceQuery) == string(OC_RSRVD_INTERFACE_DEFAULT))
{
if (!OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_ACTUATOR))
if (!OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_READ))
{
throw "Failed to set actuator interface";
throw "Failed to set read interface";
}
if (!OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_DEFAULT))
......@@ -767,7 +767,7 @@ void UpnpConnector::onAdd(std::string uri)
else
{
DEBUG_PRINT("Adding generic upnp service");
createResource(uri, UPNP_SERVICE_RESOURCE, OC_RSRVD_INTERFACE_ACTUATOR,
createResource(uri, UPNP_SERVICE_RESOURCE, OC_RSRVD_INTERFACE_READ,
resourceEntityHandler, (void *) GENERIC_SERVICE_CALLBACK, resourceProperties);
// create resources for links
if (!service.second->m_links.empty())
......@@ -778,12 +778,12 @@ void UpnpConnector::onAdd(std::string uri)
string linkRt = service.second->m_links[i].rt;
if (UPNP_ACTION_RESOURCE == linkRt)
{
createResource(linkUri, linkRt, OC_RSRVD_INTERFACE_ACTUATOR,
createResource(linkUri, linkRt, OC_RSRVD_INTERFACE_READ_WRITE,
resourceEntityHandler, (void *) GENERIC_ACTION_CALLBACK, resourceProperties);
}
else if (UPNP_STATE_VAR_RESOURCE == linkRt)
{
createResource(linkUri, linkRt, OC_RSRVD_INTERFACE_SENSOR,
createResource(linkUri, linkRt, OC_RSRVD_INTERFACE_READ,
resourceEntityHandler, (void *) GENERIC_STATE_VAR_CALLBACK, resourceProperties);
}
else
......
......@@ -212,6 +212,8 @@ OCEntityHandlerResult UpnpDevice::processGetRequest(OCRepPayload *payload, strin
}
// continue getting larger icons
width = -1;
height = -1;
int nextWidth = 0;
int nextHeight = 0;
bool gettingIcons = true;
......
......@@ -33,12 +33,237 @@ OCEntityHandlerResult UpnpGenericService::processGetRequest(string uri, OCRepPay
throw "payload is null";
}
//TODO use async version with callback
DEBUG_PRINT("TODO: process get request for " << uri << " resource type " << resourceType);
// TODO use introspection to get actions and state variables
// TODO create action resource if it doesn't exist
// TODO create state variable resource if it doesn't exist
// TODO add action and state variable links to payload
if (UPNP_ACTION_RESOURCE == resourceType)
{
GUPnPServiceInfo *serviceInfo = GUPNP_SERVICE_INFO(m_proxy);
if (GUPNP_IS_SERVICE_INFO(serviceInfo))
{
GUPnPServiceIntrospection *introspection = gupnp_service_info_get_introspection(serviceInfo, NULL);
if (introspection != NULL)
{
size_t actionNamePos = uri.rfind("/");
string actionName = uri.substr(actionNamePos+1);
const GUPnPServiceActionInfo *actionInfo = gupnp_service_introspection_get_action(introspection, actionName.c_str());
if (actionInfo != NULL)
{
if (OCRepPayloadSetPropString(payload, ACTION_NAME.c_str(), actionInfo->name))
{
DEBUG_PRINT(m_uri << ": " << ACTION_NAME << ": " << actionInfo->name);
}
else
{
ERROR_PRINT("Failed to set " << m_uri << ": " << ACTION_NAME << " value in payload");
}
const GList *arguments = (GList *)actionInfo->arguments;
if (arguments != NULL)
{
vector<_genArg> inputArgs;
vector<_genArg> outputArgs;
const GList *argsList;
for (argsList = arguments; argsList != NULL; argsList = argsList->next)
{
const GUPnPServiceActionArgInfo *argInfo = (GUPnPServiceActionArgInfo *)argsList->data;
const char *argName = argInfo->name;
const GUPnPServiceActionArgDirection argDir = argInfo->direction;
const char *relatedVar = argInfo->related_state_variable;
// get the arg type from the related state variable
string argType;
const GUPnPServiceStateVariableInfo *stateVarInfo = gupnp_service_introspection_get_state_variable(introspection, relatedVar);
if (stateVarInfo != NULL)
{
const GType type = stateVarInfo->type;
const string gType = g_type_name(type);
argType = GTypeToUpnpTypeMap[gType];
if ((argType == nullptr) || (argType.empty()))
{
ERROR_PRINT("No type found for GType " << gType);
}
}
else
{
ERROR_PRINT("No related state var info for " << m_uri << ": " << STATE_VAR_NAME << ": " << relatedVar);
}
_genArg genericArg;
genericArg.name = argName;
genericArg.type = argType;
if (GUPNP_SERVICE_ACTION_ARG_DIRECTION_IN == argDir)
{
inputArgs.push_back(genericArg);
}
else if (GUPNP_SERVICE_ACTION_ARG_DIRECTION_OUT == argDir)
{
outputArgs.push_back(genericArg);
}
else
{
ERROR_PRINT("Unknown arg direction for " << m_uri << ": " << argDir);
}
}
if (!inputArgs.empty())
{
DEBUG_PRINT("Setting input args for " << uri);
const OCRepPayload *args[inputArgs.size()];
size_t dimensions[MAX_REP_ARRAY_DEPTH] = {inputArgs.size(), 0, 0};
for (unsigned int i = 0; i < inputArgs.size(); ++i) {
DEBUG_PRINT(INPUT_ARGS << "[" << i << "]");
DEBUG_PRINT("\t" << GEN_NAME << "=" << inputArgs[i].name);
DEBUG_PRINT("\t" << GEN_TYPE << "=" << inputArgs[i].type);
DEBUG_PRINT("\t" << GEN_VALUE << "=" << inputArgs[i].value);
OCRepPayload *argPayload = OCRepPayloadCreate();
OCRepPayloadSetPropString(argPayload, GEN_NAME.c_str(), inputArgs[i].name.c_str());
OCRepPayloadSetPropString(argPayload, GEN_TYPE.c_str(), inputArgs[i].type.c_str());
OCRepPayloadSetPropString(argPayload, GEN_VALUE.c_str(), inputArgs[i].value.c_str());
args[i] = argPayload;
}
OCRepPayloadSetPropObjectArray(payload, INPUT_ARGS.c_str(), args, dimensions);
}
if (!outputArgs.empty())
{
DEBUG_PRINT("Setting output args for " << uri);
const OCRepPayload *args[outputArgs.size()];
size_t dimensions[MAX_REP_ARRAY_DEPTH] = {outputArgs.size(), 0, 0};
for (unsigned int i = 0; i < outputArgs.size(); ++i) {
DEBUG_PRINT(OUTPUT_ARGS << "[" << i << "]");
DEBUG_PRINT("\t" << GEN_NAME << "=" << outputArgs[i].name);
DEBUG_PRINT("\t" << GEN_TYPE << "=" << outputArgs[i].type);
DEBUG_PRINT("\t" << GEN_VALUE << "=" << outputArgs[i].value);
OCRepPayload *argPayload = OCRepPayloadCreate();
OCRepPayloadSetPropString(argPayload, GEN_NAME.c_str(), outputArgs[i].name.c_str());
OCRepPayloadSetPropString(argPayload, GEN_TYPE.c_str(), outputArgs[i].type.c_str());
OCRepPayloadSetPropString(argPayload, GEN_VALUE.c_str(), outputArgs[i].value.c_str());
args[i] = argPayload;
}
OCRepPayloadSetPropObjectArray(payload, OUTPUT_ARGS.c_str(), args, dimensions);
}
}
}
else
{
ERROR_PRINT("No action info for " << m_uri << ": " << ACTION_NAME << ": " << actionName);
}
g_object_unref(introspection);
}
}
else
{
ERROR_PRINT("GUPNP_SERVICE_INFO failed for proxy for " << m_uri);
}
}
if (UPNP_STATE_VAR_RESOURCE == resourceType)
{
GUPnPServiceInfo *serviceInfo = GUPNP_SERVICE_INFO(m_proxy);
if (GUPNP_IS_SERVICE_INFO(serviceInfo))
{
GUPnPServiceIntrospection *introspection = gupnp_service_info_get_introspection(serviceInfo, NULL);
if (introspection != NULL)
{
size_t stateVarNamePos = uri.rfind("/");
string stateVarName = uri.substr(stateVarNamePos+1);
const GUPnPServiceStateVariableInfo *stateVarInfo = gupnp_service_introspection_get_state_variable(introspection, stateVarName.c_str());
if (stateVarInfo != NULL)
{
if (OCRepPayloadSetPropString(payload, STATE_VAR_NAME.c_str(), stateVarInfo->name))
{
DEBUG_PRINT(m_uri << ": " << STATE_VAR_NAME << ": " << stateVarInfo->name);
}
else
{
ERROR_PRINT("Failed to set " << m_uri << ": " << STATE_VAR_NAME << " value in payload");
}
const GType type = stateVarInfo->type;
const string gType = g_type_name(type);
const string upnpType = GTypeToUpnpTypeMap[gType];
if ((upnpType != nullptr) && (! upnpType.empty()))
{
if (OCRepPayloadSetPropString(payload, DATA_TYPE.c_str(), upnpType.c_str()))
{
DEBUG_PRINT(m_uri << ": " << DATA_TYPE << ": " << gType << "->" << upnpType);
}
else
{
ERROR_PRINT("Failed to set " << m_uri << ": " << DATA_TYPE << " value in payload");
}
}
else
{
ERROR_PRINT("No type found for GType " << gType);
}
const GValue defaultValue = stateVarInfo->default_value;
GValue strValue;
memset(&strValue, 0, sizeof (GValue));
g_value_init(&strValue, G_TYPE_STRING);
g_value_transform(&defaultValue, &strValue);
char *defaultValueAsString = g_value_dup_string(&strValue);
if (defaultValueAsString != NULL)
{
if (OCRepPayloadSetPropString(payload, DEFAULT_VALUE.c_str(), defaultValueAsString))
{
DEBUG_PRINT(m_uri << ": " << DEFAULT_VALUE << ": " << defaultValueAsString);
}
else
{
ERROR_PRINT("Failed to set " << m_uri << ": " << DEFAULT_VALUE << " value in payload");
}
g_free(defaultValueAsString);
}
g_value_unset(&strValue);
if (! stateVarInfo->is_numeric)
{
GList *allowedValues = (GList *)stateVarInfo->allowed_values;
if (allowedValues != NULL)
{
unsigned allowedValuesLength = g_list_length(allowedValues);
char **allowedValuesArray = (char **)OICCalloc(allowedValuesLength, sizeof(char *));
if (allowedValuesArray)
{
int allowedValuesArrayIndex = 0;
const GList *avList;
for (avList = allowedValues; avList != NULL; avList = avList->next)
{
allowedValuesArray[allowedValuesArrayIndex++] = (char *)avList->data;
}
if (allowedValuesArrayIndex)
{
DEBUG_PRINT("Setting allowed values for " << uri);
size_t dimensions[MAX_REP_ARRAY_DEPTH] = {allowedValuesLength, 0, 0};
for (unsigned int i = 0; i < allowedValuesLength; ++i) {
DEBUG_PRINT(ALLOWED_VALUE_LIST << "[" << i << "] = " << allowedValuesArray[i]);
}
OCRepPayloadSetStringArray(payload, ALLOWED_VALUE_LIST.c_str(), (const char **)allowedValuesArray, dimensions);
}
OICFree(allowedValuesArray);
}
}
}
}
else
{
ERROR_PRINT("No state var info for " << m_uri << ": " << STATE_VAR_NAME << ": " << stateVarName);
}
g_object_unref(introspection);
}
}
else
{
ERROR_PRINT("GUPNP_SERVICE_INFO failed for proxy for " << m_uri);
}
}
return UpnpService::processGetRequest(uri, payload, resourceType);
}
......
......@@ -32,6 +32,37 @@
using namespace std;
// for state variables
static const string STATE_VAR_NAME = "name";
static const string DATA_TYPE = "dataType";
static const string DEFAULT_VALUE = "defaultValue";
static const string ALLOWED_VALUE_LIST = "allowedValueList";
// for actions
static const string ACTION_NAME = "actionName";
static const string INPUT_ARGS = "inputArgs";
static const string OUTPUT_ARGS = "outputArgs";
// for generic args
static const string GEN_NAME = "genName";
static const string GEN_TYPE = "genType";
static const string GEN_VALUE = "genValue";
struct _genArg {
string name;
string type;
string value;
};
// GType to Upnp Type map
static map<string, string> GTypeToUpnpTypeMap =
{
{"gboolean", "boolean"},
{"gchararray","string"},
{"gint", "int"},
{"guint", "ui4"},
};
class UpnpGenericService: public UpnpService
{
friend class UpnpService;
......
......@@ -259,11 +259,6 @@ UpnpResource::Ptr UpnpManager::processService(GUPnPServiceProxy *proxy,
}
}
// if (introspection != NULL)
// {
// pService->processIntrospection(proxy, introspection);
// }
pService->setProxy(proxy);
pService->setReady(true);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment