zeroconf.cpp
Go to the documentation of this file.
00001 
00011 /*****************************************************************************
00012  ** Includes
00013  *****************************************************************************/
00014 
00015 #include <boost/function.hpp>
00016 
00017 #include <ros/ros.h>
00018 #include <zeroconf_msgs/AddListener.h>
00019 #include <zeroconf_msgs/RemoveListener.h>
00020 #include <zeroconf_msgs/AddService.h>
00021 #include <zeroconf_msgs/ListDiscoveredServices.h>
00022 #include <zeroconf_msgs/ListPublishedServices.h>
00023 
00024 #include "../../include/zeroconf_avahi/zeroconf.hpp"
00025 
00026 /*****************************************************************************
00027  ** Namespaces
00028  *****************************************************************************/
00029 
00030 using namespace zeroconf_avahi;
00031 using namespace zeroconf_msgs;
00032 
00033 /*****************************************************************************
00034  ** Interface
00035  *****************************************************************************/
00036 
00043 class ZeroconfNode
00044 {
00045 
00046 private:
00047   typedef boost::function<void(zeroconf_msgs::DiscoveredService)> connection_signal_cb;
00048 
00049 public:
00050   void init(ros::NodeHandle &nh)
00051   {
00052     /*********************
00053      ** Ros Comms
00054      **********************/
00055     server_add_listener = nh.advertiseService("add_listener", &ZeroconfNode::add_listener, this);
00056     server_remove_listener = nh.advertiseService("remove_listener", &ZeroconfNode::remove_listener, this);
00057     server_add_service = nh.advertiseService("add_service", &ZeroconfNode::add_service, this);
00058     server_remove_service = nh.advertiseService("remove_service", &ZeroconfNode::remove_service, this);
00059     server_list_discovered_services = nh.advertiseService("list_discovered_services",
00060                                                           &ZeroconfNode::list_discovered_services, this);
00061     server_list_published_services = nh.advertiseService("list_published_services",
00062                                                          &ZeroconfNode::list_published_services, this);
00063     pub_new_connections = nh.advertise<DiscoveredService>("new_connections", 10);
00064     pub_lost_connections = nh.advertise<DiscoveredService>("lost_connections", 10);
00065 
00066     /*********************
00067      ** Signals
00068      **********************/
00069     // The callback functions use the publishers, so they must come after.
00070     connection_signal_cb new_connection_signal = std::bind1st(std::mem_fun(&ZeroconfNode::new_connections), this);
00071     connection_signal_cb old_connection_signal = std::bind1st(std::mem_fun(&ZeroconfNode::lost_connections), this);
00072     zeroconf.connect_signal_callbacks(new_connection_signal, old_connection_signal);
00073 
00074     /*********************
00075      ** Parameters
00076      **********************/
00077     ros::NodeHandle local_nh("~");
00078     // listeners
00079     XmlRpc::XmlRpcValue value;
00080     XmlRpc::XmlRpcValue::iterator iter;
00081     if (local_nh.getParam("listeners", value))
00082     {
00083       if (value.getType() != XmlRpc::XmlRpcValue::TypeArray)
00084       {
00085         ROS_ERROR_STREAM("Zeroconf: param variable 'listeners' has malformed type, should be of type array");
00086       }
00087       else
00088       {
00089         for (int i = 0; i < value.size(); ++i)
00090         {
00091           zeroconf.add_listener(value[i]);
00092         }
00093       }
00094     }
00095     // services
00096     XmlRpc::XmlRpcValue value_services;
00097     if (local_nh.getParam("services", value_services))
00098     {
00099       if (value_services.getType() != XmlRpc::XmlRpcValue::TypeArray)
00100       {
00101         ROS_ERROR_STREAM("Zeroconf: param variable 'services' has malformed type, should be of type array");
00102       }
00103       else
00104       {
00105         for (int i = 0; i < value_services.size(); ++i)
00106         {
00107           XmlRpc::XmlRpcValue value_service = value_services[i];
00108           if (value_service.getType() != XmlRpc::XmlRpcValue::TypeStruct)
00109           {
00110             ROS_ERROR_STREAM(
00111                 "Zeroconf: " << i << "th element of param variable 'services' has malformed type, should be of type struct");
00112             break;
00113           }
00114           zeroconf_msgs::PublishedService service;
00115           XmlRpc::XmlRpcValue value_name = value_service["name"];
00116           if (value_name.getType() != XmlRpc::XmlRpcValue::TypeString)
00117           {
00118             ROS_ERROR_STREAM("Zeroconf: services[" << i << "]['name'] has malformed type, should be of type string");
00119             break;
00120           }
00121           service.name = std::string(value_name);
00122           if (service.name == "Ros Master")
00123           {
00124             // add some special ros magic to easily identify master's.
00125             service.name = service.name + " (" + ros::master::getHost() + ")";
00126           }
00127           XmlRpc::XmlRpcValue value_type = value_service["type"];
00128           if (value_type.getType() != XmlRpc::XmlRpcValue::TypeString)
00129           {
00130             ROS_ERROR_STREAM("Zeroconf: services[" << i << "]['type'] has malformed type, should be of type string");
00131             break;
00132           }
00133           service.type = std::string(value_type);
00134           XmlRpc::XmlRpcValue value_domain = value_service["domain"];
00135           if (value_domain.getType() != XmlRpc::XmlRpcValue::TypeString)
00136           {
00137             ROS_ERROR_STREAM("Zeroconf: services[" << i << "]['domain'] has malformed type, should be of type string");
00138             break;
00139           }
00140           service.domain = std::string(value_domain);
00141           XmlRpc::XmlRpcValue value_port = value_service["port"];
00142           if (value_port.getType() == XmlRpc::XmlRpcValue::TypeInvalid)
00143           {
00144             service.port = ros::master::getPort();
00145             // wasn't set, so default to ros master's port
00146             ROS_WARN_STREAM(
00147                 "Zeroconf: services[" << service.name << "]['port'] wasn't set, default to ros master's port [" << service.port << "]");
00148           }
00149           else if (value_port.getType() != XmlRpc::XmlRpcValue::TypeInt)
00150           {
00151             ROS_ERROR_STREAM(
00152                 "Zeroconf: services[" << service.name << "]['port'] has malformed type, should be of type int");
00153             break;
00154           }
00155           else
00156           {
00157             service.port = value_port;
00158           }
00159           XmlRpc::XmlRpcValue value_description = value_service["description"];
00160           if (value_description.getType() != XmlRpc::XmlRpcValue::TypeString)
00161           {
00162             service.description = "";
00163           }
00164           else
00165           {
00166             service.description = std::string(value_description);
00167           }
00168           zeroconf.add_service(service);
00169         }
00170       }
00171     }
00172   }
00173 
00174 private:
00175   bool add_listener(AddListener::Request &request, AddListener::Response &response)
00176   {
00177     ROS_DEBUG_STREAM("Zeroconf: serving an add_listener call... [" << request.service_type << "]");
00178     response.result = zeroconf.add_listener(request.service_type);
00179     return true;
00180   }
00181   bool remove_listener(RemoveListener::Request &request, RemoveListener::Response &response)
00182   {
00183     ROS_DEBUG_STREAM("Zeroconf: serving a remove_listener call... [" << request.service_type << "]");
00184     response.result = zeroconf.remove_listener(request.service_type);
00185     return true;
00186   }
00187   bool add_service(AddService::Request &request, AddService::Response &response)
00188   {
00189     response.result = zeroconf.add_service(request.service);
00190     return true;
00191   }
00192   bool remove_service(AddService::Request &request, AddService::Response &response)
00193   {
00194     response.result = zeroconf.remove_service(request.service);
00195     return true;
00196   }
00197   bool list_discovered_services(ListDiscoveredServices::Request &request, ListDiscoveredServices::Response &response)
00198   {
00199     ROS_DEBUG_STREAM("Zeroconf: serving a list_discovered_services call... [" << request.service_type << "]");
00200     zeroconf.list_discovered_services(request.service_type, response.services);
00201     return true;
00202   }
00203   bool list_published_services(ListPublishedServices::Request &request, ListPublishedServices::Response &response)
00204   {
00205     zeroconf.list_published_services(request.service_type, response.services);
00206     return true;
00207   }
00208   void new_connections(DiscoveredService service)
00209   {
00210     pub_new_connections.publish(service);
00211   }
00212   void lost_connections(DiscoveredService service)
00213   {
00214     pub_lost_connections.publish(service);
00215   }
00216 
00217   Zeroconf zeroconf;
00218   ros::ServiceServer server_add_listener, server_remove_listener, server_add_service, server_remove_service;
00219   ros::ServiceServer server_list_discovered_services, server_list_published_services;
00220   ros::Publisher pub_new_connections, pub_lost_connections;
00221 };
00222 
00223 /*****************************************************************************
00224  ** Main
00225  *****************************************************************************/
00226 
00227 int main(int argc, char **argv)
00228 {
00229 
00230   ros::init(argc, argv, "zeroconf");
00231   ros::NodeHandle nh;
00232   ZeroconfNode zeroconf_node;
00233   zeroconf_node.init(nh);
00234   ros::spin();
00235   return 0;
00236 }


zeroconf_avahi
Author(s): Daniel Stonier
autogenerated on Thu Jan 2 2014 12:14:44