diff --git a/doc/release/yarp_3_9_master/feature_device_iChatBot_interface.md b/doc/release/yarp_3_9_master/feature_device_iChatBot_interface.md new file mode 100644 index 0000000000..0441df5b51 --- /dev/null +++ b/doc/release/yarp_3_9_master/feature_device_iChatBot_interface.md @@ -0,0 +1,11 @@ +feature_device_iChatBot_interface {#master} +--------------- + +### Devices - libYARP_dev + +#### `IChatBot` + +* Added a `yarp` `interface` to interact with chatbots. It allows to send messages and receive answers and to manage the bot language. + +* This does not features "implementation-specific" functionalities that could benefit the user but are not universally available among the various chatbot that can be found online. The idea is to open new PR in the future with new interfaces derived from `yarp::dev::IChatBot` that will model different "classes" of +chatbots (an example on how chatbots can be classified, can be found in this article: [A critical review of state-of-the-art chatbot designs and applications](https://doi.org/10.1002/widm.1434)) \ No newline at end of file diff --git a/src/devices/CMakeLists.txt b/src/devices/CMakeLists.txt index 827c8f65f5..c5e7086f59 100644 --- a/src/devices/CMakeLists.txt +++ b/src/devices/CMakeLists.txt @@ -20,6 +20,7 @@ yarp_begin_plugin_library(yarpmod add_subdirectory(openNI2DepthCamera) add_subdirectory(fakeDepthCamera) add_subdirectory(fakebot) + add_subdirectory(fakeChatBotDevice) add_subdirectory(fakeMotionControl) add_subdirectory(fakeAnalogSensor) add_subdirectory(fakeBattery) @@ -46,6 +47,7 @@ yarp_begin_plugin_library(yarpmod add_subdirectory(portaudioPlayer) add_subdirectory(portaudioRecorder) add_subdirectory(imuBosch_BNO055) + add_subdirectory(IChatBotMsgs) add_subdirectory(ILLMMsgs) add_subdirectory(IAudioGrabberMsgs) add_subdirectory(IMap2DMsgs) @@ -68,6 +70,8 @@ yarp_begin_plugin_library(yarpmod add_subdirectory(SDLJoypad) add_subdirectory(battery_nwc_yarp) add_subdirectory(battery_nws_yarp) + add_subdirectory(chatBot_nwc_yarp) + add_subdirectory(chatBot_nws_yarp) add_subdirectory(upowerBattery) add_subdirectory(Rangefinder2D_nws_yarp) add_subdirectory(Rangefinder2D_nwc_yarp) diff --git a/src/devices/IChatBotMsgs/CMakeLists.txt b/src/devices/IChatBotMsgs/CMakeLists.txt new file mode 100644 index 0000000000..595fa29cae --- /dev/null +++ b/src/devices/IChatBotMsgs/CMakeLists.txt @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT YARP_COMPILE_DEVICE_PLUGINS) + return() +endif() + +include(YarpChooseIDL) +yarp_choose_idl(ICHATBOTMSGS_THRIFT IChatBotMsgs.thrift) + +add_library(IChatBotMsgs OBJECT) + +target_sources(IChatBotMsgs PRIVATE ${ICHATBOTMSGS_THRIFT_GEN_FILES}) + +target_link_libraries(IChatBotMsgs + PRIVATE + YARP::YARP_dev + YARP::YARP_os + YARP::YARP_sig +) + +target_include_directories(IChatBotMsgs PUBLIC ${ICHATBOTMSGS_THRIFT_BUILD_INTERFACE_INCLUDE_DIRS}) + +set_property(TARGET IChatBotMsgs PROPERTY FOLDER "Devices/Shared") diff --git a/src/devices/IChatBotMsgs/IChatBotMsgs.thrift b/src/devices/IChatBotMsgs/IChatBotMsgs.thrift new file mode 100644 index 0000000000..4af726cea0 --- /dev/null +++ b/src/devices/IChatBotMsgs/IChatBotMsgs.thrift @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +struct return_interact{ + 1: bool result; + 2: string messageOut; +} + +struct return_getLanguage{ + 1: bool result; + 2: string language; +} + +service IChatBotMsgs { + return_interact interactRPC(1: string messageIn); + bool setLanguageRPC(1: string language); + return_getLanguage getLanguageRPC(); + bool resetBotRPC(); +} diff --git a/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs.cpp b/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs.cpp new file mode 100644 index 0000000000..ffe75c07f5 --- /dev/null +++ b/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs.cpp @@ -0,0 +1,1037 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +// Autogenerated by Thrift Compiler (0.14.1-yarped) +// +// This is an automatically generated file. +// It could get re-generated if the ALLOW_IDL_GENERATION flag is on. + +#include + +#include + +#include + +// interactRPC helper class declaration +class IChatBotMsgs_interactRPC_helper : + public yarp::os::Portable +{ +public: + IChatBotMsgs_interactRPC_helper() = default; + explicit IChatBotMsgs_interactRPC_helper(const std::string& messageIn); + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + class Command : + public yarp::os::idl::WirePortable + { + public: + Command() = default; + explicit Command(const std::string& messageIn); + + ~Command() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool writeTag(const yarp::os::idl::WireWriter& writer) const; + bool writeArgs(const yarp::os::idl::WireWriter& writer) const; + + bool read(yarp::os::idl::WireReader& reader) override; + bool readTag(yarp::os::idl::WireReader& reader); + bool readArgs(yarp::os::idl::WireReader& reader); + + std::string messageIn{}; + }; + + class Reply : + public yarp::os::idl::WirePortable + { + public: + Reply() = default; + ~Reply() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool read(yarp::os::idl::WireReader& reader) override; + + return_interact return_helper{}; + }; + + using funcptr_t = return_interact (*)(const std::string&); + void call(IChatBotMsgs* ptr); + + Command cmd; + Reply reply; + + static constexpr const char* s_tag{"interactRPC"}; + static constexpr size_t s_tag_len{1}; + static constexpr size_t s_cmd_len{2}; + static constexpr size_t s_reply_len{2}; + static constexpr const char* s_prototype{"return_interact IChatBotMsgs::interactRPC(const std::string& messageIn)"}; + static constexpr const char* s_help{""}; +}; + +// setLanguageRPC helper class declaration +class IChatBotMsgs_setLanguageRPC_helper : + public yarp::os::Portable +{ +public: + IChatBotMsgs_setLanguageRPC_helper() = default; + explicit IChatBotMsgs_setLanguageRPC_helper(const std::string& language); + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + class Command : + public yarp::os::idl::WirePortable + { + public: + Command() = default; + explicit Command(const std::string& language); + + ~Command() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool writeTag(const yarp::os::idl::WireWriter& writer) const; + bool writeArgs(const yarp::os::idl::WireWriter& writer) const; + + bool read(yarp::os::idl::WireReader& reader) override; + bool readTag(yarp::os::idl::WireReader& reader); + bool readArgs(yarp::os::idl::WireReader& reader); + + std::string language{}; + }; + + class Reply : + public yarp::os::idl::WirePortable + { + public: + Reply() = default; + ~Reply() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool read(yarp::os::idl::WireReader& reader) override; + + bool return_helper{false}; + }; + + using funcptr_t = bool (*)(const std::string&); + void call(IChatBotMsgs* ptr); + + Command cmd; + Reply reply; + + static constexpr const char* s_tag{"setLanguageRPC"}; + static constexpr size_t s_tag_len{1}; + static constexpr size_t s_cmd_len{2}; + static constexpr size_t s_reply_len{1}; + static constexpr const char* s_prototype{"bool IChatBotMsgs::setLanguageRPC(const std::string& language)"}; + static constexpr const char* s_help{""}; +}; + +// getLanguageRPC helper class declaration +class IChatBotMsgs_getLanguageRPC_helper : + public yarp::os::Portable +{ +public: + IChatBotMsgs_getLanguageRPC_helper() = default; + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + class Command : + public yarp::os::idl::WirePortable + { + public: + Command() = default; + ~Command() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool writeTag(const yarp::os::idl::WireWriter& writer) const; + bool writeArgs(const yarp::os::idl::WireWriter& writer) const; + + bool read(yarp::os::idl::WireReader& reader) override; + bool readTag(yarp::os::idl::WireReader& reader); + bool readArgs(yarp::os::idl::WireReader& reader); + }; + + class Reply : + public yarp::os::idl::WirePortable + { + public: + Reply() = default; + ~Reply() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool read(yarp::os::idl::WireReader& reader) override; + + return_getLanguage return_helper{}; + }; + + using funcptr_t = return_getLanguage (*)(); + void call(IChatBotMsgs* ptr); + + Command cmd; + Reply reply; + + static constexpr const char* s_tag{"getLanguageRPC"}; + static constexpr size_t s_tag_len{1}; + static constexpr size_t s_cmd_len{1}; + static constexpr size_t s_reply_len{2}; + static constexpr const char* s_prototype{"return_getLanguage IChatBotMsgs::getLanguageRPC()"}; + static constexpr const char* s_help{""}; +}; + +// resetBotRPC helper class declaration +class IChatBotMsgs_resetBotRPC_helper : + public yarp::os::Portable +{ +public: + IChatBotMsgs_resetBotRPC_helper() = default; + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + class Command : + public yarp::os::idl::WirePortable + { + public: + Command() = default; + ~Command() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool writeTag(const yarp::os::idl::WireWriter& writer) const; + bool writeArgs(const yarp::os::idl::WireWriter& writer) const; + + bool read(yarp::os::idl::WireReader& reader) override; + bool readTag(yarp::os::idl::WireReader& reader); + bool readArgs(yarp::os::idl::WireReader& reader); + }; + + class Reply : + public yarp::os::idl::WirePortable + { + public: + Reply() = default; + ~Reply() override = default; + + bool write(yarp::os::ConnectionWriter& connection) const override; + bool read(yarp::os::ConnectionReader& connection) override; + + bool write(const yarp::os::idl::WireWriter& writer) const override; + bool read(yarp::os::idl::WireReader& reader) override; + + bool return_helper{false}; + }; + + using funcptr_t = bool (*)(); + void call(IChatBotMsgs* ptr); + + Command cmd; + Reply reply; + + static constexpr const char* s_tag{"resetBotRPC"}; + static constexpr size_t s_tag_len{1}; + static constexpr size_t s_cmd_len{1}; + static constexpr size_t s_reply_len{1}; + static constexpr const char* s_prototype{"bool IChatBotMsgs::resetBotRPC()"}; + static constexpr const char* s_help{""}; +}; + +// interactRPC helper class implementation +IChatBotMsgs_interactRPC_helper::IChatBotMsgs_interactRPC_helper(const std::string& messageIn) : + cmd{messageIn} +{ +} + +bool IChatBotMsgs_interactRPC_helper::write(yarp::os::ConnectionWriter& connection) const +{ + return cmd.write(connection); +} + +bool IChatBotMsgs_interactRPC_helper::read(yarp::os::ConnectionReader& connection) +{ + return reply.read(connection); +} + +IChatBotMsgs_interactRPC_helper::Command::Command(const std::string& messageIn) : + messageIn{messageIn} +{ +} + +bool IChatBotMsgs_interactRPC_helper::Command::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + if (!writer.writeListHeader(s_cmd_len)) { + return false; + } + return write(writer); +} + +bool IChatBotMsgs_interactRPC_helper::Command::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + if (!reader.readListHeader()) { + reader.fail(); + return false; + } + return read(reader); +} + +bool IChatBotMsgs_interactRPC_helper::Command::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writeTag(writer)) { + return false; + } + if (!writeArgs(writer)) { + return false; + } + return true; +} + +bool IChatBotMsgs_interactRPC_helper::Command::writeTag(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeTag(s_tag, 1, s_tag_len)) { + return false; + } + return true; +} + +bool IChatBotMsgs_interactRPC_helper::Command::writeArgs(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeString(messageIn)) { + return false; + } + return true; +} + +bool IChatBotMsgs_interactRPC_helper::Command::read(yarp::os::idl::WireReader& reader) +{ + if (!readTag(reader)) { + return false; + } + if (!readArgs(reader)) { + return false; + } + return true; +} + +bool IChatBotMsgs_interactRPC_helper::Command::readTag(yarp::os::idl::WireReader& reader) +{ + std::string tag = reader.readTag(s_tag_len); + if (reader.isError()) { + return false; + } + if (tag != s_tag) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_interactRPC_helper::Command::readArgs(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readString(messageIn)) { + reader.fail(); + return false; + } + if (!reader.noMore()) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_interactRPC_helper::Reply::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + return write(writer); +} + +bool IChatBotMsgs_interactRPC_helper::Reply::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + return read(reader); +} + +bool IChatBotMsgs_interactRPC_helper::Reply::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.isNull()) { + if (!writer.writeListHeader(s_reply_len)) { + return false; + } + if (!writer.write(return_helper)) { + return false; + } + } + return true; +} + +bool IChatBotMsgs_interactRPC_helper::Reply::read(yarp::os::idl::WireReader& reader) +{ + if (!reader.readListReturn()) { + return false; + } + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.read(return_helper)) { + reader.fail(); + return false; + } + return true; +} + +void IChatBotMsgs_interactRPC_helper::call(IChatBotMsgs* ptr) +{ + reply.return_helper = ptr->interactRPC(cmd.messageIn); +} + +// setLanguageRPC helper class implementation +IChatBotMsgs_setLanguageRPC_helper::IChatBotMsgs_setLanguageRPC_helper(const std::string& language) : + cmd{language} +{ +} + +bool IChatBotMsgs_setLanguageRPC_helper::write(yarp::os::ConnectionWriter& connection) const +{ + return cmd.write(connection); +} + +bool IChatBotMsgs_setLanguageRPC_helper::read(yarp::os::ConnectionReader& connection) +{ + return reply.read(connection); +} + +IChatBotMsgs_setLanguageRPC_helper::Command::Command(const std::string& language) : + language{language} +{ +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + if (!writer.writeListHeader(s_cmd_len)) { + return false; + } + return write(writer); +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + if (!reader.readListHeader()) { + reader.fail(); + return false; + } + return read(reader); +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writeTag(writer)) { + return false; + } + if (!writeArgs(writer)) { + return false; + } + return true; +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::writeTag(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeTag(s_tag, 1, s_tag_len)) { + return false; + } + return true; +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::writeArgs(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeString(language)) { + return false; + } + return true; +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::read(yarp::os::idl::WireReader& reader) +{ + if (!readTag(reader)) { + return false; + } + if (!readArgs(reader)) { + return false; + } + return true; +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::readTag(yarp::os::idl::WireReader& reader) +{ + std::string tag = reader.readTag(s_tag_len); + if (reader.isError()) { + return false; + } + if (tag != s_tag) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_setLanguageRPC_helper::Command::readArgs(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readString(language)) { + reader.fail(); + return false; + } + if (!reader.noMore()) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_setLanguageRPC_helper::Reply::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + return write(writer); +} + +bool IChatBotMsgs_setLanguageRPC_helper::Reply::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + return read(reader); +} + +bool IChatBotMsgs_setLanguageRPC_helper::Reply::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.isNull()) { + if (!writer.writeListHeader(s_reply_len)) { + return false; + } + if (!writer.writeBool(return_helper)) { + return false; + } + } + return true; +} + +bool IChatBotMsgs_setLanguageRPC_helper::Reply::read(yarp::os::idl::WireReader& reader) +{ + if (!reader.readListReturn()) { + return false; + } + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readBool(return_helper)) { + reader.fail(); + return false; + } + return true; +} + +void IChatBotMsgs_setLanguageRPC_helper::call(IChatBotMsgs* ptr) +{ + reply.return_helper = ptr->setLanguageRPC(cmd.language); +} + +// getLanguageRPC helper class implementation +bool IChatBotMsgs_getLanguageRPC_helper::write(yarp::os::ConnectionWriter& connection) const +{ + return cmd.write(connection); +} + +bool IChatBotMsgs_getLanguageRPC_helper::read(yarp::os::ConnectionReader& connection) +{ + return reply.read(connection); +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + if (!writer.writeListHeader(s_cmd_len)) { + return false; + } + return write(writer); +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + if (!reader.readListHeader()) { + reader.fail(); + return false; + } + return read(reader); +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writeTag(writer)) { + return false; + } + if (!writeArgs(writer)) { + return false; + } + return true; +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::writeTag(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeTag(s_tag, 1, s_tag_len)) { + return false; + } + return true; +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::writeArgs(const yarp::os::idl::WireWriter& writer [[maybe_unused]]) const +{ + return true; +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::read(yarp::os::idl::WireReader& reader) +{ + if (!readTag(reader)) { + return false; + } + if (!readArgs(reader)) { + return false; + } + return true; +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::readTag(yarp::os::idl::WireReader& reader) +{ + std::string tag = reader.readTag(s_tag_len); + if (reader.isError()) { + return false; + } + if (tag != s_tag) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_getLanguageRPC_helper::Command::readArgs(yarp::os::idl::WireReader& reader) +{ + if (!reader.noMore()) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_getLanguageRPC_helper::Reply::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + return write(writer); +} + +bool IChatBotMsgs_getLanguageRPC_helper::Reply::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + return read(reader); +} + +bool IChatBotMsgs_getLanguageRPC_helper::Reply::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.isNull()) { + if (!writer.writeListHeader(s_reply_len)) { + return false; + } + if (!writer.write(return_helper)) { + return false; + } + } + return true; +} + +bool IChatBotMsgs_getLanguageRPC_helper::Reply::read(yarp::os::idl::WireReader& reader) +{ + if (!reader.readListReturn()) { + return false; + } + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.read(return_helper)) { + reader.fail(); + return false; + } + return true; +} + +void IChatBotMsgs_getLanguageRPC_helper::call(IChatBotMsgs* ptr) +{ + reply.return_helper = ptr->getLanguageRPC(); +} + +// resetBotRPC helper class implementation +bool IChatBotMsgs_resetBotRPC_helper::write(yarp::os::ConnectionWriter& connection) const +{ + return cmd.write(connection); +} + +bool IChatBotMsgs_resetBotRPC_helper::read(yarp::os::ConnectionReader& connection) +{ + return reply.read(connection); +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + if (!writer.writeListHeader(s_cmd_len)) { + return false; + } + return write(writer); +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + if (!reader.readListHeader()) { + reader.fail(); + return false; + } + return read(reader); +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writeTag(writer)) { + return false; + } + if (!writeArgs(writer)) { + return false; + } + return true; +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::writeTag(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeTag(s_tag, 1, s_tag_len)) { + return false; + } + return true; +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::writeArgs(const yarp::os::idl::WireWriter& writer [[maybe_unused]]) const +{ + return true; +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::read(yarp::os::idl::WireReader& reader) +{ + if (!readTag(reader)) { + return false; + } + if (!readArgs(reader)) { + return false; + } + return true; +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::readTag(yarp::os::idl::WireReader& reader) +{ + std::string tag = reader.readTag(s_tag_len); + if (reader.isError()) { + return false; + } + if (tag != s_tag) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_resetBotRPC_helper::Command::readArgs(yarp::os::idl::WireReader& reader) +{ + if (!reader.noMore()) { + reader.fail(); + return false; + } + return true; +} + +bool IChatBotMsgs_resetBotRPC_helper::Reply::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + return write(writer); +} + +bool IChatBotMsgs_resetBotRPC_helper::Reply::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + return read(reader); +} + +bool IChatBotMsgs_resetBotRPC_helper::Reply::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.isNull()) { + if (!writer.writeListHeader(s_reply_len)) { + return false; + } + if (!writer.writeBool(return_helper)) { + return false; + } + } + return true; +} + +bool IChatBotMsgs_resetBotRPC_helper::Reply::read(yarp::os::idl::WireReader& reader) +{ + if (!reader.readListReturn()) { + return false; + } + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readBool(return_helper)) { + reader.fail(); + return false; + } + return true; +} + +void IChatBotMsgs_resetBotRPC_helper::call(IChatBotMsgs* ptr) +{ + reply.return_helper = ptr->resetBotRPC(); +} + +// Constructor +IChatBotMsgs::IChatBotMsgs() +{ + yarp().setOwner(*this); +} + +return_interact IChatBotMsgs::interactRPC(const std::string& messageIn) +{ + if (!yarp().canWrite()) { + yError("Missing server method '%s'?", IChatBotMsgs_interactRPC_helper::s_prototype); + } + IChatBotMsgs_interactRPC_helper helper{messageIn}; + bool ok = yarp().write(helper, helper); + return ok ? helper.reply.return_helper : return_interact{}; +} + +bool IChatBotMsgs::setLanguageRPC(const std::string& language) +{ + if (!yarp().canWrite()) { + yError("Missing server method '%s'?", IChatBotMsgs_setLanguageRPC_helper::s_prototype); + } + IChatBotMsgs_setLanguageRPC_helper helper{language}; + bool ok = yarp().write(helper, helper); + return ok ? helper.reply.return_helper : bool{}; +} + +return_getLanguage IChatBotMsgs::getLanguageRPC() +{ + if (!yarp().canWrite()) { + yError("Missing server method '%s'?", IChatBotMsgs_getLanguageRPC_helper::s_prototype); + } + IChatBotMsgs_getLanguageRPC_helper helper{}; + bool ok = yarp().write(helper, helper); + return ok ? helper.reply.return_helper : return_getLanguage{}; +} + +bool IChatBotMsgs::resetBotRPC() +{ + if (!yarp().canWrite()) { + yError("Missing server method '%s'?", IChatBotMsgs_resetBotRPC_helper::s_prototype); + } + IChatBotMsgs_resetBotRPC_helper helper{}; + bool ok = yarp().write(helper, helper); + return ok ? helper.reply.return_helper : bool{}; +} + +// help method +std::vector IChatBotMsgs::help(const std::string& functionName) +{ + bool showAll = (functionName == "--all"); + std::vector helpString; + if (showAll) { + helpString.emplace_back("*** Available commands:"); + helpString.emplace_back(IChatBotMsgs_interactRPC_helper::s_tag); + helpString.emplace_back(IChatBotMsgs_setLanguageRPC_helper::s_tag); + helpString.emplace_back(IChatBotMsgs_getLanguageRPC_helper::s_tag); + helpString.emplace_back(IChatBotMsgs_resetBotRPC_helper::s_tag); + helpString.emplace_back("help"); + } else { + if (functionName == IChatBotMsgs_interactRPC_helper::s_tag) { + helpString.emplace_back(IChatBotMsgs_interactRPC_helper::s_prototype); + } + if (functionName == IChatBotMsgs_setLanguageRPC_helper::s_tag) { + helpString.emplace_back(IChatBotMsgs_setLanguageRPC_helper::s_prototype); + } + if (functionName == IChatBotMsgs_getLanguageRPC_helper::s_tag) { + helpString.emplace_back(IChatBotMsgs_getLanguageRPC_helper::s_prototype); + } + if (functionName == IChatBotMsgs_resetBotRPC_helper::s_tag) { + helpString.emplace_back(IChatBotMsgs_resetBotRPC_helper::s_prototype); + } + if (functionName == "help") { + helpString.emplace_back("std::vector help(const std::string& functionName = \"--all\")"); + helpString.emplace_back("Return list of available commands, or help message for a specific function"); + helpString.emplace_back("@param functionName name of command for which to get a detailed description. If none or '--all' is provided, print list of available commands"); + helpString.emplace_back("@return list of strings (one string per line)"); + } + } + if (helpString.empty()) { + helpString.emplace_back("Command not found"); + } + return helpString; +} + +// read from ConnectionReader +bool IChatBotMsgs::read(yarp::os::ConnectionReader& connection) +{ + constexpr size_t max_tag_len = 1; + size_t tag_len = 1; + + yarp::os::idl::WireReader reader(connection); + reader.expectAccept(); + if (!reader.readListHeader()) { + reader.fail(); + return false; + } + + std::string tag = reader.readTag(1); + bool direct = (tag == "__direct__"); + if (direct) { + tag = reader.readTag(1); + } + while (tag_len <= max_tag_len && !reader.isError()) { + if (tag == IChatBotMsgs_interactRPC_helper::s_tag) { + IChatBotMsgs_interactRPC_helper helper; + if (!helper.cmd.readArgs(reader)) { + return false; + } + + helper.call(this); + + yarp::os::idl::WireWriter writer(reader); + if (!helper.reply.write(writer)) { + return false; + } + reader.accept(); + return true; + } + if (tag == IChatBotMsgs_setLanguageRPC_helper::s_tag) { + IChatBotMsgs_setLanguageRPC_helper helper; + if (!helper.cmd.readArgs(reader)) { + return false; + } + + helper.call(this); + + yarp::os::idl::WireWriter writer(reader); + if (!helper.reply.write(writer)) { + return false; + } + reader.accept(); + return true; + } + if (tag == IChatBotMsgs_getLanguageRPC_helper::s_tag) { + IChatBotMsgs_getLanguageRPC_helper helper; + if (!helper.cmd.readArgs(reader)) { + return false; + } + + helper.call(this); + + yarp::os::idl::WireWriter writer(reader); + if (!helper.reply.write(writer)) { + return false; + } + reader.accept(); + return true; + } + if (tag == IChatBotMsgs_resetBotRPC_helper::s_tag) { + IChatBotMsgs_resetBotRPC_helper helper; + if (!helper.cmd.readArgs(reader)) { + return false; + } + + helper.call(this); + + yarp::os::idl::WireWriter writer(reader); + if (!helper.reply.write(writer)) { + return false; + } + reader.accept(); + return true; + } + if (tag == "help") { + std::string functionName; + if (!reader.readString(functionName)) { + functionName = "--all"; + } + auto help_strings = help(functionName); + yarp::os::idl::WireWriter writer(reader); + if (!writer.isNull()) { + if (!writer.writeListHeader(2)) { + return false; + } + if (!writer.writeTag("many", 1, 0)) { + return false; + } + if (!writer.writeListBegin(0, help_strings.size())) { + return false; + } + for (const auto& help_string : help_strings) { + if (!writer.writeString(help_string)) { + return false; + } + } + if (!writer.writeListEnd()) { + return false; + } + } + reader.accept(); + return true; + } + if (reader.noMore()) { + reader.fail(); + return false; + } + std::string next_tag = reader.readTag(1); + if (next_tag.empty()) { + break; + } + tag.append("_").append(next_tag); + tag_len = std::count(tag.begin(), tag.end(), '_') + 1; + } + return false; +} diff --git a/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs.h b/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs.h new file mode 100644 index 0000000000..2cd2ca6186 --- /dev/null +++ b/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs.h @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +// Autogenerated by Thrift Compiler (0.14.1-yarped) +// +// This is an automatically generated file. +// It could get re-generated if the ALLOW_IDL_GENERATION flag is on. + +#ifndef YARP_THRIFT_GENERATOR_SERVICE_ICHATBOTMSGS_H +#define YARP_THRIFT_GENERATOR_SERVICE_ICHATBOTMSGS_H + +#include +#include +#include +#include + +class IChatBotMsgs : + public yarp::os::Wire +{ +public: + // Constructor + IChatBotMsgs(); + + virtual return_interact interactRPC(const std::string& messageIn); + + virtual bool setLanguageRPC(const std::string& language); + + virtual return_getLanguage getLanguageRPC(); + + virtual bool resetBotRPC(); + + // help method + virtual std::vector help(const std::string& functionName = "--all"); + + // read from ConnectionReader + bool read(yarp::os::ConnectionReader& connection) override; +}; + +#endif // YARP_THRIFT_GENERATOR_SERVICE_ICHATBOTMSGS_H diff --git a/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs_index.txt b/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs_index.txt new file mode 100644 index 0000000000..7559b6003a --- /dev/null +++ b/src/devices/IChatBotMsgs/idl_generated_code/IChatBotMsgs_index.txt @@ -0,0 +1,6 @@ +return_interact.h +return_interact.cpp +return_getLanguage.h +return_getLanguage.cpp +IChatBotMsgs.h +IChatBotMsgs.cpp diff --git a/src/devices/IChatBotMsgs/idl_generated_code/return_getLanguage.cpp b/src/devices/IChatBotMsgs/idl_generated_code/return_getLanguage.cpp new file mode 100644 index 0000000000..23ab0f9fc5 --- /dev/null +++ b/src/devices/IChatBotMsgs/idl_generated_code/return_getLanguage.cpp @@ -0,0 +1,178 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +// Autogenerated by Thrift Compiler (0.14.1-yarped) +// +// This is an automatically generated file. +// It could get re-generated if the ALLOW_IDL_GENERATION flag is on. + +#include + +// Constructor with field values +return_getLanguage::return_getLanguage(const bool result, + const std::string& language) : + WirePortable(), + result(result), + language(language) +{ +} + +// Read structure on a Wire +bool return_getLanguage::read(yarp::os::idl::WireReader& reader) +{ + if (!read_result(reader)) { + return false; + } + if (!read_language(reader)) { + return false; + } + if (reader.isError()) { + return false; + } + return true; +} + +// Read structure on a Connection +bool return_getLanguage::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + if (!reader.readListHeader(2)) { + return false; + } + if (!read(reader)) { + return false; + } + return true; +} + +// Write structure on a Wire +bool return_getLanguage::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!write_result(writer)) { + return false; + } + if (!write_language(writer)) { + return false; + } + if (writer.isError()) { + return false; + } + return true; +} + +// Write structure on a Connection +bool return_getLanguage::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + if (!writer.writeListHeader(2)) { + return false; + } + if (!write(writer)) { + return false; + } + return true; +} + +// Convert to a printable string +std::string return_getLanguage::toString() const +{ + yarp::os::Bottle b; + if (!yarp::os::Portable::copyPortable(*this, b)) { + return {}; + } + return b.toString(); +} + +// read result field +bool return_getLanguage::read_result(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readBool(result)) { + reader.fail(); + return false; + } + return true; +} + +// write result field +bool return_getLanguage::write_result(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeBool(result)) { + return false; + } + return true; +} + +// read (nested) result field +bool return_getLanguage::nested_read_result(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readBool(result)) { + reader.fail(); + return false; + } + return true; +} + +// write (nested) result field +bool return_getLanguage::nested_write_result(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeBool(result)) { + return false; + } + return true; +} + +// read language field +bool return_getLanguage::read_language(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readString(language)) { + reader.fail(); + return false; + } + return true; +} + +// write language field +bool return_getLanguage::write_language(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeString(language)) { + return false; + } + return true; +} + +// read (nested) language field +bool return_getLanguage::nested_read_language(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readString(language)) { + reader.fail(); + return false; + } + return true; +} + +// write (nested) language field +bool return_getLanguage::nested_write_language(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeString(language)) { + return false; + } + return true; +} diff --git a/src/devices/IChatBotMsgs/idl_generated_code/return_getLanguage.h b/src/devices/IChatBotMsgs/idl_generated_code/return_getLanguage.h new file mode 100644 index 0000000000..eadf04c716 --- /dev/null +++ b/src/devices/IChatBotMsgs/idl_generated_code/return_getLanguage.h @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +// Autogenerated by Thrift Compiler (0.14.1-yarped) +// +// This is an automatically generated file. +// It could get re-generated if the ALLOW_IDL_GENERATION flag is on. + +#ifndef YARP_THRIFT_GENERATOR_STRUCT_RETURN_GETLANGUAGE_H +#define YARP_THRIFT_GENERATOR_STRUCT_RETURN_GETLANGUAGE_H + +#include +#include + +class return_getLanguage : + public yarp::os::idl::WirePortable +{ +public: + // Fields + bool result{false}; + std::string language{}; + + // Default constructor + return_getLanguage() = default; + + // Constructor with field values + return_getLanguage(const bool result, + const std::string& language); + + // Read structure on a Wire + bool read(yarp::os::idl::WireReader& reader) override; + + // Read structure on a Connection + bool read(yarp::os::ConnectionReader& connection) override; + + // Write structure on a Wire + bool write(const yarp::os::idl::WireWriter& writer) const override; + + // Write structure on a Connection + bool write(yarp::os::ConnectionWriter& connection) const override; + + // Convert to a printable string + std::string toString() const; + + // If you want to serialize this class without nesting, use this helper + typedef yarp::os::idl::Unwrapped unwrapped; + +private: + // read/write result field + bool read_result(yarp::os::idl::WireReader& reader); + bool write_result(const yarp::os::idl::WireWriter& writer) const; + bool nested_read_result(yarp::os::idl::WireReader& reader); + bool nested_write_result(const yarp::os::idl::WireWriter& writer) const; + + // read/write language field + bool read_language(yarp::os::idl::WireReader& reader); + bool write_language(const yarp::os::idl::WireWriter& writer) const; + bool nested_read_language(yarp::os::idl::WireReader& reader); + bool nested_write_language(const yarp::os::idl::WireWriter& writer) const; +}; + +#endif // YARP_THRIFT_GENERATOR_STRUCT_RETURN_GETLANGUAGE_H diff --git a/src/devices/IChatBotMsgs/idl_generated_code/return_interact.cpp b/src/devices/IChatBotMsgs/idl_generated_code/return_interact.cpp new file mode 100644 index 0000000000..80a3a71554 --- /dev/null +++ b/src/devices/IChatBotMsgs/idl_generated_code/return_interact.cpp @@ -0,0 +1,178 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +// Autogenerated by Thrift Compiler (0.14.1-yarped) +// +// This is an automatically generated file. +// It could get re-generated if the ALLOW_IDL_GENERATION flag is on. + +#include + +// Constructor with field values +return_interact::return_interact(const bool result, + const std::string& messageOut) : + WirePortable(), + result(result), + messageOut(messageOut) +{ +} + +// Read structure on a Wire +bool return_interact::read(yarp::os::idl::WireReader& reader) +{ + if (!read_result(reader)) { + return false; + } + if (!read_messageOut(reader)) { + return false; + } + if (reader.isError()) { + return false; + } + return true; +} + +// Read structure on a Connection +bool return_interact::read(yarp::os::ConnectionReader& connection) +{ + yarp::os::idl::WireReader reader(connection); + if (!reader.readListHeader(2)) { + return false; + } + if (!read(reader)) { + return false; + } + return true; +} + +// Write structure on a Wire +bool return_interact::write(const yarp::os::idl::WireWriter& writer) const +{ + if (!write_result(writer)) { + return false; + } + if (!write_messageOut(writer)) { + return false; + } + if (writer.isError()) { + return false; + } + return true; +} + +// Write structure on a Connection +bool return_interact::write(yarp::os::ConnectionWriter& connection) const +{ + yarp::os::idl::WireWriter writer(connection); + if (!writer.writeListHeader(2)) { + return false; + } + if (!write(writer)) { + return false; + } + return true; +} + +// Convert to a printable string +std::string return_interact::toString() const +{ + yarp::os::Bottle b; + if (!yarp::os::Portable::copyPortable(*this, b)) { + return {}; + } + return b.toString(); +} + +// read result field +bool return_interact::read_result(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readBool(result)) { + reader.fail(); + return false; + } + return true; +} + +// write result field +bool return_interact::write_result(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeBool(result)) { + return false; + } + return true; +} + +// read (nested) result field +bool return_interact::nested_read_result(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readBool(result)) { + reader.fail(); + return false; + } + return true; +} + +// write (nested) result field +bool return_interact::nested_write_result(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeBool(result)) { + return false; + } + return true; +} + +// read messageOut field +bool return_interact::read_messageOut(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readString(messageOut)) { + reader.fail(); + return false; + } + return true; +} + +// write messageOut field +bool return_interact::write_messageOut(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeString(messageOut)) { + return false; + } + return true; +} + +// read (nested) messageOut field +bool return_interact::nested_read_messageOut(yarp::os::idl::WireReader& reader) +{ + if (reader.noMore()) { + reader.fail(); + return false; + } + if (!reader.readString(messageOut)) { + reader.fail(); + return false; + } + return true; +} + +// write (nested) messageOut field +bool return_interact::nested_write_messageOut(const yarp::os::idl::WireWriter& writer) const +{ + if (!writer.writeString(messageOut)) { + return false; + } + return true; +} diff --git a/src/devices/IChatBotMsgs/idl_generated_code/return_interact.h b/src/devices/IChatBotMsgs/idl_generated_code/return_interact.h new file mode 100644 index 0000000000..8d533fe575 --- /dev/null +++ b/src/devices/IChatBotMsgs/idl_generated_code/return_interact.h @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +// Autogenerated by Thrift Compiler (0.14.1-yarped) +// +// This is an automatically generated file. +// It could get re-generated if the ALLOW_IDL_GENERATION flag is on. + +#ifndef YARP_THRIFT_GENERATOR_STRUCT_RETURN_INTERACT_H +#define YARP_THRIFT_GENERATOR_STRUCT_RETURN_INTERACT_H + +#include +#include + +class return_interact : + public yarp::os::idl::WirePortable +{ +public: + // Fields + bool result{false}; + std::string messageOut{}; + + // Default constructor + return_interact() = default; + + // Constructor with field values + return_interact(const bool result, + const std::string& messageOut); + + // Read structure on a Wire + bool read(yarp::os::idl::WireReader& reader) override; + + // Read structure on a Connection + bool read(yarp::os::ConnectionReader& connection) override; + + // Write structure on a Wire + bool write(const yarp::os::idl::WireWriter& writer) const override; + + // Write structure on a Connection + bool write(yarp::os::ConnectionWriter& connection) const override; + + // Convert to a printable string + std::string toString() const; + + // If you want to serialize this class without nesting, use this helper + typedef yarp::os::idl::Unwrapped unwrapped; + +private: + // read/write result field + bool read_result(yarp::os::idl::WireReader& reader); + bool write_result(const yarp::os::idl::WireWriter& writer) const; + bool nested_read_result(yarp::os::idl::WireReader& reader); + bool nested_write_result(const yarp::os::idl::WireWriter& writer) const; + + // read/write messageOut field + bool read_messageOut(yarp::os::idl::WireReader& reader); + bool write_messageOut(const yarp::os::idl::WireWriter& writer) const; + bool nested_read_messageOut(yarp::os::idl::WireReader& reader); + bool nested_write_messageOut(const yarp::os::idl::WireWriter& writer) const; +}; + +#endif // YARP_THRIFT_GENERATOR_STRUCT_RETURN_INTERACT_H diff --git a/src/devices/chatBot_nwc_yarp/CMakeLists.txt b/src/devices/chatBot_nwc_yarp/CMakeLists.txt new file mode 100644 index 0000000000..98c84d75ee --- /dev/null +++ b/src/devices/chatBot_nwc_yarp/CMakeLists.txt @@ -0,0 +1,51 @@ +# SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +yarp_prepare_plugin(chatBot_nwc_yarp + CATEGORY device + TYPE ChatBot_nwc_yarp + INCLUDE ChatBot_nwc_yarp.h + DEFAULT ON +) + +if(NOT SKIP_chatBot_nwc_yarp) + yarp_add_plugin(chatBot_nwc_yarp) + + target_sources(chatBot_nwc_yarp + PRIVATE + ChatBot_nwc_yarp.cpp + ChatBot_nwc_yarp.h + ) + + target_sources(chatBot_nwc_yarp PRIVATE $) + + target_include_directories(chatBot_nwc_yarp PRIVATE $) + + target_link_libraries(chatBot_nwc_yarp + PRIVATE + YARP::YARP_os + YARP::YARP_dev + ) + list(APPEND YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS + YARP_os + YARP_dev + ) + + yarp_install( + TARGETS chatBot_nwc_yarp + EXPORT YARP_${YARP_PLUGIN_MASTER} + COMPONENT ${YARP_PLUGIN_MASTER} + LIBRARY DESTINATION ${YARP_DYNAMIC_PLUGINS_INSTALL_DIR} + ARCHIVE DESTINATION ${YARP_STATIC_PLUGINS_INSTALL_DIR} + YARP_INI DESTINATION ${YARP_PLUGIN_MANIFESTS_INSTALL_DIR} + ) + + set(YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS ${YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS} PARENT_SCOPE) + + set_property(TARGET chatBot_nwc_yarp PROPERTY FOLDER "Plugins/Device/NWC") + + if(YARP_COMPILE_TESTS) + add_subdirectory(tests) + endif() + +endif() diff --git a/src/devices/chatBot_nwc_yarp/ChatBot_nwc_yarp.cpp b/src/devices/chatBot_nwc_yarp/ChatBot_nwc_yarp.cpp new file mode 100644 index 0000000000..2d76d03c9a --- /dev/null +++ b/src/devices/chatBot_nwc_yarp/ChatBot_nwc_yarp.cpp @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "ChatBot_nwc_yarp.h" +#include +#include +#include + +namespace +{ + YARP_LOG_COMPONENT(CHATBOT_NWC_YARP, "yarp.device.chatBot_nwc_yarp") +} + +bool ChatBot_nwc_yarp::open(yarp::os::Searchable &config) +{ + std::string local_rpc = config.find("local").asString(); + std::string remote_rpc = config.find("remote").asString(); + + if (local_rpc == "") + { + yCError(CHATBOT_NWC_YARP) << "open() error you have to provide a valid 'local' param"; + return false; + } + + if (remote_rpc == "") + { + yCError(CHATBOT_NWC_YARP) << "open() error you have to provide valid 'remote' param"; + return false; + } + + if (!m_thriftClientPort.open(local_rpc)) + { + yCError(CHATBOT_NWC_YARP) << "Cannot open rpc port, check network"; + + return false; + } + + bool ok = false; + + ok = yarp::os::Network::connect(local_rpc, remote_rpc); + + if (!ok) + { + yCError(CHATBOT_NWC_YARP) << "open() error could not connect to" << remote_rpc; + return false; + } + + if (!m_thriftClient.yarp().attachAsClient(m_thriftClientPort)) + { + yCError(CHATBOT_NWC_YARP) << "Cannot attach the m_thriftClientPort port as client"; + return false; + } + + yCDebug(CHATBOT_NWC_YARP) << "Opening of nwc successful"; + return true; +} + +bool ChatBot_nwc_yarp::close() +{ + m_thriftClientPort.close(); + return true; +} + +bool ChatBot_nwc_yarp::interact(const std::string& messageIn, std::string& messageOut) +{ + return_interact output = m_thriftClient.interactRPC(messageIn); + if(!output.result) + { + yCError(CHATBOT_NWC_YARP) << "Could not interact with the chatbot"; + return false; + } + + messageOut = output.messageOut; + return true; +} + +bool ChatBot_nwc_yarp::setLanguage(const std::string& language) +{ + if(!m_thriftClient.setLanguageRPC(language)) + { + yCError(CHATBOT_NWC_YARP) << "Could not set the chatbot language to" << language; + return false; + } + return true; +} + +bool ChatBot_nwc_yarp::getLanguage(std::string& language) +{ + return_getLanguage output = m_thriftClient.getLanguageRPC(); + if(!output.result) + { + yCError(CHATBOT_NWC_YARP) << "Could not retrieve the currently set language"; + return false; + } + language = output.language; + return true; +} + +bool ChatBot_nwc_yarp::resetBot() +{ + if(!m_thriftClient.resetBotRPC()) + { + yCError(CHATBOT_NWC_YARP) << "Could not reset the chatbot"; + return false; + } + return true; +} diff --git a/src/devices/chatBot_nwc_yarp/ChatBot_nwc_yarp.h b/src/devices/chatBot_nwc_yarp/ChatBot_nwc_yarp.h new file mode 100644 index 0000000000..240735b72e --- /dev/null +++ b/src/devices/chatBot_nwc_yarp/ChatBot_nwc_yarp.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef YARP_DEV_CHATBOT_NWC_YARP_H +#define YARP_DEV_CHATBOT_NWC_YARP_H + +#include +#include +#include +#include "IChatBotMsgs.h" + + /** + * @ingroup dev_impl_network_clients + * + * \brief `chatBot_nwc_yarp`: The client side of any IChatBot capable device. + * + * Parameters required by this device are: + * | Parameter name | SubParameter | Type | Units | Default Value | Required | Description | Notes | + * |:--------------:|:--------------:|:-------:|:--------------:|:-------------:|:-----------: |:-----------------------------------------------------------------:|:-----:| + * | local | - | string | - | - | Yes | Full port name opened by the nwc device. | | + * | remote | - | string | - | - | Yes | Full port name of the port opened on the server side, to which the nwc connects to. | | + */ +class ChatBot_nwc_yarp : public yarp::dev::DeviceDriver, + public yarp::dev::IChatBot +{ +protected: + // thrift interface + IChatBotMsgs m_thriftClient; + + // rpc port + yarp::os::Port m_thriftClientPort; + +public: + + //From DeviceDriver + bool open(yarp::os::Searchable& config) override; + bool close() override; + + //From IChatBot + bool interact(const std::string& messageIn, std::string& messageOut) override; + bool setLanguage(const std::string& language) override; + bool getLanguage(std::string& language) override; + bool resetBot() override; +}; + +#endif // YARP_DEV_CHATBOT_NWC_YARP_H diff --git a/src/devices/chatBot_nwc_yarp/tests/CMakeLists.txt b/src/devices/chatBot_nwc_yarp/tests/CMakeLists.txt new file mode 100644 index 0000000000..e0dc71f5d5 --- /dev/null +++ b/src/devices/chatBot_nwc_yarp/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +create_device_test(chatBot_nwc_yarp) diff --git a/src/devices/chatBot_nwc_yarp/tests/chatBot_nwc_yarp_test.cpp b/src/devices/chatBot_nwc_yarp/tests/chatBot_nwc_yarp_test.cpp new file mode 100644 index 0000000000..fd7e0a391d --- /dev/null +++ b/src/devices/chatBot_nwc_yarp/tests/chatBot_nwc_yarp_test.cpp @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include + +using namespace yarp::dev; +using namespace yarp::os; + +TEST_CASE("dev::ChatBot_nwc", "[yarp::dev]") +{ + YARP_REQUIRE_PLUGIN("fakeChatBotDevice", "device"); + YARP_REQUIRE_PLUGIN("chatBot_nws_yarp", "device"); + YARP_REQUIRE_PLUGIN("chatBot_nwc_yarp", "device"); + + Network::setLocalMode(true); + + SECTION("Checking chatBot_nwc device") + { + yarp::dev::IChatBot* iChatBot=nullptr; + PolyDriver ddnws; + PolyDriver ddfake; + PolyDriver ddnwc; + + ////////"Checking opening ChatBot_nws_yarp and ChatBot_nwc_yarp polydrivers" + { + Property pnws_cfg; + pnws_cfg.put("device", "chatBot_nws_yarp"); + pnws_cfg.put("name", "/chatBot_nws"); + REQUIRE(ddnws.open(pnws_cfg)); + + Property pdev_cfg; + pdev_cfg.put("device", "fakeChatBotDevice"); + REQUIRE(ddfake.open(pdev_cfg)); + + {yarp::dev::WrapperSingle* ww_nws; + REQUIRE(ddnws.view(ww_nws)); + REQUIRE(ww_nws!=nullptr); + bool result_att = ww_nws->attach(&ddfake); + REQUIRE(result_att); } + + Property pnwc_cfg; + pnwc_cfg.put("device", "chatBot_nwc_yarp"); + pnwc_cfg.put("local", "/chatBot_nwc/rpc"); + pnwc_cfg.put("remote", "/chatBot_nws/rpc"); + REQUIRE(ddnwc.open(pnwc_cfg)); + REQUIRE(ddnwc.view(iChatBot)); + } + + yarp::dev::tests::exec_iChatBot_test_1(iChatBot); + + //"Close all polydrivers and check" + { + CHECK(ddnwc.close()); + yarp::os::Time::delay(0.1); + CHECK(ddnws.close()); + yarp::os::Time::delay(0.1); + CHECK(ddfake.close()); + } + } + + Network::setLocalMode(false); +} diff --git a/src/devices/chatBot_nws_yarp/CMakeLists.txt b/src/devices/chatBot_nws_yarp/CMakeLists.txt new file mode 100644 index 0000000000..1c31c17a0f --- /dev/null +++ b/src/devices/chatBot_nws_yarp/CMakeLists.txt @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +yarp_prepare_plugin(chatBot_nws_yarp + CATEGORY device + TYPE ChatBot_nws_yarp + INCLUDE ChatBot_nws_yarp.h + DEFAULT ON +) + +if(NOT SKIP_chatBot_nws_yarp) + yarp_add_plugin(yarp_chatBot_nws_yarp) + + target_sources(yarp_chatBot_nws_yarp + PRIVATE + ChatBotRPC_CallbackHelper.cpp + IChatBotMsgsImpl.cpp + ChatBot_nws_yarp.cpp + ChatBot_nws_yarp.h + ) + + target_link_libraries(yarp_chatBot_nws_yarp + PRIVATE + YARP::YARP_os + YARP::YARP_sig + YARP::YARP_dev + ) + list(APPEND YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS + YARP_os + YARP_sig + YARP_dev + ) + + target_sources(yarp_chatBot_nws_yarp PRIVATE $) + target_include_directories(yarp_chatBot_nws_yarp PRIVATE $) + + yarp_install( + TARGETS yarp_chatBot_nws_yarp + EXPORT YARP_${YARP_PLUGIN_MASTER} + COMPONENT ${YARP_PLUGIN_MASTER} + LIBRARY DESTINATION ${YARP_DYNAMIC_PLUGINS_INSTALL_DIR} + ARCHIVE DESTINATION ${YARP_STATIC_PLUGINS_INSTALL_DIR} + YARP_INI DESTINATION ${YARP_PLUGIN_MANIFESTS_INSTALL_DIR} + ) + + set(YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS ${YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS} PARENT_SCOPE) + + set_property(TARGET yarp_chatBot_nws_yarp PROPERTY FOLDER "Plugins/Device/NWS") + + if(YARP_COMPILE_TESTS) + add_subdirectory(tests) + endif() + +endif() diff --git a/src/devices/chatBot_nws_yarp/ChatBotRPC_CallbackHelper.cpp b/src/devices/chatBot_nws_yarp/ChatBotRPC_CallbackHelper.cpp new file mode 100644 index 0000000000..3013162d91 --- /dev/null +++ b/src/devices/chatBot_nws_yarp/ChatBotRPC_CallbackHelper.cpp @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "ChatBot_nws_yarp.h" + +#include +#include +#include + +namespace { +YARP_LOG_COMPONENT(CHATBOTRPC_HELPER, "yarp.devices.chatBot_nws_yarp.ChatBotRPC_CallbackHelper") +} + +bool ChatBotRPC_CallbackHelper::setCommunications(yarp::dev::IChatBot* iChat, yarp::os::Port* p) +{ + if (iChat ==nullptr || p==nullptr) + { + yCError(CHATBOTRPC_HELPER) << "Could not get IChatBot interface/output port"; + return false; + } + m_iChatBot = iChat; + m_outPort = p; + + return true; +} + +void ChatBotRPC_CallbackHelper::onRead(yarp::os::Bottle &b) +{ + if (m_iChatBot) + { + std::string response; + bool ok = m_iChatBot->interact(b.get(0).asString(), response); + + yCWarning(CHATBOTRPC_HELPER) << "Sent:" << b.get(0).asString() << "Got" << response; + + yarp::os::Bottle toSend; + toSend.addString(response); + if (!ok) + { + yCError(CHATBOTRPC_HELPER) << "Problems during interaction with the chatBot"; + } + else + { + if (m_outPort && m_outPort->getOutputCount() > 0) + { + m_outPort->write(toSend); + } + } + } + else + { + yCError(CHATBOTRPC_HELPER)<< "IChatBot interface was not set"; + } +} diff --git a/src/devices/chatBot_nws_yarp/ChatBot_nws_yarp.cpp b/src/devices/chatBot_nws_yarp/ChatBot_nws_yarp.cpp new file mode 100644 index 0000000000..c141bbac20 --- /dev/null +++ b/src/devices/chatBot_nws_yarp/ChatBot_nws_yarp.cpp @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "ChatBot_nws_yarp.h" + +#include +#include +#include + +namespace { +YARP_LOG_COMPONENT(CHATBOT_NWS_YARP, "yarp.devices.chatBot_nws_yarp") +} + +ChatBot_nws_yarp::~ChatBot_nws_yarp() +{ + closeMain(); +} + +bool ChatBot_nws_yarp::close() +{ + return closeMain(); +} + +bool ChatBot_nws_yarp::open(Searchable& prop) +{ + std::string rootName = + prop.check("name",Value("/chatBot_nws"), + "prefix for port names").asString(); + + m_inputBuffer.attach(m_inputPort); + if(!m_inputPort.open(rootName+"/text:i")) + { + yCError(CHATBOT_NWS_YARP) << "Could not open port" << rootName+"/text:i"; + return false; + } + if(!m_outputPort.open(rootName + "/text:o")) + { + yCError(CHATBOT_NWS_YARP) << "Could not open port" << rootName+"/text:o"; + return false; + } + if (!m_thriftServerPort.open(rootName+"/rpc")) + { + yCError(CHATBOT_NWS_YARP, "Failed to open rpc port"); + return false; + } + m_thriftServerPort.setReader(*this); + + yCInfo(CHATBOT_NWS_YARP, "Device waiting for attach..."); + return true; +} + +bool ChatBot_nws_yarp::attach(yarp::dev::PolyDriver* deviceToAttach) +{ + if (deviceToAttach->isValid()) + { + deviceToAttach->view(m_iChatBot); + } + + if (nullptr == m_iChatBot) + { + yCError(CHATBOT_NWS_YARP, "Subdevice passed to attach method is invalid"); + return false; + } + + yCInfo(CHATBOT_NWS_YARP, "Attach done"); + + m_cbkHelper = new ChatBotRPC_CallbackHelper(); + if(!m_cbkHelper->setCommunications(m_iChatBot,&m_outputPort)) + { + yCError(CHATBOT_NWS_YARP) << "Error setting ChatBot_CallbackHelper object interfaces"; + delete m_cbkHelper; + m_cbkHelper=nullptr; + return false; + } + m_inputBuffer.useCallback(*m_cbkHelper); + if(!m_msgsImpl.setInterfaces(m_iChatBot)) + { + yCError(CHATBOT_NWS_YARP) << "Error setting IChatBotMsgsImpl object interfaces"; + return false; + } + + return true; +} + +bool ChatBot_nws_yarp::detach() +{ + m_iChatBot = nullptr; + return true; +} + +bool ChatBot_nws_yarp::closeMain() +{ + //close the port connection here + m_inputBuffer.disableCallback(); + m_inputPort.close(); + m_outputPort.close(); + m_thriftServerPort.close(); + if (m_cbkHelper) {delete m_cbkHelper; m_cbkHelper=nullptr;} + return true; +} + +bool ChatBot_nws_yarp::read(yarp::os::ConnectionReader& connection) +{ + bool b = m_msgsImpl.read(connection); + if (b) + { + return true; + } + else + { + yCError(CHATBOT_NWS_YARP, "read() Command failed"); + return false; + } +} diff --git a/src/devices/chatBot_nws_yarp/ChatBot_nws_yarp.h b/src/devices/chatBot_nws_yarp/ChatBot_nws_yarp.h new file mode 100644 index 0000000000..389292ef97 --- /dev/null +++ b/src/devices/chatBot_nws_yarp/ChatBot_nws_yarp.h @@ -0,0 +1,114 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef YARP_DEV_CHATBOT_NWS_YARP_H +#define YARP_DEV_CHATBOT_NWS_YARP_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IChatBotMsgs.h" + +using namespace yarp::os; +using namespace yarp::dev; + +// Callback implementation after buffered input. +class ChatBotRPC_CallbackHelper : + public yarp::os::TypedReaderCallback +{ +protected: + yarp::dev::IChatBot* m_iChatBot{nullptr}; + yarp::os::Port* m_outPort{nullptr}; + +public: + virtual ~ChatBotRPC_CallbackHelper() override {}; + + bool setCommunications(yarp::dev::IChatBot* iser, yarp::os::Port* port); + + using yarp::os::TypedReaderCallback::onRead; + void onRead(yarp::os::Bottle& b) override; +}; + +// rpc commands +class IChatBotMsgsImpl : public IChatBotMsgs +{ +private: + std::mutex m_mutex; + yarp::dev::IChatBot* m_iChatBot{nullptr}; + +public: + return_interact interactRPC(const std::string& messageIn) override; + bool setLanguageRPC(const std::string& language) override; + return_getLanguage getLanguageRPC() override; + bool resetBotRPC() override; + +public: + bool setInterfaces(yarp::dev::IChatBot* iChatBot); + std::mutex* getMutex() { return &m_mutex; } +}; + + +/** + * @ingroup dev_impl_nws_yarp + * + * \brief `ChatBot_nws_yarp`: A wrapper for a plugin able to interact with a chatbot or implementing one. + * + * The network interface is composed by two ports. + * When a text bottle is received on the input port, the attached subdevice sends it to the chatbot + * and sends the bot resonse on the output port + * The same functionality is available also via rpc port, which also provides additional functionalities, + * such as setting the language, resetting the bot and performing backup and restore operations. + * + * Parameters required by this device are: + * | Parameter name | SubParameter | Type | Units | Default Value | Required | Description | Notes | + * |:--------------:|:--------------:|:-------:|:--------------:|:----------------------------:|:----------: |:---------------------------------------------------------------------:|:-----------------------------------------------------------------------------------:| + * | name | - | string | - | /chatBot_nws | No | full name of the port opened by the device | MUST start with a '/' character, xxx/text:i, xxx/rpc, xxx/audio:o ports are opened | + */ +class ChatBot_nws_yarp : + public yarp::dev::DeviceDriver, + public yarp::dev::WrapperSingle, + public yarp::os::PortReader +{ +private: + yarp::dev::IChatBot* m_iChatBot{ nullptr }; + yarp::os::Port m_inputPort; + yarp::os::Port m_outputPort; + yarp::os::RpcServer m_thriftServerPort; + IChatBotMsgsImpl m_msgsImpl; + + yarp::os::PortReaderBuffer m_inputBuffer; + ChatBotRPC_CallbackHelper* m_cbkHelper{ nullptr }; + + // yarp::dev::IWrapper + bool attach(yarp::dev::PolyDriver* deviceToAttach) override; + bool detach() override; + +private: + bool closeMain(); + +public: + ChatBot_nws_yarp() = default; + ChatBot_nws_yarp(const ChatBot_nws_yarp&) = delete; + ChatBot_nws_yarp(ChatBot_nws_yarp&&) = delete; + ChatBot_nws_yarp& operator=(const ChatBot_nws_yarp&) = delete; + ChatBot_nws_yarp& operator=(ChatBot_nws_yarp&&) = delete; + virtual ~ChatBot_nws_yarp() override; + + bool open(yarp::os::Searchable& config) override; + bool close() override; + bool read(yarp::os::ConnectionReader& connection) override; +}; + +#endif // YARP_DEV_CHATBOT_NWS_YARP_H diff --git a/src/devices/chatBot_nws_yarp/IChatBotMsgsImpl.cpp b/src/devices/chatBot_nws_yarp/IChatBotMsgsImpl.cpp new file mode 100644 index 0000000000..a82970dfd3 --- /dev/null +++ b/src/devices/chatBot_nws_yarp/IChatBotMsgsImpl.cpp @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "ChatBot_nws_yarp.h" + +#include +#include +#include + +namespace { +YARP_LOG_COMPONENT(ICHATBOTMSGSIMPL, "yarp.devices.chatBot_nws_yarp.ChatBotRPC_CallbackHelper") +} + +bool IChatBotMsgsImpl::setInterfaces(yarp::dev::IChatBot* iChatBot) +{ + if(!iChatBot) + { + yCError(ICHATBOTMSGSIMPL) << "Invalid pointer to IChatBot device"; + return false; + } + + m_iChatBot = iChatBot; + + return true; +} + +return_interact IChatBotMsgsImpl::interactRPC(const std::string& messageIn) +{ + std::lock_guard lg(m_mutex); + return_interact response; + std::string messageOut; + + if(!m_iChatBot->interact(messageIn,messageOut)) + { + yCError(ICHATBOTMSGSIMPL) << "An error occurred while interacting with the chatBot"; + response.result = false; + return response; + } + + response.messageOut = messageOut; + response.result = true; + return response; +} + +bool IChatBotMsgsImpl::setLanguageRPC(const std::string& language) +{ + std::lock_guard lg(m_mutex); + if(!m_iChatBot->setLanguage(language)) + { + yCError(ICHATBOTMSGSIMPL) << "Could not set bot language to" << language; + return false; + } + + return true; +} + +return_getLanguage IChatBotMsgsImpl::getLanguageRPC() +{ + std::lock_guard lg(m_mutex); + return_getLanguage response; + std::string language; + if(!m_iChatBot->getLanguage(language)) + { + yCError(ICHATBOTMSGSIMPL) << "Could not retrieve the chatbot language"; + response.result = false; + return response; + } + + response.result = true; + response.language = language; + + return response; +} + +bool IChatBotMsgsImpl::resetBotRPC() +{ + std::lock_guard lg(m_mutex); + if(!m_iChatBot->resetBot()) + { + yCError(ICHATBOTMSGSIMPL) << "Could not reset the bot"; + + return false; + } + + return true; +} diff --git a/src/devices/chatBot_nws_yarp/tests/CMakeLists.txt b/src/devices/chatBot_nws_yarp/tests/CMakeLists.txt new file mode 100644 index 0000000000..c352981757 --- /dev/null +++ b/src/devices/chatBot_nws_yarp/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +create_device_test(chatBot_nws_yarp) diff --git a/src/devices/chatBot_nws_yarp/tests/chatBot_nws_yarp_test.cpp b/src/devices/chatBot_nws_yarp/tests/chatBot_nws_yarp_test.cpp new file mode 100644 index 0000000000..5d45b48561 --- /dev/null +++ b/src/devices/chatBot_nws_yarp/tests/chatBot_nws_yarp_test.cpp @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#include + +using namespace yarp::dev; +using namespace yarp::os; + +TEST_CASE("dev::chatBot_nws_yarp", "[yarp::dev]") +{ + YARP_REQUIRE_PLUGIN("fakeChatBotDevice", "device"); + YARP_REQUIRE_PLUGIN("chatBot_nws_yarp", "device"); + + Network::setLocalMode(true); + + SECTION("Checking chatBot_nws_yarp device alone") + { + PolyDriver dd; + + ////////"Checking opening polydriver with no attached device" + { + Property pnws_cfg; + pnws_cfg.put("device", "chatBot_nws_yarp"); + pnws_cfg.put("name", "/chatBot_nws"); + REQUIRE(dd.open(pnws_cfg)); + } + + yarp::os::Time::delay(1.0); + + //"Close all polydrivers and check" + { + CHECK(dd.close()); + } + } + + SECTION("Checking chatBot_nws_yarp device attached to fake device") + { + PolyDriver ddnws; + PolyDriver ddfake; + + ////////"Checking opening polydriver and attach device" + { + Property pnws_cfg; + pnws_cfg.put("device", "chatBot_nws_yarp"); + pnws_cfg.put("name", "/chatBot_nws"); + REQUIRE(ddnws.open(pnws_cfg)); + + Property pdev_cfg; + pdev_cfg.put("device", "fakeChatBotDevice"); + REQUIRE(ddfake.open(pdev_cfg)); + + {yarp::dev::WrapperSingle* ww_nws; + REQUIRE(ddnws.view(ww_nws)); + REQUIRE(ww_nws!=nullptr); + bool result_att = ww_nws->attach(&ddfake); + REQUIRE(result_att); } + } + + //tests + { + Port po; + Port pi; + CHECK(po.open("/test:o")); + CHECK(Network::connect("/test:o","/chatBot_nws/text:i")); + CHECK(pi.open("/test:i")); + CHECK(Network::connect("/chatBot_nws/text:o", "/test:i")); + yarp::os::Time::delay(0.5); + + yarp::os::Bottle b; + b.addString("Hello!"); + CHECK(po.write(b)); + yarp::os::Time::delay(0.5); + yarp::os::Bottle resp; + CHECK(pi.read(resp)); + CHECK(resp.get(0).asString() == "Hello there."); + + po.close(); + pi.close(); + } + yarp::os::Time::delay(0.5); + + //"Close all polydrivers and check" + { + CHECK(ddnws.close()); + CHECK(ddfake.close()); + } + } + + Network::setLocalMode(false); +} diff --git a/src/devices/fakeChatBotDevice/CMakeLists.txt b/src/devices/fakeChatBotDevice/CMakeLists.txt new file mode 100644 index 0000000000..c4b5a01d7e --- /dev/null +++ b/src/devices/fakeChatBotDevice/CMakeLists.txt @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +if (YARP_COMPILE_ALL_FAKE_DEVICES) + set(ENABLE_yarpmod_fakeChatBotDevice ON CACHE BOOL "" FORCE) +endif() + +yarp_prepare_plugin(fakeChatBotDevice + CATEGORY device + TYPE FakeChatBotDevice + INCLUDE FakeChatBotDevice.h + +) +if(NOT SKIP_fakeChatBotDevice) + + yarp_add_plugin(yarp_fakeChatBotDevice) + + target_sources(yarp_fakeChatBotDevice + PRIVATE + FakeChatBotDevice.cpp + FakeChatBotDevice.h + ) + + target_link_libraries(yarp_fakeChatBotDevice + PRIVATE + YARP::YARP_os + YARP::YARP_dev + ) + list(APPEND YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS + YARP_os + YARP_dev + ) + + yarp_install( + TARGETS yarp_fakeChatBotDevice + EXPORT YARP_${YARP_PLUGIN_MASTER} + COMPONENT ${YARP_PLUGIN_MASTER} + LIBRARY DESTINATION ${YARP_DYNAMIC_PLUGINS_INSTALL_DIR} + ARCHIVE DESTINATION ${YARP_STATIC_PLUGINS_INSTALL_DIR} + YARP_INI DESTINATION ${YARP_PLUGIN_MANIFESTS_INSTALL_DIR} + ) + set(YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS ${YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS} PARENT_SCOPE) + + set_property(TARGET yarp_fakeChatBotDevice PROPERTY FOLDER "Plugins/Device/Fake") + + if(YARP_COMPILE_TESTS) + add_subdirectory(tests) + endif() + +endif() diff --git a/src/devices/fakeChatBotDevice/FakeChatBotDevice.cpp b/src/devices/fakeChatBotDevice/FakeChatBotDevice.cpp new file mode 100644 index 0000000000..4621c62d18 --- /dev/null +++ b/src/devices/fakeChatBotDevice/FakeChatBotDevice.cpp @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "FakeChatBotDevice.h" +#include +#include + +YARP_LOG_COMPONENT(FAKECHATBOTDEVICE, "yarp.devices.FakeChatBotDevice") + +FakeChatBotDevice::FakeChatBotDevice() : + m_lang{"eng"}, + m_fallback{"Sorry, I did not get that. Can you repeat?"}, + m_noInput{"I heard nothing. Can you please speak up?"}, + m_status{"greetings"}, + m_qAndA{ + {"greetings", + {{"Hello!","Hello there."},{"Who are you?","I am just a fake chatbot"}, + {"Goodbye!", "Already? Ok... bye."}} + }, + {"chatting", + {{"Hello!","Hello again."},{"Who are you?","I am just a fake chatbot"}, + {"Goodbye!", "Bye bye!"}} + } + } +{} + +bool FakeChatBotDevice::interact(const std::string& messageIn, std::string& messageOut) +{ + if(messageIn.empty()) + { + messageOut = m_noInput; + return true; + } + if(m_qAndA[m_status].count(messageIn) < 1) + { + messageOut = m_fallback; + return true; + } + + messageOut = m_qAndA[m_status][messageIn]; + + if(m_status == std::string("greetings")) + { + m_status = "chatting"; + } + + return true; +} + +bool FakeChatBotDevice::setLanguage(const std::string& language) +{ + if (language != "eng") + { + yCError(FAKECHATBOTDEVICE) << "Unsopported language. Only English is supported for the moment being"; + return false; + } + m_lang = language; + + return true; +} + +bool FakeChatBotDevice::getLanguage(std::string& language) +{ + language = m_lang; + + return true; +} + +bool FakeChatBotDevice::resetBot() +{ + m_status = "greetings"; + return true; +} diff --git a/src/devices/fakeChatBotDevice/FakeChatBotDevice.h b/src/devices/fakeChatBotDevice/FakeChatBotDevice.h new file mode 100644 index 0000000000..cdbcf6e07a --- /dev/null +++ b/src/devices/fakeChatBotDevice/FakeChatBotDevice.h @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_CHATBOTDEVICE_H +#define FAKE_CHATBOTDEVICE_H + +#include +#include +#include +#include + +/** +* @ingroup dev_impl_fake dev_impl_other +* +* @brief `fakeChatBotDevice` : a fake device which implements the IChatBot interface for testing purposes. +* +*/ +class FakeChatBotDevice : public yarp::dev::IChatBot, + public yarp::dev::DeviceDriver +{ + +public: + FakeChatBotDevice(); + bool interact(const std::string& messageIn, std::string& messageOut) override; + bool setLanguage(const std::string& language) override; + bool getLanguage(std::string& language) override; + bool resetBot() override; + +private: + std::string m_currBot; + std::string m_lang; + std::string m_fallback; + std::string m_noInput; + std::string m_status; + std::map> m_qAndA; +}; + +#endif // FAKE_CHATBOTDEVICE_H diff --git a/src/devices/fakeChatBotDevice/tests/CMakeLists.txt b/src/devices/fakeChatBotDevice/tests/CMakeLists.txt new file mode 100644 index 0000000000..edfa16cfa0 --- /dev/null +++ b/src/devices/fakeChatBotDevice/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +create_device_test(fakeChatBotDevice) diff --git a/src/devices/fakeChatBotDevice/tests/fakeChatBotDevice_test.cpp b/src/devices/fakeChatBotDevice/tests/fakeChatBotDevice_test.cpp new file mode 100644 index 0000000000..93567f5a1a --- /dev/null +++ b/src/devices/fakeChatBotDevice/tests/fakeChatBotDevice_test.cpp @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include + +using namespace yarp::dev; +using namespace yarp::os; + +TEST_CASE("dev::fakeChatBotDeviceTest", "[yarp::dev]") +{ + YARP_REQUIRE_PLUGIN("fakeChatBotDevice", "device"); + + Network::setLocalMode(true); + + SECTION("Checking fakeChatBotdevice") + { + PolyDriver fakeChatBotdev; + IChatBot* iChatBot = nullptr; + + ////////"Checking opening polydriver" + { + Property chatBot_cfg; + chatBot_cfg.put("device", "fakeChatBotDevice"); + REQUIRE(fakeChatBotdev.open(chatBot_cfg)); + REQUIRE(fakeChatBotdev.view(iChatBot)); + } + + //execute tests + yarp::dev::tests::exec_iChatBot_test_1(iChatBot); + + //"Close all polydrivers and check" + CHECK(fakeChatBotdev.close()); + } + + Network::setLocalMode(false); +} diff --git a/src/libYARP_dev/src/CMakeLists.txt b/src/libYARP_dev/src/CMakeLists.txt index d96c6be20c..fdab102d74 100644 --- a/src/libYARP_dev/src/CMakeLists.txt +++ b/src/libYARP_dev/src/CMakeLists.txt @@ -39,6 +39,7 @@ set(YARP_dev_HDRS yarp/dev/IAxisInfo.h yarp/dev/IBattery.h yarp/dev/ICalibrator.h + yarp/dev/IChatBot.h yarp/dev/IControlCalibration.h yarp/dev/IControlDebug.h yarp/dev/IControlLimits.h @@ -170,6 +171,7 @@ set(YARP_dev_SRCS yarp/dev/IAudioVisualGrabber.cpp yarp/dev/IAudioVisualStream.cpp yarp/dev/IBattery.cpp + yarp/dev/IChatBot.cpp yarp/dev/IDepthVisualParams.cpp yarp/dev/IFrameGrabberControls.cpp yarp/dev/IFrameGrabberControlsDC1394.cpp @@ -409,6 +411,7 @@ set(YARP_dev_test_HDRS yarp/dev/tests/IBatteryTest.h yarp/dev/tests/IJoypadControllerTest.h yarp/dev/tests/ILLMTest.h + yarp/dev/tests/IChatBotTest.h ) set(YARP_dev_test_SRCS @@ -420,6 +423,7 @@ set(YARP_dev_test_SRCS yarp/dev/tests/IBatteryTest.cpp yarp/dev/tests/IJoypadControllerTest.cpp yarp/dev/tests/ILLMTest.cpp + yarp/dev/tests/IChatBotTest.cpp ) if(TARGET YARP::YARP_math) diff --git a/src/libYARP_dev/src/yarp/dev/IChatBot.cpp b/src/libYARP_dev/src/yarp/dev/IChatBot.cpp new file mode 100644 index 0000000000..cd0790a6cd --- /dev/null +++ b/src/libYARP_dev/src/yarp/dev/IChatBot.cpp @@ -0,0 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +yarp::dev::IChatBot::~IChatBot() = default; diff --git a/src/libYARP_dev/src/yarp/dev/IChatBot.h b/src/libYARP_dev/src/yarp/dev/IChatBot.h new file mode 100644 index 0000000000..1cbd8ad09e --- /dev/null +++ b/src/libYARP_dev/src/yarp/dev/IChatBot.h @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef YARP_DEV_ICHATBOT_H +#define YARP_DEV_ICHATBOT_H + +#include + +#include +#include + + +namespace yarp::dev { +class IChatBot; +} // namespace yarp + +/** + * @ingroup dev_iface_other + * + * IChatBot interface. Provides methods to interact with chatbots. + */ +class YARP_dev_API yarp::dev::IChatBot +{ +public: + /** + * Destructor + */ + virtual ~IChatBot(); + + /** + * Sends a message to the chatbot + * @param messageIn the text of the input message + * @param messageOut the output message + * @return true/false + */ + virtual bool interact(const std::string& messageIn, std::string& messageOut) = 0; + + /** + * Sets the chat bot language. + * \param language a string (code) representing the speech language (e.g. ita, eng...). Default value is "auto". + * \return true on success + */ + virtual bool setLanguage(const std::string& language="auto") = 0; + + /** + * Gets the current chatbot language. + * \param language the returned string (code) representing the speech language (e.g. ita, eng...). Default value is "auto". + * \return true on success + */ + virtual bool getLanguage(std::string& language) = 0; + + /** + * Resets the chatbot + * \return true on success + */ + virtual bool resetBot() = 0; +}; + + +#endif //YARP_DEV_ICHATBOT_H diff --git a/src/libYARP_dev/src/yarp/dev/all.h b/src/libYARP_dev/src/yarp/dev/all.h index dcc148ca09..1365618c1b 100644 --- a/src/libYARP_dev/src/yarp/dev/all.h +++ b/src/libYARP_dev/src/yarp/dev/all.h @@ -40,6 +40,7 @@ #include #include #include +#include #ifndef YARP_NO_DEPRECATED // since YARP 3.5 #define YARP_INCLUDING_DEPRECATED_HEADER_YARP_DEV_FRAMEGRABBER_H_ON_PURPOSE diff --git a/src/libYARP_dev/src/yarp/dev/tests/IChatBotTest.cpp b/src/libYARP_dev/src/yarp/dev/tests/IChatBotTest.cpp new file mode 100644 index 0000000000..a681725d2a --- /dev/null +++ b/src/libYARP_dev/src/yarp/dev/tests/IChatBotTest.cpp @@ -0,0 +1,6 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "IChatBotTest.h" diff --git a/src/libYARP_dev/src/yarp/dev/tests/IChatBotTest.h b/src/libYARP_dev/src/yarp/dev/tests/IChatBotTest.h new file mode 100644 index 0000000000..763ed97d61 --- /dev/null +++ b/src/libYARP_dev/src/yarp/dev/tests/IChatBotTest.h @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ICHATBOTTEST_H +#define ICHATBOTTEST_H + +#include +#include + +using namespace yarp::dev; + +namespace yarp::dev::tests { +inline void exec_iChatBot_test_1(yarp::dev::IChatBot* ichatbot) +{ + REQUIRE(ichatbot != nullptr); + + bool b; + + b = ichatbot->setLanguage("eng"); + CHECK(b); + + std::string tempLang; + b = ichatbot->getLanguage(tempLang); + CHECK(b); + CHECK(tempLang == std::string("eng")); + + b = ichatbot->resetBot(); + CHECK(b); + + std::string messageIn{"Hello!"}; + std::string messageOut; + b = ichatbot->interact(messageIn,messageOut); + CHECK(b); +} +} + +#endif //ICHATBOTTEST_H diff --git a/tests/misc/check_tests_skip.txt b/tests/misc/check_tests_skip.txt index d2e72c3612..c1ed7eb161 100644 --- a/tests/misc/check_tests_skip.txt +++ b/tests/misc/check_tests_skip.txt @@ -32,3 +32,4 @@ ./src/devices/AnalogSensorClient ./src/devices/AnalogWrapper ./src/devices/ILLMMsgs +./src/devices/IChatBotMsgs