Initial version of atomic measurement. 17/29317/1
authorHerve Jourdain <herve.jourdain@beechwoods.com>
Wed, 19 Dec 2018 07:45:55 +0000 (15:45 +0800)
committerHerve Jourdain <herve.jourdain@beechwoods.com>
Mon, 4 Mar 2019 12:53:24 +0000 (12:53 +0000)
Implementation of atomic measurements in iotivity, including C, C++ and Java/Android APIs.

Change-Id: Idda2f9f39c98b7307de756774186bbd7fddf434d
Signed-off-by: Herve Jourdain <herve.jourdain@beechwoods.com>
(cherry picked from commit e7aa9277995159e287b9739ae5184ec9b6ccae1a)

25 files changed:
java/iotivity-android/src/main/java/org/iotivity/base/OcPlatform.java
java/jni/JniOcPlatform.cpp
java/jni/JniOcPlatform.h
resource/IPCA/unittests/mockInProcServerWrapper.cpp
resource/csdk/include/octypes.h
resource/csdk/stack/SConscript
resource/csdk/stack/include/internal/ocatomicmeasurement.h [new file with mode: 0644]
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/internal/ocresourcehandler.h
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/octbstack_product.def
resource/csdk/stack/src/ocatomicmeasurement.c [new file with mode: 0644]
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c
resource/include/IServerWrapper.h
resource/include/InProcServerWrapper.h
resource/include/OCPlatform.h
resource/include/OCPlatform_impl.h
resource/src/InProcServerWrapper.cpp
resource/src/OCPlatform.cpp
resource/src/OCPlatform_impl.cpp

index 4df5814..16dcae0 100644 (file)
@@ -853,6 +853,59 @@ public final class OcPlatform {
             OcResourceHandle ocResourceCollectionHandle,
             OcResourceHandle[] ocResourceHandleArray) throws OcException;
 
+    /**
+     * Add a resource to a collection / atomic measurement resource
+     *
+     * @param ocResourceAmColHandle handle to the collection / atomic measurement resource
+     * @param ocResourceHandle      handle to resource to be added to the collection / atomic measurement resource
+     * @param isAtomicMeasurement   boolean indicating if this is a collection or an atomic measurement
+     * @throws OcException if failure
+     */
+    public static void bindResourceAM(
+            OcResourceHandle ocResourceAmColHandle,
+            OcResourceHandle ocResourceHandle,
+            boolean isAtomicMeasurement) throws OcException {
+        OcPlatform.initCheck();
+        OcPlatform.bindResourceAM0(ocResourceAmColHandle, ocResourceHandle, isAtomicMeasurement);
+    }
+
+    private static native void bindResourceAM0(
+            OcResourceHandle ocResourceAmColHandle,
+            OcResourceHandle ocResourceHandle,
+            boolean isAtomicMeasurement) throws OcException;
+
+    /**
+     * Add multiple resources to a collection / atomic measurement resource.
+     *
+     * @param ocResourceAmColHandle handle to the collection / atomic measurement resource
+     * @param ocResourceHandleList  reference to list of resource handles to be added to the
+     *                              collection / atomic measurement resource
+     * @param isAtomicMeasurement   boolean indicating if this is a collection or an atomic measurement
+     * @throws OcException if failure
+     */
+    public static void bindResourcesAM(
+            OcResourceHandle ocResourceAmColHandle,
+            List<OcResourceHandle> ocResourceHandleList,
+            boolean isAtomicMeasurement) throws OcException {
+        OcPlatform.initCheck();
+
+        if (ocResourceHandleList == null) {
+            throw new OcException(ErrorCode.INVALID_PARAM, "ocResourceHandleList cannot be null");
+        }
+
+        OcPlatform.bindResourcesAM0(
+                ocResourceAmColHandle,
+                ocResourceHandleList.toArray(
+                        new OcResourceHandle[ocResourceHandleList.size()]),
+                isAtomicMeasurement
+        );
+    }
+
+    private static native void bindResourcesAM0(
+            OcResourceHandle ocResourceAmColHandle,
+            OcResourceHandle[] ocResourceHandleArray,
+            boolean isAtomicMeasurement) throws OcException;
+
     /**
      * Unbind a resource from a collection resource.
      *
@@ -917,6 +970,24 @@ public final class OcPlatform {
             OcResourceHandle ocResourceHandle,
             String resourceTypeName) throws OcException;
 
+    /**
+     * Adds a type to the rts-m of a resource
+     *
+     * @param ocResourceHandle handle to the resource
+     * @param resourceTypeName new typename to add to the rts-m of the resource
+     * @throws OcException if failure
+     */
+    public static void bindRtsMToResource(
+            OcResourceHandle ocResourceHandle,
+            String resourceTypeName) throws OcException {
+        OcPlatform.initCheck();
+        OcPlatform.bindRtsMToResource0(ocResourceHandle, resourceTypeName);
+    }
+
+    private static native void bindRtsMToResource0(
+            OcResourceHandle ocResourceHandle,
+            String resourceTypeName) throws OcException;
+
     /**
      * Binds an interface to a particular resource
      *
@@ -1156,6 +1227,20 @@ public final class OcPlatform {
     private static native void sendResponse0(OcResourceResponse ocResourceResponse)
             throws OcException;
 
+    /**
+     * This function notifies the atomic measurement that a new atomic measurement is available
+     * (because one or more of the values of the resources composing it have changed).
+     *
+     * @param handle            Handle of resource.
+     *
+     */
+    public static void notifyNewAMAvailable(OcResourceHandle resourceHandle) throws OcException {
+        OcPlatform.initCheck();
+        OcPlatform.notifyNewAMAvailable0(resourceHandle);
+    }
+
+    private static native void notifyNewAMAvailable0(OcResourceHandle resourceHandle) throws OcException;
+
     /**
      * An OnResourceFoundListener can be registered via the OcPlatform.findResource call.
      * Event listeners are notified asynchronously
index ed41591..30b198f 100644 (file)
@@ -30,6 +30,9 @@
 #include "ocpayload.h"
 #include "RDClient.h"
 
+#include "JniOcRequestHandle.h"
+#include "JniOcRepresentation.h"
+
 #ifdef WITH_CLOUD
 #include "JniOcAccountManager.h"
 #endif
@@ -1983,6 +1986,135 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResources0(
     }
 }
 
+/*
+* Class:     org_iotivity_base_OcPlatform
+* Method:    bindResourceAM0
+* Signature: (Lorg/iotivity/base/OcResourceHandle;Lorg/iotivity/base/OcResourceHandle;Z)V
+*/
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResourceAM0
+(JNIEnv *env, jclass clazz, jobject jResourceAmColHandle, jobject jResourceHandle, jboolean jIsAtomicMeasurement)
+{
+    OC_UNUSED(clazz);
+    LOGI("OcPlatform_bindResourceAM");
+    if (!jResourceAmColHandle)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "resourceAmColHandle cannot be null");
+        return;
+    }
+    if (!jResourceHandle)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "resourceHandle cannot be null");
+        return;
+    }
+    JniOcResourceHandle* jniOcResourceAmColHandle =
+        JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceAmColHandle);
+    if (!jniOcResourceAmColHandle)
+    {
+        return;
+    }
+
+    JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
+        env, jResourceHandle);
+    if (!jniOcResourceHandle)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = OCPlatform::bindResourceAM(
+            jniOcResourceAmColHandle->getOCResourceHandle(),
+            jniOcResourceHandle->getOCResourceHandle(),
+            jIsAtomicMeasurement
+            );
+
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Failed to bind collection / atomic measurement resource");
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+* Class:     org_iotivity_base_OcPlatform
+* Method:    bindResourcesAM0
+* Signature: (Lorg/iotivity/base/OcResourceHandle;[Lorg/iotivity/base/OcResourceHandle;Z)V
+*/
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResourcesAM0(
+    JNIEnv *env,
+    jclass clazz,
+    jobject jResourceAmColHandle,
+    jobjectArray jResourceHandleArray,
+    jboolean jIsAtomicMeasurement)
+{
+    OC_UNUSED(clazz);
+    LOGI("OcPlatform_bindResourcesAM");
+
+    if (!jResourceAmColHandle)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "resourceAmColHandle cannot be null");
+        return;
+    }
+    if (!jResourceHandleArray)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "resourceHandleList cannot be null");
+        return;
+    }
+
+    JniOcResourceHandle* jniOcResourceAmColHandle =
+        JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceAmColHandle);
+    if (!jniOcResourceAmColHandle)
+    {
+        return;
+    }
+
+    std::vector<OCResourceHandle> resourceHandleList;
+    int len = env->GetArrayLength(jResourceHandleArray);
+    for (int i = 0; i < len; ++i)
+    {
+        jobject jResourceHandle = env->GetObjectArrayElement(jResourceHandleArray, i);
+        if (!jResourceHandle)
+        {
+            ThrowOcException(JNI_EXCEPTION, "resource handle cannot be null");
+            return;
+        }
+
+        JniOcResourceHandle* jniOcResourceHandle =
+            JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+        if (!jniOcResourceHandle)
+        {
+            return;
+        }
+
+        resourceHandleList.push_back(
+            jniOcResourceHandle->getOCResourceHandle());
+    }
+
+    try
+    {
+        OCStackResult result = OCPlatform::bindResourcesAM(
+            jniOcResourceAmColHandle->getOCResourceHandle(),
+            resourceHandleList,
+            jIsAtomicMeasurement
+            );
+
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Failed to bind collection / atomic measurement resources");
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
 /*
 * Class:     org_iotivity_base_OcPlatform
 * Method:    unbindResource0
@@ -2161,6 +2293,56 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindTypeToResource0(
     }
 }
 
+/*
+* Class:     org_iotivity_base_OcPlatform
+* Method:    bindRtsMToResource0
+* Signature: (Lorg/iotivity/base/OcResourceHandle;Ljava/lang/String;)V
+*/
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindRtsMToResource0(
+    JNIEnv *env,
+    jclass clazz,
+    jobject jResourceHandle,
+    jstring jResourceTypeName)
+{
+    OC_UNUSED(clazz);
+    LOGI("OcPlatform_bindRtsMToResource");
+    if (!jResourceHandle)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "resourceHandle cannot be null");
+        return;
+    }
+    std::string typeName;
+    if (jResourceTypeName)
+    {
+        typeName = env->GetStringUTFChars(jResourceTypeName, nullptr);
+    }
+
+    JniOcResourceHandle* jniOcResourceHandle =
+        JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+    if (!jniOcResourceHandle)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = OCPlatform::bindRtsMToResource(
+            jniOcResourceHandle->getOCResourceHandle(),
+            typeName
+            );
+
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Failed to add type to the rts-m of the resource");
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
 /*
 * Class:     org_iotivity_base_OcPlatform
 * Method:    bindInterfaceToResource0
@@ -2663,6 +2845,46 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_sendResponse0(
     }
 }
 
+/*
+* Class:     org_iotivity_base_OcPlatform
+* Method:    notifyNewAMAvailable0
+* Signature: (Lorg/iotivity/base/OcResourceHandle;)V
+*/
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_notifyNewAMAvailable0
+    (JNIEnv *env, jclass clazz, jobject jResourceHandle)
+{
+    OC_UNUSED(clazz);
+    LOGD("OcPlatform_notifyNewAMAvailable");
+    if (!jResourceHandle)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "resourceHandle cannot be null");
+        return;
+    }
+
+    JniOcResourceHandle* jniOcResourceHandle =
+        JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+    if (!jniOcResourceHandle)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result =
+            OCPlatform::notifyNewAMAvailable(jniOcResourceHandle->getOCResourceHandle());
+
+        if ((OC_STACK_OK != result) && (OC_STACK_NO_OBSERVERS != result))
+        {
+            ThrowOcException(result, "failed to send new AM available notification");
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
 /*
 * Class:     org_iotivity_base_OcPlatform
 * Method:    constructAccountManagerObject0
index 2440c7c..4fea9bc 100644 (file)
@@ -275,6 +275,22 @@ extern "C" {
     JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResources0
         (JNIEnv *, jclass, jobject, jobjectArray);
 
+    /*
+    * Class:     org_iotivity_base_OcPlatform
+    * Method:    bindResourceAM0
+    * Signature: (Lorg/iotivity/base/OcResourceHandle;Lorg/iotivity/base/OcResourceHandle;Z)V
+    */
+    JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResourceAM0
+        (JNIEnv *, jclass, jobject, jobject, jboolean);
+
+    /*
+    * Class:     org_iotivity_base_OcPlatform
+    * Method:    bindResourcesAM0
+    * Signature: (Lorg/iotivity/base/OcResourceHandle;[Lorg/iotivity/base/OcResourceHandle;Z)V
+    */
+    JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResourcesAM0
+        (JNIEnv *, jclass, jobject, jobjectArray, jboolean);
+
     /*
     * Class:     org_iotivity_base_OcPlatform
     * Method:    unbindResource0
@@ -299,6 +315,14 @@ extern "C" {
     JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindTypeToResource0
         (JNIEnv *, jclass, jobject, jstring);
 
+    /*
+    * Class:     org_iotivity_base_OcPlatform
+    * Method:    bindRtsMToResource0
+    * Signature: (Lorg/iotivity/base/OcResourceHandle;Ljava/lang/String;)V
+    */
+    JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindRtsMToResource0
+        (JNIEnv *, jclass, jobject, jstring);
+
     /*
     * Class:     org_iotivity_base_OcPlatform
     * Method:    bindInterfaceToResource0
@@ -372,6 +396,14 @@ extern "C" {
     JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_sendResponse0
         (JNIEnv *, jclass, jobject);
 
+    /*
+    * Class:     org_iotivity_base_OcPlatform0
+    * Method:    notifyNewAMAvailable0
+    * Signature: (Lorg/iotivity/base/OcResourceHandle;)V
+    */
+    JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_notifyNewAMAvailable0
+        (JNIEnv *, jclass, jobject);
+
     /*
     * Class:     org_iotivity_base_OcPlatform
     * Method:    constructAccountManagerObject0
index 2ccaf4a..df2d827 100644 (file)
@@ -97,6 +97,15 @@ namespace OC
         return OC_STACK_OK;
     }
 
+    OCStackResult InProcServerWrapper::bindRtsMToResource(const OCResourceHandle& resourceHandle,
+                     const std::string& resourceTypeName)
+    {
+        OC_UNUSED(resourceHandle);
+        OC_UNUSED(resourceTypeName);
+
+        return OC_STACK_OK;
+    }
+
     OCStackResult InProcServerWrapper::bindInterfaceToResource(
                      const OCResourceHandle& resourceHandle,
                      const std::string& resourceInterfaceName)
index f632d0f..fdbdc39 100644 (file)
@@ -168,6 +168,9 @@ extern "C" {
 /** To represent resource type with collection.*/
 #define OC_RSRVD_RESOURCE_TYPE_COLLECTION "oic.wk.col"
 
+/** To represent resource type with atomic measurement.*/
+#define OC_RSRVD_RESOURCE_TYPE_AM "oic.wk.atomicmeasurement"
+
 /** To represent resource type with RES.*/
 #define OC_RSRVD_RESOURCE_TYPE_RES      "oic.wk.res"
 
@@ -444,6 +447,9 @@ extern "C" {
 /** Allowable resource types in the links. */
 #define OC_RSRVD_RTS                     "rts"
 
+/** Mandatory resource types in the links [shall be a subset of rts]. */
+#define OC_RSRVD_RTSM                    "rts-m"
+
 /** Default relationship. */
 #define OC_RSRVD_DREL                    "drel"
 
index 15ce174..f432f11 100644 (file)
@@ -234,6 +234,7 @@ liboctbstack_src = [
     OCTBSTACK_SRC + 'ocobserve.c',
     OCTBSTACK_SRC + 'ocserverrequest.c',
     OCTBSTACK_SRC + 'occollection.c',
+    OCTBSTACK_SRC + 'ocatomicmeasurement.c',
     OCTBSTACK_SRC + 'oicgroup.c',
     OCTBSTACK_SRC + 'ocendpoint.c'
 ]
diff --git a/resource/csdk/stack/include/internal/ocatomicmeasurement.h b/resource/csdk/stack/include/internal/ocatomicmeasurement.h
new file mode 100644 (file)
index 0000000..2c4ddff
--- /dev/null
@@ -0,0 +1,77 @@
+//******************************************************************
+//
+// Copyright 2018 Beechwoods Software 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OC_ATOMICMEASUREMENT_H
+#define OC_ATOMICMEASUREMENT_H
+
+#include "ocstack.h"
+#include "ocresourcehandler.h"
+
+/**
+ * This function is the default entity handler for the atomic measurement resource.
+ * @param[in] flag Entity handler flag for the atomic measurement resource
+ * @param[in] ehRequest Entity handler request received for the atomic measurement resource
+ *
+ * @return OCStackResult
+ */
+OCStackResult DefaultAtomicMeasurementEntityHandler (OCEntityHandlerFlag flag,
+    OCEntityHandlerRequest *entityHandlerRequest);
+
+/**
+ * This function is the entity handler the atomic measurement substitutes to each of its
+ * individual resources' entity handler, in order to correctly control and process
+ * atomic measurement, and implement its restrictions.
+ * @param[in] flag Entity handler flag for the individual resource
+ * @param[in] ehRequest Entity handler request received for the individual resource
+ * @param[in] ehCallbackParam Entity handler callback parameter for the individual resource
+ *
+ * @return OCEntityHandlerResult
+ */
+OCEntityHandlerResult DefaultAtomicMeasurementResourceEntityHandler(OCEntityHandlerFlag flag,
+    OCEntityHandlerRequest *ehRequest, void *ehCallbackParam);
+
+/**
+ * This function notifies the atomic measurement that a new measurement is ready. This notification will
+ * trigger the atomic measurement sending GET requests to all the individual resources composing it.
+ * @param[in] amResourceHandle Handle of the atomic measurement resource to which the individual
+ *            resource belongs
+ *
+ * @return OCStackResult
+ */
+OCStackResult NewAtomicMeasurementReadyNotificationHandler(const OCResourceHandle amResourceHandle);
+
+/**
+ * This function creates the RepPayloadArray for links parameter of an atomic measurement resource.
+ * @param[in] resourceUri Resource URI (this should be an atomic measurement resource)
+ * @param[in] isOCFContentFormat true if content is OCF (from OCEntityHandlerRequest)
+ * @param[in] devAddr Structure pointing to the address. (from OCEntityHandlerRequest)
+ * @param[in] insertSelfLink true if links array must contain a self link
+ * @param[out] createdArraySize return value array size, Null is allowed if no need to know size
+ * @note: The destroy of OCRepPayloadValue is not supported. Instead, use
+ *        OCRepPayloadDestroy(...) to destroy RepPayload of the atomic measurement Resource
+ *
+ * @return linksRepPayloadArray The *RepPayload Array pointer for links parameter of collection
+ * @see OCLinksPayloadArrayCreate API doxygen for API usage
+ */
+OCRepPayload** BuildAtomicMeasurementLinksPayloadArray(const char* resourceUri,
+                    bool isOCFContentFormat, OCDevAddr* devAddr, bool insertSelfLink,
+                    size_t* createdArraySize);
+
+#endif //OC_ATOMICMEASUREMENT_H
index 06de75f..ad86747 100644 (file)
@@ -199,6 +199,9 @@ typedef struct OCResource {
     /** Resource type(s); linked list.*/
     OCResourceType *rsrcType;
 
+    /** Mandatory Resource type(s) in the links [collection / atomic measurement only]; linked list.*/
+    OCResourceType *rsrcTypeM;
+
     /** Resource interface(s); linked list.*/
     OCResourceInterface *rsrcInterface;
 
@@ -211,6 +214,9 @@ typedef struct OCResource {
     /** Child resource(s); linked list.*/
     OCChildResource *rsrcChildResourcesHead;
 
+    /** Is this an Atomic Measurement; boolean.*/
+    bool rsrcIsAtomicMeasurement;
+
     /** Pointer to function that handles the entity bound to the resource.
      *  This handler has to be explicitly defined by the programmer.*/
     OCEntityHandler entityHandler;
@@ -218,6 +224,13 @@ typedef struct OCResource {
     /** Callback parameter.*/
     void * entityHandlerCallbackParam;
 
+    /** Pointer to function that handles the entity bound to the resource in case of atomic measurement.
+     * In case of an atomic measurement, the entity handler will be saved here, and the atomic measurement
+     * default handler will be set as the new entity handler, to prevent individual access to resources in
+     * the atomic measurement.
+     * This handler is internal, used ONLY by atomic measurement code.*/
+    OCEntityHandler amEntityHandler;
+
     /** Properties on the resource – defines meta information on the resource.
      * (ACTIVE, DISCOVERABLE etc ). */
 
index e8d8c9a..7c9aaa5 100644 (file)
@@ -128,6 +128,8 @@ typedef enum
     OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
     OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
     OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_AM_WITH_ENTITYHANDLER,
+    OC_RESOURCE_AM_DEFAULT_ENTITYHANDLER,
     OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
     OC_RESOURCE_NOT_SPECIFIED
 } ResourceHandling;
@@ -225,6 +227,12 @@ OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
  */
 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
 
+/**
+ * A helper function that Maps an @ref OCStackResult type to an
+ * @ref OCEntityHandlerResult type.
+ */
+OCEntityHandlerResult OCStackCodeToEntityHandlerCode(OCStackResult result);
+
 /**
  * Data structure for holding enhanced device information
  */
index bd122b0..580e50a 100644 (file)
@@ -215,15 +215,6 @@ OCStackResult SendStopNotification(void);
  */
 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
                                             const char *resourceInterfaceName);
-/**
- * Bind a resource type to a resource.
- *
- * @param resource Target resource.
- * @param resourceTypeName Name of resource type.
- * @return ::OC_STACK_OK on success, some other value upon failure.
- */
-OCStackResult BindResourceTypeToResource(OCResource *resource,
-                                            const char *resourceTypeName);
 /**
  * Bind a Transport Protocol Suites type to a resource.
  *
index a2ca3fc..7d5e31f 100644 (file)
@@ -359,6 +359,28 @@ bool OC_CALL OCByteStringCopy(OCByteString *dest, const OCByteString *source);
 OCRepPayload** OC_CALL OCLinksPayloadArrayCreate(const char *resourceUri,
                        OCEntityHandlerRequest *ehRequest, bool insertSelfLink, size_t* createdArraySize);
 
+/**
+ * Creates a payloadArray for the links parameter of an atomic measurement resource.
+ * @param[in] resourceUri Resource URI (this should be a collection resource)
+ * @param[in] ehRequest parameter received from Entity Handler for client request
+ * @param[in] insertSelfLink flag to specify whether links array can contain a self link
+ * @param[out] createdArraySize return value array size, Null is allowed if no need to know size
+ *
+ * @note: API usage
+ *   OCRepPayload **linkArr = OCLinksPayloadArrayCreateAM(uri, ehRequest, false, &ArraySize);
+ *   For links parameter setting  (baseline interface response)
+ *    OCRepPayloadSetPropObjectArrayAsOwner(payload, OC_RSRVD_LINKS, linkArr, {ArraySize, 0,0});
+ *   For arrayPayload setting (linklist interface response)
+ *     payload = linkArr[0]; payload->next = linkArr[1]; ....
+ *     OICFree(linkArr)
+ * @note: The destroy of OCRepPayloadArray is not supported. Instead, use
+ *        OCRepPayloadDestroy(...) to destroy RepPayload of the collection Resource
+ *
+ * @return linksRepPayloadArray The *RepPayload Array pointer for links parameter of the atomic measurement.
+ **/
+OCRepPayload** OC_CALL OCLinksPayloadArrayCreateAM(const char *resourceUri,
+                       OCEntityHandlerRequest *ehRequest, bool insertSelfLink, size_t* createdArraySize);
+
 #ifdef __cplusplus
 }
 #endif
index 03eb91a..f3f7fed 100644 (file)
@@ -420,7 +420,18 @@ OCTpsSchemeFlags OC_CALL OCGetSupportedEndpointTpsFlags(void);
 OCStackResult OC_CALL OCBindResource(OCResourceHandle collectionHandle, OCResourceHandle resourceHandle);
 
 /**
- * This function removes a resource from a collection resource.
+ * This function adds a resource to a collection or atomic measurement resource.
+ *
+ * @param collectionHandle    Handle to the collection resource.
+ * @param resourceHandle      Handle to resource to be added to the collection resource.
+ * @param isAM                Atomic measurement or regular collection.
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+OCStackResult OC_CALL OCBindResourceAM(OCResourceHandle collectionHandle, OCResourceHandle resourceHandle, bool isAM);
+
+/**
+ * This function removes a resource from a collection or atomic measurement resource.
  *
  * @param collectionHandle   Handle to the collection resource.
  * @param resourceHandle     Handle to resource to be removed from the collection resource.
@@ -439,6 +450,18 @@ OCStackResult OC_CALL OCUnBindResource(OCResourceHandle collectionHandle, OCReso
  */
 OCStackResult OC_CALL OCBindResourceTypeToResource(OCResourceHandle handle,
                                            const char *resourceTypeName);
+
+/**
+ * This function binds a resource type to the rts-m in a resource.
+ * This function should be used only for collection or atomic measurement resources
+ *
+ * @param handle            Handle to the resource.
+ * @param resourceTypeName  Name of resource type.  Example: "core.led".
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+OCStackResult OC_CALL OCBindRtsMToResource(OCResourceHandle handle,
+        const char *resourceTypeName);
 /**
  * This function binds a resource interface to a resource.
  *
@@ -610,6 +633,16 @@ OCResourceHandle OC_CALL OCGetResourceHandleFromCollection(OCResourceHandle coll
  */
 OCEntityHandler OC_CALL OCGetResourceHandler(OCResourceHandle handle);
 
+/**
+ * This function notifies the atomic measurement that a new atomic measurement is available
+ * (because one or more of the values of the resources composing it have changed).
+ *
+ * @param handle            Handle of resource.
+ *
+ * @return OC_STACK_OK on success, some other value upon failure.
+ */
+OCStackResult OC_CALL OCNotifyNewAMAvailable(const OCResourceHandle handle);
+
 /**
  * This function notify all registered observers that the resource representation has
  * changed. If observation includes a query the client is notified only if the query is valid after
index 3116b76..64c4cea 100644 (file)
@@ -13,9 +13,11 @@ convertTriggerEnumToString
 
 FindResourceByUri
 OCBindResource
+OCBindResourceAM
 OCBindResourceHandler
 OCBindResourceInterfaceToResource
 OCBindResourceTypeToResource
+OCBindRtsMToResource
 OCByteStringCopy
 OCCancel
 OCClearResourceProperties
@@ -67,8 +69,10 @@ OCInit
 OCInit1
 OCInit2
 OCLinksPayloadArrayCreate
+OCLinksPayloadArrayCreateAM
 OCNotifyAllObservers
 OCNotifyListOfObservers
+OCNotifyNewAMAvailable
 OCPayloadDestroy
 OCPresencePayloadCreate
 OCPresencePayloadDestroy
diff --git a/resource/csdk/stack/src/ocatomicmeasurement.c b/resource/csdk/stack/src/ocatomicmeasurement.c
new file mode 100644 (file)
index 0000000..6501f43
--- /dev/null
@@ -0,0 +1,806 @@
+//******************************************************************
+//
+// Copyright 2018 Beechwoods Software 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1-2001 base
+// specification (excluding the XSI extension).
+// For POSIX.1-2001 base specification,
+// Refer http://pubs.opengroup.org/onlinepubs/009695399/
+#define _POSIX_C_SOURCE 200112L
+
+#include "ocatomicmeasurement.h"
+#include "ocpayload.h"
+#include "ocendpoint.h"
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "oic_string.h"
+#include "experimental/payload_logging.h"
+#include "cainterface.h"
+#define TAG "OIC_RI_ATOMICMEASUREMENT"
+
+//************************************************************************
+//*                                                                      *
+//* AddRTSBaselinePayload                                                *
+//*                                                                      *
+//*     Add RTS values to the response to the baseline interface request *
+//*                                                                      *
+//************************************************************************
+static bool AddRTSBaselinePayload(OCRepPayload **linkArray, int size, OCRepPayload **amPayload)
+{
+    size_t arraySize = 0;
+    int i;
+    unsigned int j;
+
+    for (i = 0; i < size; i++)
+    {
+        for (OCStringLL *pResType = linkArray[i]->types; pResType; pResType = pResType->next, arraySize++);
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Number of RTS elements : %zd", arraySize);
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {arraySize, 0, 0};
+    char **rts = (char **)OICMalloc(sizeof(char *) * arraySize);
+    if (!rts)
+    {
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    j = 0;
+    for (i = 0; i < size; i++)
+    {
+        for (OCStringLL *pResType = linkArray[i]->types; pResType; pResType = pResType->next)
+        {
+            rts[j++] = OICStrdup(pResType->value);
+        }
+    }
+
+    bool b = OCRepPayloadSetStringArrayAsOwner(*amPayload, OC_RSRVD_RTS, rts, dim);
+
+    if (!b)
+    {
+        for (j = 0; j < arraySize; j++)
+        {
+            OICFree(rts[j]);
+        }
+        OICFree(rts);
+    }
+
+    return b;
+}
+
+//**************************************************************************
+//*                                                                        *
+//* AddRTSMBaselinePayload                                                 *
+//*                                                                        *
+//*     Add RTS-M values to the response to the baseline interface request *
+//*                                                                        *
+//**************************************************************************
+static OCStackResult AddRTSMBaselinePayload(OCResource *amResource, OCRepPayload **amPayload)
+{
+    size_t arraySize = 0;
+    int i = 0;
+
+    for (OCResourceType *rsrcTypeM = amResource->rsrcTypeM; rsrcTypeM; rsrcTypeM = rsrcTypeM->next, arraySize++);
+
+    OIC_LOG_V(DEBUG, TAG, "Number of RTS-M elements : %zd", arraySize);
+
+    if (arraySize > 0)
+    {
+        size_t dim[MAX_REP_ARRAY_DEPTH] = {arraySize, 0, 0};
+        char **rtsm = (char **)OICMalloc(sizeof(char *) * arraySize);
+        if (!rtsm)
+        {
+            OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+            return OC_STACK_NO_MEMORY;
+        }
+
+        for (OCResourceType *rsrcTypeM = amResource->rsrcTypeM; rsrcTypeM; rsrcTypeM = rsrcTypeM->next, i++)
+        {
+            rtsm[i] = OICStrdup(rsrcTypeM->resourcetypename);
+        }
+
+        bool b = OCRepPayloadSetStringArrayAsOwner(*amPayload, OC_RSRVD_RTSM, rtsm, dim);
+
+        if (!b)
+        {
+            for (size_t j = 0; j < arraySize; j++)
+            {
+                OICFree(rtsm[j]);
+            }
+            OICFree(rtsm);
+        }
+
+        return b;
+    }
+    else
+        return OC_STACK_OK;
+}
+
+//***********************************************
+//*                                             *
+//* SendResponse                                *
+//*                                             *
+//*     Send a response to the request received *
+//*                                             *
+//***********************************************
+static OCStackResult SendResponse(const OCRepPayload *payload,
+                        const OCEntityHandlerRequest *ehRequest, OCEntityHandlerResult ehResult)
+{
+    OCEntityHandlerResponse response = {0};
+    response.ehResult = ehResult;
+    response.payload = (OCPayload*)payload;
+    response.persistentBufferFlag = 0;
+    response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+    return OCDoResponse(&response);
+}
+
+//**************************************************************************
+//*                                                                        *
+//* GetNumOfResourcesInAtomicMeasurement                                   *
+//*                                                                        *
+//*     Get the total number of resources composing the atomic measurement *
+//*                                                                        *
+//**************************************************************************
+static uint8_t GetNumOfResourcesInAtomicMeasurement(const OCResource *amResource)
+{
+    uint8_t size = 0;
+    for (OCChildResource *tempChildResource = amResource->rsrcChildResourcesHead;
+        tempChildResource; tempChildResource = tempChildResource->next)
+    {
+        size++;
+    }
+    OIC_LOG_V(DEBUG, TAG, "GetNumOfResourcesInAtomicMeasurement: there are %u resources in the atomic measurement", size);
+    return size;
+}
+
+//*****************************************************************
+//*                                                               *
+//* HandleLinkedListInterface                                     *
+//*                                                               *
+//*     Handler for the linked list (oic.if.ll) interface request *
+//*                                                               *
+//*****************************************************************
+static OCStackResult HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, char *ifQueryParam)
+{
+    if (!ehRequest)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCResource *amResource = (OCResource *)ehRequest->resource;
+    if (!amResource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OIC_LOG(DEBUG, TAG, "Entering HandleLinkedListInterface...");
+
+    uint8_t size = GetNumOfResourcesInAtomicMeasurement(amResource);
+    OCRepPayload *amPayload = NULL;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCStackResult ret = OC_STACK_ERROR;
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {size, 0, 0};
+    OCRepPayload **linkArr = NULL;
+
+    if (!(linkArr = OCLinksPayloadArrayCreateAM(amResource->uri, ehRequest, false, NULL)))
+    {
+        OIC_LOG(ERROR, TAG, "Failed getting LinksPayloadArray");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+
+    if (size < 1)
+    {
+        ret = OC_STACK_NO_RESOURCE;
+        goto exit;
+    }
+
+    OCPayloadFormat contentFormat = OC_FORMAT_UNDEFINED;
+    OCGetRequestPayloadVersion(ehRequest, &contentFormat, NULL);
+    // from the OCF1.0 linklist specification, ll has array of links
+    if ((0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL)) && (contentFormat == OC_FORMAT_VND_OCF_CBOR))
+    {
+        for (int n = 0; n < (int)size - 1; n++)
+        {
+            linkArr[n]->next = linkArr[n + 1];
+        }
+        amPayload = linkArr[0];
+        OICFree(linkArr);
+        ret = OC_STACK_OK;
+        goto exit;
+    }
+    else if ((contentFormat == OC_FORMAT_VND_OCF_CBOR || contentFormat == OC_FORMAT_CBOR))
+    {
+        amPayload = OCRepPayloadCreate();
+        VERIFY_PARAM_NON_NULL(TAG, linkArr, "Failed creating LinksPayloadArray");
+        if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
+        {
+            //TODO : Add resource type filtering once atomic measurements
+            // start supporting queries.
+            OCRepPayloadAddResourceType(amPayload, OC_RSRVD_RESOURCE_TYPE_AM);
+            for (OCResourceType *types = amResource->rsrcType; types; types = types->next)
+            {
+                if (0 != strcmp(OC_RSRVD_RESOURCE_TYPE_AM, types->resourcetypename))
+                {
+                    OCRepPayloadAddResourceType(amPayload, types->resourcetypename);
+                }
+            }
+            for (OCResourceInterface *itf = amResource->rsrcInterface; itf; itf = itf->next)
+            {
+                OCRepPayloadAddInterface(amPayload, itf->name);
+            }
+            AddRTSBaselinePayload(linkArr, size, &amPayload);
+            AddRTSMBaselinePayload(amResource, &amPayload);
+        }
+        OCRepPayloadSetPropObjectArrayAsOwner(amPayload, OC_RSRVD_LINKS, linkArr, dim);
+        ret = OC_STACK_OK;
+    }
+exit:
+    if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL))
+    {
+        OCRepPayloadSetPayloadRepType(amPayload, PAYLOAD_REP_ARRAY);
+    }
+    else
+    {
+        OCRepPayloadSetPayloadRepType(amPayload, PAYLOAD_REP_OBJECT_ARRAY);
+    }
+
+    if (ret == OC_STACK_OK)
+    {
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = (ret == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR;
+    }
+    ret = SendResponse(amPayload, ehRequest, ehResult);
+    OIC_LOG_V(INFO, TAG, "Send Response result from HandleLinkedListInterface = %d", (int)ret);
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)amPayload);
+    OCRepPayloadDestroy(amPayload);
+
+    return ret;
+}
+
+//**********************************************************
+//*                                                        *
+//* HandleBatchInterface                                   *
+//*                                                        *
+//*     Handler for the batch (oic.if.b) interface request *
+//*                                                        *
+//**********************************************************
+static OCStackResult HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
+{
+    if (!ehRequest)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCStackResult stackRet = OC_STACK_OK;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+    char *storeQuery = NULL;
+    OCResource *amResource = (OCResource *)ehRequest->resource;
+
+    if (amResource->rsrcChildResourcesHead)
+    {
+        storeQuery = ehRequest->query;
+        ehRequest->query = NULL;
+        OIC_LOG_V(DEBUG, TAG, "Query : %s", ehRequest->query);
+    }
+
+    uint8_t numRes = 0;
+    for (OCChildResource *tempChildResource = amResource->rsrcChildResourcesHead;
+        tempChildResource; tempChildResource = tempChildResource->next, numRes++)
+    {
+        OCResource* tempRsrcResource = tempChildResource->rsrcResource;
+        if (tempRsrcResource)
+        {
+            // Note that all entity handlers called through an atomic measurement
+            // will get the same pointer to ehRequest, the only difference
+            // is ehRequest->resource
+            ehRequest->resource = (OCResourceHandle) tempRsrcResource;
+            ehResult = tempRsrcResource->amEntityHandler(OC_REQUEST_FLAG,
+                                       ehRequest, tempRsrcResource->entityHandlerCallbackParam);
+
+            // atomic measurement doesn't handle slow resources!
+            if (ehResult == OC_EH_SLOW)
+            {
+                OIC_LOG(ERROR, TAG, "This is a slow resource, can not be handled in atomic measurement!");
+                ehResult = OC_EH_INTERNAL_SERVER_ERROR;
+            }
+            if (ehResult != OC_EH_OK)
+            {
+                OIC_LOG_V(ERROR, TAG, "Error while retrieving measurement from a resource in an atomic measurement (error = %d)!", ehResult);
+                stackRet = EntityHandlerCodeToOCStackCode(ehResult);
+                break;
+            }
+        }
+        else
+        {
+            // One of the resources in the atomic measurement does not have a resource handler!
+            OIC_LOG(ERROR, TAG, "One of the resources in the atomic measurement does not have a resource handler!!");
+            ehResult = OC_EH_INTERNAL_SERVER_ERROR;
+            stackRet = EntityHandlerCodeToOCStackCode(ehResult);
+            break;
+        }
+    }
+    ehRequest->resource = (OCResourceHandle) amResource;
+    ehRequest->query = storeQuery;
+    return stackRet;
+}
+
+//****************************************************************************************
+//*                                                                                      *
+//* DefaultAtomicMeasurementEntityHandler                                                *
+//*                                                                                      *
+//*     This function is the default entity handler for the atomic measurement resource. *
+//*     It deals with all the queries coming to the atomic measurement, and controls the *
+//*     response from the atomic measurement. It interfaces with and controls all the    *
+//*     individual resources that belong to it.                                          *
+//*                                                                                      *
+//****************************************************************************************
+OCStackResult DefaultAtomicMeasurementEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *ehRequest)
+{
+    (void) flag;
+
+    if (!ehRequest || !ehRequest->query)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OIC_LOG_V(INFO, TAG, "DefaultAtomicMeasurementEntityHandler with query %s", ehRequest->query);
+
+    char *ifQueryParam = NULL;
+    char *rtQueryParam = NULL;
+    OCStackResult result = ExtractFiltersFromQuery(ehRequest->query, &ifQueryParam, &rtQueryParam);
+    if (result != OC_STACK_OK)
+    {
+        return OC_STACK_NO_RESOURCE;
+    }
+
+    // Delete is not supported for any interface query method.
+    if (ehRequest->method == OC_REST_DELETE)
+    {
+        result = OC_STACK_ERROR;
+        goto exit;
+    }
+
+    // If a rt filter is received, send back FORBIDDEN, as per the spec 
+    if (rtQueryParam)
+    {
+        result = OC_STACK_FORBIDDEN_REQ;
+        goto exit;
+    }
+
+    // Default interface for atomic measurement is batch
+    if (!ifQueryParam)
+    {
+        ifQueryParam = OICStrdup(OC_RSRVD_INTERFACE_BATCH);
+    }
+
+    VERIFY_PARAM_NON_NULL(TAG, ifQueryParam, "Invalid Parameter ifQueryParam");
+
+    if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) || 0 == strcmp (ifQueryParam, OC_RSRVD_INTERFACE_DEFAULT))
+    {
+        if (ehRequest->method == OC_REST_PUT || ehRequest->method == OC_REST_POST)
+        {
+            result =  OC_STACK_ERROR;
+        }
+        else
+        {
+            result = HandleLinkedListInterface(ehRequest, ifQueryParam);
+        }
+    }
+    else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_BATCH))
+    {
+        if (ehRequest->method != OC_REST_GET)
+        {
+            result =  OC_STACK_INVALID_METHOD;
+        }
+        else
+        {
+            OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
+            if (request)
+            {
+                request->numResponses = GetNumOfResourcesInAtomicMeasurement((OCResource *)ehRequest->resource);
+                request->ehResponseHandler = HandleAggregateResponse;
+                result = HandleBatchInterface(ehRequest);
+            }
+        }
+    }
+
+exit:
+    if (result != OC_STACK_OK)
+    {
+        if (result == OC_STACK_ERROR)
+            result = OC_STACK_INVALID_QUERY;
+        result = SendResponse(NULL, ehRequest, OCStackCodeToEntityHandlerCode(result));
+    }
+    OICFree(ifQueryParam);
+    OICFree(rtQueryParam);
+    return result;
+}
+
+//***************************************************************************************
+//*                                                                                     *
+//* DefaultAtomicMeasurementResourceEntityHandler                                       *
+//*                                                                                     *
+//*     This function is the default entity handler for the individual resources member *
+//*     of an atomic measurement. The atomic measurement substitutes this handler to    *
+//*     each of its individual resources' entity handler, in order to correctly control *
+//*     and process atomic measurement, and implement its restrictions.                 *
+//*                                                                                     *
+//***************************************************************************************
+OCEntityHandlerResult DefaultAtomicMeasurementResourceEntityHandler(OCEntityHandlerFlag flag,
+    OCEntityHandlerRequest *ehRequest, void *ehCallbackParam)
+{
+    OCEntityHandlerResult ret = OC_EH_OK;
+
+    // Those parameters are unused
+    (void) flag;
+    (void) ehCallbackParam;
+
+    if (!ehRequest || !ehRequest->query)
+    {
+        ret = OC_EH_ERROR;
+    }
+    else
+    {
+        // Individual requests to resources member of an AM are forbidden
+        if (SendResponse(NULL, ehRequest, OC_EH_FORBIDDEN) != OC_STACK_OK)
+            ret = OC_EH_ERROR;
+    }
+
+    return ret;
+}
+
+//**************************************************************************************
+//*                                                                                    *
+//* NewAtomicMeasurementReadyNotificationHandler                                       *
+//*                                                                                    *
+//*     This function notifies the atomic measurement that a new measurement is ready. *
+//*     This notification will trigger the atomic measurement sending GET requests to  *
+//*     all the individual resources composing it.                                     *
+//*                                                                                    *
+//**************************************************************************************
+OCStackResult NewAtomicMeasurementReadyNotificationHandler(const OCResourceHandle amResourceHandle)
+{
+    OCStackResult result;
+
+    if (amResourceHandle == NULL)
+    {
+        OIC_LOG(ERROR, TAG, "NewAtomicMeasurementReadyNotificationHandler: invalid resource handle!");
+        result = OC_STACK_ERROR;
+    }
+    else
+    {
+        if (((OCResource *)amResourceHandle)->observersHead != NULL)
+        {
+            if ((result = OCNotifyAllObservers(amResourceHandle, OC_NA_QOS)) == OC_STACK_OK)
+            {
+                OIC_LOG(DEBUG, TAG, "NewAtomicMeasurementReadyNotificationHandler: OCNotifyAllObservers succeeded...");
+            }
+            else
+            {
+                OIC_LOG(ERROR, TAG, "NewAtomicMeasurementReadyNotificationHandler: OCNotifyAllObservers failed!");
+            }
+        }
+        else
+        {
+            OIC_LOG(DEBUG, TAG, "NewAtomicMeasurementReadyNotificationHandler: no observer registered, don't call OCNotifyAllObservers...");
+            result = OC_STACK_NO_OBSERVERS;
+        }
+    }
+
+    return result;
+}
+
+//**************************************************************************************************
+//*                                                                                                *
+//* addPolicyPayload                                                                               *
+//*                                                                                                *
+//*     Add the security values to the response to the baseline and linked list interface requests *
+//*                                                                                                *
+//**************************************************************************************************
+static bool addPolicyPayload(OCResourceHandle* resourceHandle, OCDevAddr* devAddr,
+                             bool isOCFContentFormat, OCRepPayload** outPolicy)
+{
+    if (resourceHandle == NULL || devAddr == NULL || outPolicy == NULL)
+    {
+        return false;
+    }
+
+    OCResourceProperty p = OCGetResourceProperties(resourceHandle);
+    OCRepPayload* policy = OCRepPayloadCreate();
+    if (policy)
+    {
+        OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
+        if (!isOCFContentFormat)
+        {
+            OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
+
+            if (p & OC_SECURE)
+            {
+                uint16_t securePort = 0;
+                if (devAddr)
+                {
+                    if (devAddr->adapter == OC_ADAPTER_IP)
+                    {
+                        if (devAddr->flags & OC_IP_USE_V6)
+                        {
+                            securePort = caglobals.ip.u6s.port;
+                        }
+                        else if (devAddr->flags & OC_IP_USE_V4)
+                        {
+                            securePort = caglobals.ip.u4s.port;
+                        }
+                    }
+                }
+                OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
+
+#if defined(TCP_ADAPTER) && defined(__WITH_TLS__)
+                // tls
+                if (devAddr)
+                {
+                    uint16_t tlsPort = 0;
+                    GetTCPPortInfo(devAddr, &tlsPort, true);
+                    OCRepPayloadSetPropInt(policy, OC_RSRVD_TLS_PORT, tlsPort);
+                }
+#endif
+            }
+#ifdef TCP_ADAPTER
+#ifdef  __WITH_TLS__
+            if (!(p & OC_SECURE))
+            {
+#endif
+                // tcp
+                if (devAddr)
+                {
+                    uint16_t tcpPort = 0;
+                    GetTCPPortInfo(devAddr, &tcpPort, false);
+                    OCRepPayloadSetPropInt(policy, OC_RSRVD_TCP_PORT, tcpPort);
+                }
+#ifdef  __WITH_TLS__
+            }
+#endif
+#endif
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    *outPolicy = policy;
+    return true;
+}
+
+//**************************************************************************************************
+//*                                                                                                *
+//* translateEndpointsPayload                                                                      *
+//*                                                                                                *
+//*     Add the endpoint values to the response to the baseline and linked list interface requests *
+//*                                                                                                *
+//**************************************************************************************************
+static bool translateEndpointsPayload(OCEndpointPayload* epPayloadOrg,
+                                      size_t size, OCRepPayload*** outArrayPayload)
+{
+    bool result = false;
+    OCRepPayload** arrayPayload = (OCRepPayload**)OICMalloc(sizeof(OCRepPayload*) * (size));
+    VERIFY_PARAM_NON_NULL(TAG, arrayPayload, "Failed creating arrayPayload");
+    VERIFY_PARAM_NON_NULL(TAG, epPayloadOrg, "Invalid Parameter epPayload");
+    VERIFY_PARAM_NON_NULL(TAG, outArrayPayload, "Invalid Parameter outArrayPayload");
+    OCEndpointPayload* epPayload = epPayloadOrg;
+
+    for (size_t i = 0; (i < size) && (epPayload != NULL) ; i++)
+    {
+        arrayPayload[i] = OCRepPayloadCreate();
+        if (!arrayPayload[i])
+        {
+            for (size_t j = 0; j < i; j++)
+            {
+                OCRepPayloadDestroy(arrayPayload[j]);
+            }
+            result = false;
+            goto exit;
+        }
+        char* createdEPStr = OCCreateEndpointString(epPayload);
+        OIC_LOG_V(DEBUG, TAG, " OCCreateEndpointString() = %s", createdEPStr);
+        OCRepPayloadSetPropString(arrayPayload[i], OC_RSRVD_ENDPOINT, createdEPStr);
+        OICFree(createdEPStr);
+
+        // in case of pri as 1, skip set property
+        if (epPayload->pri != 1 )
+            OCRepPayloadSetPropInt(arrayPayload[i], OC_RSRVD_PRIORITY, epPayload->pri);
+
+        epPayload = epPayload->next;
+        result = true;
+    }
+    *outArrayPayload = arrayPayload;
+exit:
+    OCEndpointPayloadDestroy(epPayloadOrg);
+    if (result == false)
+    {
+        OICFree(arrayPayload);
+    }
+    return result;
+}
+
+//****************************************************************************************
+//*                                                                                      *
+//* BuildAtomicMeasurementLinksPayloadArray                                              *
+//*                                                                                      *
+//*     Create the RepPayloadArray for links parameter of an atomic measurement resource *
+//*                                                                                      *
+//****************************************************************************************
+OCRepPayload** BuildAtomicMeasurementLinksPayloadArray(const char* resourceUri,
+    bool isOCFContentFormat, OCDevAddr* devAddr, bool insertSelfLink, size_t* createdArraySize)
+{
+    bool result = false;
+    OCRepPayload** arrayPayload = NULL;
+    size_t childCount = 0;
+
+    const OCResourceHandle amResourceHandle = OCGetResourceHandleAtUri(resourceUri);
+    VERIFY_PARAM_NON_NULL(TAG, amResourceHandle, "Failed geting amResourceHandle");
+
+    const OCChildResource* childResource = ((OCResource*)amResourceHandle)->rsrcChildResourcesHead;
+    VERIFY_PARAM_NON_NULL(TAG, childResource, "Failed geting childResource");
+
+    //children resources count calculation
+    const OCChildResource* childCountResource = childResource;
+    do {
+        childCount++;
+        childCountResource = childCountResource->next;
+    } while (childCountResource);
+
+    if (insertSelfLink)
+    {
+        childCount++;
+    }
+
+    arrayPayload = (OCRepPayload**)OICMalloc(sizeof(OCRepPayload*) * (childCount));
+    VERIFY_PARAM_NON_NULL(TAG, arrayPayload, "Failed creating arrayPayload");
+
+    OCResource* iterResource = childResource->rsrcResource;
+    for (size_t i = 0; i < childCount; i++)
+    {
+        arrayPayload[i] = OCRepPayloadCreate();
+        if (!arrayPayload[i])
+        {
+            for (size_t j = 0; j < i; j++)
+            {
+                OCRepPayloadDestroy(arrayPayload[j]);
+            }
+            result = false;
+            goto exit;
+        }
+
+        OCRepPayloadSetUri(arrayPayload[i], iterResource->uri);
+
+        for (OCResourceType* resType = iterResource->rsrcType; resType;
+            resType = resType->next)
+        {
+            OCRepPayloadAddResourceType(arrayPayload[i], resType->resourcetypename);
+        }
+
+        for (OCResourceInterface* resInterface = iterResource->rsrcInterface; resInterface;
+                                  resInterface = resInterface->next)
+        {
+            OCRepPayloadAddInterface(arrayPayload[i], resInterface->name);
+        }
+
+        OCRepPayload* outPolicy = NULL;
+        //Policy Map will have tls and tcp properties for legacy support,
+        // in case contents format is cbor instead of vnd.ocf/cbor
+        if (!addPolicyPayload((OCResourceHandle*)iterResource, devAddr, isOCFContentFormat,
+                               &outPolicy) ||
+            !OCRepPayloadSetPropObjectAsOwner(arrayPayload[i], OC_RSRVD_POLICY, outPolicy))
+        {
+            OCRepPayloadDestroy(outPolicy);
+            for (size_t j = 0; j <= i; j++)
+            {
+                OCRepPayloadDestroy(arrayPayload[j]);
+            }
+            result = false;
+            goto exit;
+        }
+
+        //EP is added in case contents format is vnd.ocf/cbor
+        if (isOCFContentFormat)
+        {
+            CAEndpoint_t *info = NULL;
+            size_t networkSize = 0;
+            size_t epSize = 0;
+            CAGetNetworkInformation(&info, &networkSize);
+            OIC_LOG_V(DEBUG, TAG, "Network Information size = %d", (int) networkSize);
+
+            OCEndpointPayload *listHead = NULL;
+            CreateEndpointPayloadList(iterResource,
+                devAddr, info, networkSize, &listHead, &epSize, NULL);
+            OICFree(info);
+            OIC_LOG_V(DEBUG, TAG, "Result of CreateEndpointPayloadList() = %s",
+                                  listHead ? "true":"false");
+
+            OCRepPayload** epArrayPayload = NULL;
+            size_t epsDim[MAX_REP_ARRAY_DEPTH] = { epSize, 0, 0 };
+
+            if (!translateEndpointsPayload(listHead, epSize, &epArrayPayload) ||
+                !OCRepPayloadSetPropObjectArrayAsOwner(arrayPayload[i],
+                            OC_RSRVD_ENDPOINTS, epArrayPayload, epsDim))
+            {
+                if (epArrayPayload)
+                {
+                    for (size_t j = 0; j < epSize; j++)
+                    {
+                        OCRepPayloadDestroy(epArrayPayload[j]);
+                    }
+                    OICFree(epArrayPayload);
+                }
+
+                for (size_t j = 0; j <= i; j++)
+                {
+                    OCRepPayloadDestroy(arrayPayload[j]);
+                }
+                result = false;
+                goto exit;
+            }
+        }
+
+        if (iterResource != amResourceHandle)
+        {
+            childResource = childResource->next;
+            if (childResource)
+            {
+                iterResource = childResource->rsrcResource;
+            }
+            else if (insertSelfLink)
+            {
+                iterResource = amResourceHandle;
+            }
+        }
+        else // handling selfLink case
+        {
+            OIC_LOG(INFO, TAG, "adding rel for self link");
+            const char* relArray[2] = { "self", "item" };
+            size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 2, 0, 0 };
+            if (!OCRepPayloadSetStringArray(arrayPayload[i], OC_RSRVD_REL, relArray, dimensions))
+            {
+                OIC_LOG(ERROR, TAG, "Failed setting rel property");
+                result = false;
+                goto exit;
+            }
+        }
+        result = true;
+    }
+
+exit:
+    if (!result && (arrayPayload != NULL))
+    {
+        OICFree(arrayPayload);
+        arrayPayload = NULL;
+    }
+
+    if (arrayPayload != NULL && createdArraySize != NULL)
+        *createdArraySize = childCount;
+    else if (createdArraySize != NULL)
+        *createdArraySize = 0;
+
+    return arrayPayload;
+}
index 6b0b3df..2d62a7f 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include "ocpayload.h"
 #include "occollection.h"
+#include "ocatomicmeasurement.h"
 #include "octypes.h"
 #include <string.h>
 #include "oic_malloc.h"
@@ -1619,13 +1620,17 @@ OCRepPayload* OC_CALL OCRepPayloadClone (const OCRepPayload* payload)
 
 OCRepPayload* OC_CALL OCRepPayloadBatchClone(const OCRepPayload* repPayload)
 {
+    OIC_LOG(DEBUG, TAG, "Entering OCRepPayloadBatchClone...");
+
     OCRepPayload *newPayload = OCRepPayloadCreate();
     if (!newPayload)
     {
         return NULL;
     }
 
-    newPayload->uri = OICStrdup(repPayload->uri);
+    OCRepPayloadSetPropString(newPayload, OC_RSRVD_HREF, OICStrdup(repPayload->uri));
+    OIC_LOG_V(DEBUG, TAG, "OCRepPayloadBatchClone: URI of the payload is %s!", repPayload->uri);
+
     OCRepPayload *clone = OCRepPayloadCreate();
     if (!clone)
     {
@@ -1637,6 +1642,7 @@ OCRepPayload* OC_CALL OCRepPayloadBatchClone(const OCRepPayload* repPayload)
     clone->repType = repPayload->repType;
     clone->interfaces  = CloneOCStringLL(repPayload->interfaces);
     clone->values = OCRepPayloadValueClone(repPayload->values);
+
     OCRepPayloadSetPropObjectAsOwner(newPayload, OC_RSRVD_REPRESENTATION, clone);
 
     return newPayload;
@@ -2269,7 +2275,7 @@ void OC_CALL OCEndpointPayloadDestroy(OCEndpointPayload* payload)
 OCRepPayload** OC_CALL OCLinksPayloadArrayCreate(const char* resourceUri,
                        OCEntityHandlerRequest *ehRequest, bool insertSelfLink, size_t* createdArraySize)
 {
-    OIC_LOG(DEBUG, TAG, "OCLinksPayloadValueCreate");
+    OIC_LOG(DEBUG, TAG, "OCLinksPayloadArrayCreate");
     OCRepPayload** linksRepPayloadArray = NULL;
     if ((resourceUri != NULL) && (ehRequest != NULL))
     {
@@ -2287,6 +2293,27 @@ OCRepPayload** OC_CALL OCLinksPayloadArrayCreate(const char* resourceUri,
     return linksRepPayloadArray;
 }
 
+OCRepPayload** OC_CALL OCLinksPayloadArrayCreateAM(const char* resourceUri,
+                       OCEntityHandlerRequest *ehRequest, bool insertSelfLink, size_t* createdArraySize)
+{
+    OIC_LOG(DEBUG, TAG, "OCLinksPayloadArrayCreateAM");
+    OCRepPayload** linksRepPayloadArray = NULL;
+    if ((resourceUri != NULL) && (ehRequest != NULL))
+    {
+        OCPayloadFormat contentFormat = OC_FORMAT_UNDEFINED;
+        if ((OC_STACK_OK != OCGetRequestPayloadVersion(ehRequest, &contentFormat, NULL)) &&
+            (contentFormat == OC_FORMAT_VND_OCF_CBOR || contentFormat == OC_FORMAT_CBOR))
+            return NULL;
+
+        linksRepPayloadArray = BuildAtomicMeasurementLinksPayloadArray(resourceUri, contentFormat, &ehRequest->devAddr,
+            insertSelfLink, createdArraySize);
+
+        OIC_LOG_V(DEBUG, TAG, "return value of BuildAtomicMeasurementLinksPayloadArray() = %s",
+                 (linksRepPayloadArray != NULL) ? "true" : "false");
+    }
+    return linksRepPayloadArray;
+}
+
 OCStackResult OC_CALL OCGetRequestPayloadVersion(OCEntityHandlerRequest *ehRequest,
                                   OCPayloadFormat* pContentFormat, uint16_t* pAcceptVersion)
 {
index 06f8646..71c07bf 100644 (file)
@@ -43,6 +43,7 @@
 #include "ocresourcehandler.h"
 #include "ocobserve.h"
 #include "occollection.h"
+#include "ocatomicmeasurement.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 #include "experimental/logger.h"
@@ -1424,16 +1425,32 @@ OCStackResult DetermineResourceHandling (const OCServerRequest *request,
 
         if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
         {
-            // Collection resource
-            if (resourcePtr->entityHandler != defaultResourceEHandler)
+            // Collection or AM resource
+            if (resourcePtr->rsrcIsAtomicMeasurement)
             {
-                *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
-                return OC_STACK_OK;
+                if (resourcePtr->entityHandler != defaultResourceEHandler)
+                {
+                    *handling = OC_RESOURCE_AM_WITH_ENTITYHANDLER;
+                    return OC_STACK_OK;
+                }
+                else
+                {
+                    *handling = OC_RESOURCE_AM_DEFAULT_ENTITYHANDLER;
+                    return OC_STACK_OK;
+                }
             }
             else
             {
-                *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
-                return OC_STACK_OK;
+                if (resourcePtr->entityHandler != defaultResourceEHandler)
+                {
+                    *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
+                    return OC_STACK_OK;
+                }
+                else
+                {
+                    *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
+                    return OC_STACK_OK;
+                }
             }
         }
         else
@@ -1519,6 +1536,70 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
     return result;
 }
 
+OCEntityHandlerResult OCStackCodeToEntityHandlerCode(OCStackResult result)
+{
+    OCStackResult ehResult;
+
+    switch (result)
+    {
+        case OC_STACK_OK:
+            ehResult = OC_EH_OK;
+            break;
+        case OC_STACK_SLOW_RESOURCE:
+            ehResult = OC_EH_SLOW;
+            break;
+        case OC_STACK_ERROR:
+            ehResult = OC_EH_ERROR;
+            break;
+        case OC_STACK_FORBIDDEN_REQ:
+            ehResult = OC_EH_FORBIDDEN;
+            break;
+        case OC_STACK_INTERNAL_SERVER_ERROR:
+            ehResult = OC_EH_INTERNAL_SERVER_ERROR;
+            break;
+        case OC_STACK_RESOURCE_CREATED:
+            ehResult = OC_EH_RESOURCE_CREATED;
+            break;
+        case OC_STACK_RESOURCE_DELETED:
+            ehResult = OC_EH_RESOURCE_DELETED;
+            break;
+        case OC_STACK_RESOURCE_CHANGED:
+            ehResult = OC_EH_CHANGED;
+            break;
+        case OC_STACK_NO_RESOURCE:
+            ehResult = OC_EH_RESOURCE_NOT_FOUND;
+            break;
+        case OC_STACK_INVALID_QUERY:
+            ehResult = OC_EH_BAD_REQ;
+            break;
+        case OC_STACK_UNAUTHORIZED_REQ:
+            ehResult = OC_EH_UNAUTHORIZED_REQ;
+            break;
+        case OC_STACK_INVALID_OPTION:
+            ehResult = OC_EH_BAD_OPT;
+            break;
+        case OC_STACK_INVALID_METHOD:
+            ehResult = OC_EH_METHOD_NOT_ALLOWED;
+            break;
+        case OC_STACK_NOT_ACCEPTABLE:
+            ehResult = OC_EH_NOT_ACCEPTABLE;
+            break;
+        case OC_STACK_TOO_LARGE_REQ:
+            ehResult = OC_EH_TOO_LARGE;
+            break;
+        case OC_STACK_SERVICE_UNAVAILABLE:
+            ehResult = OC_EH_SERVICE_UNAVAILABLE;
+            break;
+        case OC_STACK_COMM_ERROR:
+            ehResult = OC_EH_RETRANSMIT_TIMEOUT;
+            break;
+        default:
+            ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
 {
     if (!resource)
@@ -2349,6 +2430,134 @@ static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerReques
     return result;
 }
 
+static OCStackResult HandleAMResourceDefaultEntityHandler(OCServerRequest *request,
+                                                          OCResource *resource)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
+    ResourceObserver *resObs = NULL;
+    OCEntityHandlerRequest ehRequest = {0};
+
+    if (!request || !resource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
+    VERIFY_SUCCESS(result);
+
+    if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
+    {
+        OIC_LOG(INFO, TAG, "HandleAMResourceDefaultEntityHandler: no observation requested");
+        ehFlag = OC_REQUEST_FLAG;
+    }
+    else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
+    {
+        OIC_LOG(INFO, TAG, "HandleAMResourceDefaultEntityHandler: observation registration requested");
+
+        ResourceObserver *obs = GetObserverUsingToken(resource,
+                                                      request->requestToken, request->tokenLength);
+
+        if (obs)
+        {
+            OIC_LOG (INFO, TAG, "Observer with this token already present");
+            OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
+            OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
+            OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
+
+            // server requests are usually free'd when the response is sent out
+            // for the request in ocserverrequest.c : HandleSingleResponse()
+            // Since we are making an early return and not responding, the server request
+            // needs to be deleted.
+            DeleteServerRequest (request);
+            return OC_STACK_OK;
+        }
+
+        result = GenerateObserverId(&ehRequest.obsInfo.obsId);
+        VERIFY_SUCCESS(result);
+
+        result = AddObserver ((const char*)(request->resourceUrl),
+                (const char *)(request->query),
+                ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
+                resource, request->qos, request->acceptFormat,
+                request->acceptVersion, &request->devAddr);
+
+        if(result == OC_STACK_OK)
+        {
+            OIC_LOG(INFO, TAG, "HandleAMResourceDefaultEntityHandler: added observer successfully");
+            request->observeResult = OC_STACK_OK;
+            ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
+        }
+        else if (result == OC_STACK_RESOURCE_ERROR)
+        {
+            OIC_LOG(INFO, TAG, "HandleAMResourceDefaultEntityHandler: the Resource is not active, discoverable or observable");
+            request->observeResult = OC_STACK_ERROR;
+            ehFlag = OC_REQUEST_FLAG;
+        }
+        else
+        {
+            // The error in observeResult for the request will be used when responding to this
+            // request by omitting the observation option/sequence number.
+            request->observeResult = OC_STACK_ERROR;
+            OIC_LOG(ERROR, TAG, "HandleAMResourceDefaultEntityHandler: observer Addition failed");
+            ehFlag = OC_REQUEST_FLAG;
+            DeleteServerRequest(request);
+            goto exit;
+        }
+    }
+    else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
+    {
+        OIC_LOG(INFO, TAG, "HandleAMResourceDefaultEntityHandler: deregistering observation requested");
+
+        resObs = GetObserverUsingToken (resource,
+                                        request->requestToken, request->tokenLength);
+
+        if (NULL == resObs)
+        {
+            // Stack does not contain this observation request
+            // Either token is incorrect or observation list is corrupted
+            result = OC_STACK_ERROR;
+            goto exit;
+        }
+        ehRequest.obsInfo.obsId = resObs->observeId;
+        ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
+
+        result = DeleteObserverUsingToken (resource,
+                                           request->requestToken, request->tokenLength);
+
+        if(result == OC_STACK_OK)
+        {
+            OIC_LOG(INFO, TAG, "Removed observer successfully");
+            request->observeResult = OC_STACK_OK;
+            // There should be no observe option header for de-registration response.
+            // Set as an invalid value here so we can detect it later and remove the field in response.
+            request->observationOption = MAX_SEQUENCE_NUMBER + 1;
+        }
+        else
+        {
+            request->observeResult = OC_STACK_ERROR;
+            OIC_LOG(ERROR, TAG, "Observer Removal failed");
+            DeleteServerRequest(request);
+            goto exit;
+        }
+    }
+    else
+    {
+        result = OC_STACK_ERROR;
+        goto exit;
+    }
+
+    result = DefaultAtomicMeasurementEntityHandler(ehFlag, &ehRequest);
+    if(result == OC_STACK_ERROR)
+    {
+        DeleteServerRequest(request);
+    }
+
+exit:
+    OCPayloadDestroy(ehRequest.payload);
+    return result;
+}
+
 OCStackResult
 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
 {
@@ -2386,6 +2595,16 @@ ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerReque
             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
             break;
         }
+        case OC_RESOURCE_AM_WITH_ENTITYHANDLER:
+        {
+            ret = HandleResourceWithEntityHandler (request, resource);
+            break;
+        }
+        case OC_RESOURCE_AM_DEFAULT_ENTITYHANDLER:
+        {
+            ret = HandleAMResourceDefaultEntityHandler (request, resource);
+            break;
+        }
         case OC_RESOURCE_NOT_SPECIFIED:
         {
             ret = OC_STACK_NO_RESOURCE;
index 6e3e85a..7bd6564 100644 (file)
@@ -846,16 +846,18 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
     }
 
     OIC_LOG(INFO, TAG, "Inside HandleAggregateResponse");
+    OIC_LOG_V(DEBUG, TAG, "HandleAggregateResponse: resource uri is %s!", ehResponse->resourceUri);
 
     OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
     OCServerResponse *serverResponse = GetServerResponseUsingHandle((OCServerRequest *)
                                                                     ehResponse->requestHandle);
-
     OCStackResult stackRet = OC_STACK_ERROR;
     if(serverRequest)
     {
         if(!serverResponse)
         {
+            OIC_LOG_V(DEBUG, TAG, "HandleAggregateResponse: resource uri (serverRequest) is %s!", serverRequest->resourceUrl);
+
             OIC_LOG(INFO, TAG, "This is the first response fragment");
             stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
             if (OC_STACK_OK != stackRet)
@@ -873,7 +875,14 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
             goto exit;
         }
 
+        if (ehResponse->payload)
+            ((OCRepPayload *)ehResponse->payload)->uri = OICStrdup(ehResponse->resourceUri);
         OCRepPayload *newPayload = OCRepPayloadBatchClone((OCRepPayload *)ehResponse->payload);
+        if (ehResponse->payload)
+        {
+            OICFree(((OCRepPayload *)ehResponse->payload)->uri);
+            ((OCRepPayload *)ehResponse->payload)->uri = NULL;
+        }
 
         OCRepPayloadSetPayloadRepType(newPayload, PAYLOAD_REP_ARRAY);
 
index 092e87b..91cbb8e 100644 (file)
@@ -73,6 +73,7 @@
 #include "platform_features.h"
 #include "oic_platform.h"
 #include "caping.h"
+#include "ocatomicmeasurement.h"
 
 #ifdef UWP_APP
 #include "ocsqlite3helper.h"
@@ -228,7 +229,7 @@ static void insertResource(OCResource *resource);
 static OCResource *findResource(OCResource *resource);
 
 /**
- * Insert a resource type into a resource's resource type linked list.
+ * Insert a resource type into a resource's resource type or rts-m linked list.
  * If resource type already exists, it will not be inserted and the
  * resourceType will be free'd.
  * resourceType->next should be null to avoid memory leaks.
@@ -236,9 +237,11 @@ static OCResource *findResource(OCResource *resource);
  *
  * @param resource Resource where resource type is to be inserted.
  * @param resourceType Resource type to be inserted.
+ * @param isRtsM Resource type to be inserted in rts-m or resource type linked list.
  */
 static void insertResourceType(OCResource *resource,
-        OCResourceType *resourceType);
+        OCResourceType *resourceType,
+        bool isRtsM);
 
 /**
  * Get a resource type at the specified index within a resource.
@@ -482,6 +485,17 @@ static OCStackResult OCInitializeInternal(OCMode mode, OCTransportFlags serverFl
  */
 static OCStackResult OCDeInitializeInternal(void);
 
+/**
+ * Bind a resource type to a resource.
+ *
+ * @param resource Target resource.
+ * @param resourceTypeName Name of resource type.
+ * @param isRtsM Bind to rts-m or resource type linked list.
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+static OCStackResult BindResourceTypeToResource(OCResource* resource,
+    const char *resourceTypeName, bool isRtsM);
+
 //-----------------------------------------------------------------------------
 // Internal functions
 //-----------------------------------------------------------------------------
@@ -4251,7 +4265,7 @@ OCStackResult OC_CALL OCCreateResourceWithEp(OCResourceHandle *handle,
             | OC_ACTIVE);
 
     // Add the resourcetype to the resource
-    result = BindResourceTypeToResource(pointer, resourceTypeName);
+    result = BindResourceTypeToResource(pointer, resourceTypeName, false);
     if (result != OC_STACK_OK)
     {
         OIC_LOG(ERROR, TAG, "Error adding resourcetype");
@@ -4286,9 +4300,19 @@ OCStackResult OC_CALL OCCreateResourceWithEp(OCResourceHandle *handle,
         pointer->entityHandlerCallbackParam = NULL;
     }
 
-    // Initialize a pointer indicating child resources in case of collection
+    // Initialize an entity handler in case of atomic measurement, to store the entity handler of the resource
+    // when it's added to an atomic measurement
+    pointer->amEntityHandler = NULL;
+
+    // Initialize a pointer indicating child resources in case of collection or atomic measurement
     pointer->rsrcChildResourcesHead = NULL;
 
+    // Initialize a pointer indicating rts-m in case of collection or atomic measurement
+    pointer->rsrcTypeM = NULL;
+
+    // Initialize a boolean indicating if this resource is an atomic measurement
+    pointer->rsrcIsAtomicMeasurement = false;
+
     // Initialize a pointer indicating observers to this resource
     pointer->observersHead = NULL;
 
@@ -4313,35 +4337,65 @@ exit:
 
 OCStackResult OC_CALL OCBindResource(
         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
+{
+    return OCBindResourceAM(collectionHandle, resourceHandle, false);
+}
+
+OCStackResult OC_CALL OCBindResourceAM(
+        OCResourceHandle amcolHandle, OCResourceHandle resourceHandle, bool isAM)
 {
     OCResource *resource = NULL;
     OCChildResource *tempChildResource = NULL;
     OCChildResource *newChildResource = NULL;
+    bool isFirstInAmCol;
+    OCStackResult result = OC_STACK_ERROR;
 
     OIC_LOG(INFO, TAG, "Entering OCBindResource");
 
     // Validate parameters
-    VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
+    VERIFY_NON_NULL(amcolHandle, ERROR, OC_STACK_ERROR);
     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
     // Container cannot contain itself
-    if (collectionHandle == resourceHandle)
+    if (amcolHandle == resourceHandle)
     {
-        OIC_LOG(ERROR, TAG, "Added handle equals collection handle");
+        if (isAM)
+        {
+            OIC_LOG(ERROR, TAG, "Added handle equals atomic measurement handle");
+        }
+        else
+        {
+            OIC_LOG(ERROR, TAG, "Added handle equals collection handle");
+        }
         return OC_STACK_INVALID_PARAM;
     }
 
     // Use the handle to find the resource in the resource linked list
-    resource = findResource((OCResource *) collectionHandle);
+    resource = findResource((OCResource *) amcolHandle);
     if (!resource)
     {
-        OIC_LOG(ERROR, TAG, "Collection handle not found");
+        if (isAM)
+        {
+            OIC_LOG(ERROR, TAG, "atomic measurement handle not found");
+        }
+        else
+        {
+            OIC_LOG(ERROR, TAG, "Collection handle not found");
+        }
         return OC_STACK_INVALID_PARAM;
     }
 
-    // Look for an open slot to add add the child resource.
+    // Check if the resource exists already and is of the same type
+    if (resource->rsrcChildResourcesHead && resource->rsrcIsAtomicMeasurement != isAM)
+    {
+        OIC_LOG_V(ERROR, TAG, "atomic measurement / collection mismatch: created with isAM = %d, currently called with isAM = %d!",
+                  resource->rsrcIsAtomicMeasurement, isAM);
+    }
+
+    // Look for an open slot to add the child resource.
     // If found, add it and return success
 
     tempChildResource = resource->rsrcChildResourcesHead;
+    isFirstInAmCol = (tempChildResource == NULL);
 
     while(resource->rsrcChildResourcesHead && tempChildResource->next)
     {
@@ -4368,6 +4422,40 @@ OCStackResult OC_CALL OCBindResource(
         tempChildResource->next = newChildResource;
     }
 
+    resource->rsrcIsAtomicMeasurement = isAM;
+
+    // Add the oic.wk.col or oic.wk.atomicmeasurement to the rt of the resource
+    if (isFirstInAmCol)
+    {
+        if (isAM)
+        {
+            // Add the resourcetype to the resource
+            result = BindResourceTypeToResource(resource, OC_RSRVD_RESOURCE_TYPE_AM, false);
+        }
+        else
+        {
+            // Add the resourcetype to the resource
+            result = BindResourceTypeToResource(resource, OC_RSRVD_RESOURCE_TYPE_COLLECTION, false);
+        }
+        if (result != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG, "OCBindResourceAM: error adding the resource type for collection/atomic measurement!");
+        }
+    }
+
+    // In case of atomic measurement, save the entity handler for the resource into amEntityHandler, and set the entity
+    // handler of the resource to the default entity handler of the atomic measurement
+    if (isAM)
+    {
+        newChildResource->rsrcResource->amEntityHandler = newChildResource->rsrcResource->entityHandler;
+        newChildResource->rsrcResource->entityHandler = DefaultAtomicMeasurementResourceEntityHandler;
+    }
+    else
+    {
+        
+        newChildResource->rsrcResource->amEntityHandler = NULL;
+    }
+
     OIC_LOG(INFO, TAG, "resource bound");
 
 #ifdef WITH_PRESENCE
@@ -4445,6 +4533,16 @@ OCStackResult OC_CALL OCUnBindResource(
                 }
             }
 
+            // Clean atomic measurement variables
+            if (resource->rsrcIsAtomicMeasurement)
+            {
+                tempChildResource->rsrcResource->entityHandler = tempChildResource->rsrcResource->amEntityHandler;
+                if (!resource->rsrcChildResourcesHead)
+                {
+                    resource->rsrcIsAtomicMeasurement = false;
+                }
+            }
+
             OIC_LOG(INFO, TAG, "resource unbound");
 
             // Send notification when resource is unbounded successfully.
@@ -4467,7 +4565,7 @@ OCStackResult OC_CALL OCUnBindResource(
         tempChildResource = tempChildResource->next;
     }
 
-    OIC_LOG(INFO, TAG, "resource not found in collection");
+    OIC_LOG(INFO, TAG, "resource not found in collection/atomic measurement");
 
     tempChildResource = NULL;
     tempLastChildResource = NULL;
@@ -4516,8 +4614,9 @@ static bool ValidateResourceTypeInterface(const char *resourceItemName)
     return true;
 }
 
-OCStackResult BindResourceTypeToResource(OCResource* resource,
-                                            const char *resourceTypeName)
+static OCStackResult BindResourceTypeToResource(OCResource* resource,
+                                                const char *resourceTypeName,
+                                                bool isRtsM)
 {
     OCResourceType *pointer = NULL;
     char *str = NULL;
@@ -4547,7 +4646,7 @@ OCStackResult BindResourceTypeToResource(OCResource* resource,
     pointer->resourcetypename = str;
     pointer->next = NULL;
 
-    insertResourceType(resource, pointer);
+    insertResourceType(resource, pointer, isRtsM);
     result = OC_STACK_OK;
 
 exit:
@@ -4652,7 +4751,43 @@ OCStackResult OC_CALL OCBindResourceTypeToResource(OCResourceHandle handle,
         return OC_STACK_ERROR;
     }
 
-    result = BindResourceTypeToResource(resource, resourceTypeName);
+    result = BindResourceTypeToResource(resource, resourceTypeName, false);
+
+#ifdef WITH_PRESENCE
+    if(presenceResource.handle)
+    {
+        ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
+        SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
+    }
+#endif
+
+    return result;
+}
+
+OCStackResult OC_CALL OCBindRtsMToResource(OCResourceHandle handle,
+        const char *resourceTypeName)
+{
+
+    OCStackResult result = OC_STACK_ERROR;
+    OCResource *resource = NULL;
+
+    OIC_LOG(INFO, TAG, "Entering OCBindRtsMToResource");
+
+    resource = findResource((OCResource *) handle);
+    if (!resource)
+    {
+        OIC_LOG(ERROR, TAG, "Resource not found");
+        return OC_STACK_ERROR;
+    }
+
+    // Check if the resource is a collection or an atomic measurement
+    if (!resource->rsrcChildResourcesHead)
+    {
+        OIC_LOG(ERROR, TAG, "Resource is not a collection or an atomic measurement!");
+        return OC_STACK_ERROR;
+    }
+
+    result = BindResourceTypeToResource(resource, resourceTypeName, true);
 
 #ifdef WITH_PRESENCE
     if(presenceResource.handle)
@@ -4941,6 +5076,21 @@ OCEntityHandler OC_CALL OCGetResourceHandler(OCResourceHandle handle)
     return resource->entityHandler;
 }
 
+OCStackResult OC_CALL OCNotifyNewAMAvailable(const OCResourceHandle handle)
+{
+    OCResource *resource = NULL;
+
+    resource = findResource((OCResource *)handle);
+    if (!resource)
+    {
+        OIC_LOG(ERROR, TAG, "Resource not found");
+        return OC_STACK_NO_RESOURCE;
+    }
+
+    // Call the handler
+    return NewAtomicMeasurementReadyNotificationHandler(handle);
+}
+
 void incrementSequenceNumber(OCResource * resPtr)
 {
     // Increment the sequence number
@@ -5433,6 +5583,10 @@ void deleteResourceElements(OCResource *resource)
     {
         deleteResourceType(resource->rsrcType);
     }
+    if (resource->rsrcTypeM)
+    {
+        deleteResourceType(resource->rsrcTypeM);
+    }
     if (resource->rsrcInterface)
     {
         deleteResourceInterface(resource->rsrcInterface);
@@ -5502,22 +5656,27 @@ void OCDeleteResourceAttributes(OCAttribute *rsrcAttributes)
     }
 }
 
-void insertResourceType(OCResource *resource, OCResourceType *resourceType)
+static void insertResourceType(OCResource *resource, OCResourceType *resourceType, bool isRtsM)
 {
     OCResourceType *pointer = NULL;
+    OCResourceType **prsrcType = NULL;
     OCResourceType *previous = NULL;
     if (!resource || !resourceType)
     {
         return;
     }
+    if (isRtsM)
+        prsrcType = &(resource->rsrcTypeM);
+    else
+        prsrcType = &(resource->rsrcType);
     // resource type list is empty.
-    else if (!resource->rsrcType)
+    if (!(*prsrcType))
     {
-        resource->rsrcType = resourceType;
+        (*prsrcType) = resourceType;
     }
     else
     {
-        pointer = resource->rsrcType;
+        pointer = (*prsrcType);
 
         while (pointer)
         {
@@ -5539,7 +5698,14 @@ void insertResourceType(OCResource *resource, OCResourceType *resourceType)
     }
     resourceType->next = NULL;
 
-    OIC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
+    if (isRtsM)
+    {
+        OIC_LOG_V(INFO, TAG, "Added type %s to rts-m for resource %s", resourceType->resourcetypename, resource->uri);
+    }
+    else
+    {
+        OIC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
+    }
 }
 
 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
@@ -6374,4 +6540,4 @@ OCStackResult OC_CALL OCSendPingMessage(const OCDevAddr *devAddr, bool withCusto
     return CAResultToOCResult(CASendPingMessage(&endpoint, withCustody, &pongCbData));
 }
 
-#endif // TCP_ADAPTER
\ No newline at end of file
+#endif // TCP_ADAPTER
index ec3374a..e8ac957 100644 (file)
@@ -69,10 +69,15 @@ namespace OC
 
         virtual OCStackResult unregisterResource(
                     const OCResourceHandle& resourceHandle) = 0;
+
         virtual OCStackResult bindTypeToResource(
                     const OCResourceHandle& resourceHandle,
                     const std::string& resourceTypeName) = 0;
 
+        virtual OCStackResult bindRtsMToResource(
+                    const OCResourceHandle& resourceHandle,
+                    const std::string& resourceTypeName) = 0;
+
         virtual OCStackResult bindInterfaceToResource(
                     const OCResourceHandle& resourceHandle,
                     const std::string& resourceInterfaceName) = 0;
index 436dd8d..f25702c 100644 (file)
@@ -70,6 +70,10 @@ namespace OC
                     const OCResourceHandle& resourceHandle,
                     const std::string& resourceTypeName);
 
+        virtual OCStackResult bindRtsMToResource(
+                    const OCResourceHandle& resourceHandle,
+                    const std::string& resourceTypeName);
+
         virtual OCStackResult bindInterfaceToResource(
                     const OCResourceHandle& resourceHandle,
                     const std::string& resourceInterface);
index d1ee633..be92d00 100644 (file)
@@ -491,6 +491,62 @@ namespace OC
         OCStackResult bindResources(const OCResourceHandle collectionHandle,
                 const std::vector<OCResourceHandle>& addedResourceHandleList);
 
+        /**
+        * Add a resource to a collection / atomic measurement resource.
+        *
+        * @param amColHandle handle to the collection / atomic measurement resource
+        * @param resourceHandle handle to resource to be added to the collection / atomic measurement resource
+        * @param isAtomicMeasurement boolean indicating if this is a collection or an atomic measurement
+        *
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
+        * @note bindResourceAM must be used only after the both collection / atomic measurement resource and
+        * resource to add under a collection / atomic measurement are created and respective handles obtained
+        *
+        * @par Example:
+        * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# bindResourceAM(homeResourceHandle, kitchenResourceHandle, true);
+        * @par
+        * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen", and will be
+        * an atomic measurement.
+        */
+        OCStackResult bindResourceAM(const OCResourceHandle amColHandle,
+                const OCResourceHandle resourceHandle, bool isAtomicMeasurement);
+
+        /**
+        * Add multiple resources to a collection / atomic measurement resource.
+        *
+        * @param amColHandle handle to the collection / atomic measurement resource
+        * @param addedResourceHandleList reference to list of resource handles to be added to the
+        *   collection / atomic measurement resource
+        * @param isAtomicMeasurement boolean indicating if this is a collection or an atomic measurement
+        *
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
+        * @note bindResourcesAM must be used only after the both collection / atomic measurement resource and
+        * list of resources to add under a collection / atomic measurement are created and respective handles
+        * obtained.
+        *
+        * @par Example:
+        * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+        *   homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+        *   kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
+        *   roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
+        *   rList.push_back(roomResourceHandle);
+        * -# bindResourcesAM(homeResourceHandle, rList, true);
+        * @par
+        * At the end of Step 5, resource "a/home" will contain a references to "a/kitchen" and
+        *   "a/room", and will be an atomic measurement
+        */
+        OCStackResult bindResourcesAM(const OCResourceHandle amColHandle,
+                const std::vector<OCResourceHandle>& addedResourceHandleList, bool isAtomicMeasurement);
+
         /**
         * Unbind a resource from a collection resource.
         *
@@ -556,6 +612,16 @@ namespace OC
         OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle,
                         const std::string& resourceTypeName);
 
+        /**
+        * Adds a type to the rts-m of a resource
+        * @param resourceHandle handle to the resource
+        * @param resourceTypeName new typename to add to the rts-m of the resource
+        *
+        * @return Returns ::OC_STACK_OK if success.
+        */
+        OCStackResult bindRtsMToResource(const OCResourceHandle& resourceHandle,
+                        const std::string& resourceTypeName);
+
         /**
         * Binds an interface to a particular resource
         * @param resourceHandle handle to the resource
@@ -729,6 +795,8 @@ namespace OC
          */
         OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
 
+        OCStackResult notifyNewAMAvailable(const OCResourceHandle resourceHandle);
+
 #ifdef WITH_CLOUD
         /**
          * Create an account manager object that can be used for doing request to account server.
index 90a964e..1a59f12 100644 (file)
@@ -281,6 +281,12 @@ namespace OC
         OCStackResult bindResources(const OCResourceHandle collectionHandle,
                     const std::vector<OCResourceHandle>& addedResourceHandleList);
 
+        OCStackResult bindResourceAM(const OCResourceHandle amColHandle,
+                    const OCResourceHandle resourceHandle, bool isAtomicMeasurement);
+
+        OCStackResult bindResourcesAM(const OCResourceHandle amColHandle,
+                    const std::vector<OCResourceHandle>& addedResourceHandleList, bool isAtomicMeasurement);
+
         OCStackResult unbindResource(const OCResourceHandle collectionHandle,
                     const OCResourceHandle resourceHandle);
 
@@ -290,6 +296,9 @@ namespace OC
         OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle,
                         const std::string& resourceTypeName) const;
 
+        OCStackResult bindRtsMToResource(const OCResourceHandle& resourceHandle,
+                        const std::string& resourceTypeName) const;
+
         OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle,
                         const std::string& resourceInterfaceName) const;
 
@@ -321,6 +330,8 @@ namespace OC
         OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
         std::weak_ptr<std::recursive_mutex> csdkLock();
 
+        OCStackResult notifyNewAMAvailable(const OCResourceHandle resourceHandle);
+
 #ifdef WITH_CLOUD
         OCAccountManager::Ptr constructAccountManagerObject(const std::string& host,
                                                             OCConnectivityType connectivityType);
index 6768683..6d3ac69 100644 (file)
@@ -539,6 +539,28 @@ namespace OC
         return result;
     }
 
+    OCStackResult InProcServerWrapper::bindRtsMToResource(const OCResourceHandle& resourceHandle,
+                     const std::string& resourceTypeName)
+    {
+        auto cLock = m_csdkLock.lock();
+        OCStackResult result;
+        if(cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCBindRtsMToResource(resourceHandle, resourceTypeName.c_str());
+        }
+        else
+        {
+            result = OC_STACK_ERROR;
+        }
+
+        if (result != OC_STACK_OK)
+        {
+            throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
+        }
+        return result;
+    }
+
     OCStackResult InProcServerWrapper::bindInterfaceToResource(
                      const OCResourceHandle& resourceHandle,
                      const std::string& resourceInterfaceName)
index 101b170..2fcd7be 100644 (file)
@@ -295,12 +295,31 @@ namespace OC
             return OCPlatform_impl::Instance().bindResources(collectionHandle, resourceHandles);
         }
 
+        OCStackResult bindResourceAM(const OCResourceHandle amColHandle,
+                                 const OCResourceHandle resourceHandle, bool isAtomicMeasurement)
+        {
+            return OCPlatform_impl::Instance().bindResourceAM(amColHandle, resourceHandle, isAtomicMeasurement);
+        }
+
+        OCStackResult bindResourcesAM(const OCResourceHandle amColHandle,
+                                 const std::vector<OCResourceHandle>& resourceHandles, bool isAtomicMeasurement
+                                 )
+        {
+            return OCPlatform_impl::Instance().bindResourcesAM(amColHandle, resourceHandles, isAtomicMeasurement);
+        }
+
         OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle,
                                  const std::string& resourceTypeName)
         {
             return OCPlatform_impl::Instance().bindTypeToResource(resourceHandle,resourceTypeName);
         }
 
+        OCStackResult bindRtsMToResource(const OCResourceHandle& resourceHandle,
+                                 const std::string& resourceTypeName)
+        {
+            return OCPlatform_impl::Instance().bindRtsMToResource(resourceHandle, resourceTypeName);
+        }
+
         OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle,
                                  const std::string& resourceInterfaceName)
         {
@@ -362,6 +381,11 @@ namespace OC
             return OCPlatform_impl::Instance().sendResponse(pResponse);
         }
 
+        OCStackResult notifyNewAMAvailable(const OCResourceHandle resourceHandle)
+        {
+            return OCPlatform_impl::Instance().notifyNewAMAvailable(resourceHandle);
+        }
+
 #ifdef WITH_CLOUD
         OCAccountManager::Ptr constructAccountManagerObject(const std::string& host,
                                                             OCConnectivityType connectivityType)
index ead6994..ce52517 100644 (file)
@@ -580,6 +580,28 @@ namespace OC
         return OC_STACK_OK;
     }
 
+    OCStackResult OCPlatform_impl::bindResourceAM(const OCResourceHandle amColHandle,
+                                            const OCResourceHandle resourceHandle, bool isAtomicMeasurement)
+    {
+        return result_guard(OCBindResourceAM(amColHandle, resourceHandle, isAtomicMeasurement));
+    }
+
+    OCStackResult OCPlatform_impl::bindResourcesAM(const OCResourceHandle amColHandle,
+                                            const std::vector<OCResourceHandle>& resourceHandles, bool isAtomicMeasurement)
+    {
+        for(const auto& h : resourceHandles)
+        {
+           OCStackResult r;
+
+           if (OC_STACK_OK != (r = result_guard(OCBindResourceAM(amColHandle, h, isAtomicMeasurement))))
+           {
+               return r;
+           }
+        }
+
+        return OC_STACK_OK;
+    }
+
     OCStackResult OCPlatform_impl::bindTypeToResource(const OCResourceHandle& resourceHandle,
                                              const std::string& resourceTypeName) const
     {
@@ -587,6 +609,13 @@ namespace OC
                              resourceHandle, resourceTypeName);
     }
 
+    OCStackResult OCPlatform_impl::bindRtsMToResource(const OCResourceHandle& resourceHandle,
+                                             const std::string& resourceTypeName) const
+    {
+        return checked_guard(m_server, &IServerWrapper::bindRtsMToResource,
+                             resourceHandle, resourceTypeName);
+    }
+
     OCStackResult OCPlatform_impl::bindInterfaceToResource(const OCResourceHandle& resourceHandle,
                                              const std::string& resourceInterfaceName) const
     {
@@ -653,6 +682,11 @@ namespace OC
         return m_csdkLock;
     }
 
+    OCStackResult OCPlatform_impl::notifyNewAMAvailable(const OCResourceHandle resourceHandle)
+    {
+        return result_guard(OCNotifyNewAMAvailable(resourceHandle));
+    }
+
 #ifdef WITH_CLOUD
     OCAccountManager::Ptr OCPlatform_impl::constructAccountManagerObject(const std::string& host,
                                                             OCConnectivityType connectivityType)