As you know I am working on a ProView project. It has a logical and physical distinction between plant and station nodes. Physical nodes are mainly controlled by logical nodes, including user defined applications written in C, C++ or Java. On this case we are using C and C++, C for low level ProView calls and C++ to create a nice object oriented interface. A very good approach is found on ProView General Data Handler or GDH API, where you can have access to the full node hierarchy using GDH calls. This allows managing nodes in all levels, even if you want to create new nodes in run-time. This is very nice, so I have defined a C++ class device to manage each device automatically and due to the algorithm complexity we cannot use PLC programming.
To abstract plant nodes you have two kinds of object attributes that you can use. The $IoConnect and the $SigChanCon will bring you the proper plant node reference to control the signal related device. For example if you use the gdh_NameToObjid() GDH call on that attribute reference, you will get the reference to the card object, on the card object you can get the reference to the rack object and set the send request operation to true on the next scan cycle. For example the SendReq on the PnWriteReq Profibus device object or the SendOp attribute on the Modbus module object. So, you do not really need to know the path of the plant node or create a direct reference to the plant object that you need to control.
sts = gdh_NameToObjid(nm.c_str(), &oid); if (EVEN(sts)) { errh_Error("prov_io::get_sendop_link() -> 1. Error Reading %s", nm.c_str()); return nm; } ss.str(""); ss.clear(); ss << nm.substr(0, nm.find_last_of(".")) << ".IoConnect"; ionm = ss.str(); sigcon_a = reinterpret_cast<pwr_taddress>(&sigcon); sts = gdh_GetObjectInfo(ionm.c_str(), sigcon_a, sizeof(sigcon)); if (EVEN(sts)) { errh_Error("prov_io::get_sendop_link() -> 2. Error Reading %s", ionm.c_str()); return nm; } memset(par_dev_name, 0, SEND_OP_BUFF_SZ); sts = gdh_AttrrefToName(&sigcon, par_dev_name, SEND_OP_BUFF_SZ, cdh_mName_volumeStrict); if (EVEN(sts)) { errh_Error("prov_io::get_sendop_link() -> 3. Error Reading %s", ionm.c_str()); return nm; } sts = gdh_NameToObjid(par_dev_name, &devid); if (EVEN(sts)) { errh_Error("prov_io::get_sendop_link() -> 4. Error Reading %s", par_dev_name); return nm; }
For example the code above displays an example on how to get the plant node using the $IoConnect attribute. Finally gets the Object ID of the connected plant node, allowing real control. Also, always remember to use the cdh_mName_volumeStrict flag to guarantee that the full volume path of the node will be used, allowing GDH to get the real path of the object without wasting time on finding mounted volumes and trying to make a difference between them.
With this approach, I am thinking to write some API helpers, something with the same behavior of the XML XPath standard, to allow finding nodes and node references without too much effort. I think that this will help a lot with open(), close() and scan() methods on the rt_appl class, allowing faster C and C++ development. This framework is really nice. I would like it to be more open, and I think that the authors would create a public repository and create a centralized development model like is seen in other platforms like FreeBSD.