diff options
author | Tobias Jahnke <tobias.jahnke@microchip.com> | 2017-12-20 17:29:35 +0100 |
---|---|---|
committer | Tobias Jahnke <tobias.jahnke@microchip.com> | 2017-12-20 17:29:35 +0100 |
commit | 24552c17d18bb703abe256f837c41cf694649f7e (patch) | |
tree | d0128fdeb74dd0ce433f9fd79736acdb41d8f0d3 | |
parent | def4ba56e84ba75149d35475e098e1f8420532bb (diff) |
agl-service-unicens: Rx message event
Bug-AGL: SPEC-1177
Implements /subscriberx function. Control Rx messages
will be notified to subscribers. If no subscriber is
assigned, then Rx messages are discarded. This avoids
Rx stuck issues after receiving multiple messages.
Change-Id: Idb71569b8ff6f651833d7d01c37a3eea866daf1d
Signed-off-by: Tobias Jahnke <tobias.jahnke@microchip.com>
-rw-r--r-- | conf.d/project/config.cmake | 2 | ||||
-rw-r--r-- | htdocs/UNICENS.html | 3 | ||||
-rw-r--r-- | ucs2-afb/ucs_apidef.h | 47 | ||||
-rw-r--r-- | ucs2-afb/ucs_apidef.json | 13 | ||||
-rw-r--r-- | ucs2-afb/ucs_binding.c | 101 |
5 files changed, 141 insertions, 25 deletions
diff --git a/conf.d/project/config.cmake b/conf.d/project/config.cmake index 02495cb..58f568f 100644 --- a/conf.d/project/config.cmake +++ b/conf.d/project/config.cmake @@ -199,7 +199,7 @@ set(AFB_REMPORT "1234" CACHE PATH "Default binder listening port") # Print a helper message when every thing is finished # ---------------------------------------------------- -set(CLOSING_MESSAGE "Test with: afb-daemon --ldpaths=. --port=1234 --workdir=. --roothttp=../htdocs --tracereq=common --token='' --verbose") +set(CLOSING_MESSAGE "Test with: afb-daemon --ldpaths=./package --port=1234 --workdir=. --roothttp=../htdocs --tracereq=common --token= --verbose") set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt") # Optional schema validator about now only XML, LUA and JSON diff --git a/htdocs/UNICENS.html b/htdocs/UNICENS.html index a2cdb28..e2505ae 100644 --- a/htdocs/UNICENS.html +++ b/htdocs/UNICENS.html @@ -16,7 +16,8 @@ <br> <ol> - <li><button onclick="callbinder('UNICENS','subscribe', {})">Subscribe to events</button></li> + <li><button onclick="callbinder('UNICENS','subscribe', {})">Subscribe to network events</button></li> + <li><button onclick="callbinder('UNICENS','subscriberx', {})">Subscribe to Rx message events</button></li> <li><button onclick="callbinder('UNICENS','initialise', {filename:ucs2_config})">Parse XML and Start UNICENS</button></li> </ol> <br> diff --git a/ucs2-afb/ucs_apidef.h b/ucs2-afb/ucs_apidef.h index d3dfd3c..2323599 100644 --- a/ucs2-afb/ucs_apidef.h +++ b/ucs2-afb/ucs_apidef.h @@ -34,24 +34,27 @@ static const char _afb_description_v2_UNICENS[] = "mponents/x-permissions/config\"},\"parameters\":[{\"in\":\"query\",\"nam" "e\":\"filename\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"" "responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/sub" - "scribe\":{\"description\":\"Subscribe to UNICENS Events.\",\"get\":{\"x-" + "scribe\":{\"description\":\"Subscribe to network events.\",\"get\":{\"x-" "permissions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"respon" - "ses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/writei2c\"" - ":{\"description\":\"Writes I2C command to remote node.\",\"get\":{\"x-pe" - "rmissions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"paramete" - "rs\":[{\"in\":\"query\",\"name\":\"node\",\"required\":true,\"schema\":{" - "\"type\":\"integer\",\"format\":\"int32\"}},{\"in\":\"query\",\"name\":\"" - "data\",\"required\":true,\"schema\":{\"type\":\"array\",\"format\":\"int" - "32\"},\"style\":\"simple\"}],\"responses\":{\"200\":{\"$ref\":\"#/compon" - "ents/responses/200\"}}}},\"/sendmessage\":{\"description\":\"Transmits a" - " control message to a node.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/c" - "omponents/x-permissions/monitor\"},\"parameters\":[{\"in\":\"query\",\"n" - "ame\":\"node\",\"required\":true,\"schema\":{\"type\":\"integer\",\"form" - "at\":\"int32\"}},{\"in\":\"query\",\"name\":\"msgid\",\"required\":true," - "\"schema\":{\"type\":\"integer\",\"format\":\"int32\"}},{\"in\":\"query\"" - ",\"name\":\"data\",\"required\":true,\"schema\":{\"type\":\"array\",\"fo" - "rmat\":\"int32\"},\"style\":\"simple\"}],\"responses\":{\"200\":{\"$ref\"" - ":\"#/components/responses/200\"}}}}}}" + "ses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/subscribe" + "rx\":{\"description\":\"Subscribe to Rx control message events.\",\"get\"" + ":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"" + "responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/wri" + "tei2c\":{\"description\":\"Writes I2C command to remote node.\",\"get\":" + "{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"p" + "arameters\":[{\"in\":\"query\",\"name\":\"node\",\"required\":true,\"sch" + "ema\":{\"type\":\"integer\",\"format\":\"int32\"}},{\"in\":\"query\",\"n" + "ame\":\"data\",\"required\":true,\"schema\":{\"type\":\"array\",\"format" + "\":\"int32\"},\"style\":\"simple\"}],\"responses\":{\"200\":{\"$ref\":\"" + "#/components/responses/200\"}}}},\"/sendmessage\":{\"description\":\"Tra" + "nsmits a control message to a node.\",\"get\":{\"x-permissions\":{\"$ref" + "\":\"#/components/x-permissions/monitor\"},\"parameters\":[{\"in\":\"que" + "ry\",\"name\":\"node\",\"required\":true,\"schema\":{\"type\":\"integer\"" + ",\"format\":\"int32\"}},{\"in\":\"query\",\"name\":\"msgid\",\"required\"" + ":true,\"schema\":{\"type\":\"integer\",\"format\":\"int32\"}},{\"in\":\"" + "query\",\"name\":\"data\",\"required\":true,\"schema\":{\"type\":\"array" + "\",\"format\":\"int32\"},\"style\":\"simple\"}],\"responses\":{\"200\":{" + "\"$ref\":\"#/components/responses/200\"}}}}}}" ; static const struct afb_auth _afb_auths_v2_UNICENS[] = { @@ -62,6 +65,7 @@ static const struct afb_auth _afb_auths_v2_UNICENS[] = { void ucs2_listconfig(struct afb_req req); void ucs2_initialise(struct afb_req req); void ucs2_subscribe(struct afb_req req); + void ucs2_subscriberx(struct afb_req req); void ucs2_writei2c(struct afb_req req); void ucs2_sendmessage(struct afb_req req); @@ -84,7 +88,14 @@ static const struct afb_verb_v2 _afb_verbs_v2_UNICENS[] = { .verb = "subscribe", .callback = ucs2_subscribe, .auth = &_afb_auths_v2_UNICENS[1], - .info = "Subscribe to UNICENS Events.", + .info = "Subscribe to network events.", + .session = AFB_SESSION_NONE_V2 + }, + { + .verb = "subscriberx", + .callback = ucs2_subscriberx, + .auth = &_afb_auths_v2_UNICENS[1], + .info = "Subscribe to Rx control message events.", .session = AFB_SESSION_NONE_V2 }, { diff --git a/ucs2-afb/ucs_apidef.json b/ucs2-afb/ucs_apidef.json index a150fb8..954e275 100644 --- a/ucs2-afb/ucs_apidef.json +++ b/ucs2-afb/ucs_apidef.json @@ -142,7 +142,18 @@ } }, "/subscribe": { - "description": "Subscribe to UNICENS Events.", + "description": "Subscribe to network events.", + "get": { + "x-permissions": { + "$ref": "#/components/x-permissions/monitor" + }, + "responses": { + "200": {"$ref": "#/components/responses/200"} + } + } + }, + "/subscriberx": { + "description": "Subscribe to Rx control message events.", "get": { "x-permissions": { "$ref": "#/components/x-permissions/monitor" diff --git a/ucs2-afb/ucs_binding.c b/ucs2-afb/ucs_binding.c index b72aca9..553ed36 100644 --- a/ucs2-afb/ucs_binding.c +++ b/ucs2-afb/ucs_binding.c @@ -68,11 +68,15 @@ typedef struct { typedef struct { struct afb_event node_event; - } EventData_t; +typedef struct { + struct afb_event rx_event; +} EventDataRx_t; + static ucsContextT *ucsContextS = NULL; static EventData_t *eventData = NULL; +static EventDataRx_t *eventDataRx = NULL; PUBLIC void UcsXml_CB_OnError(const char format[], uint16_t vargsCnt, ...) { /*AFB_DEBUG (afbIface, format, args); */ @@ -208,12 +212,74 @@ void UCSI_CB_OnStop(void *pTag) { sd_event_add_time(afb_daemon_get_event_loop(), NULL, CLOCK_MONOTONIC, 0, 0, OnStopCB, pTag); } +/* helper function: wraps Rx message in json and triggers notification */ +STATIC void NotifyEventRxMsg(uint16_t src_addr, uint16_t msg_id, uint8_t *data_ptr, uint32_t data_sz) { + + if (!eventDataRx) + return; + + if (data_sz > CTRL_MAX_DATA_SZ) { + AFB_NOTICE("RX-MSG: discarded, payload exceeds %d bytes", CTRL_MAX_DATA_SZ); + return; + } + + json_object *j_event_info = json_object_new_object(); + json_object *j_array = json_object_new_array(); + + if (!j_event_info || !j_array) { + if (j_event_info) { + json_object_put(j_event_info); + } + if (j_array) { + json_object_put(j_array); + } + AFB_ERROR("Failed to create json objects"); + return; + } + + uint32_t cnt = 0U; + for (cnt = 0U; cnt < data_sz; cnt++) { + json_object_array_add(j_array, json_object_new_int(data_ptr[cnt])); + } + + json_object_object_add(j_event_info, "node", json_object_new_int(src_addr)); + json_object_object_add(j_event_info, "msgid", json_object_new_int(msg_id)); + json_object_object_add(j_event_info, "data", j_array); + + afb_event_push(eventDataRx->rx_event, j_event_info); +} + +/** Asynchronous processing of Rx messages in mainloop is recommended */ +STATIC int OnAmsMessageReceivedCB (sd_event_source *source, void *pTag) { + ucsContextT *ucsContext = (ucsContextT*) pTag; + uint32_t data_sz = 0U; + uint8_t *data_ptr = NULL; + uint16_t msg_id = 0U; + uint16_t src_addr = 0U; + + while (UCSI_GetAmsMessage(&ucsContext->ucsiData, &msg_id, &src_addr, &data_ptr, &data_sz)) { + NotifyEventRxMsg(src_addr, msg_id, data_ptr, data_sz); + AFB_DEBUG("RX-MSG: src=0x%04X, msg_id=0x%04X, size=%d", src_addr, msg_id, data_sz); + UCSI_ReleaseAmsMessage(&ucsContext->ucsiData); + } + + return 0; +} + /** This callback will be raised, when ever an applicative message on the control channel arrived */ void UCSI_CB_OnAmsMessageReceived(void *pTag) { - /* If not interested, just ignore this event. - Otherwise UCSI_GetAmsMessage may now be called asynchronous (mainloop) to get the content. - Don't forget to call UCSI_ReleaseAmsMessage after that */ + static sd_event_source *src_ptr = NULL; + + if (!src_ptr) + { + /* first time usage: create and trigger event source */ + sd_event_add_defer(afb_daemon_get_event_loop(), &src_ptr, &OnAmsMessageReceivedCB, pTag); + } + else + { + sd_event_source_set_enabled(src_ptr, SD_EVENT_ONESHOT); + } } void UCSI_CB_OnRouteResult(void *pTag, uint16_t routeId, bool isActive, uint16_t connectionLabel) @@ -511,6 +577,33 @@ OnExitError: return; } +PUBLIC void ucs2_subscriberx (struct afb_req request) { + + if (!eventDataRx) { + + eventDataRx = malloc(sizeof(EventDataRx_t)); + if (eventDataRx) { + eventDataRx->rx_event = afb_daemon_make_event("rx-message"); + } + + if (!eventDataRx || !afb_event_is_valid(eventDataRx->rx_event)) { + afb_req_fail_f(request, "create-event", "Cannot create or register event"); + goto OnExitError; + } + } + + if (afb_req_subscribe(request, eventDataRx->rx_event) != 0) { + + afb_req_fail_f (request, "subscribe-event", "Cannot subscribe to event"); + goto OnExitError; + } + + afb_req_success(request,NULL,"event subscription successful"); + +OnExitError: + return; +} + static json_object * ucs2_validate_command (struct afb_req request, const char* func_name) { |