29 #include <yarp/os/BufferedPort.h>
30 #include <yarp/os/ResourceFinder.h>
31 #include <yarp/os/RFModule.h>
32 #include <yarp/os/Network.h>
33 #include <yarp/os/Time.h>
34 #include <yarp/os/Log.h>
35 #include <yarp/os/LogStream.h>
36 #include <yarp/os/Semaphore.h>
37 #include <yarp/sig/SoundFile.h>
38 #include <yarp/dev/PolyDriver.h>
40 #include <grpc++/grpc++.h>
41 #include "google/cloud/language/v1/language_service.grpc.pb.h"
42 #include "google/cloud/texttospeech/v1/cloud_tts.grpc.pb.h"
43 #include "google/cloud/dialogflow/cx/v3beta1/agent.grpc.pb.h"
44 #include "google/cloud/dialogflow/cx/v3beta1/audio_config.grpc.pb.h"
46 #include "google/cloud/dialogflow/cx/v3beta1/entity_type.grpc.pb.h"
47 #include "google/cloud/dialogflow/cx/v3beta1/intent.grpc.pb.h"
48 #include "google/cloud/dialogflow/cx/v3beta1/session_entity_type.grpc.pb.h"
49 #include "google/cloud/dialogflow/cx/v3beta1/session.grpc.pb.h"
50 #include "google/cloud/dialogflow/cx/v3beta1/webhook.grpc.pb.h"
56 #include "googleDialog_IDL.h"
58 using namespace google::cloud::language::v1;
59 using namespace google::cloud::texttospeech::v1;
60 using namespace google::cloud::dialogflow::cx::v3beta1;
63 static const std::map<grpc::StatusCode, std::string> status_code_to_string {
65 {grpc::CANCELLED,
"cancelled"},
66 {grpc::UNKNOWN,
"unknown"},
67 {grpc::INVALID_ARGUMENT,
"invalid_argument"},
68 {grpc::DEADLINE_EXCEEDED,
"deadline_exceeded"},
69 {grpc::NOT_FOUND,
"not_found"},
70 {grpc::ALREADY_EXISTS,
"already_exists"},
71 {grpc::PERMISSION_DENIED,
"permission_denied"},
72 {grpc::UNAUTHENTICATED,
"unauthenticated"},
73 {grpc::RESOURCE_EXHAUSTED ,
"resource_exhausted"},
74 {grpc::FAILED_PRECONDITION,
"failed_precondition"},
75 {grpc::ABORTED,
"aborted"},
76 {grpc::OUT_OF_RANGE,
"out_of_range"},
77 {grpc::UNIMPLEMENTED,
"unimplemented"},
78 {grpc::INTERNAL,
"internal"},
79 {grpc::UNAVAILABLE,
"unavailable"},
80 {grpc::DATA_LOSS,
"data_loss"},
81 {grpc::DO_NOT_USE,
"do_not_use"}
84 class Processing :
public yarp::os::BufferedPort<yarp::os::Bottle>
86 std::string moduleName;
87 std::string session_id;
88 std::string agent_name;
89 std::string language_code;
91 bool &input_is_empty, reset;
92 std::int64_t &processing_time;
93 yarp::os::RpcServer handlerPort;
94 yarp::os::BufferedPort<yarp::os::Bottle> targetPort;
99 Processing(
const std::string &moduleName,
const std::string agent_name,
const std::string language_code, std::string &state,
bool &input_is_empty, std::int64_t &processing_time) : state(state), input_is_empty(input_is_empty), processing_time(processing_time)
101 this->moduleName = moduleName;
102 this->session_id = getRandSession();
103 this->agent_name = agent_name;
104 this->language_code = language_code;
106 yInfo()<<
"State: " << state;
107 yInfo()<<
"input_is_empty: " << input_is_empty;
116 std::string getRandSession() {
119 for(
int i = 0; i<16; i++) {
120 session += std::to_string(rand() % 10);
128 yarp::os::BufferedPort<yarp::os::Bottle >::open(
"/" + moduleName +
"/text:i" );
129 targetPort.open(
"/"+ moduleName +
"/result:o");
137 yarp::os::BufferedPort<yarp::os::Bottle >::close();
142 void onRead( yarp::os::Bottle &bot)
144 yarp::os::Bottle &outTargets = targetPort.prepare();
147 outTargets = queryGoogleDialog(bot);
148 yDebug() <<
"bottle" << outTargets.toString();
149 if(outTargets.size()>0){
152 yInfo() <<
"State: " << state;
153 yDebug() <<
"done querying google";
157 yarp::os::Bottle queryGoogleDialog(yarp::os::Bottle& bottle)
159 std::string text = bottle.toString();
160 yarp::os::Bottle result;
161 google::cloud::dialogflow::cx::v3beta1::TextInput text_input;
162 google::cloud::dialogflow::cx::v3beta1::QueryInput query_input;
165 text_input.set_text(text.c_str());
166 query_input.set_allocated_text(&text_input);
167 query_input.set_language_code(language_code);
170 grpc::ClientContext context;
172 DetectIntentRequest request;
173 DetectIntentResponse response;
175 request.set_session(agent_name+
"/environments/draft/sessions/"+session_id);
176 request.set_allocated_query_input(&query_input);
177 std::string user_express = request.query_input().text().text();
178 yInfo() <<
"End-user expression:" << user_express;
179 if(request.query_input().text().text().size()>0){
180 input_is_empty=
false;
181 auto creds = grpc::GoogleDefaultCredentials();
182 auto channel = grpc::CreateChannel(
"dialogflow.googleapis.com", creds);
183 std::unique_ptr<Sessions::Stub> dialog (Sessions::NewStub(channel));
185 yarp::os::Time::delay(0.2);
186 const std::chrono::time_point<std::chrono::steady_clock> start = std::chrono::steady_clock::now();
188 grpc::Status dialog_status = dialog->DetectIntent(&context, request, &response);
189 std::string status_string = status_code_to_string.at(dialog_status.error_code());
192 if ( dialog_status.ok() ) {
193 const auto end = std::chrono::steady_clock::now();
194 processing_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
195 yDebug() <<
"Request processing time: " << processing_time <<
"µs";
197 yInfo() <<
"Status returned OK";
198 yInfo() <<
"\n------Response------\n";
199 if (response.query_result().response_messages().size() > 0 && response.query_result().response_messages().Get(0).text().text().size() > 0)
201 result.addString(response.query_result().response_messages().Get(0).text().text().Get(0).c_str());
202 yDebug() <<
"result bottle" << result.toString();
215 else if ( !dialog_status.ok() ) {
216 yError() <<
"Status Returned Cancelled";
217 checkState(
"Failure_" + status_string);
218 yInfo() << dialog_status.error_message();
221 else if (request.query_input().text().text().size()==0){
223 yError() <<
"Input is empty";
225 request.release_query_input();
226 query_input.release_text();
231 bool setLanguageCode(
const std::string &languageCode)
233 language_code = languageCode;
238 std::string getLanguageCode()
240 return language_code;
244 bool start_acquisition()
250 bool stop_acquisition()
256 bool checkState(std::string new_state)
258 if(new_state!=state){
271 yarp::os::Bottle bot;
273 bot.addString(
"Exit");
274 queryGoogleDialog(bot);
279 class Module :
public yarp::os::RFModule,
public googleDialog_IDL
281 yarp::os::ResourceFinder *rf;
282 yarp::os::RpcServer rpcPort;
284 std::int64_t processing_time;
286 yarp::os::BufferedPort<yarp::os::Bottle> statePort;
288 Processing *processing;
289 friend class processing;
292 std::vector<std::string> allLanguageCodes;
295 bool attach(yarp::os::RpcServer &source)
297 return this->yarp().attachAsServer(source);
303 bool configure(yarp::os::ResourceFinder &rf)
307 this->input_is_empty=
false;
308 this->processing_time=0;
309 std::string moduleName = rf.check(
"name", yarp::os::Value(
"googleDialog"),
"module name (string)").asString();
310 std::string agent_name = rf.check(
"agent", yarp::os::Value(
"1"),
"name of the agent").asString();
311 std::string language_code = rf.check(
"language", yarp::os::Value(
"en-US"),
"language of the dialogflow").asString();
313 if (rf.check(
"languageCodes",
"Getting language codes"))
315 yarp::os::Bottle &grp=rf.findGroup(
"languageCodes");
318 for (
int i=0; i<sz; i++)
319 allLanguageCodes.push_back(grp.get(1+i).asString());
322 yDebug() <<
"this is the project" << rf.check(
"project");
323 yDebug() <<
"Module name" << moduleName;
324 yDebug() <<
"agent name" << agent_name;
325 yDebug() <<
"language of the dialog" << language_code;
326 setName(moduleName.c_str());
328 rpcPort.open((
"/"+getName(
"/rpc")).c_str());
329 statePort.open(
"/"+ moduleName +
"/state:o");
333 processing =
new Processing( moduleName, agent_name, language_code, state, input_is_empty, processing_time);
344 bool setLanguage(
const std::string& languageCode)
346 bool returnVal =
false;
348 std::string language;
350 for (
int i = 0; i < allLanguageCodes.size(); i++)
352 if (languageCode == allLanguageCodes[i])
354 language = languageCode;
355 processing->setLanguageCode(languageCode);
365 std::string getLanguageCode()
367 return processing->getLanguageCode();
397 yarp::os::Bottle &outTargets = statePort.prepare();
399 outTargets.addString(state);
400 yDebug() <<
"outTarget:" << outTargets.toString().c_str();
407 std::string getState()
413 std::int64_t getProcessingTime()
415 return processing_time;
421 processing->resetDialog();
427 int main(
int argc,
char *argv[])
429 yarp::os::Network::init();
431 yarp::os::Network yarp;
432 if (!yarp.checkNetwork())
434 yError(
"YARP server not available!");
439 yarp::os::ResourceFinder rf;
441 rf.setVerbose(
true );
442 rf.setDefaultContext(
"googleDialog" );
443 rf.setDefaultConfigFile(
"config.ini" );
444 rf.setDefault(
"name",
"googleDialog");
445 rf.configure(argc,argv);
447 return module.runModule(rf);