00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <pepperl_fuchs_r2000/http_command_interface.h>
00012 #include <iostream>
00013 #include <boost/asio.hpp>
00014 #include <boost/property_tree/json_parser.hpp>
00015
00016 namespace pepperl_fuchs {
00017
00018
00019 HttpCommandInterface::HttpCommandInterface(const std::string &http_host, int http_port)
00020 {
00021 http_host_ = http_host;
00022 http_port_ = http_port;
00023 http_status_code_ = 0;
00024 }
00025
00026
00027 int HttpCommandInterface::httpGet(const std::string request_path, std::string &header, std::string &content)
00028 {
00029 header = "";
00030 content = "";
00031 using boost::asio::ip::tcp;
00032 try
00033 {
00034 boost::asio::io_service io_service;
00035
00036
00037 tcp::resolver resolver(io_service);
00038 tcp::resolver::query query(http_host_, std::to_string(http_port_));
00039 tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
00040 tcp::resolver::iterator end;
00041
00042
00043 tcp::socket socket(io_service);
00044 boost::system::error_code error = boost::asio::error::host_not_found;
00045
00046
00047 while (error && endpoint_iterator != end)
00048 {
00049 socket.close();
00050 socket.connect(*endpoint_iterator++, error);
00051 }
00052 if (error)
00053 throw boost::system::system_error(error);
00054
00055
00056 boost::asio::streambuf request;
00057 std::ostream request_stream(&request);
00058 request_stream << "GET " << request_path << " HTTP/1.0\r\n\r\n";
00059
00060 boost::asio::write(socket, request);
00061
00062
00063
00064
00065 boost::asio::streambuf response;
00066 boost::asio::read_until(socket, response, "\r\n");
00067
00068
00069 std::istream response_stream(&response);
00070 std::string http_version;
00071 response_stream >> http_version;
00072 unsigned int status_code;
00073 response_stream >> status_code;
00074 std::string status_message;
00075 std::getline(response_stream, status_message);
00076 if (!response_stream || http_version.substr(0, 5) != "HTTP/")
00077 {
00078 std::cout << "Invalid response\n";
00079 return 0;
00080 }
00081
00082
00083 boost::asio::read_until(socket, response, "\r\n\r\n");
00084
00085
00086 std::string tmp;
00087 while (std::getline(response_stream, tmp) && tmp != "\r")
00088 header += tmp+"\n";
00089
00090
00091 while (std::getline(response_stream, tmp))
00092 content += tmp;
00093
00094
00095 while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error))
00096 {
00097 response_stream.clear();
00098 while (std::getline(response_stream, tmp))
00099 content += tmp;
00100 }
00101
00102 if (error != boost::asio::error::eof)
00103 throw boost::system::system_error(error);
00104
00105
00106 for( std::size_t i=0; i<header.size(); i++ )
00107 if( header[i] == '\r' )
00108 header[i] = ' ';
00109
00110 for( std::size_t i=0; i<content.size(); i++ )
00111 if( content[i] == '\r' )
00112 content[i] = ' ';
00113
00114 return status_code;
00115 }
00116 catch (std::exception& e)
00117 {
00118 std::cerr << "Exception: " << e.what() << std::endl;
00119 return 0;
00120 }
00121 }
00122
00123
00124 bool HttpCommandInterface::sendHttpCommand(const std::string cmd, const std::map<std::string, std::string> param_values)
00125 {
00126
00127 std::string request_str = "/cmd/" + cmd + "?";
00128 for( auto& kv : param_values )
00129 request_str += kv.first + "=" + kv.second + "&";
00130 if(request_str.back() == '&' )
00131 request_str = request_str.substr(0,request_str.size()-1);
00132
00133
00134 std::string header, content;
00135 http_status_code_ = httpGet(request_str,header,content);
00136
00137
00138 try
00139 {
00140 std::stringstream ss(content);
00141 boost::property_tree::json_parser::read_json(ss,pt_);
00142 }
00143 catch (std::exception& e)
00144 {
00145 std::cerr << "ERROR: Exception: " << e.what() << std::endl;
00146 return false;
00147 }
00148
00149
00150 if( http_status_code_ != 200 )
00151 return false;
00152 else
00153 return true;
00154 }
00155
00156
00157 bool HttpCommandInterface::sendHttpCommand(const std::string cmd, const std::string param, const std::string value)
00158 {
00159 std::map<std::string, std::string> param_values;
00160 if( param != "" )
00161 param_values[param] = value;
00162 return sendHttpCommand(cmd,param_values);
00163 }
00164
00165
00166 bool HttpCommandInterface::setParameter(const std::string name, const std::string value)
00167 {
00168 return sendHttpCommand("set_parameter",name,value) && checkErrorCode();
00169 }
00170
00171
00172 boost::optional< std::string > HttpCommandInterface::getParameter(const std::string name)
00173 {
00174 if( !sendHttpCommand("get_parameter","list",name) || ! checkErrorCode() )
00175 return boost::optional<std::string>();
00176 return pt_.get_optional<std::string>(name);
00177 }
00178
00179
00180 std::map< std::string, std::string > HttpCommandInterface::getParameters(const std::vector<std::string> &names)
00181 {
00182
00183 std::map< std::string, std::string > key_values;
00184 std::string namelist;
00185 for( const auto& s: names )
00186 namelist += (s + ";");
00187 namelist.substr(0,namelist.size()-1);
00188
00189
00190 if( !sendHttpCommand("get_parameter","list",namelist) || ! checkErrorCode() )
00191 return key_values;
00192
00193
00194 for( const auto& s: names )
00195 {
00196 auto ov = pt_.get_optional<std::string>(s);
00197 if( ov )
00198 key_values[s] = *ov;
00199 else
00200 key_values[s] = "--COULD NOT RETRIEVE VALUE--";
00201 }
00202
00203 return key_values;
00204 }
00205
00206
00207 bool HttpCommandInterface::checkErrorCode()
00208 {
00209
00210 boost::optional<int> error_code = pt_.get_optional<int>("error_code");
00211 boost::optional<std::string> error_text = pt_.get_optional<std::string>("error_text");
00212 if( !error_code || (*error_code) != 0 || !error_text || (*error_text) != "success" )
00213 {
00214 if( error_text )
00215 std::cerr << "ERROR: scanner replied: " << *error_text << std::endl;
00216 return false;
00217 }
00218 return true;
00219 }
00220
00221
00222 boost::optional<ProtocolInfo> HttpCommandInterface::getProtocolInfo()
00223 {
00224
00225 if( !sendHttpCommand("get_protocol_info") || !checkErrorCode() )
00226 return boost::optional<ProtocolInfo>();
00227
00228
00229 boost::optional<std::string> protocol_name = pt_.get_optional<std::string>("protocol_name");
00230 boost::optional<int> version_major = pt_.get_optional<int>("version_major");
00231 boost::optional<int> version_minor = pt_.get_optional<int>("version_minor");
00232 auto ocommands = pt_.get_child_optional("commands");
00233 if( !protocol_name || !version_major || !version_minor || !ocommands )
00234 return boost::optional<ProtocolInfo>();
00235
00236 ProtocolInfo pi;
00237 pi.protocol_name = *protocol_name;
00238 pi.version_major = *version_major;
00239 pi.version_minor = *version_minor;
00240
00241
00242 boost::property_tree::ptree commands = *ocommands;
00243 for( auto i= commands.begin(); i!=commands.end(); i++ )
00244 {
00245 std::string cmd = i->second.get<std::string>("");
00246 pi.commands.push_back(cmd);
00247 }
00248
00249 return pi;
00250 }
00251
00252
00253 std::vector< std::string > HttpCommandInterface::getParameterList()
00254 {
00255
00256 std::vector< std::string > parameter_list;
00257 if( !sendHttpCommand("list_parameters") || !checkErrorCode() )
00258 return parameter_list;
00259
00260
00261 auto oparameters = pt_.get_child_optional("parameters");
00262 if( !oparameters )
00263 return parameter_list;
00264
00265
00266 boost::property_tree::ptree parameters = *oparameters;
00267 for( auto i= parameters.begin(); i!=parameters.end(); i++ )
00268 {
00269 std::string param = i->second.get<std::string>("");
00270 parameter_list.push_back(param);
00271 }
00272
00273 return parameter_list;
00274
00275 }
00276
00277
00278 boost::optional<HandleInfo> HttpCommandInterface::requestHandleTCP(int start_angle)
00279 {
00280
00281 std::map< std::string, std::string > params;
00282 params["packet_type"] = "C";
00283 params["start_angle"] = std::to_string(start_angle);
00284
00285
00286 if( !sendHttpCommand("request_handle_tcp", params) || !checkErrorCode() )
00287 return boost::optional<HandleInfo>();
00288
00289
00290 boost::optional<int> port = pt_.get_optional<int>("port");
00291 boost::optional<std::string> handle = pt_.get_optional<std::string>("handle");
00292 if(!port || !handle)
00293 return boost::optional<HandleInfo>();
00294
00295
00296 HandleInfo hi;
00297 hi.handle_type = HandleInfo::HANDLE_TYPE_TCP;
00298 hi.handle = *handle;
00299 hi.hostname = http_host_;
00300 hi.port = *port;
00301 hi.packet_type = 'C';
00302 hi.start_angle = start_angle;
00303 hi.watchdog_enabled = true;
00304 hi.watchdog_timeout = 60000;
00305 return hi;
00306 }
00307
00308
00309 boost::optional<HandleInfo> HttpCommandInterface::requestHandleUDP(int port, std::string hostname, int start_angle)
00310 {
00311
00312 if( hostname == "" )
00313 hostname = discoverLocalIP();
00314 std::map< std::string, std::string > params;
00315 params["packet_type"] = "C";
00316 params["start_angle"] = std::to_string(start_angle);
00317 params["port"] = std::to_string(port);
00318 params["address"] = hostname;
00319
00320
00321 if( !sendHttpCommand("request_handle_udp", params) || !checkErrorCode() )
00322 return boost::optional<HandleInfo>();
00323
00324
00325 boost::optional<std::string> handle = pt_.get_optional<std::string>("handle");
00326 if(!handle)
00327 return boost::optional<HandleInfo>();
00328
00329
00330 HandleInfo hi;
00331 hi.handle_type = HandleInfo::HANDLE_TYPE_UDP;
00332 hi.handle = *handle;
00333 hi.hostname = hostname;
00334 hi.port = port;
00335 hi.packet_type = 'C';
00336 hi.start_angle = start_angle;
00337 hi.watchdog_enabled = true;
00338 hi.watchdog_timeout = 60000;
00339 return hi;
00340 }
00341
00342
00343 bool HttpCommandInterface::releaseHandle(const std::string& handle)
00344 {
00345 if( !sendHttpCommand("release_handle", "handle", handle) || !checkErrorCode() )
00346 return false;
00347 return true;
00348 }
00349
00350
00351 bool HttpCommandInterface::startScanOutput(const std::string& handle)
00352 {
00353 if( !sendHttpCommand("start_scanoutput", "handle", handle) || !checkErrorCode() )
00354 return false;
00355 return true;
00356 }
00357
00358
00359 bool HttpCommandInterface::stopScanOutput(const std::string& handle)
00360 {
00361 if( !sendHttpCommand("stop_scanoutput", "handle", handle) || !checkErrorCode() )
00362 return false;
00363 return true;
00364 }
00365
00366 bool HttpCommandInterface::feedWatchdog(const std::string &handle)
00367 {
00368 if( !sendHttpCommand("feed_watchdog", "handle", handle) || !checkErrorCode() )
00369 return false;
00370 return true;
00371 }
00372
00373
00374 bool HttpCommandInterface::rebootDevice()
00375 {
00376 if( !sendHttpCommand("reboot_device") || !checkErrorCode() )
00377 return false;
00378 return true;
00379 }
00380
00381
00382 bool HttpCommandInterface::resetParameters(const std::vector<std::string> &names)
00383 {
00384
00385 std::string namelist;
00386 for( const auto& s: names )
00387 namelist += (s + ";");
00388 namelist.substr(0,namelist.size()-1);
00389
00390 if( !sendHttpCommand("reset_parameter","list",namelist) || ! checkErrorCode() )
00391 return false;
00392
00393 return true;
00394 }
00395
00396
00397 std::string HttpCommandInterface::discoverLocalIP()
00398 {
00399 std::string local_ip;
00400 try
00401 {
00402 using boost::asio::ip::udp;
00403 boost::asio::io_service netService;
00404 udp::resolver resolver(netService);
00405 udp::resolver::query query(udp::v4(), http_host_ , "");
00406 udp::resolver::iterator endpoints = resolver.resolve(query);
00407 udp::endpoint ep = *endpoints;
00408 udp::socket socket(netService);
00409 socket.connect(ep);
00410 boost::asio::ip::address addr = socket.local_endpoint().address();
00411 local_ip = addr.to_string();
00412 }
00413 catch (std::exception& e)
00414 {
00415 std::cerr << "Could not deal with socket-exception: " << e.what() << std::endl;
00416 }
00417
00418 return local_ip;
00419 }
00420
00421
00422 }