summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt44
-rw-r--r--src/plugins/CMakeLists.txt153
-rw-r--r--src/plugins/TestMain.cpp20
-rw-r--r--src/plugins/VshlCapabilitiesApi.cpp411
-rw-r--r--src/plugins/VshlCapabilitiesApi.h39
-rw-r--r--src/plugins/afb/AFBApiImpl.cpp78
-rw-r--r--src/plugins/afb/AFBApiImpl.h61
-rw-r--r--src/plugins/afb/AFBRequestImpl.cpp37
-rw-r--r--src/plugins/afb/AFBRequestImpl.h49
-rw-r--r--src/plugins/afb/include/AFBEventImpl.h77
-rw-r--r--src/plugins/afb/src/AFBEventImpl.cpp89
-rwxr-xr-xsrc/plugins/agreement.sh43
-rw-r--r--src/plugins/capabilities/CapabilitiesFactory.cpp71
-rw-r--r--src/plugins/capabilities/CapabilitiesFactory.h69
-rw-r--r--src/plugins/capabilities/CapabilityMessagingService.cpp117
-rw-r--r--src/plugins/capabilities/CapabilityMessagingService.h82
-rw-r--r--src/plugins/capabilities/communication/include/PhoneControlCapability.h57
-rw-r--r--src/plugins/capabilities/communication/include/PhoneControlMessages.h208
-rw-r--r--src/plugins/capabilities/communication/src/PhoneControlCapability.cpp52
-rw-r--r--src/plugins/capabilities/core/include/MessageChannel.h68
-rw-r--r--src/plugins/capabilities/core/include/PublisherForwarder.h73
-rw-r--r--src/plugins/capabilities/core/include/SubscriberForwarder.h84
-rw-r--r--src/plugins/capabilities/core/src/MessageChannel.cpp51
-rw-r--r--src/plugins/capabilities/core/src/PublisherForwarder.cpp69
-rw-r--r--src/plugins/capabilities/core/src/SubscriberForwarder.cpp139
-rw-r--r--src/plugins/capabilities/guimetadata/include/GuiMetadataCapability.h57
-rw-r--r--src/plugins/capabilities/guimetadata/include/GuiMetadataMessages.h59
-rw-r--r--src/plugins/capabilities/guimetadata/src/GuiMetadataCapability.cpp52
-rw-r--r--src/plugins/capabilities/navigation/include/NavigationCapability.h57
-rw-r--r--src/plugins/capabilities/navigation/include/NavigationMessages.h56
-rw-r--r--src/plugins/capabilities/navigation/src/NavigationCapability.cpp52
-rw-r--r--src/plugins/capabilities/playbackcontroller/include/PlaybackControllerCapability.h57
-rw-r--r--src/plugins/capabilities/playbackcontroller/include/PlaybackControllerMessages.h64
-rw-r--r--src/plugins/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp52
-rw-r--r--src/plugins/capabilities/test/CapabilityMessagingServiceTest.cpp96
-rw-r--r--src/plugins/capabilities/test/PublisherForwarderTest.cpp116
-rw-r--r--src/plugins/capabilities/test/SubscriberForwarderTest.cpp262
-rw-r--r--src/plugins/cmake/gtest.cmake44
-rw-r--r--src/plugins/interfaces/afb/IAFBApi.h98
-rw-r--r--src/plugins/interfaces/capabilities/ICapability.h58
-rw-r--r--src/plugins/interfaces/utilities/events/IEventFilter.h46
-rw-r--r--src/plugins/interfaces/utilities/logging/ILogger.h42
-rw-r--r--src/plugins/test/common/ConsoleLogger.cpp31
-rw-r--r--src/plugins/test/common/ConsoleLogger.h37
-rw-r--r--src/plugins/test/mocks/AFBApiMock.h41
-rw-r--r--src/plugins/test/mocks/AFBEventMock.h47
-rw-r--r--src/plugins/test/mocks/AFBRequestMock.h33
-rw-r--r--src/plugins/test/mocks/CapabilityMock.h35
-rw-r--r--src/plugins/utilities/events/EventRouter.cpp68
-rw-r--r--src/plugins/utilities/events/EventRouter.h66
-rw-r--r--src/plugins/utilities/logging/Logger.cpp56
-rw-r--r--src/plugins/utilities/logging/Logger.h53
-rw-r--r--src/vshl-capabilities-apidef.h53
-rw-r--r--src/vshl-capabilities-apidef.json109
-rw-r--r--src/vshl-capabilities-binding.c126
-rw-r--r--src/vshl-capabilities-binding.h25
56 files changed, 4289 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..6bc208f
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,44 @@
+###########################################################################
+# Copyright 2017-2018 Amazon.com, Inc. or its affiliates. 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.
+###########################################################################
+
+# Add target to project dependency list
+PROJECT_TARGET_ADD(vshl-capabilities)
+ set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ set(CMAKE_CXX_EXTENSIONS OFF)
+
+ # Define project Targets
+ add_library(${TARGET_NAME} MODULE
+ ${TARGET_NAME}-binding.c
+ )
+
+ set(OPENAPI_DEF "${TARGET_NAME}-apidef" CACHE STRING "name and path to the JSON API definition without extension")
+
+ # Binder exposes a unique public entry point
+ SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+ PREFIX "afb-"
+ LABELS "BINDINGV3"
+ LINK_FLAGS ${BINDINGS_LINK_FLAG}
+ OUTPUT_NAME ${TARGET_NAME}
+ )
+
+ # Library dependencies (include updates automatically)
+ TARGET_LINK_LIBRARIES(${TARGET_NAME}
+ afb-helpers
+ ctl-utilities
+ ${link_libraries})
+
+add_subdirectory("plugins") \ No newline at end of file
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
new file mode 100644
index 0000000..705b13d
--- /dev/null
+++ b/src/plugins/CMakeLists.txt
@@ -0,0 +1,153 @@
+###########################################################################
+# Copyright 2017-2018 Amazon.com, Inc. or its affiliates. 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.
+###########################################################################
+
+PROJECT_TARGET_ADD(vshl-capabilities-api)
+
+ set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ set(CMAKE_CXX_EXTENSIONS OFF)
+
+ set(VSHL_CAPABILITIES_LIB_SRC
+ ${CMAKE_CURRENT_SOURCE_DIR}/VshlCapabilitiesApi.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/VshlCapabilitiesApi.h
+
+ # Interfaces
+ ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/afb/IAFBApi.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/capabilities/ICapability.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/utilities/events/IEventFilter.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/utilities/logging/ILogger.h
+
+ # AFB
+ ${CMAKE_CURRENT_SOURCE_DIR}/afb/AFBApiImpl.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/afb/AFBApiImpl.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/afb/AFBRequestImpl.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/afb/AFBRequestImpl.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/afb/include/AFBEventImpl.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/afb/src/AFBEventImpl.cpp
+
+ #Capabilities
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/CapabilitiesFactory.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/CapabilitiesFactory.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/CapabilityMessagingService.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/CapabilityMessagingService.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/core/include/MessageChannel.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/core/src/MessageChannel.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/core/include/PublisherForwarder.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/core/src/PublisherForwarder.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/core/include/SubscriberForwarder.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/core/src/SubscriberForwarder.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/communication/include/PhoneControlMessages.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/communication/include/PhoneControlCapability.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/communication/src/PhoneControlCapability.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/playbackcontroller/include/PlaybackControllerMessages.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/playbackcontroller/include/PlaybackControllerCapability.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/navigation/include/NavigationMessages.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/navigation/include/NavigationCapability.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/navigation/src/NavigationCapability.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/guimetadata/include/GuiMetadataMessages.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/guimetadata/include/GuiMetadataCapability.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/guimetadata/src/GuiMetadataCapability.cpp
+
+ #Utilities
+ ${CMAKE_CURRENT_SOURCE_DIR}/utilities/events/EventRouter.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/utilities/events/EventRouter.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/utilities/logging/Logger.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/utilities/logging/Logger.cpp
+ )
+
+ # Define targets
+ ADD_LIBRARY(${TARGET_NAME} MODULE
+ ${VSHL_CAPABILITIES_LIB_SRC}
+ )
+
+ # VSHL Capabilities plugin properties
+ SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+ LABELS "PLUGIN"
+ PREFIX ""
+ SUFFIX ".ctlso"
+ OUTPUT_NAME ${TARGET_NAME}
+ )
+
+ # Define target includes
+ TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME}
+ PUBLIC ${GLIB_PKG_INCLUDE_DIRS}
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}"
+ PRIVATE "${CMAKE_SOURCE_DIR}/app-controller/ctl-lib"
+ )
+
+ # Library dependencies (include updates automatically)
+ TARGET_LINK_LIBRARIES(${TARGET_NAME}
+ afb-helpers
+ ${GLIB_PKG_LIBRARIES}
+ ${link_libraries}
+ )
+
+ option(ENABLE_UNIT_TESTS "Build unit tests or not" OFF)
+ if (ENABLE_UNIT_TESTS)
+ execute_process(
+ COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/agreement.sh"
+ RESULT_VARIABLE AGREEMENT_RESULT
+ )
+ message(STATUS "Agreement Result: ${AGREEMENT_RESULT}")
+ if (${AGREEMENT_RESULT} MATCHES "1")
+ message(FATAL_ERROR "User agreement not accepted. Quitting")
+ endif()
+
+ include(cmake/gtest.cmake)
+
+ set(VSHL_CAPABILITIES_TEST_SRC ${VSHL_CAPABILITIES_LIB_SRC})
+ list(APPEND VSHL_CAPABILITIES_TEST_SRC
+ # Main
+ ${CMAKE_CURRENT_SOURCE_DIR}/TestMain.cpp
+
+ # Test common
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/common/ConsoleLogger.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/common/ConsoleLogger.cpp
+
+ # Test Mocks
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/mocks/AFBApiMock.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/mocks/AFBEventMock.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/mocks/AFBRequestMock.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/mocks/CapabilityMock.h
+
+ # Capabilities
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/test/CapabilityMessagingServiceTest.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/test/PublisherForwarderTest.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/capabilities/test/SubscriberForwarderTest.cpp
+ )
+
+ ADD_EXECUTABLE(${TARGET_NAME}_Test
+ ${VSHL_CAPABILITIES_TEST_SRC}
+ )
+
+ TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME}_Test
+ PUBLIC ${GLIB_PKG_INCLUDE_DIRS}
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}"
+ PRIVATE "${CMAKE_SOURCE_DIR}/app-controller/ctl-lib"
+ )
+
+ TARGET_LINK_LIBRARIES(${TARGET_NAME}_Test
+ afb-helpers
+ libgtest
+ libgmock
+ ${GLIB_PKG_LIBRARIES}
+ ${link_libraries}
+ )
+
+ ENABLE_TESTING()
+ ADD_TEST(VshlCapabilitiesTest ${TARGET_NAME}_Test)
+ endif() \ No newline at end of file
diff --git a/src/plugins/TestMain.cpp b/src/plugins/TestMain.cpp
new file mode 100644
index 0000000..d4fcbec
--- /dev/null
+++ b/src/plugins/TestMain.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "gtest/gtest.h"
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+} \ No newline at end of file
diff --git a/src/plugins/VshlCapabilitiesApi.cpp b/src/plugins/VshlCapabilitiesApi.cpp
new file mode 100644
index 0000000..c02fb8f
--- /dev/null
+++ b/src/plugins/VshlCapabilitiesApi.cpp
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "VshlCapabilitiesApi.h"
+
+#include <list>
+
+#include "afb/AFBApiImpl.h"
+#include "afb/AFBRequestImpl.h"
+#include "capabilities/CapabilitiesFactory.h"
+#include "capabilities/CapabilityMessagingService.h"
+#include "utilities/events/EventRouter.h"
+#include "utilities/logging/Logger.h"
+
+#include "json.hpp"
+
+using namespace std;
+
+CTLP_CAPI_REGISTER("vshlsupport-api");
+
+static std::string TAG = "vshlcapabilities::plugins::VshlCapabilitiesApi";
+
+static std::string EVENTS_JSON_ATTR_VA_ID = "va_id";
+static std::string EVENTS_JSON_ATTR_EVENTS = "events";
+
+static std::string CAPABILITIES_JSON_ATTR_ACTION = "action";
+static std::string CAPABILITIES_JSON_ATTR_ACTIONS = "actions";
+static std::string CAPABILITIES_JSON_ATTR_PAYLOAD = "payload";
+
+static std::shared_ptr<vshlcapabilities::utilities::logging::Logger> sLogger;
+static std::shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> sAfbApi;
+static std::unique_ptr<vshlcapabilities::capabilities::CapabilitiesFactory> sCapabilitiesFactory;
+static std::unique_ptr<vshlcapabilities::capabilities::CapabilityMessagingService> sCapabilityMessagingService;
+static std::unique_ptr<vshlcapabilities::utilities::events::EventRouter> sEventRouter;
+
+using json = nlohmann::json;
+using Level = vshlcapabilities::utilities::logging::Logger::Level;
+
+CTLP_ONLOAD(plugin, ret) {
+ if (plugin->api == nullptr) {
+ return -1;
+ }
+
+ // Logger
+ sLogger = vshlcapabilities::utilities::logging::Logger::create(plugin->api);
+
+ // AFB Wrapper
+ sAfbApi = vshlcapabilities::afb::AFBApiImpl::create(plugin->api);
+
+ // EventRouter
+ sEventRouter = vshlcapabilities::utilities::events::EventRouter::create(sLogger);
+ if (!sEventRouter) {
+ sLogger->log(Level::ERROR, TAG, "Failed to create EventRouter");
+ return -1;
+ }
+
+ sCapabilitiesFactory = vshlcapabilities::capabilities::CapabilitiesFactory::create(sLogger);
+ if (!sCapabilitiesFactory) {
+ sLogger->log(Level::ERROR, TAG, "Failed to create CapabilitiesFactory");
+ return -1;
+ }
+
+ sCapabilityMessagingService = vshlcapabilities::capabilities::CapabilityMessagingService::create(sLogger, sAfbApi);
+ if (!sCapabilityMessagingService) {
+ sLogger->log(Level::ERROR, TAG, "Failed to create CapabilityMessagingService");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+CTLP_CAPI(guiMetadataSubscribe, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> guMetadataCapability = sCapabilitiesFactory->getGuiMetadata();
+ if (!guMetadataCapability) {
+ sLogger->log(
+ Level::WARNING,
+ TAG,
+ "guimetadataSubscribe: Failed to "
+ "fetch guimetadata capability "
+ "object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "guimetadataSubscribe: No arguments supplied.");
+ return -1;
+ }
+
+ json subscribeJson = json::parse(json_object_to_json_string(eventJ));
+ if (subscribeJson.find(CAPABILITIES_JSON_ATTR_ACTIONS) == subscribeJson.end()) {
+ sLogger->log(Level::ERROR, TAG, "guimetadataSubscribe: No events array found in subscribe json");
+ return -1;
+ }
+ list<string> events(subscribeJson[CAPABILITIES_JSON_ATTR_ACTIONS].get<list<string>>());
+
+ // SUbscribe this client for the guimetadata events.
+ auto request = vshlcapabilities::afb::AFBRequestImpl::create(source->request);
+ for (auto event : events) {
+ if (!sCapabilityMessagingService->subscribe(*request, guMetadataCapability, event)) {
+ sLogger->log(Level::ERROR, TAG, "guimetadataSubscribe: Failed to subscribe to event: " + event);
+ return -1;
+ }
+ }
+
+ AFB_ReqSuccess(
+ source->request, json_object_new_string("Subscription to guimetadata events successfully completed."), NULL);
+ return 0;
+}
+
+CTLP_CAPI(guiMetadataPublish, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> guMetadataCapability = sCapabilitiesFactory->getGuiMetadata();
+ if (!guMetadataCapability) {
+ sLogger->log(
+ Level::WARNING,
+ TAG,
+ "guimetadataPublish: Failed to fetch "
+ "guimetadata capability object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "guimetadataPublish: No arguments supplied.");
+ return -1;
+ }
+
+ json_object* actionJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_ACTION.c_str());
+ if (actionJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "guimetadataPublish: No action found in publish json");
+ return -1;
+ }
+
+ std::string action = std::string(json_object_get_string(actionJ));
+ if (action.empty()) {
+ sLogger->log(Level::ERROR, TAG, "guimetadataPublish: Invalid action input found in publish json");
+ return -1;
+ }
+
+ json_object* payloadJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_PAYLOAD.c_str());
+ if (payloadJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "guimetadataPublish: No playload found in publish json");
+ return -1;
+ }
+
+ if (!sCapabilityMessagingService->publish(guMetadataCapability, action, payloadJ)) {
+ sLogger->log(Level::ERROR, TAG, "guimetadataPublish: Failed to publish message: " + action);
+ return -1;
+ }
+
+ AFB_ReqSuccess(source->request, json_object_new_string("Successfully published guimetadata messages."), NULL);
+ return 0;
+}
+
+CTLP_CAPI(phonecontrolSubscribe, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> phoneControlCapability = sCapabilitiesFactory->getPhoneControl();
+ if (!phoneControlCapability) {
+ sLogger->log(Level::WARNING, TAG, "phoneControlSubscribe: Failed to fetch phone control capability object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "phoneControlSubscribe: No arguments supplied.");
+ return -1;
+ }
+
+ json subscribeJson = json::parse(json_object_to_json_string(eventJ));
+ if (subscribeJson.find(CAPABILITIES_JSON_ATTR_ACTIONS) == subscribeJson.end()) {
+ sLogger->log(Level::ERROR, TAG, "phoneControlSubscribe: No events array found in subscribe json");
+ return -1;
+ }
+ list<string> events(subscribeJson[CAPABILITIES_JSON_ATTR_ACTIONS].get<list<string>>());
+
+ // SUbscribe this client for the phone call control events.
+ auto request = vshlcapabilities::afb::AFBRequestImpl::create(source->request);
+ for (auto event : events) {
+ if (!sCapabilityMessagingService->subscribe(*request, phoneControlCapability, event)) {
+ sLogger->log(Level::ERROR, TAG, "phoneControlSubscribe: Failed to subscribe to event: " + event);
+ return -1;
+ }
+ }
+
+ AFB_ReqSuccess(
+ source->request, json_object_new_string("Subscription to phone control events successfully completed."), NULL);
+ return 0;
+}
+
+CTLP_CAPI(phonecontrolPublish, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> phoneControlCapability = sCapabilitiesFactory->getPhoneControl();
+ if (!phoneControlCapability) {
+ sLogger->log(Level::WARNING, TAG, "phoneControlPublish: Failed to fetch navigation capability object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "phoneControlPublish: No arguments supplied.");
+ return -1;
+ }
+
+ json_object* actionJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_ACTION.c_str());
+ if (actionJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "phoneControlPublish: No action found in publish json");
+ return -1;
+ }
+
+ std::string action = std::string(json_object_get_string(actionJ));
+ if (action.empty()) {
+ sLogger->log(Level::ERROR, TAG, "phoneControlPublish: Invalid action input found in publish json");
+ return -1;
+ }
+
+ json_object* payloadJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_PAYLOAD.c_str());
+ if (payloadJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "phoneControlPublish: No playload found in publish json");
+ return -1;
+ }
+
+ if (!sCapabilityMessagingService->publish(phoneControlCapability, action, payloadJ)) {
+ sLogger->log(Level::ERROR, TAG, "phoneControlPublish: Failed to publish message: " + action);
+ return -1;
+ }
+
+ AFB_ReqSuccess(source->request, json_object_new_string("Successfully published phone control messages."), NULL);
+ return 0;
+}
+
+CTLP_CAPI(navigationSubscribe, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> navigationCapability = sCapabilitiesFactory->getNavigation();
+ if (!navigationCapability) {
+ sLogger->log(Level::WARNING, TAG, "navigationSubscribe: Failed to fetch navigation capability object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "navigationSubscribe: No arguments supplied.");
+ return -1;
+ }
+
+ json subscribeJson = json::parse(json_object_to_json_string(eventJ));
+ if (subscribeJson.find(CAPABILITIES_JSON_ATTR_ACTIONS) == subscribeJson.end()) {
+ sLogger->log(Level::ERROR, TAG, "navigationSubscribe: No events array found in subscribe json");
+ return -1;
+ }
+ list<string> events(subscribeJson[CAPABILITIES_JSON_ATTR_ACTIONS].get<list<string>>());
+
+ // SUbscribe this client for the navigation events.
+ auto request = vshlcapabilities::afb::AFBRequestImpl::create(source->request);
+ for (auto event : events) {
+ if (!sCapabilityMessagingService->subscribe(*request, navigationCapability, event)) {
+ sLogger->log(Level::ERROR, TAG, "navigationSubscribe: Failed to subscribe to event: " + event);
+ return -1;
+ }
+ }
+
+ AFB_ReqSuccess(
+ source->request, json_object_new_string("Subscription to navigation events successfully completed."), NULL);
+ return 0;
+}
+
+CTLP_CAPI(navigationPublish, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> navigationCapability = sCapabilitiesFactory->getNavigation();
+ if (!navigationCapability) {
+ sLogger->log(Level::WARNING, TAG, "navigationPublish: Failed to fetch navigation capability object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "navigationPublish: No arguments supplied.");
+ return -1;
+ }
+
+ json_object* actionJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_ACTION.c_str());
+ if (actionJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "navigationPublish: No action found in publish json");
+ return -1;
+ }
+
+ std::string action = std::string(json_object_get_string(actionJ));
+ if (action.empty()) {
+ sLogger->log(Level::ERROR, TAG, "navigationPublish: Invalid action input found in publish json");
+ return -1;
+ }
+
+ json_object* payloadJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_PAYLOAD.c_str());
+ if (payloadJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "navigationPublish: No playload found in publish json");
+ return -1;
+ }
+
+ if (!sCapabilityMessagingService->publish(navigationCapability, action, payloadJ)) {
+ sLogger->log(Level::ERROR, TAG, "navigationPublish: Failed to publish message: " + action);
+ return -1;
+ }
+
+ AFB_ReqSuccess(source->request, json_object_new_string("Successfully published navigation messages."), NULL);
+ return 0;
+}
+
+CTLP_CAPI(playbackControllerSubscribe, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> playbackcontrollerCapability = sCapabilitiesFactory->getPlaybackController();
+ if (!playbackcontrollerCapability) {
+ sLogger->log(Level::WARNING, TAG, "playbackControllerSubscribe: Failed to fetch playbackcontroller capability object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "playbackControllerSubscribe: No arguments supplied.");
+ return -1;
+ }
+
+ json subscribeJson = json::parse(json_object_to_json_string(eventJ));
+ if (subscribeJson.find(CAPABILITIES_JSON_ATTR_ACTIONS) == subscribeJson.end()) {
+ sLogger->log(Level::ERROR, TAG, "playbackControllerSubscribe: No events array found in subscribe json");
+ return -1;
+ }
+ list<string> events(subscribeJson[CAPABILITIES_JSON_ATTR_ACTIONS].get<list<string>>());
+
+ // SUbscribe this client for the navigation events.
+ auto request = vshlcapabilities::afb::AFBRequestImpl::create(source->request);
+ for (auto event : events) {
+ if (!sCapabilityMessagingService->subscribe(*request, playbackcontrollerCapability, event)) {
+ sLogger->log(Level::ERROR, TAG, "playbackControllerSubscribe: Failed to subscribe to event: " + event);
+ return -1;
+ }
+ }
+
+ AFB_ReqSuccess(
+ source->request, json_object_new_string("Subscription to playbackcontroller events successfully completed."), NULL);
+ return 0;
+}
+
+CTLP_CAPI(playbackControllerPublish, source, argsJ, eventJ) {
+ if (sCapabilitiesFactory == nullptr || sCapabilityMessagingService == nullptr) {
+ return -1;
+ }
+
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> playbackcontrollerCapability = sCapabilitiesFactory->getPlaybackController();
+ if (!playbackcontrollerCapability) {
+ sLogger->log(Level::WARNING, TAG, "playbackControllerPublish: Failed to fetch playbackcontroller capability object.");
+ return -1;
+ }
+
+ if (eventJ == nullptr) {
+ sLogger->log(Level::WARNING, TAG, "playbackControllerPublish: No arguments supplied.");
+ return -1;
+ }
+
+ json_object* actionJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_ACTION.c_str());
+ if (actionJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "playbackControllerPublish: No action found in publish json");
+ return -1;
+ }
+
+ std::string action = std::string(json_object_get_string(actionJ));
+ if (action.empty()) {
+ sLogger->log(Level::ERROR, TAG, "playbackControllerPublish: Invalid action input found in publish json");
+ return -1;
+ }
+
+ json_object* payloadJ = json_object_object_get(eventJ , CAPABILITIES_JSON_ATTR_PAYLOAD.c_str());
+ if (payloadJ == nullptr) {
+ sLogger->log(Level::ERROR, TAG, "playbackControllerPublish: No playload found in publish json");
+ return -1;
+ }
+
+ if (!sCapabilityMessagingService->publish(playbackcontrollerCapability, action, payloadJ)) {
+ sLogger->log(Level::ERROR, TAG, "playbackControllerPublish: Failed to publish message: " + action);
+ return -1;
+ }
+
+ AFB_ReqSuccess(source->request, json_object_new_string("Successfully published playbackcontroller messages."), NULL);
+ return 0;
+} \ No newline at end of file
diff --git a/src/plugins/VshlCapabilitiesApi.h b/src/plugins/VshlCapabilitiesApi.h
new file mode 100644
index 0000000..1ef1d71
--- /dev/null
+++ b/src/plugins/VshlCapabilitiesApi.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-2018 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_API_INCLUDE
+#define VSHL_CAPABILITIES_API_INCLUDE
+
+#include "ctl-plugin.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CTLP_ONLOAD(plugin, ret);
+CTLP_INIT(plugin, ret);
+int guiMetadataSubscribe(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+int guiMetadataPublish(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+int phonecontrolSubscribe(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+int phonecontrolPublish(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+int navigationSubscribe(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+int navigationPublish(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+int playbackControllerSubscribe(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+int playbackControllerPublish(CtlSourceT* source, json_object* argsJ, json_object* queryJ);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // VSHL_CAPABILITIES_API_INCLUDE
diff --git a/src/plugins/afb/AFBApiImpl.cpp b/src/plugins/afb/AFBApiImpl.cpp
new file mode 100644
index 0000000..443a412
--- /dev/null
+++ b/src/plugins/afb/AFBApiImpl.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "afb/AFBApiImpl.h"
+
+#include "afb/include/AFBEventImpl.h"
+#include "utilities/logging/Logger.h"
+
+extern "C" {
+#define AFB_BINDING_VERSION 3
+
+#include "afb-definitions.h"
+}
+
+static std::string TAG = "vshlcapabilities::afb::AFBApiImpl";
+
+/**
+ * Specifies the severity level of a log message
+ */
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+using namespace vshlcapabilities::common::interfaces;
+using namespace vshlcapabilities::utilities::logging;
+
+namespace vshlcapabilities {
+namespace afb {
+
+std::unique_ptr<AFBApiImpl> AFBApiImpl::create(AFB_ApiT api) {
+ return std::unique_ptr<AFBApiImpl>(new AFBApiImpl(api));
+}
+
+AFBApiImpl::AFBApiImpl(AFB_ApiT api) : mApi(api), mLogger(Logger::create(api)) {
+}
+
+AFBApiImpl::~AFBApiImpl() {
+}
+
+std::shared_ptr<IAFBApi::IAFBEvent> AFBApiImpl::createEvent(const std::string& eventName) {
+ return AFBEventImpl::create(mLogger, mApi, eventName);
+}
+
+int AFBApiImpl::callSync(
+ const std::string& api,
+ const std::string& verb,
+ struct json_object* request,
+ struct json_object** result,
+ std::string& error,
+ std::string& info) {
+ char* errorStr = NULL;
+ char* infoStr = NULL;
+ int rc = AFB_ApiSync(mApi, api.c_str(), verb.c_str(), request, result, &errorStr, &infoStr);
+
+ if (errorStr) {
+ error = errorStr;
+ free(errorStr);
+ }
+
+ if (infoStr) {
+ info = infoStr;
+ free(infoStr);
+ }
+
+ return rc;
+}
+
+} // namespace afb
+} // namespace vshl
diff --git a/src/plugins/afb/AFBApiImpl.h b/src/plugins/afb/AFBApiImpl.h
new file mode 100644
index 0000000..a8d8e08
--- /dev/null
+++ b/src/plugins/afb/AFBApiImpl.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_AFB_AFBAPIIMPL_H_
+#define VSHL_AFB_AFBAPIIMPL_H_
+
+#include <memory>
+
+extern "C" {
+#include "ctl-plugin.h"
+}
+
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace afb {
+
+class AFBApiImpl : public vshlcapabilities::common::interfaces::IAFBApi {
+public:
+ static std::unique_ptr<AFBApiImpl> create(AFB_ApiT api);
+
+ ~AFBApiImpl();
+
+ std::shared_ptr<IAFBEvent> createEvent(const std::string& eventName) override;
+
+ int callSync(
+ const std::string& api,
+ const std::string& verb,
+ struct json_object* request,
+ struct json_object** result,
+ std::string& error,
+ std::string& info) override;
+
+private:
+ AFBApiImpl(AFB_ApiT api);
+
+ // AFB API Binding
+ AFB_ApiT mApi;
+
+ // Logger
+ std::shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace afb
+} // namespace vshl
+
+#endif // VSHL_AFB_AFBAPIIMPL_H_
diff --git a/src/plugins/afb/AFBRequestImpl.cpp b/src/plugins/afb/AFBRequestImpl.cpp
new file mode 100644
index 0000000..3e20172
--- /dev/null
+++ b/src/plugins/afb/AFBRequestImpl.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "afb/AFBRequestImpl.h"
+
+extern "C" {
+#include "afb-definitions.h"
+}
+
+namespace vshlcapabilities {
+namespace afb {
+
+std::unique_ptr<AFBRequestImpl> AFBRequestImpl::create(AFB_ReqT afbRequest) {
+ return std::unique_ptr<AFBRequestImpl>(new AFBRequestImpl(afbRequest));
+}
+
+AFBRequestImpl::AFBRequestImpl(AFB_ReqT afbRequest) : mAfbRequest(afbRequest) {
+}
+
+void* AFBRequestImpl::getNativeRequest() {
+ return mAfbRequest;
+}
+
+} // namespace afb
+} // namespace vshl
diff --git a/src/plugins/afb/AFBRequestImpl.h b/src/plugins/afb/AFBRequestImpl.h
new file mode 100644
index 0000000..c155f31
--- /dev/null
+++ b/src/plugins/afb/AFBRequestImpl.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_AFB_AFBREQUESTIMPL_H_
+#define VSHL_AFB_AFBREQUESTIMPL_H_
+
+#include <memory>
+
+extern "C" {
+#include "ctl-plugin.h"
+}
+
+#include "interfaces/afb/IAFBApi.h"
+
+namespace vshlcapabilities {
+namespace afb {
+
+/**
+ * AFB Request impl
+ */
+class AFBRequestImpl : public vshlcapabilities::common::interfaces::IAFBRequest {
+public:
+ static std::unique_ptr<AFBRequestImpl> create(AFB_ReqT afbRequest);
+
+ // {@c IAFBRequest Implementation
+ void *getNativeRequest() override;
+ // @c IAFBRequest Implementation }
+
+private:
+ AFBRequestImpl(AFB_ReqT afbRequest);
+
+ AFB_ReqT mAfbRequest;
+};
+
+} // namespace afb
+} // namespace vshl
+
+#endif // VSHL_AFB_AFBREQUESTIMPL_H_
diff --git a/src/plugins/afb/include/AFBEventImpl.h b/src/plugins/afb/include/AFBEventImpl.h
new file mode 100644
index 0000000..2dda513
--- /dev/null
+++ b/src/plugins/afb/include/AFBEventImpl.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_AFB_EVENT_H_
+#define VSHL_AFB_EVENT_H_
+
+#include <memory>
+#include <string>
+
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+extern "C" {
+#include "ctl-plugin.h"
+#include <json-c/json.h>
+}
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace afb {
+/*
+ * This class encapsulates AFB Event.
+ */
+class AFBEventImpl : public vshlcapabilities::common::interfaces::IAFBApi::IAFBEvent {
+public:
+ static unique_ptr<AFBEventImpl>
+ create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, AFB_ApiT api,
+ const string &eventName);
+
+ // Destructor
+ ~AFBEventImpl();
+
+ /// { @c IAFBEvent implementation
+ string getName() const override;
+ bool isValid() override;
+ int publishEvent(struct json_object *payload) override;
+ bool subscribe(vshlcapabilities::common::interfaces::IAFBRequest &request) override;
+ bool unsubscribe(vshlcapabilities::common::interfaces::IAFBRequest &request) override;
+ /// @c IAFBEvent implementation }
+
+private:
+ AFBEventImpl(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ AFB_ApiT api, const string &eventName);
+
+ // Make the event. This is a lazy make that happens
+ // usually during the subscribe stage.
+ void makeEventIfNeccessary();
+
+ // Binding API reference
+ AFB_ApiT mAfbApi;
+
+ // AFB Event
+ afb_event_t mAfbEvent;
+
+ // Event Name
+ string mEventName;
+
+ // Logger
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace afb
+} // namespace vshl
+
+#endif // VSHL_AFB_EVENT_H_
diff --git a/src/plugins/afb/src/AFBEventImpl.cpp b/src/plugins/afb/src/AFBEventImpl.cpp
new file mode 100644
index 0000000..7ddac36
--- /dev/null
+++ b/src/plugins/afb/src/AFBEventImpl.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "afb/include/AFBEventImpl.h"
+
+static string TAG = "vshlcapabilities::afb::Event";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+using namespace vshlcapabilities::common::interfaces;
+
+namespace vshlcapabilities {
+namespace afb {
+
+unique_ptr<AFBEventImpl> AFBEventImpl::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ AFB_ApiT api,
+ const string& eventName) {
+ return unique_ptr<AFBEventImpl>(new AFBEventImpl(logger, api, eventName));
+}
+
+AFBEventImpl::AFBEventImpl(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ AFB_ApiT api,
+ const string& eventName) :
+ mLogger(logger),
+ mAfbApi(api),
+ mEventName(eventName),
+ mAfbEvent(nullptr) {
+}
+
+AFBEventImpl::~AFBEventImpl() {
+}
+
+string AFBEventImpl::getName() const {
+ return mEventName;
+}
+
+bool AFBEventImpl::isValid() {
+ makeEventIfNeccessary();
+ return afb_event_is_valid(mAfbEvent) == 1 ? true : false;
+}
+
+bool AFBEventImpl::subscribe(IAFBRequest& requestInterface) {
+ makeEventIfNeccessary();
+ auto request = static_cast<AFB_ReqT>(requestInterface.getNativeRequest());
+ if (isValid() && afb_req_subscribe(request, mAfbEvent) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
+bool AFBEventImpl::unsubscribe(IAFBRequest& requestInterface) {
+ makeEventIfNeccessary();
+ auto request = static_cast<AFB_ReqT>(requestInterface.getNativeRequest());
+ if (isValid() && afb_req_unsubscribe(request, mAfbEvent) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
+int AFBEventImpl::publishEvent(struct json_object* payload) {
+ makeEventIfNeccessary();
+ return afb_event_push(mAfbEvent, payload);
+}
+
+void AFBEventImpl::makeEventIfNeccessary() {
+ if (mAfbEvent) {
+ return;
+ }
+
+ mLogger->log(Level::NOTICE, TAG, "Creating VSHL event: " + mEventName);
+ mAfbEvent = afb_api_make_event(mAfbApi, mEventName.c_str());
+}
+
+} // namespace afb
+} // namespace vshl
diff --git a/src/plugins/agreement.sh b/src/plugins/agreement.sh
new file mode 100755
index 0000000..2a8eb71
--- /dev/null
+++ b/src/plugins/agreement.sh
@@ -0,0 +1,43 @@
+#********************************************************************************
+# Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+# A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "license" file accompanying this file. This file 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.
+#*********************************************************************************
+
+agreement_check() {
+ cat << EOF
+
+*******************************************************************************
+The scripts provided herein will retrieve several third-party libraries,
+environments, and/or other software packages at build-time
+("External Dependencies") from third-party sources. These are terms and
+conditions that you need to agree to abide by if you choose to build the
+External Dependencies. Licenses for the External Dependencies may be found at
+README.md. If you do not agree with every term and condition
+associated with the External Dependencies, enter “QUIT” in the command line
+when prompted by the script.
+*******************************************************************************
+
+EOF
+
+ answer="dummy"
+ while [ ! -z $answer ]; do
+ read -p "Type \"QUIT\" to exit the script now, press ENTER to continue: " -r answer
+ if [ "$answer" = "QUIT" ]; then
+ exit 1
+ fi
+ echo ""
+ done
+}
+
+agreement_check
+exit 0 \ No newline at end of file
diff --git a/src/plugins/capabilities/CapabilitiesFactory.cpp b/src/plugins/capabilities/CapabilitiesFactory.cpp
new file mode 100644
index 0000000..7a65842
--- /dev/null
+++ b/src/plugins/capabilities/CapabilitiesFactory.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/CapabilitiesFactory.h"
+
+#include "capabilities/communication/include/PhoneControlCapability.h"
+#include "capabilities/guimetadata/include/GuiMetadataCapability.h"
+#include "capabilities/navigation/include/NavigationCapability.h"
+#include "capabilities/playbackcontroller/include/PlaybackControllerCapability.h"
+
+static string TAG = "vshlcapabilities::core::CapabilitiesFactory";
+
+namespace vshlcapabilities {
+namespace capabilities {
+
+// Create CapabilitiesFactory
+std::unique_ptr<CapabilitiesFactory> CapabilitiesFactory::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ auto capabilitiesFactory = std::unique_ptr<CapabilitiesFactory>(new CapabilitiesFactory(logger));
+ return capabilitiesFactory;
+}
+
+CapabilitiesFactory::CapabilitiesFactory(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ mLogger = logger;
+}
+
+std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getGuiMetadata() {
+ if (!mGuiMetadata) {
+ mGuiMetadata = vshlcapabilities::capabilities::guimetadata::GuiMetadata::create(mLogger);
+ }
+ return mGuiMetadata;
+}
+
+std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getPhoneControl() {
+ if (!mPhoneControl) {
+ mPhoneControl = vshlcapabilities::capabilities::phonecontrol::PhoneControl::create(mLogger);
+ }
+ return mPhoneControl;
+}
+
+std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getNavigation(
+ ) {
+ if (!mNavigation) {
+ mNavigation = vshlcapabilities::capabilities::navigation::Navigation::create(mLogger);
+ }
+ return mNavigation;
+}
+
+std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getPlaybackController(
+ ) {
+ if (!mPlaybackController) {
+ mPlaybackController = vshlcapabilities::capabilities::playbackcontroller::PlaybackController::create(mLogger);
+ }
+ return mPlaybackController;
+}
+
+} // namespace capabilities
+} // namespace vshl \ No newline at end of file
diff --git a/src/plugins/capabilities/CapabilitiesFactory.h b/src/plugins/capabilities/CapabilitiesFactory.h
new file mode 100644
index 0000000..b97fcfe
--- /dev/null
+++ b/src/plugins/capabilities/CapabilitiesFactory.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_CAPABILITIESFACTORY_H_
+#define VSHL_CAPABILITIES_CAPABILITIESFACTORY_H_
+
+#include <memory>
+
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+/*
+ * Factory for creating different capability objects.
+ */
+class CapabilitiesFactory {
+public:
+ // Create CapabilitiesFactory
+ static std::unique_ptr<CapabilitiesFactory> create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ // GUI Metadata capability
+ std::shared_ptr<common::interfaces::ICapability> getGuiMetadata();
+
+ // Phone call control capability
+ std::shared_ptr<common::interfaces::ICapability> getPhoneControl();
+
+ // Navigation capability
+ std::shared_ptr<common::interfaces::ICapability> getNavigation();
+
+ // PLaybackcontroller capability
+ std::shared_ptr<common::interfaces::ICapability> getPlaybackController();
+
+ // Destructor
+ ~CapabilitiesFactory() = default;
+
+private:
+ // Constructor
+ CapabilitiesFactory(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ // Capabilities
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> mGuiMetadata;
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> mPhoneControl;
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> mNavigation;
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> mPlaybackController;
+
+ // Logger
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_CAPABILITIESFACTORY_H_
diff --git a/src/plugins/capabilities/CapabilityMessagingService.cpp b/src/plugins/capabilities/CapabilityMessagingService.cpp
new file mode 100644
index 0000000..8dd6e26
--- /dev/null
+++ b/src/plugins/capabilities/CapabilityMessagingService.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/CapabilityMessagingService.h"
+
+#include "capabilities/core/include/PublisherForwarder.h"
+#include "capabilities/core/include/SubscriberForwarder.h"
+
+static string TAG = "vshlcapabilities::capabilities::CapabilityMessagingService";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace capabilities {
+
+// Create a CapabilityMessagingService.
+unique_ptr<CapabilityMessagingService> CapabilityMessagingService::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi) {
+ if (logger == nullptr) {
+ return nullptr;
+ }
+
+ if (afbApi == nullptr) {
+ logger->log(Level::ERROR, TAG, "Failed to create CapabilityMessagingService: AFB API null");
+ return nullptr;
+ }
+
+ auto capabilityMessageService =
+ std::unique_ptr<CapabilityMessagingService>(new CapabilityMessagingService(logger, afbApi));
+ return capabilityMessageService;
+}
+
+CapabilityMessagingService::~CapabilityMessagingService() {
+ mMessageChannelsMap.clear();
+}
+
+CapabilityMessagingService::CapabilityMessagingService(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi) :
+ mAfbApi(afbApi),
+ mLogger(logger) {
+}
+
+// Subscribe to capability specific messages.
+bool CapabilityMessagingService::subscribe(
+ vshlcapabilities::common::interfaces::IAFBRequest& request,
+ shared_ptr<common::interfaces::ICapability> capability,
+ const string action) {
+ auto capabilityName = capability->getName();
+
+ if (capabilityName.empty()) {
+ mLogger->log(Level::ERROR, TAG, "Failed to subscribe to message. Invalid input.");
+ return false;
+ }
+
+ auto messageChannel = getMessageChannel(capability);
+ return messageChannel->subscribe(request, action);
+}
+
+// Publish capability messages.
+bool CapabilityMessagingService::publish(
+ shared_ptr<common::interfaces::ICapability> capability,
+ const string action,
+ json_object* payload) {
+ auto capabilityName = capability->getName();
+
+ if (capabilityName.empty()) {
+ mLogger->log(Level::ERROR, TAG, "Failed to publish message. Invalid input.");
+ return false;
+ }
+
+ auto messageChannelIt = mMessageChannelsMap.find(capabilityName);
+ if (messageChannelIt == mMessageChannelsMap.end()) {
+ mLogger->log(
+ Level::ERROR,
+ TAG,
+ "No one subscribed for a message of capability. " + capabilityName);
+ return false;
+ }
+
+ return messageChannelIt->second->publish(action, payload);
+}
+
+shared_ptr<vshlcapabilities::capabilities::core::MessageChannel> CapabilityMessagingService::getMessageChannel(
+ shared_ptr<common::interfaces::ICapability> capability) {
+ auto capabilityName = capability->getName();
+
+ if (capabilityName.empty()) {
+ mLogger->log(Level::ERROR, TAG, "Failed to create message channel. Invalid input.");
+ return nullptr;
+ }
+
+ auto messageChannelIt = mMessageChannelsMap.find(capabilityName);
+ if (messageChannelIt == mMessageChannelsMap.end()) {
+ mLogger->log(Level::INFO, TAG, "Creating new message channel for capability: " + capabilityName);
+ auto messageChannel = vshlcapabilities::capabilities::core::MessageChannel::create(mLogger, mAfbApi, capability);
+ mMessageChannelsMap.insert(make_pair(capabilityName, messageChannel));
+ return messageChannel;
+ }
+
+ return messageChannelIt->second;
+}
+
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/CapabilityMessagingService.h b/src/plugins/capabilities/CapabilityMessagingService.h
new file mode 100644
index 0000000..79edfa8
--- /dev/null
+++ b/src/plugins/capabilities/CapabilityMessagingService.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_CAPABILITYMESSAGINGSERVICE_H_
+#define VSHL_CAPABILITIES_CAPABILITYMESSAGINGSERVICE_H_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "capabilities/core/include/MessageChannel.h"
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+/*
+ * This hosts service APIs that clients can use to subscribe and
+ * forward capability messages. Each capability has a name and
+ * direction (upstream/downstream). Upstream messages are from
+ * voiceagents to Apps and downstream messages are Apps to voiceagents.
+ * This class will use a factory to create publisher and subcribers for
+ * each capability and create assiociations between them.
+ */
+class CapabilityMessagingService {
+public:
+ // Create a CapabilityMessagingService.
+ static std::unique_ptr<CapabilityMessagingService>
+ create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi);
+
+ // Subscribe to capability specific messages.
+ bool subscribe(vshlcapabilities::common::interfaces::IAFBRequest &request,
+ shared_ptr<common::interfaces::ICapability> capability,
+ const string action);
+
+ // Publish capability messages.
+ bool publish(shared_ptr<common::interfaces::ICapability> capability,
+ const string action, json_object* payload);
+
+ // Destructor
+ ~CapabilityMessagingService();
+
+private:
+ // Constructor
+ CapabilityMessagingService(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi);
+
+ // Binding API reference
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> mAfbApi;
+
+ // Create a message channel for the capability.
+ shared_ptr<vshlcapabilities::capabilities::core::MessageChannel>
+ getMessageChannel(shared_ptr<common::interfaces::ICapability> capability);
+
+ // Map of capabilities to message channels.
+ unordered_map<string, shared_ptr<vshlcapabilities::capabilities::core::MessageChannel>>
+ mMessageChannelsMap;
+
+ // Logger
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_CAPABILITYMESSAGINGSERVICE_H_
diff --git a/src/plugins/capabilities/communication/include/PhoneControlCapability.h b/src/plugins/capabilities/communication/include/PhoneControlCapability.h
new file mode 100644
index 0000000..87dc339
--- /dev/null
+++ b/src/plugins/capabilities/communication/include/PhoneControlCapability.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_PHONECONTROL_CAPABILITY_H_
+#define VSHL_CAPABILITIES_PHONECONTROL_CAPABILITY_H_
+
+#include <memory>
+
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace phonecontrol {
+
+/*
+ * PhoneControl capability. Calls are initiated in the endpoint.
+ */
+class PhoneControl : public common::interfaces::ICapability {
+public:
+ // Create a PhoneControl.
+ static std::shared_ptr<PhoneControl> create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ ~PhoneControl() = default;
+
+protected:
+ string getName() const override;
+
+ list<string> getUpstreamMessages() const override;
+
+ list<string> getDownstreamMessages() const override;
+
+private:
+ PhoneControl(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace phonecontrol
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_PHONECONTROL_CAPABILITY_H_
diff --git a/src/plugins/capabilities/communication/include/PhoneControlMessages.h b/src/plugins/capabilities/communication/include/PhoneControlMessages.h
new file mode 100644
index 0000000..23d2fae
--- /dev/null
+++ b/src/plugins/capabilities/communication/include/PhoneControlMessages.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_PHONECONTROL_MESSAGES_H_
+#define VSHL_CAPABILITIES_PHONECONTROL_MESSAGES_H_
+
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace phonecontrol {
+
+static string NAME = "phonecontrol";
+
+/*
+ ******************************************************************************************************
+ * Supported actions from VA -> APPS
+ ******************************************************************************************************
+ */
+
+/* Dial message sent from VA to app handling the calling.
+ *
+ * payload:
+ * {
+ * "callId": "{{STRING}}",
+ * "callee": {
+ * "details": "{{STRING}}",
+ * "defaultAddress": {
+ * "protocol": "{{STRING}}",
+ * "format": "{{STRING}}",
+ * "value": "{{STRING}}"
+ * },
+ * "alternativeAddresses": [{
+ * "protocol": "{{STRING}}",
+ * "format": "{{STRING}}",
+ * "value": {{STRING}}
+ * }]
+ * }
+ * }
+ * }
+ *
+ * callId (required): A unique identifier for the call
+ * callee (required): The destination of the outgoing call
+ * callee.details (optional): Descriptive information about the callee
+ * callee.defaultAddress (required): The default address to use for calling the callee
+ * callee.alternativeAddresses (optional): An array of alternate addresses for the existing callee
+ * address.protocol (required): The protocol for this address of the callee (e.g. PSTN, SIP, H323, etc.)
+ * address.format (optional): The format for this address of the callee (e.g. E.164, E.163, E.123, DIN5008, etc.)
+ * address.value (required): The address of the callee.
+ *
+ */
+static string PHONECONTROL_DIAL = "dial";
+/**
+ * Notifies the platform implementation to redial the last called phone number.
+ *
+ * After returning @c true, if no stored number is available to be redialed, @c PhoneCallController::callFailed with
+ * @c CallError::NO_NUMBER_FOR_REDIAL should be called.
+ *
+ * @param [in] payload Details of the redial request in structured JSON format. See the following
+ * payload:
+ * {
+ * "callId": "{{STRING}}"
+ * }
+ * @li callId (required): A unique identifier for the call
+ *
+ * @return @c true if the platform implementation successfully handled the call
+ */
+static string PHONECONTROL_REDIAL = "redial";
+/**
+ * Notifies the platform implementation to answer an inbound call
+ *
+ * @param [in] payload Details of the answer request in structured JSON format. See the following
+ * payload:
+ * {
+ * "callId": "{{STRING}}",
+ * }
+ * @li callId (required): The unique identifier for the call to answer
+ */
+static string PHONECONTROL_ANSWER = "answer";
+/**
+ * Notifies the platform implementation to end an ongoing call or stop inbound or outbound call setup
+ *
+ * @param [in] payload Details of the stop request in structured JSON format. See the following
+ * payload:
+ * {
+ * "callId": "{{STRING}}"
+ * }
+ * @li callId (required): The unique identifier for the call to be stopped
+ */
+static string PHONECONTROL_STOP = "stop";
+/**
+ * Notifies the platform implementation to send a DTMF signal to the calling device
+ *
+ * @param [in] payload Details of the DTMF request in structured JSON format. See the following
+ * payload:
+ * {
+ * "callId": "{{STRING}}",
+ * "signal": "{{STRING}}"
+ * }
+ * @li callId (required): The unique identifier for the call
+ * @li signal (required): The DTMF string to be sent to the calling device associated with the callId
+ */
+static string PHONECONTROL_SEND_DTMF = "send_dtmf";
+
+/*
+ ******************************************************************************************************
+ * Supported actions from Apps -> VA
+ ******************************************************************************************************
+ */
+
+/*
+ * App notifies the voiceagents of a change in connection state of a calling device.
+ *
+ * payload:
+ * {
+ * "state" : "{{STRING}}" // CONNECTED or DISCONNECTED
+ * }
+ */
+static string PHONECONTROL_CONNECTIONSTATE_CHANGED = "connection_state_changed";
+/*
+ * App notifies the voiceagents that call is activated
+ *
+ * callId must match the one that is sent by VA with DIAL message above.
+ *
+ * payload:
+ * {
+ * "callId" : "{{STRING}}"
+ * "state" : "{{STRING}}" // IDLE, ACTIVE, TRYING, INBOUND_RINGING, OUTBOUND_RINGING, INVITED
+ * }
+ */
+static string PHONECONTROL_CALL_STATE_CHANGED = "call_state_changed";
+/*
+ * App notifies the voiceagents of an error in initiating or maintaining a
+ * call on a calling device
+ *
+ * callId must match the one that is sent by VA with DIAL message above.
+ * error: below status codes.
+ * 4xx: Validation failure for the input from the DIAL message
+ * 500: Internal error on the platform unrelated to the cellular network
+ * 503: Error on the platform related to the cellular network
+ *
+ * payload :
+ * {
+ * "callId" : "{{STRING}}"
+ * "error" : "{{STRING}}"
+ * }
+ */
+static string PHONECONTROL_CALL_FAILED = "call_failed";
+/**
+ * App notifies the voiceagents that a caller id was received for an inbound call
+ * payload :
+ * {
+ * "callId" : "{{STRING}}"
+ * "callerId" : "{{STRING}}"
+ * }
+ *
+ * @param [in] callId The unique identifier for the call associated with the callId
+ * @param [in] callerId The caller's identifier or phone number
+ */
+static string PHONECONTROL_CALLERID_RECEIVED = "caller_id_received";
+
+/**
+ * Notifies the Engine that sending the DTMF signal succeeded.
+ * payload :
+ * {
+ * "callId" : "{{STRING}}"
+ * }
+ * @param [in] callId The unique identifier for the associated call
+ *
+ * PhoneCallController::sendDTMF
+ */
+static string PHONECONTROL_SEND_DTMF_SUCCEEDED = "send_dtmf_succeeded";
+
+// List of actions that are delivered from VA -> Apps
+static list<string> PHONECONTROL_UPSTREAM_ACTIONS = {
+ PHONECONTROL_DIAL,
+ PHONECONTROL_REDIAL,
+ PHONECONTROL_ANSWER,
+ PHONECONTROL_STOP,
+ PHONECONTROL_SEND_DTMF
+};
+
+// List of actions that are delivered from Apps -> VA
+static list<string> PHONECONTROL_DOWNSTREAM_ACTIONS = {PHONECONTROL_CONNECTIONSTATE_CHANGED,
+ PHONECONTROL_CALL_STATE_CHANGED,
+ PHONECONTROL_CALL_FAILED,
+ PHONECONTROL_CALLERID_RECEIVED,
+ PHONECONTROL_SEND_DTMF_SUCCEEDED};
+
+} // namespace phonecontrol
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_PHONECONTROL_MESSAGES_H_
diff --git a/src/plugins/capabilities/communication/src/PhoneControlCapability.cpp b/src/plugins/capabilities/communication/src/PhoneControlCapability.cpp
new file mode 100644
index 0000000..75296bf
--- /dev/null
+++ b/src/plugins/capabilities/communication/src/PhoneControlCapability.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/communication/include/PhoneControlCapability.h"
+#include "capabilities/communication/include/PhoneControlMessages.h"
+
+const string TAG = "vshlcapabilities::capabilities::phonecontrol";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace phonecontrol {
+
+// Create a phonecontrol.
+shared_ptr<PhoneControl> PhoneControl::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ auto phonecontrol = std::shared_ptr<PhoneControl>(new PhoneControl(logger));
+ return phonecontrol;
+}
+
+PhoneControl::PhoneControl(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ mLogger = logger;
+}
+
+string PhoneControl::getName() const {
+ return NAME;
+}
+
+list<string> PhoneControl::getUpstreamMessages() const {
+ return PHONECONTROL_UPSTREAM_ACTIONS;
+}
+
+list<string> PhoneControl::getDownstreamMessages() const {
+ return PHONECONTROL_DOWNSTREAM_ACTIONS;
+}
+
+} // namespace phonecontrol
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/core/include/MessageChannel.h b/src/plugins/capabilities/core/include/MessageChannel.h
new file mode 100644
index 0000000..79e4eab
--- /dev/null
+++ b/src/plugins/capabilities/core/include/MessageChannel.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_CORE_MESSAGECHANNEL_H_
+#define VSHL_CAPABILITIES_CORE_MESSAGECHANNEL_H_
+
+#include <memory>
+
+#include "capabilities/core/include/PublisherForwarder.h"
+#include "capabilities/core/include/SubscriberForwarder.h"
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace core {
+/*
+ * MessageChannel has one end as publisher forwarder and the other end
+ * as subscriber forwarder.
+ */
+class MessageChannel {
+public:
+ // Create a MessageChannel.
+ static std::shared_ptr<MessageChannel>
+ create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability);
+
+ // Sends the message
+ bool publish(const string action, json_object* payload);
+
+ // Subscribe
+ bool subscribe(vshlcapabilities::common::interfaces::IAFBRequest &request,
+ const string action);
+
+ // Destructor
+ virtual ~MessageChannel() = default;
+
+private:
+ // Constructor
+ MessageChannel(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability);
+
+ // Forwarders
+ shared_ptr<PublisherForwarder> mPublisherForwarder;
+ shared_ptr<SubscriberForwarder> mSubscriberForwarder;
+};
+
+} // namespace core
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_CORE_MESSAGECHANNEL_H_
diff --git a/src/plugins/capabilities/core/include/PublisherForwarder.h b/src/plugins/capabilities/core/include/PublisherForwarder.h
new file mode 100644
index 0000000..01e9523
--- /dev/null
+++ b/src/plugins/capabilities/core/include/PublisherForwarder.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_CORE_PUBLISHERFORWARDER_H_
+#define VSHL_CAPABILITIES_CORE_PUBLISHERFORWARDER_H_
+
+#include <memory>
+
+#include "capabilities/core/include/SubscriberForwarder.h"
+
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace core {
+/*
+ * This class is responsible for forwarding the messages to be published
+ * to subscriber forwarder. Subscriber forwarder will deliver the messages
+ * as AFB Events to all the subscribed clients.
+ * There is one PublisherForwarder and one SubscriberForwarder per capability.
+ */
+class PublisherForwarder {
+public:
+ // Create a PublisherForwarder.
+ static std::shared_ptr<PublisherForwarder> create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability);
+
+ // Connect a subscriber forwarder to this publisher forwarder
+ void setSubscriberForwarder(shared_ptr<SubscriberForwarder> subscriberForwarder);
+
+ // Forward message to the subscriber forwarder
+ bool forwardMessage(const string action, json_object* payload);
+
+ // Destructor
+ ~PublisherForwarder();
+
+private:
+ // Constructor
+ PublisherForwarder(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability);
+
+ // Subscriber forwarder connected to this publisher forwarder.
+ shared_ptr<SubscriberForwarder> mSubscriberForwarder;
+
+ // Capability
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> mCapability;
+
+ // Logger
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace core
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_CORE_PUBLISHERFORWARDER_H_
diff --git a/src/plugins/capabilities/core/include/SubscriberForwarder.h b/src/plugins/capabilities/core/include/SubscriberForwarder.h
new file mode 100644
index 0000000..ac469b3
--- /dev/null
+++ b/src/plugins/capabilities/core/include/SubscriberForwarder.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_CORE_SUBSCRIBERFORWARDER_H_
+#define VSHL_CAPABILITIES_CORE_SUBSCRIBERFORWARDER_H_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace core {
+/*
+ * This class is responsible for forwarding the messages publishing
+ * to the actual clients using AFB.
+ */
+class SubscriberForwarder {
+public:
+ // Create a SubscriberForwarder.
+ static std::shared_ptr<SubscriberForwarder>
+ create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability);
+
+ // Publish a capability message to the actual client.
+ bool forwardMessage(const string action, json_object* payload);
+
+ // Subscribe
+ bool subscribe(vshlcapabilities::common::interfaces::IAFBRequest &request,
+ const string action);
+
+ // Destructor
+ ~SubscriberForwarder();
+
+private:
+ // Constructor
+ SubscriberForwarder(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability);
+
+ // Creates both upstream and downstream events
+ void createEvents();
+
+ // Binding API reference
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> mAfbApi;
+
+ // Capability
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> mCapability;
+
+ // Maps of capability action events to its corresponding Event object.
+ // Event name maps to Action Name
+ unordered_map<string, shared_ptr<common::interfaces::IAFBApi::IAFBEvent>>
+ mUpstreamEventsMap;
+ unordered_map<string, shared_ptr<common::interfaces::IAFBApi::IAFBEvent>>
+ mDownstreamEventsMap;
+
+ // Logger
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace core
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_CORE_SUBSCRIBERFORWARDER_H_
diff --git a/src/plugins/capabilities/core/src/MessageChannel.cpp b/src/plugins/capabilities/core/src/MessageChannel.cpp
new file mode 100644
index 0000000..f4e55dd
--- /dev/null
+++ b/src/plugins/capabilities/core/src/MessageChannel.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/core/include/MessageChannel.h"
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace core {
+
+// Create a MessageChannel.
+std::shared_ptr<MessageChannel> MessageChannel::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> api,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) {
+ auto messageChannel = std::shared_ptr<MessageChannel>(new MessageChannel(logger, api, capability));
+ return messageChannel;
+}
+
+MessageChannel::MessageChannel(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> api,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) {
+ // Subscriber forwarder
+ mSubscriberForwarder = SubscriberForwarder::create(logger, api, capability);
+ // Publisher forwarder
+ mPublisherForwarder = PublisherForwarder::create(logger, capability);
+ mPublisherForwarder->setSubscriberForwarder(mSubscriberForwarder);
+}
+
+bool MessageChannel::publish(const string action, json_object* payload) {
+ return mPublisherForwarder->forwardMessage(action, payload);
+}
+
+bool MessageChannel::subscribe(vshlcapabilities::common::interfaces::IAFBRequest& request, const string action) {
+ return mSubscriberForwarder->subscribe(request, action);
+}
+
+} // namespace core
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/core/src/PublisherForwarder.cpp b/src/plugins/capabilities/core/src/PublisherForwarder.cpp
new file mode 100644
index 0000000..8f8f542
--- /dev/null
+++ b/src/plugins/capabilities/core/src/PublisherForwarder.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/core/include/PublisherForwarder.h"
+
+static string TAG = "vshlcapabilities::capabilities::PublisherForwarder";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace core {
+
+// Create a PublisherForwarder.
+std::shared_ptr<PublisherForwarder> PublisherForwarder::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) {
+ if (logger == nullptr) {
+ return nullptr;
+ }
+
+ if (capability == nullptr) {
+ logger->log(Level::ERROR, TAG, "Failed to create PublisherForwarder: Capability null");
+ return nullptr;
+ }
+
+ auto publisherForwarder = std::shared_ptr<PublisherForwarder>(new PublisherForwarder(logger, capability));
+ return publisherForwarder;
+}
+
+// Constructor
+PublisherForwarder::PublisherForwarder(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) {
+ mCapability = capability;
+ mLogger = logger;
+}
+
+// Destructor
+PublisherForwarder::~PublisherForwarder() {
+}
+
+void PublisherForwarder::setSubscriberForwarder(shared_ptr<SubscriberForwarder> subscriberForwarder) {
+ mSubscriberForwarder = subscriberForwarder;
+}
+
+bool PublisherForwarder::forwardMessage(const string action, json_object* payload) {
+ if (!mSubscriberForwarder) {
+ mLogger->log(Level::ERROR, TAG, "Failed to forward message for capability: " + mCapability->getName());
+ return false;
+ }
+
+ return mSubscriberForwarder->forwardMessage(action, payload);
+}
+
+} // namespace core
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/core/src/SubscriberForwarder.cpp b/src/plugins/capabilities/core/src/SubscriberForwarder.cpp
new file mode 100644
index 0000000..970dbf0
--- /dev/null
+++ b/src/plugins/capabilities/core/src/SubscriberForwarder.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/core/include/SubscriberForwarder.h"
+
+static string TAG = "vshlcapabilities::capabilities::SubscriberForwarder";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace core {
+
+// Create a SubscriberForwarder.
+std::shared_ptr<SubscriberForwarder> SubscriberForwarder::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) {
+ if (logger == nullptr) {
+ return nullptr;
+ }
+
+ if (afbApi == nullptr) {
+ logger->log(Level::ERROR, TAG, "Failed to create SubscriberForwarder: AFB API null");
+ return nullptr;
+ }
+
+ if (capability == nullptr) {
+ logger->log(Level::ERROR, TAG, "Failed to create SubscriberForwarder: Capability null");
+ return nullptr;
+ }
+
+ auto subscriberForwarder =
+ std::shared_ptr<SubscriberForwarder>(new SubscriberForwarder(logger, afbApi, capability));
+ return subscriberForwarder;
+}
+
+SubscriberForwarder::SubscriberForwarder(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger,
+ shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi,
+ shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) :
+ mAfbApi(afbApi),
+ mLogger(logger),
+ mCapability(capability) {
+ createEvents();
+}
+
+SubscriberForwarder::~SubscriberForwarder() {
+ mUpstreamEventsMap.clear();
+ mDownstreamEventsMap.clear();
+}
+
+void SubscriberForwarder::createEvents() {
+ if (!mCapability) {
+ mLogger->log(Level::NOTICE, TAG, "Create Events failed. No capability assigned.");
+ return;
+ }
+
+ // Upstream events
+ auto upstreamEvents = mCapability->getUpstreamMessages();
+ for (auto upstreamEventName : upstreamEvents) {
+ auto it = mUpstreamEventsMap.find(upstreamEventName);
+ if (it == mUpstreamEventsMap.end() && mAfbApi) {
+ // create a new event and add it to the map.
+ shared_ptr<common::interfaces::IAFBApi::IAFBEvent> event = mAfbApi->createEvent(upstreamEventName);
+ if (event == nullptr) {
+ mLogger->log(Level::ERROR, TAG, "Failed to create upstream event: " + upstreamEventName);
+ } else {
+ mUpstreamEventsMap.insert(make_pair(upstreamEventName, event));
+ }
+ }
+ }
+
+ // Downstream events
+ auto downstreamEvents = mCapability->getDownstreamMessages();
+ for (auto downstreamEventName : downstreamEvents) {
+ auto it = mDownstreamEventsMap.find(downstreamEventName);
+ if (it == mDownstreamEventsMap.end() && mAfbApi) {
+ // create a new event and add it to the map.
+ shared_ptr<common::interfaces::IAFBApi::IAFBEvent> event = mAfbApi->createEvent(downstreamEventName);
+ if (event == nullptr) {
+ mLogger->log(Level::ERROR, TAG, "Failed to create downstream event: " + downstreamEventName);
+ } else {
+ mDownstreamEventsMap.insert(make_pair(downstreamEventName, event));
+ }
+ }
+ }
+}
+
+bool SubscriberForwarder::forwardMessage(const string action, json_object* payload) {
+ auto upstreamEventIt = mUpstreamEventsMap.find(action);
+ if (upstreamEventIt != mUpstreamEventsMap.end()) {
+ mLogger->log(Level::NOTICE, TAG, "Publishing upstream event: " + action);
+ upstreamEventIt->second->publishEvent(payload);
+ return true;
+ }
+
+ auto downstreamEventIt = mDownstreamEventsMap.find(action);
+ if (downstreamEventIt != mDownstreamEventsMap.end()) {
+ mLogger->log(Level::NOTICE, TAG, "Publishing downstream event: " + action);
+ downstreamEventIt->second->publishEvent(payload);
+ return true;
+ }
+
+ mLogger->log(Level::NOTICE, TAG, "Failed to publish upstream event: " + action);
+ return false;
+}
+
+bool SubscriberForwarder::subscribe(vshlcapabilities::common::interfaces::IAFBRequest& request, const string action) {
+ auto upstreamEventIt = mUpstreamEventsMap.find(action);
+ if (upstreamEventIt != mUpstreamEventsMap.end()) {
+ mLogger->log(Level::NOTICE, TAG, "Subscribing to upstream event: " + action);
+ return upstreamEventIt->second->subscribe(request);
+ }
+
+ auto downstreamEventIt = mDownstreamEventsMap.find(action);
+ if (downstreamEventIt != mDownstreamEventsMap.end()) {
+ mLogger->log(Level::NOTICE, TAG, "Subscribing to downstream event: " + action);
+ return downstreamEventIt->second->subscribe(request);
+ }
+
+ mLogger->log(Level::NOTICE, TAG, "Failed to subscribe to upstream event: " + action);
+ return false;
+}
+
+} // namespace core
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/guimetadata/include/GuiMetadataCapability.h b/src/plugins/capabilities/guimetadata/include/GuiMetadataCapability.h
new file mode 100644
index 0000000..ecaf09f
--- /dev/null
+++ b/src/plugins/capabilities/guimetadata/include/GuiMetadataCapability.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_GUIMETADATA_CAPABILITY_H_
+#define VSHL_CAPABILITIES_GUIMETADATA_CAPABILITY_H_
+
+#include <memory>
+
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace guimetadata {
+
+/*
+ * GuiMetadata capability
+ */
+class GuiMetadata : public common::interfaces::ICapability {
+public:
+ // Create a GuiMetadata.
+ static std::shared_ptr<GuiMetadata> create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ ~GuiMetadata() = default;
+
+protected:
+ string getName() const override;
+
+ list<string> getUpstreamMessages() const override;
+
+ list<string> getDownstreamMessages() const override;
+
+private:
+ GuiMetadata(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace guimetadata
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_GUIMETADATA_CAPABILITY_H_
diff --git a/src/plugins/capabilities/guimetadata/include/GuiMetadataMessages.h b/src/plugins/capabilities/guimetadata/include/GuiMetadataMessages.h
new file mode 100644
index 0000000..07f4725
--- /dev/null
+++ b/src/plugins/capabilities/guimetadata/include/GuiMetadataMessages.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_GUIMETADATA_ACTIONS_H_
+#define VSHL_CAPABILITIES_GUIMETADATA_ACTIONS_H_
+
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace guimetadata {
+
+static string NAME = "guimetadata";
+
+/*
+ ******************************************************************************************************
+ * Supported actions from VA -> APPS
+ ******************************************************************************************************
+ */
+static string GUIMETADATA_RENDER_TEMPLATE = "render_template";
+static string GUIMETADATA_CLEAR_TEMPLATE = "clear_template";
+static string GUIMETADATA_RENDER_PLAYER_INFO = "render_player_info";
+static string GUIMETADATA_CLEAR_PLAYER_INFO = "clear_player_info";
+
+
+// List of actions that are delivered from VA -> Apps
+static list<string> GUIMETADATA_UPSTREAM_ACTIONS = {GUIMETADATA_RENDER_TEMPLATE,
+ GUIMETADATA_CLEAR_TEMPLATE,
+ GUIMETADATA_RENDER_PLAYER_INFO,
+ GUIMETADATA_CLEAR_PLAYER_INFO};
+
+/*
+ ******************************************************************************************************
+ * Supported actions from APPS -> VA
+ ******************************************************************************************************
+ */
+
+// List of actions that are delivered from Apps -> VA
+static list<string> GUIMETADATA_DOWNSTREAM_ACTIONS = {};
+
+} // namespace guimetadata
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_GUIMETADATA_ACTIONS_H_
diff --git a/src/plugins/capabilities/guimetadata/src/GuiMetadataCapability.cpp b/src/plugins/capabilities/guimetadata/src/GuiMetadataCapability.cpp
new file mode 100644
index 0000000..df90c91
--- /dev/null
+++ b/src/plugins/capabilities/guimetadata/src/GuiMetadataCapability.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/guimetadata/include/GuiMetadataCapability.h"
+#include "capabilities/guimetadata/include/GuiMetadataMessages.h"
+
+const string TAG = "vshlcapabilities::capabilities::guimetadata";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace guimetadata {
+
+// Create a GuiMetadata.
+shared_ptr<GuiMetadata> GuiMetadata::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ auto guiMetadata = std::shared_ptr<GuiMetadata>(new GuiMetadata(logger));
+ return guiMetadata;
+}
+
+GuiMetadata::GuiMetadata(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ mLogger = logger;
+}
+
+string GuiMetadata::getName() const {
+ return NAME;
+}
+
+list<string> GuiMetadata::getUpstreamMessages() const {
+ return GUIMETADATA_UPSTREAM_ACTIONS;
+}
+
+list<string> GuiMetadata::getDownstreamMessages() const {
+ return GUIMETADATA_DOWNSTREAM_ACTIONS;
+}
+
+} // namespace guimetadata
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/navigation/include/NavigationCapability.h b/src/plugins/capabilities/navigation/include/NavigationCapability.h
new file mode 100644
index 0000000..bb055a8
--- /dev/null
+++ b/src/plugins/capabilities/navigation/include/NavigationCapability.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_NAVIGATION_CAPABILITY_H_
+#define VSHL_CAPABILITIES_NAVIGATION_CAPABILITY_H_
+
+#include <memory>
+
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace navigation {
+
+/*
+ * Navigation capability
+ */
+class Navigation : public common::interfaces::ICapability {
+public:
+ // Create a Navigation.
+ static std::shared_ptr<Navigation> create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ ~Navigation() = default;
+
+protected:
+ string getName() const override;
+
+ list<string> getUpstreamMessages() const override;
+
+ list<string> getDownstreamMessages() const override;
+
+private:
+ Navigation(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace navigation
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_NAVIGATION_CAPABILITY_H_
diff --git a/src/plugins/capabilities/navigation/include/NavigationMessages.h b/src/plugins/capabilities/navigation/include/NavigationMessages.h
new file mode 100644
index 0000000..00c0c65
--- /dev/null
+++ b/src/plugins/capabilities/navigation/include/NavigationMessages.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_NAVIGATION_ACTIONS_H_
+#define VSHL_CAPABILITIES_NAVIGATION_ACTIONS_H_
+
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace navigation {
+
+static string NAME = "navigation";
+
+/*
+ ******************************************************************************************************
+ * Supported actions from VA -> APPS
+ ******************************************************************************************************
+ */
+static string NAVIGATION_SET_DESTINATION = "set_destination";
+static string NAVIGATION_CANCEL = "cancel_navigation";
+
+// Supported actions from Apps -> VA
+
+// List of actions that are delivered from VA -> Apps
+static list<string> NAVIGATION_UPSTREAM_ACTIONS = {
+ NAVIGATION_SET_DESTINATION,
+ NAVIGATION_CANCEL,
+};
+
+/*
+ ******************************************************************************************************
+ * Supported actions from APPS -> VA
+ ******************************************************************************************************
+ */
+static list<string> NAVIGATION_DOWNSTREAM_ACTIONS = {};
+
+} // namespace navigation
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_NAVIGATION_ACTIONS_H_
diff --git a/src/plugins/capabilities/navigation/src/NavigationCapability.cpp b/src/plugins/capabilities/navigation/src/NavigationCapability.cpp
new file mode 100644
index 0000000..e1c6cda
--- /dev/null
+++ b/src/plugins/capabilities/navigation/src/NavigationCapability.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/navigation/include/NavigationCapability.h"
+#include "capabilities/navigation/include/NavigationMessages.h"
+
+const string TAG = "vshlcapabilities::capabilities::navigation";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace navigation {
+
+// Create a Navigation.
+shared_ptr<Navigation> Navigation::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ auto navigation = std::shared_ptr<Navigation>(new Navigation(logger));
+ return navigation;
+}
+
+Navigation::Navigation(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ mLogger = logger;
+}
+
+string Navigation::getName() const {
+ return NAME;
+}
+
+list<string> Navigation::getUpstreamMessages() const {
+ return NAVIGATION_UPSTREAM_ACTIONS;
+}
+
+list<string> Navigation::getDownstreamMessages() const {
+ return NAVIGATION_DOWNSTREAM_ACTIONS;
+}
+
+} // namespace navigation
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerCapability.h b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerCapability.h
new file mode 100644
index 0000000..e80b213
--- /dev/null
+++ b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerCapability.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_PLAYBACKCONTROLLER_CAPABILITY_H_
+#define VSHL_CAPABILITIES_PLAYBACKCONTROLLER_CAPABILITY_H_
+
+#include <memory>
+
+#include "interfaces/capabilities/ICapability.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace playbackcontroller {
+
+/*
+ * PlaybackController capability. Calls are initiated in the endpoint.
+ */
+class PlaybackController : public common::interfaces::ICapability {
+public:
+ // Create a PlaybackController.
+ static std::shared_ptr<PlaybackController> create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ ~PlaybackController() = default;
+
+protected:
+ string getName() const override;
+
+ list<string> getUpstreamMessages() const override;
+
+ list<string> getDownstreamMessages() const override;
+
+private:
+ PlaybackController(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace playbackcontroller
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_PLAYBACKCONTROLLER_CAPABILITY_H_
diff --git a/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerMessages.h b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerMessages.h
new file mode 100644
index 0000000..224b8dd
--- /dev/null
+++ b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerMessages.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_CAPABILITIES_PLAYBACKCONTROLLER_MESSAGES_H_
+#define VSHL_CAPABILITIES_PLAYBACKCONTROLLER_MESSAGES_H_
+
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace playbackcontroller {
+
+static string NAME = "playbackcontroller";
+
+/*
+ ******************************************************************************************************
+ * Supported actions from APPS -> VA
+ ******************************************************************************************************
+ */
+// List of actions that are delivered from VA -> Apps
+static list<string> PLAYBACKCONTROLLER_UPSTREAM_ACTIONS = {
+
+};
+
+
+/*
+ ******************************************************************************************************
+ * Supported actions from VA -> APPS
+ ******************************************************************************************************
+ */
+// List of actions that are delivered from Apps -> VA
+/*
+ * payload :
+ * {
+ * "button" : "{{STRING}}" // play, pause, next, previous, skip-forward, skip-backward
+ * }
+ * @param [in] button Button pressed by the user.
+ *
+ */
+static string PLAYBACKCONTROLLER_BUTTONPRESSED = "button_pressed";
+
+static list<string> PLAYBACKCONTROLLER_DOWNSTREAM_ACTIONS = {
+ PLAYBACKCONTROLLER_BUTTONPRESSED
+};
+
+} // namespace playbackcontroller
+} // namespace capabilities
+} // namespace vshl
+
+#endif // VSHL_CAPABILITIES_PLAYBACKCONTROLLER_MESSAGES_H_
diff --git a/src/plugins/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp b/src/plugins/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp
new file mode 100644
index 0000000..a5abbed
--- /dev/null
+++ b/src/plugins/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "capabilities/playbackcontroller/include/PlaybackControllerCapability.h"
+#include "capabilities/playbackcontroller/include/PlaybackControllerMessages.h"
+
+const string TAG = "vshlcapabilities::capabilities::playbackcontroller";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace capabilities {
+namespace playbackcontroller {
+
+// Create a playbackcontroller.
+shared_ptr<PlaybackController> PlaybackController::create(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ auto playbackcontroller = std::shared_ptr<PlaybackController>(new PlaybackController(logger));
+ return playbackcontroller;
+}
+
+PlaybackController::PlaybackController(
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ mLogger = logger;
+}
+
+string PlaybackController::getName() const {
+ return NAME;
+}
+
+list<string> PlaybackController::getUpstreamMessages() const {
+ return PLAYBACKCONTROLLER_UPSTREAM_ACTIONS;
+}
+
+list<string> PlaybackController::getDownstreamMessages() const {
+ return PLAYBACKCONTROLLER_DOWNSTREAM_ACTIONS;
+}
+
+} // namespace playbackcontroller
+} // namespace capabilities
+} // namespace vshl
diff --git a/src/plugins/capabilities/test/CapabilityMessagingServiceTest.cpp b/src/plugins/capabilities/test/CapabilityMessagingServiceTest.cpp
new file mode 100644
index 0000000..5d3971d
--- /dev/null
+++ b/src/plugins/capabilities/test/CapabilityMessagingServiceTest.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 <gtest/gtest.h>
+
+#include "capabilities/CapabilityMessagingService.h"
+
+#include "test/common/ConsoleLogger.h"
+#include "test/mocks/AFBApiMock.h"
+#include "test/mocks/AFBEventMock.h"
+#include "test/mocks/AFBRequestMock.h"
+#include "test/mocks/CapabilityMock.h"
+
+using namespace vshlcapabilities::common::interfaces;
+using namespace vshlcapabilities::capabilities;
+using namespace vshlcapabilities::test::common;
+
+namespace vshlcapabilities {
+namespace test {
+
+class CapabilityMessagingServiceTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mConsoleLogger = std::make_shared<ConsoleLogger>();
+ mAfbApi = std::make_shared<::testing::NiceMock<AFBApiMock>>();
+ }
+
+ std::shared_ptr<::testing::NiceMock<AFBApiMock>> mAfbApi;
+ std::shared_ptr<ConsoleLogger> mConsoleLogger;
+};
+
+TEST_F(CapabilityMessagingServiceTest, failsInitializationOnInvalidParams) {
+ auto service = CapabilityMessagingService::create(mConsoleLogger, nullptr);
+ ASSERT_EQ(service, nullptr);
+
+ service = CapabilityMessagingService::create(nullptr, mAfbApi);
+ ASSERT_EQ(service, nullptr);
+}
+
+TEST_F(CapabilityMessagingServiceTest, initializesSuccessfully) {
+ auto service = CapabilityMessagingService::create(mConsoleLogger, mAfbApi);
+ ASSERT_NE(service, nullptr);
+}
+
+TEST_F(CapabilityMessagingServiceTest, canSubscribeAndPublishCapabilityEvents) {
+ auto service = CapabilityMessagingService::create(mConsoleLogger, mAfbApi);
+
+ auto capability = std::make_shared<::testing::NiceMock<CapabilityMock>>();
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+ std::string capabilityName = "weather";
+
+ ON_CALL(*capability, getName()).WillByDefault(::testing::Return(capabilityName));
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ // We don't care if and how many times subscribe method is called on event.
+ std::shared_ptr<AFBEventMock> mockEvent(new ::testing::NiceMock<AFBEventMock>());
+ ON_CALL(*mockEvent, subscribe(::testing::_)).WillByDefault(::testing::Return(true));
+ ON_CALL(*mockEvent, publishEvent(::testing::_)).WillByDefault(::testing::Return(true));
+ auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> {
+ mockEvent->setName(eventName);
+ return mockEvent;
+ };
+
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator));
+
+ auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>();
+ std::string payload = "The answer to life the universe and everything = 42";
+
+ bool result = service->publish(capability, *upstreamEvents.begin(), payload);
+ ASSERT_FALSE(result); // Without subscribing to the event. Publish should fail.
+
+ result = service->subscribe(*request, capability, *upstreamEvents.begin());
+ ASSERT_TRUE(result);
+
+ result = service->subscribe(*request, capability, *downstreamEvents.begin());
+ ASSERT_TRUE(result);
+
+ result = service->publish(capability, *downstreamEvents.begin(), payload);
+ ASSERT_TRUE(result);
+}
+
+} // namespace test
+} // namespace vshl \ No newline at end of file
diff --git a/src/plugins/capabilities/test/PublisherForwarderTest.cpp b/src/plugins/capabilities/test/PublisherForwarderTest.cpp
new file mode 100644
index 0000000..8fb499c
--- /dev/null
+++ b/src/plugins/capabilities/test/PublisherForwarderTest.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 <gtest/gtest.h>
+
+#include "capabilities/core/include/PublisherForwarder.h"
+#include "capabilities/core/include/SubscriberForwarder.h"
+
+#include "test/common/ConsoleLogger.h"
+#include "test/mocks/AFBApiMock.h"
+#include "test/mocks/AFBEventMock.h"
+#include "test/mocks/CapabilityMock.h"
+
+using namespace vshlcapabilities::common::interfaces;
+using namespace vshlcapabilities::capabilities::core;
+using namespace vshlcapabilities::test::common;
+
+namespace vshlcapabilities {
+namespace test {
+
+class PublisherForwarderTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mConsoleLogger = std::make_shared<ConsoleLogger>();
+ mAfbApi = std::make_shared<::testing::StrictMock<AFBApiMock>>();
+
+ mEventCreatorFn = [](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> {
+ std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>());
+ mockEvent->setName(eventName);
+ return mockEvent;
+ };
+ }
+
+ std::shared_ptr<SubscriberForwarder> createSubscriberForwarder(
+ std::shared_ptr<::testing::StrictMock<CapabilityMock>> capability) {
+ EXPECT_CALL(*capability, getUpstreamMessages()).Times(1);
+ EXPECT_CALL(*capability, getDownstreamMessages()).Times(1);
+
+ return SubscriberForwarder::create(mConsoleLogger, mAfbApi, capability);
+ }
+
+ std::shared_ptr<PublisherForwarder> createPublisherForwarder(
+ std::shared_ptr<::testing::StrictMock<CapabilityMock>> capability) {
+ return PublisherForwarder::create(mConsoleLogger, capability);
+ }
+
+ std::shared_ptr<::testing::StrictMock<AFBApiMock>> mAfbApi;
+ std::shared_ptr<ConsoleLogger> mConsoleLogger;
+ std::function<std::shared_ptr<IAFBApi::IAFBEvent>(const std::string&)> mEventCreatorFn;
+ std::shared_ptr<::testing::StrictMock<AFBEventMock>> mAfbEventMock;
+};
+
+TEST_F(PublisherForwarderTest, failsInitializationOnInvalidParams) {
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+
+ auto forwarder = PublisherForwarder::create(mConsoleLogger, nullptr);
+ ASSERT_EQ(forwarder, nullptr);
+
+ forwarder = PublisherForwarder::create(nullptr, capability);
+ ASSERT_EQ(forwarder, nullptr);
+}
+
+TEST_F(PublisherForwarderTest, initializesCorrectly) {
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ auto forwarder = createPublisherForwarder(capability);
+
+ ASSERT_NE(forwarder, nullptr);
+}
+
+TEST_F(PublisherForwarderTest, canForwardMessages) {
+ std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>());
+ ON_CALL(*mockEvent, publishEvent(::testing::_)).WillByDefault(::testing::Return(true));
+ EXPECT_CALL(*mockEvent, publishEvent(::testing::_)).Times(4);
+ auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> {
+ return mockEvent;
+ };
+
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator));
+ EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4);
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto publisherForwarder = createPublisherForwarder(capability);
+ ASSERT_NE(publisherForwarder, nullptr);
+
+ auto subscriberForwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(subscriberForwarder, nullptr);
+
+ std::string payload = "The answer to life the universe and everything = 42";
+ publisherForwarder->setSubscriberForwarder(subscriberForwarder);
+
+ auto itCapability = downstreamEvents.begin();
+ ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload));
+ ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload));
+ itCapability = upstreamEvents.begin();
+ ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload));
+ ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload));
+}
+
+} // namespace test
+} // namespace vshl \ No newline at end of file
diff --git a/src/plugins/capabilities/test/SubscriberForwarderTest.cpp b/src/plugins/capabilities/test/SubscriberForwarderTest.cpp
new file mode 100644
index 0000000..c3d72de
--- /dev/null
+++ b/src/plugins/capabilities/test/SubscriberForwarderTest.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 <gtest/gtest.h>
+
+#include "capabilities/core/include/SubscriberForwarder.h"
+
+#include "test/common/ConsoleLogger.h"
+#include "test/mocks/AFBApiMock.h"
+#include "test/mocks/AFBEventMock.h"
+#include "test/mocks/AFBRequestMock.h"
+#include "test/mocks/CapabilityMock.h"
+
+using namespace vshlcapabilities::common::interfaces;
+using namespace vshlcapabilities::capabilities::core;
+using namespace vshlcapabilities::test::common;
+
+namespace vshlcapabilities {
+namespace test {
+
+class SubscriberForwarderTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mConsoleLogger = std::make_shared<ConsoleLogger>();
+ mAfbApi = std::make_shared<::testing::StrictMock<AFBApiMock>>();
+
+ mEventCreatorFn = [](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> {
+ std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>());
+ mockEvent->setName(eventName);
+ return mockEvent;
+ };
+ }
+
+ std::shared_ptr<SubscriberForwarder> createSubscriberForwarder(
+ std::shared_ptr<::testing::StrictMock<CapabilityMock>> capability) {
+ EXPECT_CALL(*capability, getUpstreamMessages()).Times(1);
+ EXPECT_CALL(*capability, getDownstreamMessages()).Times(1);
+
+ return SubscriberForwarder::create(mConsoleLogger, mAfbApi, capability);
+ }
+
+ std::shared_ptr<::testing::StrictMock<AFBApiMock>> mAfbApi;
+ std::shared_ptr<ConsoleLogger> mConsoleLogger;
+ std::function<std::shared_ptr<IAFBApi::IAFBEvent>(const std::string&)> mEventCreatorFn;
+ std::shared_ptr<::testing::StrictMock<AFBEventMock>> mAfbEventMock;
+};
+
+TEST_F(SubscriberForwarderTest, failsInitializationOnInvalidParams) {
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+
+ auto forwarder = SubscriberForwarder::create(mConsoleLogger, mAfbApi, nullptr);
+ ASSERT_EQ(forwarder, nullptr);
+
+ forwarder = SubscriberForwarder::create(mConsoleLogger, nullptr, capability);
+ ASSERT_EQ(forwarder, nullptr);
+
+ forwarder = SubscriberForwarder::create(nullptr, mAfbApi, capability);
+ ASSERT_EQ(forwarder, nullptr);
+}
+
+TEST_F(SubscriberForwarderTest, initializesCorrectly) {
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ auto forwarder = createSubscriberForwarder(capability);
+
+ ASSERT_NE(forwarder, nullptr);
+}
+
+TEST_F(SubscriberForwarderTest, createsEventsOnInitialization) {
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(mEventCreatorFn));
+
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto itCapability = upstreamEvents.begin();
+ EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1);
+ itCapability++;
+ EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1);
+
+ itCapability = downstreamEvents.begin();
+ EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1);
+ itCapability++;
+ EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1);
+
+ auto forwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(forwarder, nullptr);
+}
+
+TEST_F(SubscriberForwarderTest, canNotSubscribeToNonExistentEvents) {
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(mEventCreatorFn));
+ EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4);
+
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto forwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(forwarder, nullptr);
+
+ auto nonExistentEvents = std::list<std::string>({"non", "existent", "events"});
+ auto itCapability = nonExistentEvents.begin();
+ auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>();
+ ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++));
+ ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++));
+ ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++));
+}
+
+TEST_F(SubscriberForwarderTest, canNotSubscribeOnEventCreationFailure) {
+ // Fail the event creation and return null event.
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Return(nullptr));
+ EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4);
+
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto forwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(forwarder, nullptr);
+
+ auto itCapability = downstreamEvents.begin();
+ auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>();
+ std::string payload = "The answer to life the universe and everything = 42";
+ ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++));
+ ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++));
+ itCapability = upstreamEvents.begin();
+ ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++));
+ ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++));
+}
+
+TEST_F(SubscriberForwarderTest, canSubscribeToEvents) {
+ std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>());
+ ON_CALL(*mockEvent, subscribe(::testing::_)).WillByDefault(::testing::Return(true));
+ EXPECT_CALL(*mockEvent, subscribe(::testing::_)).Times(4);
+ auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> {
+ return mockEvent;
+ };
+
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator));
+ EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4);
+
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto forwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(forwarder, nullptr);
+
+ auto itCapability = downstreamEvents.begin();
+ auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>();
+ ASSERT_TRUE(forwarder->subscribe(*request, *itCapability++));
+ ASSERT_TRUE(forwarder->subscribe(*request, *itCapability));
+ itCapability = upstreamEvents.begin();
+ ASSERT_TRUE(forwarder->subscribe(*request, *itCapability++));
+ ASSERT_TRUE(forwarder->subscribe(*request, *itCapability));
+}
+
+TEST_F(SubscriberForwarderTest, canNotPublishNonExistentEvents) {
+ std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>());
+ EXPECT_CALL(*mockEvent, publishEvent(::testing::_)).Times(0);
+ auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> {
+ return mockEvent;
+ };
+
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator));
+ EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4);
+
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto forwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(forwarder, nullptr);
+
+ auto nonExistentEvents = std::list<std::string>({"non", "existent", "events"});
+ auto itCapability = nonExistentEvents.begin();
+ ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, "My-Payload"));
+ ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, "My-Payload"));
+ ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, "My-Payload"));
+}
+
+TEST_F(SubscriberForwarderTest, canNotPublishOnEventCreationFailure) {
+ // Fail the event creation and return null event.
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Return(nullptr));
+ EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4);
+
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto forwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(forwarder, nullptr);
+
+ auto itCapability = downstreamEvents.begin();
+ std::string payload = "The answer to life the universe and everything = 42";
+ ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload));
+ ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload));
+ itCapability = upstreamEvents.begin();
+ ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload));
+ ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload));
+}
+
+TEST_F(SubscriberForwarderTest, canPublishEvents) {
+ std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>());
+ ON_CALL(*mockEvent, publishEvent(::testing::_)).WillByDefault(::testing::Return(true));
+ EXPECT_CALL(*mockEvent, publishEvent(::testing::_)).Times(4);
+ auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> {
+ return mockEvent;
+ };
+
+ ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator));
+ EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4);
+
+ std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"});
+ std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"});
+
+ auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>();
+ ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents));
+ ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents));
+
+ auto forwarder = createSubscriberForwarder(capability);
+ ASSERT_NE(forwarder, nullptr);
+
+ auto itCapability = downstreamEvents.begin();
+ std::string payload = "The answer to life the universe and everything = 42";
+ ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload));
+ ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload));
+ itCapability = upstreamEvents.begin();
+ ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload));
+ ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload));
+}
+
+} // namespace test
+} // namespace vshl \ No newline at end of file
diff --git a/src/plugins/cmake/gtest.cmake b/src/plugins/cmake/gtest.cmake
new file mode 100644
index 0000000..def6559
--- /dev/null
+++ b/src/plugins/cmake/gtest.cmake
@@ -0,0 +1,44 @@
+# gtest
+
+find_package(Threads REQUIRED)
+
+# Enable ExternalProject CMake module
+INCLUDE(ExternalProject)
+
+ExternalProject_Add(
+ gtest
+ URL https://github.com/google/googletest/archive/release-1.8.1.zip
+ SOURCE_DIR "${CMAKE_BINARY_DIR}/gtest-src"
+ BINARY_DIR "${CMAKE_BINARY_DIR}/gtest-build"
+ INSTALL_COMMAND ""
+ LOG_DOWNLOAD ON
+ LOG_CONFIGURE ON
+ LOG_BUILD ON
+)
+
+# Get GTest source and binary directories from CMake project
+ExternalProject_Get_Property(gtest source_dir binary_dir)
+
+# Create a libgtest target to be used as a dependency by test programs
+ADD_LIBRARY(libgtest INTERFACE)
+TARGET_INCLUDE_DIRECTORIES(libgtest
+ INTERFACE
+ ${source_dir}/googletest/include
+)
+TARGET_LINK_LIBRARIES(libgtest
+ INTERFACE
+ ${binary_dir}/googlemock/gtest/libgtest.a
+ ${CMAKE_THREAD_LIBS_INIT}
+)
+
+# Create a libgmock target to be used as a dependency by test programs
+ADD_LIBRARY(libgmock INTERFACE)
+TARGET_INCLUDE_DIRECTORIES(libgmock
+ INTERFACE
+ ${source_dir}/googlemock/include
+)
+TARGET_LINK_LIBRARIES(libgmock
+ INTERFACE
+ ${binary_dir}/googlemock/libgmock.a
+ ${CMAKE_THREAD_LIBS_INIT}
+) \ No newline at end of file
diff --git a/src/plugins/interfaces/afb/IAFBApi.h b/src/plugins/interfaces/afb/IAFBApi.h
new file mode 100644
index 0000000..b607fd8
--- /dev/null
+++ b/src/plugins/interfaces/afb/IAFBApi.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_COMMON_INTERFACES_AFBAPI_H_
+#define VSHL_COMMON_INTERFACES_AFBAPI_H_
+
+#include <memory>
+#include <string>
+
+#include <json-c/json_object.h>
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace common {
+namespace interfaces {
+
+/**
+ * Interface to represent AFB Request.
+ */
+class IAFBRequest {
+public:
+ /**
+ * Gets the native request object.
+ */
+ virtual void* getNativeRequest() = 0;
+};
+
+/**
+ * Interface to encapsulate all AFB (AGL Application Framework Binding)
+ * functions.
+ */
+class IAFBApi {
+public:
+ /**
+ * Interface to represent AFB Event
+ */
+ class IAFBEvent {
+ public:
+ /**
+ * Gets human readable name of the event.
+ */
+ virtual std::string getName() const = 0;
+
+ /**
+ * Returns true if event is valid. False otherwise.
+ */
+ virtual bool isValid() = 0;
+
+ /**
+ * Publish event to all observers.
+ *
+ * @return The number of observers that received the event.
+ */
+ virtual int publishEvent(struct json_object* payload) = 0;
+
+ /**
+ * Subscribe to the event
+ *
+ * @c request Party interested in the event.
+ */
+ virtual bool subscribe(IAFBRequest& request) = 0;
+
+ /**
+ * Unsubscribe to the event
+ *
+ * @c request Party no longer interested in the event.
+ */
+ virtual bool unsubscribe(IAFBRequest& request) = 0;
+ };
+
+ virtual std::shared_ptr<IAFBEvent> createEvent(const std::string& eventName) = 0;
+
+ virtual int callSync(
+ const std::string& api,
+ const std::string& verb,
+ struct json_object* request,
+ struct json_object** result,
+ std::string& error,
+ std::string& info) = 0;
+};
+
+} // namespace interfaces
+} // namespace common
+} // namespace vshl
+
+#endif // VSHL_COMMON_INTERFACES_AFBAPI_H_
diff --git a/src/plugins/interfaces/capabilities/ICapability.h b/src/plugins/interfaces/capabilities/ICapability.h
new file mode 100644
index 0000000..ebdd4e8
--- /dev/null
+++ b/src/plugins/interfaces/capabilities/ICapability.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_COMMON_INTERFACES_ICAPABILITY_H_
+#define VSHL_COMMON_INTERFACES_ICAPABILITY_H_
+
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace common {
+namespace interfaces {
+
+/*
+ * This interface defines the structure for a specific voiceagent capability.
+ */
+class ICapability {
+public:
+ /*
+ * Returns the capability's name.
+ */
+ virtual string getName() const = 0;
+
+ /*
+ * Returns the list of upstream messages.
+ */
+ virtual list<string> getUpstreamMessages() const = 0;
+
+ /*
+ * Returns the list of downstream messages
+ */
+ virtual list<string> getDownstreamMessages() const = 0;
+
+ /**
+ * Virtual destructor to assure proper cleanup of derived types.
+ */
+ virtual ~ICapability() = default;
+};
+
+} // namespace interfaces
+} // namespace common
+} // namespace vshl
+
+#endif // VSHL_COMMON_INTERFACES_ICAPABILITY_H_
diff --git a/src/plugins/interfaces/utilities/events/IEventFilter.h b/src/plugins/interfaces/utilities/events/IEventFilter.h
new file mode 100644
index 0000000..a4e3c64
--- /dev/null
+++ b/src/plugins/interfaces/utilities/events/IEventFilter.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_COMMON_INTERFACES_IEVENTFILTER_H_
+#define VSHL_COMMON_INTERFACES_IEVENTFILTER_H_
+
+#include <string>
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace common {
+namespace interfaces {
+/*
+ * This is an abstract class that is responsible for filtering the events
+ * that are delivered to the high level voice service from apps or voiceagents.
+ */
+class IEventFilter {
+public:
+ // Name of the event filter.
+ virtual string getName() = 0;
+
+ // Every event filter needs to implement this method and
+ // return true if consuming the event or false otherwise.
+ virtual bool onIncomingEvent(const string eventName, const string voiceAgentId, const string payload) = 0;
+
+ // Destructor
+ virtual ~IEventFilter() = default;
+};
+
+} // namespace interfaces
+} // namespace common
+} // namespace vshl
+
+#endif // VSHL_COMMON_INTERFACES_IEVENTFILTER_H_
diff --git a/src/plugins/interfaces/utilities/logging/ILogger.h b/src/plugins/interfaces/utilities/logging/ILogger.h
new file mode 100644
index 0000000..4cf25aa
--- /dev/null
+++ b/src/plugins/interfaces/utilities/logging/ILogger.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_COMMON_INTERFACES_LOGGER_H_
+#define VSHL_COMMON_INTERFACES_LOGGER_H_
+
+#include <string>
+
+namespace vshlcapabilities {
+namespace common {
+namespace interfaces {
+
+class ILogger {
+public:
+ enum Level {
+ DEBUG,
+ INFO,
+ WARNING,
+ ERROR,
+ NOTICE,
+ };
+
+ virtual void log(Level level, const std::string &tag,
+ const std::string &message) = 0;
+};
+
+} // namespace interfaces
+} // namespace common
+} // namespace vshl
+
+#endif // VSHL_COMMON_INTERFACES_LOGGER_H_
diff --git a/src/plugins/test/common/ConsoleLogger.cpp b/src/plugins/test/common/ConsoleLogger.cpp
new file mode 100644
index 0000000..a2a2598
--- /dev/null
+++ b/src/plugins/test/common/ConsoleLogger.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include <iostream>
+
+#include "test/common/ConsoleLogger.h"
+
+namespace vshlcapabilities {
+namespace test {
+namespace common {
+
+void ConsoleLogger::log(Level level, const std::string& tag, const std::string& message) {
+ string format_msg = "Tag: " + tag + ", message: " + message;
+ std::cout << format_msg << std::endl;
+}
+
+} // namespace common
+} // namespace test
+} // namespace vshl
diff --git a/src/plugins/test/common/ConsoleLogger.h b/src/plugins/test/common/ConsoleLogger.h
new file mode 100644
index 0000000..2f81086
--- /dev/null
+++ b/src/plugins/test/common/ConsoleLogger.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_TEST_COMMON_CONSOLE_LOGGER_H_
+#define VSHL_TEST_COMMON_CONSOLE_LOGGER_H_
+
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace test {
+namespace common {
+
+class ConsoleLogger : public vshlcapabilities::common::interfaces::ILogger {
+public:
+ // ILogger interface
+ void log(Level level, const std::string &tag,
+ const std::string &message) override;
+};
+
+} // namespace common
+} // namespace test
+} // namespace vshl
+
+#endif // VSHL_TEST_COMMON_CONSOLE_LOGGER_H_
diff --git a/src/plugins/test/mocks/AFBApiMock.h b/src/plugins/test/mocks/AFBApiMock.h
new file mode 100644
index 0000000..8cefa39
--- /dev/null
+++ b/src/plugins/test/mocks/AFBApiMock.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_TEST_MOCKS_AFBAPIMOCK_H_
+#define VSHL_TEST_MOCKS_AFBAPIMOCK_H_
+
+#include <gmock/gmock.h>
+
+#include "interfaces/afb/IAFBApi.h"
+
+namespace vshlcapabilities {
+namespace test {
+
+class AFBApiMock : public vshlcapabilities::common::interfaces::IAFBApi {
+public:
+ MOCK_METHOD1(createEvent, std::shared_ptr<IAFBEvent>(const std::string& eventName));
+ MOCK_METHOD6(
+ callSync,
+ int(const std::string& api,
+ const std::string& verb,
+ struct json_object* request,
+ struct json_object** result,
+ std::string& error,
+ std::string& info));
+};
+
+} // namespace test
+} // namespace vshl
+
+#endif // VSHL_TEST_MOCKS_AFBAPIMOCK_H_ \ No newline at end of file
diff --git a/src/plugins/test/mocks/AFBEventMock.h b/src/plugins/test/mocks/AFBEventMock.h
new file mode 100644
index 0000000..f4e2b67
--- /dev/null
+++ b/src/plugins/test/mocks/AFBEventMock.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_TEST_MOCKS_AFBEVENTMOCK_H_
+#define VSHL_TEST_MOCKS_AFBEVENTMOCK_H_
+
+#include <gmock/gmock.h>
+
+#include "interfaces/afb/IAFBApi.h"
+
+namespace vshlcapabilities {
+namespace test {
+
+class AFBEventMock : public vshlcapabilities::common::interfaces::IAFBApi::IAFBEvent {
+public:
+ void setName(const std::string& name) {
+ mName = name;
+ }
+
+ std::string getName() const override {
+ return mName;
+ }
+
+ MOCK_METHOD0(isValid, bool());
+ MOCK_METHOD1(publishEvent, int(struct json_object* payload));
+ MOCK_METHOD1(subscribe, bool(vshlcapabilities::common::interfaces::IAFBRequest& request));
+ MOCK_METHOD1(unsubscribe, bool(vshlcapabilities::common::interfaces::IAFBRequest& request));
+
+private:
+ std::string mName;
+};
+
+} // namespace test
+} // namespace vshl
+
+#endif // VSHL_TEST_MOCKS_AFBEVENTMOCK_H_ \ No newline at end of file
diff --git a/src/plugins/test/mocks/AFBRequestMock.h b/src/plugins/test/mocks/AFBRequestMock.h
new file mode 100644
index 0000000..0aaeede
--- /dev/null
+++ b/src/plugins/test/mocks/AFBRequestMock.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_TEST_MOCKS_AFBREQUESTMOCK_H_
+#define VSHL_TEST_MOCKS_AFBREQUESTMOCK_H_
+
+#include <gmock/gmock.h>
+
+#include "interfaces/afb/IAFBApi.h"
+
+namespace vshlcapabilities {
+namespace test {
+
+class AFBRequestMock : public vshlcapabilities::common::interfaces::IAFBRequest {
+public:
+ MOCK_METHOD0(getNativeRequest, void*());
+};
+
+} // namespace test
+} // namespace vshl
+
+#endif // VSHL_TEST_MOCKS_AFBREQUESTMOCK_H_ \ No newline at end of file
diff --git a/src/plugins/test/mocks/CapabilityMock.h b/src/plugins/test/mocks/CapabilityMock.h
new file mode 100644
index 0000000..aaa0bd5
--- /dev/null
+++ b/src/plugins/test/mocks/CapabilityMock.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_TEST_MOCKS_CAPABILITYMOCK_H_
+#define VSHL_TEST_MOCKS_CAPABILITYMOCK_H_
+
+#include <gmock/gmock.h>
+
+#include "interfaces/capabilities/ICapability.h"
+
+namespace vshlcapabilities {
+namespace test {
+
+class CapabilityMock : public vshlcapabilities::common::interfaces::ICapability {
+public:
+ MOCK_CONST_METHOD0(getName, std::string());
+ MOCK_CONST_METHOD0(getUpstreamMessages, std::list<std::string>());
+ MOCK_CONST_METHOD0(getDownstreamMessages, std::list<std::string>());
+};
+
+} // namespace test
+} // namespace vshl
+
+#endif // VSHL_TEST_MOCKS_CAPABILITYMOCK_H_ \ No newline at end of file
diff --git a/src/plugins/utilities/events/EventRouter.cpp b/src/plugins/utilities/events/EventRouter.cpp
new file mode 100644
index 0000000..e715ca8
--- /dev/null
+++ b/src/plugins/utilities/events/EventRouter.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "utilities/events/EventRouter.h"
+
+static string TAG = "vshlcapabilities::utilities::events::EventRouter";
+
+using Level = vshlcapabilities::common::interfaces::ILogger::Level;
+
+namespace vshlcapabilities {
+namespace utilities {
+namespace events {
+
+unique_ptr<EventRouter> EventRouter::create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) {
+ return std::unique_ptr<EventRouter>(new EventRouter(logger));
+}
+
+EventRouter::EventRouter(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) : mLogger(logger) {
+}
+
+EventRouter::~EventRouter() {
+ mEventFilters.clear();
+}
+
+bool EventRouter::handleIncomingEvent(const string eventName, const string voiceAgentId, const string payload) {
+ for (auto eventFilter : mEventFilters) {
+ if (eventFilter->onIncomingEvent(eventName, voiceAgentId, payload)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool EventRouter::addEventFilter(shared_ptr<vshlcapabilities::common::interfaces::IEventFilter> filter) {
+ if (!filter) {
+ mLogger->log(Level::ERROR, TAG, "Failed to add event filter. Invalid arguments.");
+ return false;
+ }
+
+ mEventFilters.insert(filter);
+ return true;
+}
+
+bool EventRouter::removeEventFilter(shared_ptr<vshlcapabilities::common::interfaces::IEventFilter> filter) {
+ if (!filter) {
+ mLogger->log(Level::ERROR, TAG, "Failed to add remove filter. Invalid arguments.");
+ return false;
+ }
+
+ mEventFilters.erase(filter);
+ return true;
+}
+
+} // namespace events
+} // namespace utilities
+} // namespace vshl
diff --git a/src/plugins/utilities/events/EventRouter.h b/src/plugins/utilities/events/EventRouter.h
new file mode 100644
index 0000000..1286128
--- /dev/null
+++ b/src/plugins/utilities/events/EventRouter.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_UTILITIES_EVENTS_EVENTMANAGER_H_
+#define VSHL_UTILITIES_EVENTS_EVENTMANAGER_H_
+
+#include <memory>
+#include <string>
+#include <unordered_set>
+
+#include "interfaces/utilities/events/IEventFilter.h"
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace utilities {
+namespace events {
+/*
+ * This class is responsible for routing incoming events to
+ * the appropriate event listener for consumption.
+ * Note: The listeners should implement the IEventFilter class.
+ */
+class EventRouter {
+public:
+ static unique_ptr<EventRouter> create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ // Destructor
+ ~EventRouter();
+
+ // Add event filter as listerner.
+ bool addEventFilter(shared_ptr<vshlcapabilities::common::interfaces::IEventFilter> filter);
+
+ // Remove event filter as listerner.
+ bool removeEventFilter(shared_ptr<vshlcapabilities::common::interfaces::IEventFilter> filter);
+
+ // This method is called by the controller for routing
+ // the event to appropriate listener.
+ bool handleIncomingEvent(const string eventName, const string voiceAgentId, const string payload);
+
+private:
+ EventRouter(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger);
+
+ // set of event filters.
+ unordered_set<shared_ptr<vshlcapabilities::common::interfaces::IEventFilter>> mEventFilters;
+
+ // Logger
+ shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace events
+} // namespace utilities
+} // namespace vshl
+
+#endif // VSHL_UTILITIES_EVENTS_EVENTROUTER_H_
diff --git a/src/plugins/utilities/logging/Logger.cpp b/src/plugins/utilities/logging/Logger.cpp
new file mode 100644
index 0000000..c121556
--- /dev/null
+++ b/src/plugins/utilities/logging/Logger.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 "utilities/logging/Logger.h"
+
+namespace vshlcapabilities {
+namespace utilities {
+namespace logging {
+
+// Constructor
+Logger::Logger(AFB_ApiT api) {
+ mApi = api;
+}
+
+unique_ptr<Logger> Logger::create(AFB_ApiT api) {
+ auto logger = std::unique_ptr<Logger>(new Logger(api));
+ return logger;
+}
+
+void Logger::log(Level level, const std::string& tag, const std::string& message) {
+ string format_msg = "Tag: " + tag + ", message: " + message;
+ switch (level) {
+ case Level::NOTICE:
+ AFB_ApiNotice(mApi, format_msg.c_str());
+ break;
+ case Level::WARNING:
+ AFB_ApiWarning(mApi, format_msg.c_str());
+ break;
+ case Level::DEBUG:
+ AFB_ApiDebug(mApi, format_msg.c_str());
+ break;
+ case Level::ERROR:
+ AFB_ApiError(mApi, format_msg.c_str());
+ break;
+ case Level::INFO:
+ AFB_ApiInfo(mApi, format_msg.c_str());
+ break;
+ default:
+ break;
+ }
+}
+
+} // namespace logging
+} // namespace utilities
+} // namespace vshl
diff --git a/src/plugins/utilities/logging/Logger.h b/src/plugins/utilities/logging/Logger.h
new file mode 100644
index 0000000..56f810d
--- /dev/null
+++ b/src/plugins/utilities/logging/Logger.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 VSHL_UTILITIES_LOGGING_LOGGER_H_
+#define VSHL_UTILITIES_LOGGING_LOGGER_H_
+
+#include <memory>
+
+extern "C" {
+#define AFB_BINDING_VERSION 3
+#include "afb-definitions.h"
+#include "ctl-plugin.h"
+};
+
+#include "interfaces/utilities/logging/ILogger.h"
+
+using namespace std;
+
+namespace vshlcapabilities {
+namespace utilities {
+namespace logging {
+
+class Logger : public vshlcapabilities::common::interfaces::ILogger {
+public:
+ static std::unique_ptr<Logger> create(AFB_ApiT api);
+
+ // ILogger interface
+ void log(Level level, const std::string &tag,
+ const std::string &message) override;
+
+private:
+ Logger(AFB_ApiT api);
+
+ // Binding API reference
+ AFB_ApiT mApi;
+};
+
+} // namespace logging
+} // namespace utilities
+} // namespace vshl
+
+#endif // VSHL_UTILITIES_LOGGING_LOGGER_H_
diff --git a/src/vshl-capabilities-apidef.h b/src/vshl-capabilities-apidef.h
new file mode 100644
index 0000000..6ce4cb3
--- /dev/null
+++ b/src/vshl-capabilities-apidef.h
@@ -0,0 +1,53 @@
+
+static const char _afb_description_vshl_capabilities[] =
+ "{\"openapi\":\"3.0.0\",\"$schema\":\"http://iot.bzh/download/openapi/sch"
+ "ema-3.0/default-schema.json\",\"info\":{\"description\":\"\",\"title\":\""
+ "High Level Voice Service Capabilities APIs\",\"version\":\"0.1\",\"x-bin"
+ "ding-c-generator\":{\"api\":\"vshl-capabilities\",\"version\":3,\"prefix"
+ "\":\"afv_\",\"postfix\":\"\",\"start\":null,\"onevent\":null,\"init\":\""
+ "init\",\"scope\":\"\",\"private\":false,\"noconcurrency\":true}},\"serve"
+ "rs\":[{\"url\":\"ws://{host}:{port}/api/monitor\",\"description\":\"TS c"
+ "aching binding\",\"variables\":{\"host\":{\"default\":\"localhost\"},\"p"
+ "ort\":{\"default\":\"1234\"}},\"x-afb-events\":[{\"$ref\":\"#/components"
+ "/schemas/afb-event\"}]}],\"components\":{\"schemas\":{\"afb-reply\":{\"$"
+ "ref\":\"#/components/schemas/afb-reply-v3\"},\"afb-event\":{\"$ref\":\"#"
+ "/components/schemas/afb-event-v3\"},\"afb-reply-v3\":{\"title\":\"Generi"
+ "c response.\",\"type\":\"object\",\"required\":[\"jtype\",\"request\"],\""
+ "properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-reply\"},\""
+ "request\":{\"type\":\"object\",\"required\":[\"status\"],\"properties\":"
+ "{\"status\":{\"type\":\"string\"},\"info\":{\"type\":\"string\"},\"token"
+ "\":{\"type\":\"string\"},\"uuid\":{\"type\":\"string\"},\"reqid\":{\"typ"
+ "e\":\"string\"}}},\"response\":{\"type\":\"object\"}}},\"afb-event-v3\":"
+ "{\"type\":\"object\",\"required\":[\"jtype\",\"event\"],\"properties\":{"
+ "\"jtype\":{\"type\":\"string\",\"const\":\"afb-event\"},\"event\":{\"typ"
+ "e\":\"string\"},\"data\":{\"type\":\"object\"}}}},\"responses\":{\"200\""
+ ":{\"description\":\"A complex object array response\",\"content\":{\"app"
+ "lication/json\":{\"schema\":{\"$ref\":\"#/components/schemas/afb-reply\""
+ "}}}}}}}"
+;
+
+
+static const struct afb_verb_v3 _afb_verbs_vshl_capabilities[] = {
+ {
+ .verb = NULL,
+ .callback = NULL,
+ .auth = NULL,
+ .info = NULL,
+ .session = 0,
+ .vcbdata = NULL,
+ .glob = 0
+ }
+};
+
+const struct afb_binding_v3 afbBindingV3 = {
+ .api = "vshl-capabilities",
+ .specification = _afb_description_vshl_capabilities,
+ .info = "",
+ .verbs = _afb_verbs_vshl_capabilities,
+ .preinit = NULL,
+ .init = init,
+ .onevent = NULL,
+ .userdata = NULL,
+ .noconcurrency = 1
+};
+
diff --git a/src/vshl-capabilities-apidef.json b/src/vshl-capabilities-apidef.json
new file mode 100644
index 0000000..158bf5a
--- /dev/null
+++ b/src/vshl-capabilities-apidef.json
@@ -0,0 +1,109 @@
+{
+ "openapi": "3.0.0",
+ "$schema": "http://iot.bzh/download/openapi/schema-3.0/default-schema.json",
+ "info": {
+ "description": "",
+ "title": "High Level Voice Service Capabilities APIs",
+ "version": "0.1",
+ "x-binding-c-generator": {
+ "api": "vshl-capabilities",
+ "version": 3,
+ "prefix": "afv_",
+ "postfix": "",
+ "start": null,
+ "onevent": null,
+ "init": "init",
+ "scope": "",
+ "private": false,
+ "noconcurrency": true
+ }
+ },
+ "servers": [{
+ "url": "ws://{host}:{port}/api/monitor",
+ "description": "TS caching binding",
+ "variables": {
+ "host": {
+ "default": "localhost"
+ },
+ "port": {
+ "default": "1234"
+ }
+ },
+ "x-afb-events": [{
+ "$ref": "#/components/schemas/afb-event"
+ }]
+ }],
+ "components": {
+ "schemas": {
+ "afb-reply": {
+ "$ref": "#/components/schemas/afb-reply-v3"
+ },
+ "afb-event": {
+ "$ref": "#/components/schemas/afb-event-v3"
+ },
+ "afb-reply-v3": {
+ "title": "Generic response.",
+ "type": "object",
+ "required": ["jtype", "request"],
+ "properties": {
+ "jtype": {
+ "type": "string",
+ "const": "afb-reply"
+ },
+ "request": {
+ "type": "object",
+ "required": ["status"],
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "info": {
+ "type": "string"
+ },
+ "token": {
+ "type": "string"
+ },
+ "uuid": {
+ "type": "string"
+ },
+ "reqid": {
+ "type": "string"
+ }
+ }
+ },
+ "response": {
+ "type": "object"
+ }
+ }
+ },
+ "afb-event-v3": {
+ "type": "object",
+ "required": ["jtype", "event"],
+ "properties": {
+ "jtype": {
+ "type": "string",
+ "const": "afb-event"
+ },
+ "event": {
+ "type": "string"
+ },
+ "data": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "A complex object array response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/afb-reply"
+ }
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/vshl-capabilities-binding.c b/src/vshl-capabilities-binding.c
new file mode 100644
index 0000000..b38210a
--- /dev/null
+++ b/src/vshl-capabilities-binding.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+#define _GNU_SOURCE
+#include "vshl-capabilities-binding.h"
+
+afb_dynapi* AFB_default;
+
+// Config Section definition (note: controls section index should match handle
+// retrieval in HalConfigExec)
+static CtlSectionT ctrlSections[] = {{.key = "plugins", .loadCB = PluginConfig},
+ {.key = "controls", .loadCB = ControlConfig},
+ {.key = NULL}};
+
+static AFB_ApiVerbs ctrlApiVerbs[] = {
+ {.verb = NULL} /* marker for end of the array */
+};
+
+static int ctrlLoadStaticVerbs(afb_dynapi* apiHandle, AFB_ApiVerbs* verbs) {
+ int errcount = 0;
+
+ for (int idx = 0; verbs[idx].verb; idx++) {
+ errcount += afb_dynapi_add_verb(
+ apiHandle,
+ ctrlApiVerbs[idx].verb,
+ NULL,
+ ctrlApiVerbs[idx].callback,
+ (void*)&ctrlApiVerbs[idx],
+ ctrlApiVerbs[idx].auth,
+ 0);
+ }
+
+ return errcount;
+};
+
+// next generation dynamic API-V3 mode
+#include <signal.h>
+
+static int CtrlInitOneApi(AFB_ApiT apiHandle)
+{
+ CtlConfigT *ctrlConfig;
+
+ if(!apiHandle)
+ return -1;
+
+ // Retrieve section config from api handle
+ ctrlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle);
+ if(!ctrlConfig)
+ return -2;
+
+ return CtlConfigExec(apiHandle, ctrlConfig);
+}
+
+static int ctrlLoadOneApi(void* cbdata, AFB_ApiT apiHandle) {
+ CtlConfigT* ctrlConfig = (CtlConfigT*)cbdata;
+
+ // save closure as api's data context
+ afb_dynapi_set_userdata(apiHandle, ctrlConfig);
+
+ // add static controls verbs
+ int err = ctrlLoadStaticVerbs(apiHandle, ctrlApiVerbs);
+ if (err) {
+ AFB_ApiError(apiHandle, "ctrlLoadStaticVerbs fail to register static V2 verbs");
+ return ERROR;
+ }
+
+ // load section for corresponding API
+ err = CtlLoadSections(apiHandle, ctrlConfig, ctrlSections);
+ if (err) {
+ AFB_ApiError(apiHandle, "CtlLoadSections fail to load the sections");
+ return ERROR;
+ }
+
+ // declare an event event manager for this API;
+ afb_dynapi_on_event(apiHandle, CtrlDispatchApiEvent);
+
+ // init API function (does not receive user closure ???
+ afb_dynapi_on_init(apiHandle, CtrlInitOneApi);
+
+ afb_dynapi_seal(apiHandle);
+ return err;
+}
+
+int afbBindingEntry(afb_dynapi* apiHandle) {
+ AFB_default = apiHandle;
+ AFB_ApiNotice(apiHandle, "Controller in afbBindingEntry");
+
+ const char* dirList = getenv("CONTROL_CONFIG_PATH");
+ if (!dirList) dirList = CONTROL_CONFIG_PATH;
+
+ const char* configPath = CtlConfigSearch(apiHandle, dirList, "");
+ if (!configPath) {
+ AFB_ApiError(apiHandle, "CtlPreInit: No %s* config found in %s ", GetBinderName(), dirList);
+ return ERROR;
+ }
+
+ // load config file and create API
+ CtlConfigT* ctrlConfig = CtlLoadMetaData(apiHandle, configPath);
+ if (!ctrlConfig) {
+ AFB_ApiError(apiHandle, "CtrlBindingDyn No valid control config file in:\n-- %s", configPath);
+ return ERROR;
+ }
+
+ if (!ctrlConfig->api) {
+ AFB_ApiError(apiHandle, "CtrlBindingDyn API Missing from metadata in:\n-- %s", configPath);
+ return ERROR;
+ }
+
+ AFB_ApiNotice(apiHandle, "Controller API='%s' info='%s'", ctrlConfig->api, ctrlConfig->info);
+
+ // create one API per config file (Pre-V3 return code ToBeChanged)
+ int status = afb_dynapi_new_api(apiHandle, ctrlConfig->api, ctrlConfig->info, 1, ctrlLoadOneApi, ctrlConfig);
+
+ return status;
+}
diff --git a/src/vshl-capabilities-binding.h b/src/vshl-capabilities-binding.h
new file mode 100644
index 0000000..75e7c91
--- /dev/null
+++ b/src/vshl-capabilities-binding.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. 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.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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 _CTL_BINDING_INCLUDE_
+#define _CTL_BINDING_INCLUDE_
+
+#define AFB_BINDING_VERSION 3
+#include <ctl-config.h>
+
+#ifndef ERROR
+#define ERROR -1
+#endif
+
+#endif /* _CTL_BINDING_INCLUDE_ */ \ No newline at end of file