YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
MonitorLua.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <yarp/os/Network.h>
7#include <yarp/os/Log.h>
8#include <yarp/os/LogStream.h>
9#include <lua.hpp>
10#include "MonitorLua.h"
11#include "MonitorLogComponent.h"
12
13using namespace yarp::os;
14
15
19MonitorLua::MonitorLua() : bHasAcceptCallback(false),
20 bHasUpdateCallback(false),
21 bHasUpdateReplyCallback(false),
22 trigger(nullptr)
23{
24 L = luaL_newstate();
26
35 registerExtraFunctions();
36}
37
39{
40 if(L){
41 // stop trigger thread if it is running
42 if(trigger) {
43 trigger->stop();
44 delete trigger;
45 trigger = nullptr;
46 }
47 // call PortMonitor.destroy if exists
48 if(getLocalFunction("destroy"))
49 {
50 if (lua_pcall(L, 0, 0, 0) != 0) {
52 }
53 }
54 // closing lua state handler
55 lua_close(L);
56 }
57}
58
59bool MonitorLua::load(const Property &options)
60{
62 if(luaL_loadfile(L, options.find("filename").asString().c_str()))
63 {
64 yCError(PORTMONITORCARRIER, "Cannot load script file");
66 lua_pop(L,1);
67 lua_close(L);
68 L = nullptr;
69 return false;
70 }
71
72 if(lua_pcall(L,0, LUA_MULTRET, 0))
73 {
74 yCError(PORTMONITORCARRIER, "Cannot run script file");
76 lua_pop(L,1);
77 lua_close(L);
78 L = nullptr;
79 return false;
80 }
81
85 lua_pushlightuserdata(L, this);
86 lua_setglobal(L, "PortMonitor_Owner");
87
88 lua_getglobal(L, "PortMonitor");
89 if(lua_istable(L, -1) == 0)
90 {
91 yCError(PORTMONITORCARRIER, "The script file does not contain any valid \'PortMonitor\' object.");
92 lua_pop(L, 1);
93 lua_close(L);
94 L = nullptr;
95 return false;
96 }
97
98 bool result = true;
99 // call PortMonitor.create if exists
100 luaMutex.lock();
101 if(getLocalFunction("create"))
102 {
103 // mapping to swig type
104 swig_type_info *propType = SWIG_TypeQuery(L, "yarp::os::Property *");
105 if(!propType)
106 {
107 yCError(PORTMONITORCARRIER, "Swig type of Property is not found");
108 lua_pop(L, 1);
109 luaMutex.unlock();
110 return false;
111 }
112 // getting the swig-type pointer
113 SWIG_NewPointerObj(L, &options, propType, 0);
114 if(lua_pcall(L, 1, 1, 0) != 0)
115 {
117 lua_pop(L, 1);
118 lua_close(L);
119 L = nullptr;
120 luaMutex.unlock();
121 return false;
122 } else {
123 result = lua_toboolean(L, -1);
124 }
125 }
126 lua_pop(L,1);
127
128 // Check if there is accept callback
129 bHasAcceptCallback = getLocalFunction("accept");
130 lua_pop(L,1);
131
132 // Check if there is update callback
133 bHasUpdateCallback = getLocalFunction("update");
134 lua_pop(L,1);
135
136 // Check if there is update callback
137 bHasUpdateReplyCallback = getLocalFunction("update_reply");
138 lua_pop(L,1);
139 luaMutex.unlock();
140 return result;
141}
142
144{
145 luaMutex.lock();
146 if(getLocalFunction("accept"))
147 {
148 // mapping to swig type
149 swig_type_info *thingsType = SWIG_TypeQuery(L, "yarp::os::Things *");
150 if(!thingsType)
151 {
152 yCError(PORTMONITORCARRIER, "Swig type of Things is not found");
153 lua_pop(L, 1);
154 luaMutex.unlock();
155 return false;
156 }
157
158 // getting the swig-type pointer
159 SWIG_NewPointerObj(L, &thing, thingsType, 0);
160 if(lua_pcall(L, 1, 1, 0) != 0)
161 {
163 lua_pop(L, 1);
164 luaMutex.unlock();
165 return false;
166 }
167
168 // converting the results
169 bool result = lua_toboolean(L, -1);
170 lua_pop(L, 1);
171 luaMutex.unlock();
172 return result;
173 }
174
175 lua_pop(L, 1);
176 luaMutex.unlock();
177 return true;
178}
179
180
182{
183 luaMutex.lock();
184 if(getLocalFunction("update"))
185 {
186 // mapping to swig type
187 swig_type_info *thingsType = SWIG_TypeQuery(L, "yarp::os::Things *");
188 if(!thingsType)
189 {
190 yCError(PORTMONITORCARRIER, "Swig type of Things is not found");
191 lua_pop(L, 1);
192 luaMutex.unlock();
193 return thing;
194 }
195
196 // getting the swig-type pointer
197 SWIG_NewPointerObj(L, &thing, thingsType, 0);
198 if(lua_pcall(L, 1, 1, 0) != 0)
199 {
201 lua_pop(L, 1);
202 luaMutex.unlock();
203 return thing;
204 }
205
206 // converting the results
207 yarp::os::Things* result;
208 if(SWIG_Lua_ConvertPtr(L, -1, (void**)(&result), thingsType, 0) != SWIG_OK )
209 {
210 yCError(PORTMONITORCARRIER, "Cannot get a valid return value from PortMonitor.update");
211 lua_pop(L, 1);
212 luaMutex.unlock();
213 return thing;
214 }
215 else
216 {
217 lua_pop(L, 1);
218 luaMutex.unlock();
219 return *result;
220 }
221 }
222
223 lua_pop(L,1);
224 luaMutex.unlock();
225 return thing;
226}
227
229{
230 luaMutex.lock();
231 if(getLocalFunction("update_reply"))
232 {
233 // mapping to swig type
234 swig_type_info *thingsType = SWIG_TypeQuery(L, "yarp::os::Things *");
235 if(!thingsType)
236 {
237 yCError(PORTMONITORCARRIER, "Swig type of Things is not found");
238 lua_pop(L, 1);
239 luaMutex.unlock();
240 return thing;
241 }
242
243 // getting the swig-type pointer
244 SWIG_NewPointerObj(L, &thing, thingsType, 0);
245 if(lua_pcall(L, 1, 1, 0) != 0)
246 {
248 lua_pop(L, 1);
249 luaMutex.unlock();
250 return thing;
251 }
252
253 // converting the results
254 yarp::os::Things* result;
255 if(SWIG_Lua_ConvertPtr(L, -1, (void**)(&result), thingsType, 0) != SWIG_OK )
256 {
257 yCError(PORTMONITORCARRIER, "Cannot get a valid return value from PortMonitor.update_reply");
258 lua_pop(L, 1);
259 luaMutex.unlock();
260 return thing;
261 }
262 else
263 {
264 lua_pop(L, 1);
265 luaMutex.unlock();
266 return *result;
267 }
268 }
269
270 lua_pop(L,1);
271 luaMutex.unlock();
272 return thing;
273}
274
276{
277 luaMutex.lock();
278 if(getLocalFunction("setparam"))
279 {
280 // mapping to swig type
281 swig_type_info *propType = SWIG_TypeQuery(L, "yarp::os::Property *");
282 if(!propType)
283 {
284 yCError(PORTMONITORCARRIER, "Swig type of Property is not found");
285 lua_pop(L, 1);
286 luaMutex.unlock();
287 return false;
288 }
289
290 // getting the swig-type pointer
291 SWIG_NewPointerObj(L, &params, propType, 0);
292 if(lua_pcall(L, 1, 0, 0) != 0)
293 {
295 lua_pop(L, 1);
296 luaMutex.unlock();
297 return false;
298 }
299 luaMutex.unlock();
300 return true;
301 }
302
303 lua_pop(L,1);
304 luaMutex.unlock();
305 return true;
306}
307
309{
310 luaMutex.lock();
311 if(getLocalFunction("getparam"))
312 {
313 // mapping to swig type
314 swig_type_info *propType = SWIG_TypeQuery(L, "yarp::os::Property *");
315 if(!propType)
316 {
317 yCError(PORTMONITORCARRIER, "Swig type of Property is not found");
318 lua_pop(L, 1);
319 luaMutex.unlock();
320 return false;
321 }
322
323 // calling PortMonitor.getparam from lua
324 if(lua_pcall(L, 0, 1, 0) != 0)
325 {
327 lua_pop(L, 1);
328 luaMutex.unlock();
329 return false;
330 }
331
332 // converting the results
333 yarp::os::Property* result;
334 if(SWIG_Lua_ConvertPtr(L, -1, (void**)(&result), propType, 0) != SWIG_OK )
335 {
336 yCError(PORTMONITORCARRIER, "Cannot get a valid return value from PortMonitor.getparam");
337 lua_pop(L, 1);
338 luaMutex.unlock();
339 return false;
340 }
341 else
342 {
343 params = *result;
344 lua_pop(L, 1);
345 luaMutex.unlock();
346 return true;
347 }
348 }
349
350 lua_pop(L,1);
351 luaMutex.unlock();
352 return true;
353}
354
356{
357 luaMutex.lock();
358 if(getLocalFunction("trig"))
359 {
360 if(lua_pcall(L, 0, 0, 0) != 0)
361 {
363 lua_pop(L, 1);
364 luaMutex.unlock();
365 return false;
366 }
367 luaMutex.unlock();
368 return true;
369 }
370
371 lua_pop(L, 1);
372 luaMutex.unlock();
373 return true;
374}
375
376
377bool MonitorLua::getLocalFunction(const char *name)
378{
379 lua_pushstring(L, name);
380 lua_gettable(L, -2);
381 return (lua_isfunction(L, -1) == 1);
382}
383
384
385bool MonitorLua::registerExtraFunctions()
386{
387#if LUA_VERSION_NUM > 501
388 lua_newtable(L);
389 luaL_setfuncs (L, MonitorLua::portMonitorLib, 0);
390 lua_pushvalue(L, -1);
391 lua_setglobal(L, "PortMonitor");
392#else
393 // deprecated
394 //luaL_openlib(L, "PortMonitor", MonitorLua::portMonitorLib, 0);
395 luaL_register(L, "PortMonitor", MonitorLua::portMonitorLib);
396#endif
397 return true;
398}
399
400
402{
403 if (constraint == "") {
404 return true;
405 }
406
408
413 std::string strConstraint = constraint;
414 std::string strDummy = strConstraint;
415 searchReplace(strDummy, "(", " ");
416 searchReplace(strDummy, ")", " ");
417 // wrap it with some guard space
418 strDummy = " " + strDummy + " ";
419 std::string delimiter = " ";
420 size_t pos = 0;
421 std::string token;
422 while ((pos = strDummy.find(delimiter)) != std::string::npos)
423 {
424 token = strDummy.substr(0, pos);
425 if(token.size() && !isKeyword(token.c_str()))
426 {
427 record.lock();
428 std::string value = (record.hasEvent(token.c_str())) ? "true" : "false";
429 record.unlock();
430 searchReplace(strConstraint, token, value);
431 }
432 strDummy.erase(0, pos + delimiter.length());
433 }
434 yCTrace(PORTMONITORCARRIER, "constraint = \'%s\'", strConstraint.c_str());
435
436 /*
437 * Using lua to evaluate the boolean expression
438 * Note: this can be replaced by a homebrew boolean
439 * expression validator (e.g., BinNodeType from libyarpmanager)
440 */
441 strConstraint = "return " + strConstraint;
442
443 if(luaL_dostring(L, strConstraint.c_str()) != 0)
444 {
446 return false;
447 }
448
449 if(!lua_isboolean(L, -1))
450 {
452 return false;
453 }
454
455 bool accepted = (lua_toboolean(L,-1) == 1);
456 lua_pop(L, 1);
457 return accepted;
458}
459
460
461inline void MonitorLua::searchReplace(std::string& str, const std::string& oldStr, const std::string& newStr)
462{
463 size_t pos = 0;
464 while((pos = str.find(oldStr, pos)) != std::string::npos)
465 {
466 str.replace(pos, oldStr.length(), newStr);
467 pos += newStr.length();
468 }
469}
470
471inline void MonitorLua::trimString(std::string& str)
472{
473 std::string::size_type pos = str.find_last_not_of(' ');
474 if(pos != std::string::npos) {
475 str.erase(pos + 1);
476 pos = str.find_first_not_of(' ');
477 if (pos != std::string::npos) {
478 str.erase(0, pos);
479 }
480 } else {
481 str.erase(str.begin(), str.end());
482 }
483}
484
485inline bool MonitorLua::isKeyword(const char* str)
486{
487 if (!str) {
488 return false;
489 }
490
491 std::string token = str;
492 if ((token == "true") || (token == "false") || (token == "and") || (token == "or") || (token == "not")) {
493 return true;
494 }
495 return false;
496}
497
498
503int MonitorLua::setConstraint(lua_State* L)
504{
505 const char *cst = luaL_checkstring(L, 1);
506 if(cst)
507 {
508 lua_getglobal(L, "PortMonitor_Owner");
509 if(!lua_islightuserdata(L, -1))
510 {
511 yCError(PORTMONITORCARRIER, "Cannot get PortMonitor_Owner");
512 return 0;
513 }
514
515 auto* owner = static_cast<MonitorLua*>(lua_touserdata(L, -1));
517 owner->setAcceptConstraint(cst);
518 }
519 return 0;
520}
521
522int MonitorLua::getConstraint(lua_State* L)
523{
524 lua_getglobal(L, "PortMonitor_Owner");
525 if(!lua_islightuserdata(L, -1))
526 {
527 yCError(PORTMONITORCARRIER, "Cannot get PortMonitor_Owner");
528 return 0;
529 }
530
531 auto* owner = static_cast<MonitorLua*>(lua_touserdata(L, -1));
533 lua_pushstring(L, owner->getAcceptConstraint());
534 return 0;
535}
536
537
538int MonitorLua::setEvent(lua_State* L)
539{
540 double lifetime = -1.0;
541 int n_args = lua_gettop(L);
542 const char *event_name = luaL_checkstring(L, 1);
543 if(event_name)
544 {
545 // check if the event's lifetime is given as argument
546 if(n_args > 1)
547 {
548 if (lua_isnumber(L, 2)) {
549 lifetime = (double) luaL_checknumber(L,2);
550 } else {
551 yCError(PORTMONITORCARRIER, "The second arguemnt of setEvent() must be number");
552 return 0;
553 }
554 }
555
556 lua_getglobal(L, "PortMonitor_Owner");
557 if(!lua_islightuserdata(L, -1))
558 {
559 yCError(PORTMONITORCARRIER, "Cannot get PortMonitor_Owner");
560 return 0;
561 }
562 auto* owner = static_cast<MonitorLua*>(lua_touserdata(L, -1));
564 if (owner->isKeyword(event_name)) {
565 return 0;
566 }
568 record.lock();
569 record.setEvent(event_name, owner, lifetime);
570 record.unlock();
571 }
572 return 0;
573}
574
575int MonitorLua::unsetEvent(lua_State* L)
576{
577 const char *event_name = luaL_checkstring(L, 1);
578 if(event_name)
579 {
580 lua_getglobal(L, "PortMonitor_Owner");
581 if(!lua_islightuserdata(L, -1))
582 {
583 yCError(PORTMONITORCARRIER, "Cannot get PortMonitor_Owner");
584 return 0;
585 }
586 auto* owner = static_cast<MonitorLua*>(lua_touserdata(L, -1));
588 if (owner->isKeyword(event_name)) {
589 return 0;
590 }
592 record.lock();
593 record.unsetEvent(event_name, owner);
594 record.unlock();
595 }
596 return 0;
597}
598
599int MonitorLua::setTrigInterval(lua_State* L)
600{
601 double period = 0.0;
602 int n_args = lua_gettop(L);
603 if(n_args > 0) {
604 if (lua_isnumber(L, 1)) {
605 period = (double) luaL_checknumber(L,1);
606 } else {
607 yCError(PORTMONITORCARRIER, "The arguemnt of setTrigInterval() must be number");
608 return 0;
609 }
610 } else {
611 yCError(PORTMONITORCARRIER, "The setTrigInterval() require the interval number as the parameter");
612 return 0;
613 }
614
615
616 lua_getglobal(L, "PortMonitor_Owner");
617 if(!lua_islightuserdata(L, -1))
618 {
619 yCError(PORTMONITORCARRIER, "Cannot get PortMonitor_Owner");
620 return 0;
621 }
622
623 auto* owner = static_cast<MonitorLua*>(lua_touserdata(L, -1));
625
626 // start the trigger thread (MonitorTrigger) if it is not running
627 if(owner->trigger == nullptr) {
628 owner->trigger = new MonitorTrigger(owner, (int)(period*1000));
629 owner->trigger->start();
630 }
631 return 0;
632}
633
634
635#if LUA_VERSION_NUM > 501
636const struct luaL_Reg MonitorLua::portMonitorLib [] = {
637#else
638const struct luaL_reg MonitorLua::portMonitorLib [] = {
639#endif
640 {"setConstraint", MonitorLua::setConstraint},
641 {"getConstraint", MonitorLua::getConstraint},
642 {"setEvent", MonitorLua::setEvent},
643 {"unsetEvent", MonitorLua::unsetEvent},
644 {"setTrigInterval", MonitorLua::setTrigInterval},
645 {nullptr, nullptr}
646};
const yarp::os::LogComponent & PORTMONITORCARRIER()
A singleton class to record the port monitor events.
static MonitorEventRecord & getInstance()
A mini-server for performing network communication in the background.
void stop()
Call this to stop the thread, this call blocks until the thread is terminated (and releaseThread() ca...
A class for storing options and configuration information.
Definition Property.h:33
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Base class for generic things.
Definition Things.h:18
virtual std::string asString() const
Get string value.
Definition Value.cpp:234
#define yCError(component,...)
#define yCAssert(component, x)
#define yCTrace(component,...)
An interface to the operating system, including Port based communication.
~MonitorLua() override
MonitorLua()
Class MonitorLua.
bool getParams(yarp::os::Property &params) override
bool setParams(const yarp::os::Property &params) override
bool canAccept() override
bool acceptData(yarp::os::Things &thing) override
yarp::os::Things & updateReply(yarp::os::Things &thing) override
bool peerTrigged() override
MonitorTrigger * trigger
Definition MonitorLua.h:70
yarp::os::Things & updateData(yarp::os::Things &thing) override
bool load(const yarp::os::Property &options) override
static int SWIG_Lua_ConvertPtr(lua_State *L, int index, void **ptr, swig_type_info *type, int flags)
#define SWIG_NewPointerObj(L, ptr, type, owner)
static swig_type_info * SWIG_TypeQuery(lua_State *clientdata, const char *name)
#define SWIG_OK
Definition swigluarun.h:280