Moved/Added occoaptoken.h. There were some weird cyclical dependency patterns in the compiler.
CoAP token storage for observe sends.
Sending sequence numbers with observations.
Change-Id: Ib101a093c6c37066e4b6d51218fc689f2c5423e5
opt_iter.type == COAP_OPTION_URI_HOST ||
opt_iter.type == COAP_OPTION_LOCATION_PATH ||
opt_iter.type == COAP_OPTION_LOCATION_QUERY ||
- opt_iter.type == COAP_OPTION_URI_PATH ||
+ opt_iter.type == COAP_OPTION_URI_PATH ||
+ opt_iter.type == COAP_OPTION_OBSERVE ||
opt_iter.type == COAP_OPTION_URI_QUERY) {
encode = 0;
} else {
OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/occlientcb.c
OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocserverrequest.c
OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocresource.c
+OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocobserve.c
SOURCES := $(CJSON_SOURCES)
SOURCES += $(OCCOAP_SOURCES)
// Includes
//-----------------------------------------------------------------------------
#include "ocstack.h"
+#include "occoaptoken.h"
#include "ocstackinternal.h"
#include "occoaphelper.h"
#include <stdint.h>
int OCProcessCoAP();
OCCoAPToken * OCGenerateCoAPToken();
+/* Vijay: TODO: Add description */
+
+int OCCoAPSendMessage (OCDevAddr *dstAddr, OCStackResult msgCode,
+ OCQualityOfService qos, OCCoAPToken * token,
+ const char *payload, uint32_t seqNum);
#endif /* OCCOAP_H_ */
//-----------------------------------------------------------------------------
#include "coap.h"
#include "ocstack.h"
+#include "occoaptoken.h"
#include "ocstackinternal.h"
#include <unistd.h>
#include <limits.h>
#include <ctype.h>
-#define MAX_TOKEN_LENGTH (8)
-
-typedef struct {
- uint8_t token[MAX_TOKEN_LENGTH];
- size_t tokenLength;
-} OCCoAPToken;
-
// Convert OCStack code to CoAP code
uint8_t OCToCoAPResponseCode(OCStackResult result);
--- /dev/null
+
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+
+#ifndef OCCOAPTOKEN_H_
+#define OCCOAPTOKEN_H_
+
+#define MAX_TOKEN_LENGTH (8)
+
+typedef struct {
+ uint8_t token[MAX_TOKEN_LENGTH];
+ size_t tokenLength;
+} OCCoAPToken;
+
+#endif
}
OC_LOG_V(INFO, TAG, "TID %d", tid);
- OC_LOG(INFO, TAG, "Deleting PDU");
// unlike stock libcoap (deletion in handle_request in net.c), we are deleting the response here
// in the future, the response might be queued for SLOW resources
if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID)
{
+ OC_LOG(INFO, TAG, "Deleting PDU");
coap_delete_pdu(pdu);
}
int res;
uint8_t coapMsgType;
uint8_t coapMethod;
+ // Vijay: TODO Observation registration is hardcoded here - change
+ unsigned char obs[] = "0";
OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResource"));
case OC_REST_OBSERVE_ALL:
case OC_REST_OBSERVE:
coapMethod = COAP_REQUEST_GET;
+#if 0
+ // Joey's add for observation registration: not working.
+ // Vijay's change below
buflen = BUF_SIZE;
buf = _buf;
res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
buf += COAP_OPT_SIZE(buf);
}
+#endif
+ coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
+ strlen((const char *)obs), (obs)), OrderOptions);
+
break;
default:
coapMethod = 0;
return ret;
}
+int OCCoAPSendMessage (OCDevAddr *dstAddr, OCStackResult msgCode,
+ OCQualityOfService qos, OCCoAPToken * token,
+ const char *payload, uint32_t seqNum)
+{
+ coap_list_t *optList = NULL;
+ coap_pdu_t *pdu;
+ unsigned char tempBuf[BUF_SIZE_ENCODE_OPTION];
+ uint8_t coapMsgType = COAP_MESSAGE_NON;
+ coap_tid_t tid = COAP_INVALID_TID;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCCoAPSendMessage"));
+
+ printf ("Payload: %s\n", payload);
+ OC_LOG_V(INFO, TAG, "OCStack payload: %s", payload);
+ coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_CONTENT_TYPE,
+ coap_encode_var_bytes(tempBuf, COAP_MEDIATYPE_APPLICATION_JSON),
+ tempBuf), OrderOptions);
+ coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_MAXAGE,
+ coap_encode_var_bytes(tempBuf, 0x2ffff), tempBuf), OrderOptions);
+ coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
+ coap_encode_var_bytes(tempBuf, seqNum), tempBuf), OrderOptions);
+
+ pdu = GenerateCoAPPdu (coapMsgType, OCToCoAPResponseCode(msgCode),
+ coap_new_message_id(gCoAPCtx), token->tokenLength, token->token,
+ (unsigned char*) payload, optList);
+ VERIFY_NON_NULL(pdu);
+ coap_show_pdu(pdu);
+
+ tid = coap_send(gCoAPCtx, (coap_address_t*)dstAddr, pdu);
+ OC_LOG_V(INFO, TAG, "TID %d", tid);
+ if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID)
+ {
+ OC_LOG(INFO, TAG, "Deleting PDU");
+ coap_delete_pdu(pdu);
+ pdu = NULL;
+ }
+ return OC_COAP_OK;
+
+exit:
+ coap_delete_list(optList);
+ return OC_COAP_ERR;
+}
+
/**
* Stop the CoAP client or server processing
*
unsigned char * queryBuf) {
OCRequest * request = NULL;
+ OCObserveReq *obsReq = NULL;
size_t bufLen;
size_t optLen;
coap_opt_filter_t filter;
// delete last '&'
queryBuf[bufLen ? (bufLen - 1) : (bufLen)] = '\0';
+ // fill in observe, if present
+ request->observe = NULL;
+ coap_option_filter_clear(filter);
+ coap_option_setb(filter, COAP_OPTION_OBSERVE);
+ coap_option_iterator_init(rcvdRequest->pdu, &opt_iter, filter);
+ while ((option = coap_option_next(&opt_iter))) {
+ printf ("\n\n ******************* OBS ********** %d, %s\n\n\n", COAP_OPT_LENGTH(option), COAP_OPT_VALUE(option));
+ request->observe = (OCObserveReq *)OCMalloc(sizeof(OCObserveReq));
+ if (request->observe)
+ {
+ obsReq = request->observe;
+ obsReq->option = NULL;
+ obsReq->option = (unsigned char *)OCMalloc(COAP_OPT_LENGTH(option)+1);
+ if (obsReq->option)
+ {
+ memcpy(obsReq->option, COAP_OPT_VALUE(option),COAP_OPT_LENGTH(option));
+ (obsReq->option)[COAP_OPT_LENGTH(option)] = '\0';
+ }
+ else
+ {
+ OCFree (request->observe);
+ return OC_STACK_NO_MEMORY;
+ }
+ /*
+ // Vijay: TODO: Remove this code block before final commit
+ // TODO: Should we copy sizeof OCDevAddr or introspect the addr for size
+ memcpy (&(obsReq->subAddr), (OCDevAddr *) &(rcvdRequest->remote),sizeof(OCDevAddr));
+ coapTok = obsReq->coapTok;
+ coapTok->tokenLength = rcvdRequest->pdu->hdr->token_length;
+ memcpy(coapTok->token, rcvdRequest->pdu->hdr->token, coapTok->tokenLength);
+ */
+ obsReq->subAddr = (OCDevAddr *)&(rcvdRequest->remote);
+ obsReq->coapToken = rcvdRequest->pdu->hdr->token;
+ obsReq->coapTokenLen = rcvdRequest->pdu->hdr->token_length;
+ } else {
+ return OC_STACK_NO_MEMORY;
+ }
+ }
+ OC_LOG_V(INFO, TAG, "Observe option %d", request->observe);
+
*requestLoc = request;
return OC_STACK_OK;
}
#define OC_CLIENT_CB
#include <ocstack.h>
+#include <occoaptoken.h>
#include <occoap.h>
typedef struct ClientCB {
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OC_OBSERVE_H
+#define OC_OBSERVE_H
+
+/* In CoAP sequence number is a 24 bit field */
+#define MAX_SEQUENCE_NUMBER 0xFFFFFF
+#define OC_RESOURCE_OBSERVE_REGISTER "0"
+#define OC_RESOURCE_OBSERVE_DEREGISTER "1"
+
+/* Vijay: TODO add comments */
+typedef struct ObserveResourceServer {
+ // xxxxxxxxxxxxxxxx
+ unsigned char *resUri;
+ // xxxxxxxxxxxxxxxxx
+ unsigned char *query;
+ // xxxxxxxxxxxxxxxxx
+ OCCoAPToken *coapTok;
+ // xxxxxxxxxxxxxxxxx
+ OCResource *resource;
+ // xxxxxxxxxxxxxxxxx
+ OCDevAddr *addr;
+ // next node in this list
+ struct ObserveResourceServer *next;
+} ObserveResourceServer;
+
+OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request);
+
+OCStackResult SendObserverNotification (OCResourceHandle handle, OCResource *resPtr);
+
+#endif //OC_OBSERVE_H
// Includes
//-----------------------------------------------------------------------------
#include "ocstack.h"
+#include "occoaptoken.h"
#ifdef __cplusplus
extern "C" {
// NOTE: Methods supported by this resource should be based on the interface targeted
// i.e. look into the interface structure based on the query request Can be removed here; place holder for the note above
/* method_t methods; */
+ // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
+ uint32_t sequenceNum;
} OCResource;
+/* Vijay: TODO add comments */
+typedef struct {
+ // xxxxxxxxxxxxxxxx
+ unsigned char *option;
+ // xxxxxxxxxxxxxxxx
+ OCDevAddr *subAddr;
+ // xxxxxxxxxxxxxxxx
+ uint8_t *coapToken;
+ // xxxxxxxxxxxxxxxx
+ size_t coapTokenLen;
+} OCObserveReq;
+
// following structure will be created in occoap and passed up the stack on the server side
typedef struct {
// resourceUrl will be filled in occoap using the path options in received request PDU
unsigned char * resourceUrl;
// qos is indicating if the request is CON or NON
OCQualityOfService qos;
+ // this structure points to the information for processing observe option
+ OCObserveReq *observe;
// this structure will be passed to entity handler
OCEntityHandlerRequest * entityHandlerRequest;
} OCRequest;
OC_STACK_INVALID_CALLBACK,
OC_STACK_INVALID_METHOD,
OC_STACK_INVALID_PARAM,
+ OC_STACK_INVALID_OBSERVE_PARAM,
OC_STACK_NO_MEMORY,
OC_STACK_COMM_ERROR,
OC_STACK_NOTIMPL,
OC_STACK_NO_RESOURCE, /* resource not found*/
OC_STACK_RESOURCE_ERROR, /*ex: not supported method or interface*/
OC_STACK_SLOW_RESOURCE,
+ OC_STACK_NO_OBSERVERS, /* resource has no registered observers */
OC_STACK_ERROR
} OCStackResult;
CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
$(INC_DIRS) -L$(ROOT_DIR) -DTB_LOG
-LDLIBS += -loctbstack
+LDLIBS += -loctbstack -lpthread
CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS)
PROGRAMS += ocserver
if(ctx == (void*)CTX_VAL) {
OC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully");
OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
+#if 0
//* Make a GET query*/
std::ostringstream getQuery;
getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
OC_LOG_V(ERROR, TAG, "OCStack resource error");
//reOC_LOG_Vturn 0;
}
+#endif
}
return OC_STACK_KEEP_TRANSACTION;
}
"Device =============> Discovered %s @ %d.%d.%d.%d:%d",
clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
-
+
+ std::ostringstream obsReg;
+ obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
+ OCCallbackData cbData;
+ cbData.cb = clientApplicationGETCb;
+ cbData.context = (void*)CTX_VAL;
+ if (OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData)
+ != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ //return 0;
+ }
+ return OC_STACK_KEEP_TRANSACTION;
+#if 0
//* Make a GET query*/
std::ostringstream getQuery;
getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
}
return OC_STACK_KEEP_TRANSACTION;
+#endif
}
//This function is called back when a resource is discovered.
return 0;
}
- sleep(1);
+ sleep(3);
}
OC_LOG(INFO, TAG, "Exiting occlient main loop...");
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
+#include <pthread.h>
#include <ocstack.h>
#include <logger.h>
-
char *getResult(OCStackResult result);
#define TAG PCF("ocserver")
int gQuitFlag = 0;
+int gLEDUnderObservation = 0;
void createLEDResource();
typedef struct LEDRESOURCE{
OCResourceHandle handle;
- bool power;
+ bool state;
+ int power;
} LEDResource;
static LEDResource LED;
OCStackResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest ) {
const char* typeOfMessage;
+
switch (flag) {
case OC_INIT_FLAG:
typeOfMessage = "OC_INIT_FLAG";
typeOfMessage = "UNKNOWN";
}
OC_LOG_V(INFO, TAG, "Receiving message type: %s", typeOfMessage);
- if(entityHandlerRequest){ //[CL]
+ if(entityHandlerRequest && flag == OC_REQUEST_FLAG){ //[CL]
if(OC_REST_GET == entityHandlerRequest->method)
//entityHandlerRequest->resJSONPayload = reinterpret_cast<unsigned char*>(const_cast<unsigned char*> (responsePayloadGet.c_str()));
entityHandlerRequest->resJSONPayload = responsePayloadGet;
//responsePayloadGet = responsePayloadPut; // just a bad hack!
}
- }
+ } else if (entityHandlerRequest && flag == OC_OBSERVE_FLAG) {
+ gLEDUnderObservation = 1;
+ }
//OC_LOG_V(INFO, TAG, "/nReceiving message type:/n/t %s. /n/nWith request:/n/t %s", typeOfMessage, request);
}
}
+void * ChangeLEDRepresentation (void *param)
+{
+ (void)param;
+ OCStackResult result = OC_STACK_ERROR;
+
+ while (1)
+ {
+ sleep (15);
+ LED.power += 5;
+ if (gLEDUnderObservation)
+ {
+ OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", LED.power);
+ result = OCNotifyObservers (LED.handle);
+ printf ("==========> Result from stack: %s\n", getResult(result));
+ if (OC_STACK_NO_OBSERVERS == result)
+ {
+ gLEDUnderObservation = 0;
+ }
+ }
+ }
+}
+
int main() {
OC_LOG(DEBUG, TAG, "OCServer is starting...");
uint8_t addr[20] = {0};
uint8_t* paddr = NULL;
uint16_t port = USE_RANDOM_PORT;
uint8_t ifname[] = "eth0";
+ pthread_t threadId;
/*Get Ip address on defined interface and initialize coap on it with random port number
* this port number will be used as a source port in all coap communications*/
*/
createLEDResource();
+ /*
+ * Create a thread for changing the representation of the LED
+ */
+ pthread_create (&threadId, NULL, ChangeLEDRepresentation, (void *)NULL);
+
// Break from loop with Ctrl-C
OC_LOG(INFO, TAG, "Entering ocserver main loop...");
signal(SIGINT, handleSigInt);
OC_LOG(ERROR, TAG, "OCStack process error");
return 0;
}
- sleep(1);
+ sleep(3);
}
OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
return 0;
}
void createLEDResource() {
- LED.power = false;
+ LED.state = false;
OCStackResult res = OCCreateResource(&LED.handle,
"core.led",
"state:oc.bt.b;power:oc.bt.i",
case OC_STACK_SLOW_RESOURCE:
strcat(resString, "OC_STACK_SLOW_RESOURCE");
break;
+ case OC_STACK_NO_OBSERVERS:
+ strcat(resString, "OC_STACK_NO_OBSERVERS");
+ break;
case OC_STACK_ERROR:
strcat(resString, "OC_STACK_ERROR");
break;
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <string.h>
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocobserve.h"
+#include "occoap.h"
+#include "utlist.h"
+#include "debug.h"
+
+// Module Name
+#define MOD_NAME PCF("ocobserve")
+
+#define TAG PCF("OCStackObserve")
+
+#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
+
+static struct ObserveResourceServer *serverObsList = NULL;
+
+OCStackResult AddObserver (const char *resUri,
+ const char *query,
+ uint8_t *token,
+ size_t tokenLength,
+ OCDevAddr *addr,
+ OCResource *resHandle);
+
+OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request)
+{
+ OCStackResult result;
+ OCEntityHandlerRequest *ehReq = request->entityHandlerRequest;
+ OCObserveReq *obs = request->observe;
+
+ OC_LOG(INFO, TAG, "Entering ProcessObserveRequest");
+ printf ("Observer option: %s\n", obs->option);
+ if (strcmp ((char *)obs->option, OC_RESOURCE_OBSERVE_REGISTER) == 0) {
+ // Register new observation
+ printf ("Register new observation\n\n");
+ result = resource->entityHandler(OC_OBSERVE_FLAG, request->entityHandlerRequest);
+ if (OC_STACK_OK == result)
+ {
+ // Add subscriber to the server observation list
+ result = AddObserver ((const char*)(request->resourceUrl), (const char *)(ehReq->query),
+ obs->coapToken, obs->coapTokenLen, obs->subAddr, resource);
+ }
+ return result;
+ } else if (strcmp ((char *)request->observe, OC_RESOURCE_OBSERVE_DEREGISTER) == 0) {
+ // Deregister observation
+ return OC_STACK_NOTIMPL;
+ } else {
+ // Invalid option
+ return OC_STACK_INVALID_OBSERVE_PARAM;
+ }
+}
+
+OCStackResult SendObserverNotification (OCResourceHandle handle, OCResource *resPtr)
+{
+ uint8_t numObs = 0;
+ OCStackResult result;
+ ObserveResourceServer *obsRes = serverObsList;
+ OCEntityHandlerRequest entityHandlerReq;
+ unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
+ /*
+ * TODO: In the current releast all observes are set as non-confirmable since the
+ * entity handler does not have a way to specify the message QoS - add a parameter.
+ * Sending all observes NON does not confirm with the observe draft (ver14).
+ */
+ OCQualityOfService qos = OC_NON_CONFIRMABLE;
+
+ // Increment the sequence number
+ resPtr->sequenceNum += 1;
+ if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
+ resPtr->sequenceNum = 1;
+
+ // Find clients that are observing this resource
+ while (obsRes) {
+ if (obsRes->resource == handle) {
+ // Invoke the entity handler for the client to process the query according to
+ // the new representation
+ numObs++;
+ entityHandlerReq.resource = handle;
+ entityHandlerReq.query = obsRes->query;
+ entityHandlerReq.method = OC_REST_GET;
+ entityHandlerReq.reqJSONPayload = NULL;
+ entityHandlerReq.resJSONPayload = bufRes;
+ entityHandlerReq.resJSONPayloadLen = MAX_RESPONSE_LENGTH;
+ // Even if entity handler for a resource is not successful we continue calling
+ // entity handler for other resources
+ result = resPtr->entityHandler (OC_REQUEST_FLAG, &entityHandlerReq);
+ if (OC_STACK_OK == result)
+ {
+ printf ("Calling OCCoAPSendMessage: Payload: %s\n", entityHandlerReq.resJSONPayload);
+ OCCoAPSendMessage (obsRes->addr, result, qos, obsRes->coapTok,
+ (const char *)entityHandlerReq.resJSONPayload,
+ resPtr->sequenceNum);
+ }
+ }
+ obsRes = obsRes->next;
+ }
+ if (numObs == 0)
+ {
+ OC_LOG(INFO, TAG, "Resource has no observers");
+ return OC_STACK_NO_OBSERVERS;
+ }
+ return OC_STACK_OK;
+}
+
+OCStackResult AddObserver (const char *resUri,
+ const char *query,
+ uint8_t *token,
+ size_t tokenLength,
+ OCDevAddr *addr,
+ OCResource *resHandle)
+{
+ ObserveResourceServer *obsNode;
+ OCCoAPToken *tokPtr;
+
+ obsNode = (ObserveResourceServer *) OCMalloc(sizeof(ObserveResourceServer));
+ if (obsNode) {
+ obsNode->resUri = (unsigned char *)OCMalloc(sizeof(strlen(resUri)+1));
+ VERIFY_NON_NULL (obsNode->resUri);
+ memcpy (obsNode->resUri, resUri, sizeof(strlen(resUri)+1));
+ obsNode->query = (unsigned char *)OCMalloc(sizeof(strlen(query)+1));
+ VERIFY_NON_NULL (obsNode->query);
+ memcpy (obsNode->query, query, sizeof(strlen(query)+1));
+ obsNode->coapTok = (OCCoAPToken *)OCMalloc(sizeof(OCCoAPToken));
+ VERIFY_NON_NULL (obsNode->coapTok);
+ tokPtr = obsNode->coapTok;
+ memcpy (tokPtr->token, token, sizeof(OCCoAPToken));
+ tokPtr->tokenLength = tokenLength;
+ obsNode->addr = (OCDevAddr *)OCMalloc(sizeof(OCDevAddr));
+ VERIFY_NON_NULL (obsNode->addr);
+ memcpy (obsNode->addr, addr, sizeof(OCDevAddr));
+ obsNode->resource = resHandle;
+
+ LL_APPEND (serverObsList, obsNode);
+ return OC_STACK_OK;
+ }
+
+exit:
+ OCFree(obsNode->resUri);
+ OCFree(obsNode->query);
+ OCFree(obsNode->coapTok);
+ OCFree(obsNode->addr);
+ OCFree(obsNode);
+ return OC_STACK_NO_MEMORY;
+}
#include "ocserverrequest.h"
#include "ocresource.h"
#include "occlientcb.h"
+#include "ocobserve.h"
#include "ocrandom.h"
#include "debug.h"
#include "occoap.h"
if (resource)
{
result = resource->entityHandler(OC_REQUEST_FLAG, request->entityHandlerRequest);
+ if (request->observe != NULL)
+ {
+ printf ("\n *** An observe is included in message \n");
+ ProcessObserveRequest (resource, request);
+ }
}
else
{
// Validate required URI
VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
+ if (method == OC_REST_OBSERVE)
+ {
+ printf ("\n\n ********* OBSERVE REGISTRATION ******* \n\n");
+ }
// Make call to OCCoAP layer
if (OCDoCoAPResource(method, qos, _token, requiredUri, request) == OC_COAP_OK) {
OC_LOG(INFO, TAG, "Done with this function");
/**
* Notify observers that an observed value has changed.
*
- * **NOTE: This API has NOT been finalized!!!**
*
* @param handle - handle of resource
*
* OC_STACK_ERROR - stack not initialized
*/
OCStackResult OCNotifyObservers(OCResourceHandle handle) {
+ OCResource *resPtr = NULL;
+ OCStackResult result;
- TODO ("This API has NOT been finalized");
-
- OC_LOG(INFO, TAG, PCF("Entering OCNotifyObservers"));
+ OC_LOG(INFO, TAG, PCF("====>Entering OCNotifyObservers"));
- (void) handle;
+ VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
- return OC_STACK_NOTIMPL;
+ // Verify that the resource exists
+ printf ("====> Finding resource\n");
+ resPtr = findResource ((OCResource *) handle);
+ if (NULL == resPtr)
+ {
+ return OC_STACK_NO_RESOURCE;
+ } else {
+ result = SendObserverNotification (handle, resPtr);
+ return result;
+ }
}
//-----------------------------------------------------------------------------