22 #include <yarp/os/all.h> 32 OPCClient::OPCClient(
const string &moduleName)
34 opc.open(
"/" + moduleName +
"/world/opc:rpc");
39 bool OPCClient::write(Bottle &cmd, Bottle &reply,
bool Verbose)
41 if (opc.getOutputCount() > 0)
44 yDebug()<<
"Sending to OPC: "<<cmd.toString().c_str();
49 yDebug()<<
"Receiving from OPC: "<<reply.toString().c_str();
51 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
59 yWarning()<<
"Not connected to OPC...";
64 void OPCClient::interrupt()
69 void OPCClient::close()
73 for(map<int,Entity*>::iterator it=entitiesByID.begin(); it!=entitiesByID.end(); it++)
77 this->entitiesByID.clear();
80 void OPCClient::clear()
83 cmd.addVocab(Vocab::encode(
"del"));
84 cmd.addList().addString(
"all");
87 for(map<int,Entity*>::iterator it=entitiesByID.begin(); it!=entitiesByID.end(); it++)
91 this->entitiesByID.clear();
98 cmd.addVocab(Vocab::encode(
"add"));
99 Bottle& query = cmd.addList();
101 write(cmd,reply,isVerbose);
103 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
105 yError() <<
"Impossible to communicate correctly with OPC";
110 e->m_opc_id = reply.get(1).asList()->get(1).asInt();
116 entitiesByID[e->
opc_id()] = e;
122 bool OPCClient::setEntityProperty(std::string sourceEntityName, std::string propertyName, std::string targetEntityName)
124 Entity* source = getEntity(sourceEntityName,
false);
125 Entity* target = getEntity(targetEntityName,
false);
126 if (source ==
nullptr || target ==
nullptr)
129 source->m_properties[propertyName] = targetEntityName;
134 Entity* OPCClient::getEntity(
const string &name,
bool forceUpdate)
137 for(map<int,Entity*>::iterator it=entitiesByID.begin(); it!=entitiesByID.end(); it++) {
138 if(it->second->name() == name) {
147 cmd.addVocab(Vocab::encode(
"ask"));
148 Bottle& query = cmd.addList();
150 Bottle& sub = query.addList();
151 sub.addString(
"name");
153 sub.addString(name.c_str());
155 write(cmd,reply,isVerbose);
157 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
159 yError() <<
"Unable to talk correctly to OPC in getEntity with name";
160 yError() <<
"Command was:" << cmd.toString();
161 yError() <<
"Reply was:" << reply.toString();
165 if (reply.get(1).asList()->get(1).asList()->size() == 0)
171 if (reply.get(1).asList()->get(1).asList()->size() > 1)
173 yError() <<
"[IMPORTANT] Duplicated names... You should fix this!";
176 int item_id = reply.get(1).asList()->get(1).asList()->get(0).asInt();
177 return getEntity(item_id);
181 Entity *OPCClient::getEntity(
int id,
bool forceUpdate)
184 map<int, Entity*>::iterator itE = entitiesByID.find(
id);
185 if (itE != entitiesByID.end())
194 cmd.addVocab(Vocab::encode(
"get"));
195 Bottle& query = cmd.addList();
196 Bottle& sub = query.addList();
199 write(cmd,reply,isVerbose);
201 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
203 yError() <<
"Unable to talk correctly to OPC in getEntity with ID";
204 yError() <<
"Command was:" << cmd.toString();
205 yError() <<
"Reply was:" << reply.toString();
209 Bottle* reply_bottle = reply.get(1).asList();
211 yError() <<
"Unable to talk correctly to OPC in getEntity with ID";
212 yError() <<
"Reply does not contain Bottle as expected";
217 std::string newEntityType = reply_bottle->find(
"entity").asString().c_str();
220 if(newEntityType ==
"entity")
228 else if (newEntityType ==
"bodypart")
231 yError() <<
"getEntity: Unknown Entity type!";
238 newE->m_original_entity = newE->
asBottle();
241 entitiesByID[newE->
opc_id()] = newE;
246 bool OPCClient::removeEntity(
const string &name)
248 if (
Entity *e=getEntity(name,
true))
251 cmd.addVocab(Vocab::encode(
"del"));
252 Bottle &payLoad=cmd.addList().addList();
253 payLoad.addString(
"id");
254 payLoad.addInt(e->opc_id());
256 if (write(cmd,reply,isVerbose))
258 if (reply.get(0).asVocab()==yarp::os::createVocab(
'a',
'c',
'k')) {
259 entitiesByID.erase(e->opc_id());
263 yError()<<
"Unable to talk correctly to OPC in removeEntity by name for " << name <<
"(id " << e->
opc_id() <<
")";
264 yError()<<
"Command sent:" << cmd.toString();
265 yError()<<
"Reply:" << reply.toString();
273 bool OPCClient::removeEntity(
int id)
275 if (
Entity *e=getEntity(
id,
true))
278 cmd.addVocab(Vocab::encode(
"del"));
279 Bottle &payLoad=cmd.addList().addList();
280 payLoad.addString(
"id");
281 payLoad.addInt(e->opc_id());
283 if (write(cmd,reply,isVerbose))
285 if (reply.get(0).asVocab()==yarp::os::createVocab(
'a',
'c',
'k'))
287 entitiesByID.erase(e->opc_id());
291 yError()<<
"Unable to talk correctly to OPC in removeEntity by ID for id" <<
id <<
"(" << e->name() <<
")";
292 yError()<<
"Command sent:" << cmd.toString();
293 yError()<<
"Reply:" << reply.toString();
302 int OPCClient::getRelationID(
308 Entity* complement_manner)
310 Relation r(subject,verb,
object,complement_place,complement_time,complement_manner);
313 cmd.addString(
"ask");
315 Bottle& query = cmd.addList();
321 query.addList() = sub;
323 query.addString(
"&&");
326 sub.addString(
"rSubject");
328 sub.addString(r.
subject().c_str());
329 query.addList() = sub;
331 query.addString(
"&&");
334 sub.addString(
"rVerb");
336 sub.addString(r.
verb().c_str());
337 query.addList() = sub;
339 query.addString(
"&&");
342 sub.addString(
"rObject");
344 sub.addString(r.
object().c_str());
345 query.addList() = sub;
347 query.addString(
"&&");
350 sub.addString(
"rCompPlace");
353 query.addList() = sub;
355 query.addString(
"&&");
358 sub.addString(
"rCompTime");
361 query.addList() = sub;
363 query.addString(
"&&");
366 sub.addString(
"rCompManner");
369 query.addList() = sub;
371 write(cmd,reply,isVerbose);
373 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
375 yError()<<
"Unable to talk correctly to OPC in getRelationID";
376 yError() <<
"Command was:" << cmd.toString();
377 yError() <<
"Reply was:" << reply.toString();
382 if (reply.get(1).asList()->get(1).asList()->size() >= 1)
384 return (reply.get(1).asList()->get(1).asList()->get(0).asInt());
390 bool OPCClient::addRelation(
const Relation &r,
double lifeTime)
398 if (subject ==
nullptr || verb ==
nullptr)
400 yError() <<
"Verb and subject should exist before you try to add a relation";
404 return addRelation(subject,verb,
object,lifeTime,cPlace,cTime,cManner);
408 bool OPCClient::addRelation(
415 Entity* complement_manner)
419 int index = getRelationID(subject,verb,
object,complement_place,complement_time,complement_manner);
425 yWarning() <<
"This relation already exist, only reseting lifeTimer";
426 return setLifeTime(index,lifeTime);
430 Relation r(subject,verb,
object,complement_place,complement_time,complement_manner);
432 cmd.addString(
"add");
436 write(cmd,reply,isVerbose);
438 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
440 yError() <<
"Unable to talk correctly to OPC in addRelation";
441 yError() <<
"Command was:" << cmd.toString();
442 yError() <<
"Reply was:" << reply.toString();
445 index = reply.get(1).asList()->get(1).asInt();
446 return setLifeTime(index,lifeTime);
458 return removeRelation(subject,verb,
object,cPlace,cTime,cManner);
462 bool OPCClient::removeRelation(
468 Entity* complement_manner)
471 int index = getRelationID(subject,verb,
object,complement_place,complement_time,complement_manner);
475 yWarning() <<
"This relation does not exist on the OPC server, not removed";
481 cmd.addString(
"del");
486 cmd.addList().addList() = sub;
488 write(cmd,reply,isVerbose);
489 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
491 yError() <<
"Unable to talk correctly to OPC in removeRelation. Item not deleted.";
492 yError() <<
"Command was:" << cmd.toString();
493 yError() <<
"Reply was:" << reply.toString();
501 bool OPCClient::containsRelation(
507 Entity* complement_manner)
509 int index = getRelationID(subject,verb,
object,complement_place,complement_time,complement_manner);
510 return (index != -1);
513 bool OPCClient::containsRelation(
const Relation &r)
521 return containsRelation(subject,verb,
object,cPlace,cTime,cManner);
524 bool OPCClient::setLifeTime(
int opcID,
double lifeTime)
531 cmd.addString(
"del");
533 Bottle &
args = cmd.addList();
534 Bottle &
id = args.addList();
538 Bottle &props = args.addList();
540 props.addString(
"propSet");
541 props.addList().addString(
"lifeTimer");
546 cmd.addString(
"set");
548 Bottle &
args = cmd.addList();
549 Bottle &
id = args.addList();
553 Bottle &props = args.addList();
555 props.addString(
"lifeTimer");
556 props.addDouble(lifeTime);
559 write(cmd,reply,isVerbose);
560 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
562 yError() <<
"Unable to talk correctly to OPC in setLifeTime";
563 yError() <<
"Command was:" << cmd.toString();
564 yError() <<
"Reply was:" << reply.toString();
570 list<Relation> OPCClient::getRelations()
572 list<Relation> relations;
575 Bottle cmd,sub,reply;
576 cmd.addString(
"ask");
577 Bottle& cond = cmd.addList();
582 cond.addList() = sub;
583 write(cmd,reply,isVerbose);
585 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
587 yError() <<
"Unable to talk to OPC.";
592 Bottle* ids = reply.get(1).asList()->get(1).asList();
593 for(
unsigned int i=0;i<ids->size();i++)
596 int currentID = ids->get(i).asInt();
598 cmd.addString(
"get");
601 sub.addInt(currentID);
602 cmd.addList().addList() = sub;
603 write(cmd,getReply,isVerbose);
604 if (getReply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
606 yError() <<
"Unable to talk to OPC.";
610 Relation r(*getReply.get(1).asList());
611 r.m_opcId = currentID;
612 relations.push_back(r);
617 std::list<Relation> OPCClient::getRelationsMatching(std::string subject,std::string verb, std::string
object, std::string c_place, std::string c_time, std::string c_manner)
619 list<Relation> relations;
621 Bottle cmd,sub,reply;
622 cmd.addString(
"ask");
623 Bottle& cond = cmd.addList();
628 cond.addList() = sub;
629 if (subject !=
"any")
631 cond.addString(
"&&");
632 Bottle& subCond = cond.addList();
633 subCond.addString(
"rSubject");
634 subCond.addString(
"==");
635 subCond.addString(subject.c_str());
639 cond.addString(
"&&");
640 Bottle& subCond = cond.addList();
641 subCond.addString(
"rVerb");
642 subCond.addString(
"==");
643 subCond.addString(verb.c_str());
647 cond.addString(
"&&");
648 Bottle& subCond = cond.addList();
649 subCond.addString(
"rObject");
650 subCond.addString(
"==");
651 subCond.addString(
object.c_str());
655 cond.addString(
"&&");
656 Bottle& subCond = cond.addList();
657 subCond.addString(
"rCompTime");
658 subCond.addString(
"==");
659 subCond.addString(c_time.c_str());
661 if (c_place !=
"any")
663 cond.addString(
"&&");
664 Bottle& subCond = cond.addList();
665 subCond.addString(
"rCompPlace");
666 subCond.addString(
"==");
667 subCond.addString(c_place.c_str());
669 if (c_manner !=
"any")
671 cond.addString(
"&&");
672 Bottle& subCond = cond.addList();
673 subCond.addString(
"rCompManner");
674 subCond.addString(
"==");
675 subCond.addString(c_manner.c_str());
677 write(cmd,reply,isVerbose);
679 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
681 yError() <<
"Unable to talk to OPC.";
686 Bottle* ids = reply.get(1).asList()->get(1).asList();
687 for(
unsigned int i=0;i<ids->size();i++)
690 int currentID = ids->get(i).asInt();
692 cmd.addString(
"get");
695 sub.addInt(currentID);
696 cmd.addList().addList() = sub;
697 write(cmd,getReply,isVerbose);
698 if (getReply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
700 yError() <<
"Unable to talk to OPC.";
704 Relation r(*getReply.get(1).asList());
706 relations.push_back(r);
710 std::list<Relation> OPCClient::getRelationsMatchingLoosly(std::string subject, std::string verb, std::string
object, std::string c_place, std::string c_time, std::string c_manner)
712 list<Relation> relations = getRelations();
713 list<Relation> filteredRelations;
714 for (list<Relation>::iterator it = relations.begin(); it != relations.end(); it++)
716 if (it->subject() == subject ||
717 it->verb() == verb ||
718 it->object() ==
object ||
719 it->complement_time() == c_time ||
720 it->complement_place() == c_place ||
721 it->complement_manner() == c_manner)
723 filteredRelations.push_back(*it);
726 return filteredRelations;
729 std::list<Relation> OPCClient::getRelations(std::string entity)
731 list<Relation> relations = getRelations();
732 list<Relation> filteredRelations;
733 for(list<Relation>::iterator it = relations.begin(); it != relations.end() ; it++)
735 if (it->subject() == entity ||
736 it->verb() == entity ||
737 it->object() == entity ||
738 it->complement_time() == entity ||
739 it->complement_place() == entity ||
740 it->complement_manner() == entity)
742 filteredRelations.push_back(*it);
745 return filteredRelations;
748 std::list<Relation> OPCClient::getRelations(
Entity* entity)
750 return getRelations(entity->
name());
754 void OPCClient::checkout(
bool updateCache)
759 for(map<int,Entity*>::iterator it=entitiesByID.begin(); it!=entitiesByID.end(); it++)
763 entitiesByID.clear();
767 Bottle cmd,sub,reply;
768 cmd.addString(
"ask");
770 Bottle& cond = cmd.addList();
774 cond.addList() = sub;
776 write(cmd,reply,isVerbose);
777 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
779 yError() <<
"Unable to talk to OPC.";
783 Bottle* ids = reply.get(1).asList()->get(1).asList();
784 for(
unsigned int i=0;i<ids->size();i++)
786 int currentID = ids->get(i).asInt();
787 getEntity(currentID, updateCache);
790 yInfo() <<
"Checkout result: "<< ids->size() <<
" entities added.";
794 void OPCClient::update()
796 for(map<int, Entity* >::iterator it = entitiesByID.begin(); it != entitiesByID.end(); it++)
807 cmd.addVocab(Vocab::encode(
"get"));
808 Bottle& query = cmd.addList();
809 Bottle&
id = query.addList();
813 write(cmd,reply,isVerbose);
816 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
818 yError() <<
"OPC Client: error while updating " << e->
opc_id();
823 Bottle props = *reply.get(1).asList();
825 yError() <<
"Error updating entity " << e->
name() <<
"fromBottle! Type: " << e->
entity_type();
826 yDebug() <<
"OPCClient props:" << props.toString();
831 e->m_original_entity = e->
asBottle();
835 void OPCClient::commit()
837 for(map<int, Entity* >::iterator it = entitiesByID.begin(); it != entitiesByID.end(); it++)
847 cmd.addVocab(Vocab::encode(
"set"));
848 Bottle& query = cmd.addList();
849 Bottle&
id = query.addList();
853 Bottle props=e->asBottleOnlyModifiedProperties();
854 for (
unsigned int i=0; i<props.size(); i++)
855 query.addList()=*props.get(i).asList();
857 write(cmd,reply,isVerbose);
858 if (reply.get(0).asVocab()==yarp::os::createVocab(
'n',
'a',
'c',
'k'))
860 yError() <<
"OPC Client: error while commiting " << e->
opc_id();
865 std::list<Entity*> OPCClient::Entities(
const yarp::os::Bottle &condition)
867 list<Entity*> matchingEntities;
870 cmd.addString(
"ask");
871 cmd.addList() = condition;
873 write(cmd,reply,isVerbose);
875 if (reply.get(0).asVocab() == yarp::os::createVocab(
'n',
'a',
'c',
'k'))
877 yError() <<
"Unable to talk to OPC.";
878 return matchingEntities;
881 Bottle* ids = reply.get(1).asList()->get(1).asList();
882 for(
unsigned int i=0;i<ids->size();i++)
884 int currentID = ids->get(i).asInt();
885 matchingEntities.push_back(getEntity(currentID));
886 update(matchingEntities.back());
889 yInfo() <<
"Checkout result: " << ids->size() <<
" entities added.";
890 return matchingEntities;
893 list<Entity*> OPCClient::Entities(
const string &prop,
const string &op,
const string &value)
897 sub.addString(prop.c_str());
898 sub.addString(op.c_str());
899 sub.addString(value.c_str());
900 cond.addList() = sub;
901 return Entities(cond);
905 list<Entity*> OPCClient::EntitiesCache()
const 908 for(
const auto& it : this->entitiesByID)
910 lR.push_back(it.second);
917 std::list<std::shared_ptr<Entity>> OPCClient::EntitiesCacheCopy()
const 919 list<std::shared_ptr<Entity>> lR;
920 for(
const auto& it : this->entitiesByID)
922 std::shared_ptr<Entity> E;
925 E = std::shared_ptr<Agent>(
new Agent());
929 E = std::shared_ptr<Object>(
new Object());
933 E = std::shared_ptr<Action>(
new Action());
935 else if (it.second->m_entity_type ==
"bodypart")
937 E = std::shared_ptr<Bodypart>(
new Bodypart());
941 yError() <<
"EntitiesCacheCopy: Unknown entity type!";
945 E->fromBottle(it.second->asBottle());
946 E->m_opc_id = it.second->m_opc_id;
954 string OPCClient::toString()
956 string s=
"WORLD STATE \n";
957 for(
const auto& it : entitiesByID)
959 s += it.second->toString();
962 list<Relation> rels = getRelations();
963 for(
const auto& it : rels)
964 s += it.toString() +
'\n';
969 bool OPCClient::changeName(
Entity *e,
const std::string &newName)
971 for(
auto& entity : entitiesByID)
973 if(entity.second->name() == newName) {
974 yError() <<
"Entity with name " << newName <<
" is already existing.";
int opc_id() const
Return the id of an entity (which has to be unique within the OPC) Typically, modules should employ t...
std::string complement_manner() const
Get the complement of manner of the relation.
virtual bool fromBottle(const yarp::os::Bottle &b)
Fill entity fields from a bottle representation.
yarp::os::Bottle asBottle(bool ignoreID=false) const
Represent any entity that can be stored within the OPC.
std::string subject() const
Get the name of the relation's subject.
std::string complement_time() const
Get the complement of time of the relation.
Represent any physical entity (including objects and agents) that can be stored within the OPC...
void changeName(std::string sName)
Represents an action, whether composite or not.
Represents a body part of the robot.
std::string complement_place() const
Get the complement of place of the relation.
std::string object() const
Get the name of the relation's object.
std::string name() const
Return the name of an entity (which has to be unique within the OPC)
std::string verb() const
Get the type of the relation.
Represent a relation between two entities.
virtual yarp::os::Bottle asBottle() const
Return the entity as a bottle.
std::string entity_type() const
Return the specific type of an entity.