opcua_client.cpp
Go to the documentation of this file.
00001 
00025 #include <ros/ros.h>
00026 #include <signal.h>
00027 
00028 #include <opcua_helpers.h>
00029 
00030 #include "ros_opcua_msgs/Address.h"
00031 #include "ros_opcua_msgs/TypeValue.h"
00032 
00033 #include "ros_opcua_srvs/CallMethod.h"
00034 #include "ros_opcua_srvs/Connect.h"
00035 #include "ros_opcua_srvs/Disconnect.h"
00036 #include "ros_opcua_srvs/ListNode.h"
00037 #include "ros_opcua_srvs/Read.h"
00038 #include "ros_opcua_srvs/Subscribe.h"
00039 #include "ros_opcua_srvs/Write.h"
00040 #include "ros_opcua_srvs/Unsubscribe.h"
00041 
00042 #include <opc/ua/client/client.h>
00043 #include <opc/ua/subscription.h>
00044 
00046 OpcUa::UaClient _client(false);
00048 
00049 std::map<std::string, std::unique_ptr<OpcUa::Subscription>> _subscriptions;
00051 
00052 std::map<std::string, ros::Publisher> _callback_publishers;
00054 
00055 std::map<std::string, uint32_t> _subscription_handles;
00057 bool _connected = false;
00058 
00060 
00063 class SubClient : public OpcUa::SubscriptionHandler
00064 {
00072   void DataChange(uint32_t handle, const OpcUa::Node& node, const
00073 OpcUa::Variant& value, OpcUa::AttributeId attr) override
00074   {
00075     ROS_DEBUG("Callback....");
00076     _callback_publishers[OpcUa::ToString(node.GetId())].publish(convertVariantToTypeValue(value));
00077   }
00078 };
00079 
00081 
00082 SubClient _sclt;
00083 
00090 bool connect(ros_opcua_srvs::Connect::Request &req, ros_opcua_srvs::Connect::Response &res)
00091 {
00092     // TODO: set connect status
00093 
00094     ROS_DEBUG("Establishing connection to OPC-UA server on address: %s", req.endpoint.c_str());
00095     try {
00096         _client.Connect(req.endpoint);
00097         ROS_INFO("Connection to OPC-UA server on address '%s' established!", req.endpoint.c_str());
00098         res.success = true;
00099         _connected = true;
00100     }
00101     catch (const std::exception& exc){
00102         ROS_ERROR("OPC-UA client node %s: Connection to OPC-UA server on address %s failed! Message: %s", ros::this_node::getName().c_str(), req.endpoint.c_str(), exc.what());
00103 
00104         res.success = false;
00105         char err_string[100];
00106         sprintf(err_string, "Connection to OPC-UA server on address %s failed! Message: %s", req.endpoint.c_str(), exc.what());
00107         res.error_message = err_string;
00108     }
00109     catch (...) {
00110         ROS_ERROR("Connection to OPC-UA server on address %s failed with unknown exception", req.endpoint.c_str());
00111         res.success = false;
00112         res.error_message = "'Connect' service failed with Unknown exception";
00113     }
00114     return true;
00115 }
00116 
00123 bool disconnect(ros_opcua_srvs::Disconnect::Request &req, ros_opcua_srvs::Disconnect::Response &res)
00124 {
00125     ROS_DEBUG("Disconnecting from OPC-UA server...");
00126     try {
00127         _client.Disconnect();
00128         ROS_INFO("Disconnection succeded!");
00129         _connected = false;
00130         res.success = true;
00131     }
00132     catch (const std::exception& exc){
00133         ROS_ERROR("OPC-UA client node %s: Disconnection failed! (maybe client was not connected before?). Message: %s", ros::this_node::getName().c_str(), exc.what());
00134 
00135         res.success = false;
00136         char err_string[100];
00137         sprintf(err_string, "Dissconect service failed with exception: %s", exc.what());
00138         res.error_message = err_string;
00139     }
00140     catch (...) {
00141         ROS_ERROR("'Disconnect' service failed with unknown exception");
00142         res.success = false;
00143         res.error_message = "'Disconnect' service failed with unknown exception";
00144     }
00145     return true;
00146 }
00147 
00154 bool list_node(ros_opcua_srvs::ListNode::Request &req, ros_opcua_srvs::ListNode::Response &res)
00155 {
00156     ROS_DEBUG("OPC-UA client node %s: 'ListNode' service called with node Id: %s parameters", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00157 
00158     OpcUa::Node node;
00159     try {
00160       if (req.node.nodeId == "") {
00161           node = _client.GetObjectsNode();
00162       }
00163       else {
00164         node = _client.GetNode(req.node.nodeId);
00165       }
00166 
00167       for (OpcUa::Node child : node.GetChildren()){
00168           ros_opcua_msgs::Address address;
00169           address.nodeId = OpcUa::ToString(child.GetId());
00170           address.qualifiedName = child.GetBrowseName().Name;
00171           res.children.push_back(address);
00172       }
00173       res.success = true;
00174     }
00175     catch (const std::exception& exc){
00176             ROS_ERROR("OPC-UA client node %s: 'ListNode' service called with node Id: %s, parameters failed! Exception: %s", ros::this_node::getName().c_str(), req.node.nodeId.c_str(), exc.what());
00177 
00178             res.success = false;
00179             char err_string[100];
00180             sprintf(err_string, "ListNode service failed with exception: %s", exc.what());
00181             res.error_message = err_string;
00182         }
00183         catch (...)
00184         {
00185             ROS_ERROR("OPC-UA client node %s: 'ListNode' service called with node Id: %s parameters failed! Unknown exception!", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00186 
00187             res.success = false;
00188             res.error_message = "ListNode service failed with Unknown exception";
00189         }
00190         return true;
00191 }
00192 
00193 bool call_method(ros_opcua_srvs::CallMethod::Request &req, ros_opcua_srvs::CallMethod::Response &res)
00194 {
00195     ROS_DEBUG("OPC-UA client node %s: 'CallMethod' service called with node Id: %s and %s parameters", ros::this_node::getName().c_str(), req.node.nodeId.c_str(), req.method.nodeId.c_str());
00196 
00197     try {
00198         OpcUa::Node node = _client.GetNode(req.node.nodeId);
00199         OpcUa::NodeId method_id = OpcUa::ToNodeId(req.method.nodeId);
00200         std::vector<OpcUa::Variant> inputArguments;
00201 
00202         for (ros_opcua_msgs::TypeValue typeValue : req.data) {
00203             std::cout << "Variant: " <<
00204 convertTypeValueToVariant(typeValue).ToString() << std::endl;
00205             inputArguments.push_back(convertTypeValueToVariant(typeValue));
00206         }
00207 
00208         std::vector<OpcUa::Variant> outputArguments = node.CallMethod(method_id, inputArguments);
00209 
00210         for (OpcUa::Variant variant : outputArguments) {
00211             res.data.push_back(convertVariantToTypeValue(variant));
00212         }
00213 
00214         res.success = true;
00215 
00216     }
00217     catch (const std::exception& exc){
00218         ROS_ERROR("OPC-UA client node %s: 'CallMethod' service called with node Id: %s and %s parameters failed! Exception: %s", ros::this_node::getName().c_str(), req.node.nodeId.c_str(), req.method.nodeId.c_str(), exc.what());
00219 
00220         res.success = false;
00221         char err_string[100];
00222         sprintf(err_string, "Call method service failed with exception: %s", exc.what());
00223         res.error_message = err_string;
00224     }
00225     catch (...)
00226     {
00227         ROS_ERROR("OPC-UA client node %s: 'CallMethod' service called with node Id: %s parameters failed! Unknown exception!", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00228 
00229         res.success = false;
00230         res.error_message = "Call method service failed with Unknown exception";
00231     }
00232     return true;
00233 }
00234 
00241 bool read(ros_opcua_srvs::Read::Request &req, ros_opcua_srvs::Read::Response &res)
00242 {
00243     ROS_DEBUG("OPC-UA client node %s: 'Read' service called with node Id: %s parameters", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00244 
00245     try {
00246         OpcUa::Node variable = _client.GetNode(req.node.nodeId);
00247 
00248         res.success = true;
00249         res.data = convertVariantToTypeValue(variable.GetValue());
00250 
00251         if (res.data.type == "Unknown") {
00252             res.success = false;
00253             char err_string[100];
00254             sprintf(err_string, "Unknon data type!!");
00255             res.error_message = err_string;
00256             ROS_DEBUG("Reading failed!");
00257         }
00258     }
00259     catch (const std::exception& exc){
00260         ROS_ERROR("OPC-UA client node %s: 'Read' service called with node Id: %s, parameters failed! Exception: %s", ros::this_node::getName().c_str(), req.node.nodeId.c_str(), exc.what());
00261 
00262         res.success = false;
00263         char err_string[100];
00264         sprintf(err_string, "Read service failed with exception: %s", exc.what());
00265         res.error_message = err_string;
00266     }
00267     catch (...)
00268     {
00269         ROS_ERROR("OPC-UA client node %s: 'Read' service called with node Id: %s parameters failed! Unknown exception!", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00270 
00271         res.success = false;
00272         res.error_message = "Read service failed with Unknown exception";
00273     }
00274     return true;
00275 }
00276 
00283 bool write(ros_opcua_srvs::Write::Request &req, ros_opcua_srvs::Write::Response &res)
00284 {
00285     ROS_DEBUG("OPC-UA client node %s: 'Write' service called with node Id: %s, parameters", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00286 
00287     try {
00288         OpcUa::Node variable = _client.GetNode(req.node.nodeId);
00289 
00290         OpcUa::Variant variant = convertTypeValueToVariant(req.data);
00291 
00292         if (!variant.IsNul()) {
00293 //           if (variant.Type() == OpcUa::VariantType::STRING) {
00294 //             if (((std::string)variant).length() == 0) {
00295 //               variant = std::string(" ");
00296 //             }
00297 //           }
00298           variable.SetValue(variant);
00299           res.success = true;
00300         }
00301         else {
00302             res.success = false;
00303             char err_string[100];
00304             sprintf(err_string, "Unknon data type %s", req.data.type.c_str());
00305             res.error_message = err_string;
00306             ROS_DEBUG("Writing failed!");
00307         }
00308     }
00309     catch (const std::exception& exc){
00310         ROS_ERROR("OPC-UA client node %s: 'Write' service called with node Id: %s, type: '%s' parameters failed! Exception: %s", ros::this_node::getName().c_str(), req.node.nodeId.c_str(), req.data.type.c_str(), exc.what());
00311 
00312         res.success = false;
00313         char err_string[100];
00314         sprintf(err_string, "Write service failed with exception: %s", exc.what());
00315         res.error_message = err_string;
00316     }
00317     catch (...)
00318     {
00319         ROS_ERROR("OPC-UA client node %s: 'Write' service called with node Id: %s, type: '%s' parameters failed! Unknown exception!", ros::this_node::getName().c_str(), req.node.nodeId.c_str(), req.data.type.c_str());
00320 
00321         res.success = false;
00322         res.error_message = "Write service failed with Unknown exception";
00323     }
00324 
00325     return true;
00326 }
00327 
00335 bool subscribe(ros_opcua_srvs::Subscribe::Request &req, ros_opcua_srvs::Subscribe::Response &res)
00336 {
00337     ROS_DEBUG("OPC-UA client node %s: 'Subscribe' service called with node Id: %s parameters", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00338 
00339     try {
00340         // TODO: Check if already subscribed to node
00341 
00342         OpcUa::Node variable = _client.GetNode(req.node.nodeId);
00343         std::string node_string = OpcUa::ToString(variable.GetId());
00344 
00345         ros::NodeHandle nodeHandle("~");
00346         _callback_publishers[node_string] =  nodeHandle.advertise<ros_opcua_msgs::TypeValue>(req.callback_topic, 1);
00347 
00348         _subscriptions[node_string] = _client.CreateSubscription(100, _sclt);
00349         _subscription_handles[node_string] =  _subscriptions[node_string]->SubscribeDataChange(variable);
00350 
00351         ROS_INFO("Node successfully subscribed!");
00352         res.success = true;
00353     }
00354     catch (const std::exception& exc){
00355         ROS_ERROR("OPC-UA client node %s: 'Subscribe' service called with node Id: %s parameters failed!", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00356 
00357         res.success = false;
00358         char err_string[100];
00359         sprintf(err_string, "Subscribe service failed with exception: %s", exc.what());
00360         res.error_message = err_string;
00361     }
00362     catch (...)
00363     {
00364         ROS_ERROR("OPC-UA client node %s: 'Subscribe' service called with node Id: %s parameters failed!", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00365 
00366         res.success = false;
00367         res.error_message = "Subscribe service failed with Unknown exception";
00368     }
00369 
00370     return true;
00371 }
00372 
00379 bool unsubscribe(ros_opcua_srvs::Unsubscribe::Request &req, ros_opcua_srvs::Unsubscribe::Response &res)
00380 {
00381     ROS_DEBUG("OPC-UA client node %s: 'Unsubscribe' service called with node Id: %s parameters", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00382 
00383     try {
00384         // TODO: Check if already subscribed to node
00385 
00386         // TODO: Why is here return status false even the subscription was ok?
00387 
00388         OpcUa::Node variable = _client.GetNode(req.node.nodeId);
00389         std::string node_string = OpcUa::ToString(variable.GetId());
00390 
00391         _subscriptions[node_string]->UnSubscribe(_subscription_handles[node_string]);
00392         _callback_publishers[node_string].shutdown();
00393 
00394         _subscriptions.erase(node_string);
00395         _subscription_handles.erase(node_string);
00396         _callback_publishers.erase(node_string);
00397 
00398         ROS_INFO("Node successfully unsubscribed!");
00399         res.success = true;
00400     }
00401     catch (const std::exception& exc){
00402        ROS_ERROR("OPC-UA client node %s: 'Unsubscribe' service called with node Id: %s parameters failed!", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00403 
00404         res.success = false;
00405         char err_string[100];
00406         sprintf(err_string, "Unsubscribe service failed with exception: %s", exc.what());
00407         res.error_message = err_string;
00408     }
00409     catch (...)
00410     {
00411         ROS_ERROR("OPC-UA client node %s: 'Unsubscribe' service called with node Id: %s parameters failed!", ros::this_node::getName().c_str(), req.node.nodeId.c_str());
00412 
00413         res.success = false;
00414         res.error_message = "Unsubscribe service failed with Unknown exception";
00415     }
00416 
00417     return true;
00418 }
00419 
00423 void on_shutdown(int sig)
00424 {
00425   _client.Disconnect();
00426 
00427   ros::shutdown();
00428 }
00429 
00436 int main (int argc, char** argv)
00437 {
00438     ros::init(argc, argv, "opcua_client_node");
00439     ros::NodeHandle nodeHandle("~");
00440     signal(SIGINT, on_shutdown);
00441 
00442     ros::ServiceServer connect_service = nodeHandle.advertiseService("connect", connect);
00443     ROS_DEBUG("OPC-UA client node %s: 'Connect' service available on on: %s", ros::this_node::getName().c_str(), connect_service.getService().c_str());
00444     ros::ServiceServer disconnect_service = nodeHandle.advertiseService("disconnect", disconnect);
00445     ROS_DEBUG("OPC-UA client node %s: 'Disconnect' service available on: %s", ros::this_node::getName().c_str(), disconnect_service.getService().c_str());
00446 
00447     // List node
00448     ros::ServiceServer list_node_service = nodeHandle.advertiseService("list_node", list_node);
00449     ROS_DEBUG("OPC-UA client node %s: 'ListNode' service available on on: %s", ros::this_node::getName().c_str(), connect_service.getService().c_str());
00450 
00451      // Method Call
00452      ros::ServiceServer call_method_service = nodeHandle.advertiseService("call_method", call_method);
00453      ROS_DEBUG("OPC-UA client node %s: 'CallMethod' service available on: %s", ros::this_node::getName().c_str(), call_method_service.getService().c_str());
00454 
00455     // Reading of data
00456     ros::ServiceServer read_service = nodeHandle.advertiseService("read", read);
00457     ROS_DEBUG("OPC-UA client node %s: 'Read' service available on: %s", ros::this_node::getName().c_str(), read_service.getService().c_str());
00458 
00459     // Writing of data
00460     ros::ServiceServer write_service = nodeHandle.advertiseService("write", write);
00461     ROS_DEBUG("OPC-UA client node %s: 'Write' service available on: %s", ros::this_node::getName().c_str(), write_service.getService().c_str());
00462 
00463     // Subscriptions
00464     ros::ServiceServer subscribe_service = nodeHandle.advertiseService("subscribe", subscribe);
00465     ROS_DEBUG("OPC-UA client node %s: 'Subscribe' service available on: %s", ros::this_node::getName().c_str(), subscribe_service.getService().c_str());
00466     ros::ServiceServer unsubscribe_service = nodeHandle.advertiseService("unsubscribe", unsubscribe);
00467     ROS_DEBUG("OPC-UA client node %s: 'Unsubscribe' service available on: %s", ros::this_node::getName().c_str(), unsubscribe_service.getService().c_str());
00468 
00469 
00470     ROS_INFO("OPCUA client node: %s is ready!", ros::this_node::getName().c_str());
00471 
00472     ros::spin();
00473 
00474     return 0;
00475 }


ros_opcua_impl_freeopcua
Author(s): Denis Štogl
autogenerated on Sat Jun 8 2019 18:24:56