Note: Goby version 1 (shown here) is now considered obsolete. Please use version 2 for new projects, and consider upgrading old projects.

Goby Underwater Autonomy Project  Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
acomms/libmodemdriver/tools/abc_modem_simulator/abc_modem_simulator.cpp
00001 // copyright 2009 t. schneider tes@mit.edu
00002 //
00003 // This program is free software: you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation, either version 3 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This software is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this software.  If not, see <http://www.gnu.org/licenses/>.
00015 
00016 //
00017 // Usage:
00018 // 1. run abc_modem_simulator running on same port (as TCP server)
00019 // > abc_modem_simulator 54321
00020 // 2. create fake tty terminals connected to TCP as client to port 54321
00021 // > socat -d -d -v pty,raw,echo=0,link=/tmp/ttyFAKE1 TCP:localhost:54321
00022 // > socat -d -d -v pty,raw,echo=0,link=/tmp/ttyFAKE2 TCP:localhost:54321
00023 // > ...
00024 // 3. run your application connecting to /tmp/ttyFAKE1, /tmp/ttyFAKE2, etc. They will all act in the same "broadcast" pool
00025 
00026 #include <map>
00027 #include <string>
00028 
00029 #include "goby/util/linebasedcomms.h"
00030 #include "goby/util/string.h"
00031 #include "goby/acomms/acomms_constants.h" // for BROADCAST_ID
00032 
00033 std::map<int, std::string> modem_id2endpoint;
00034 
00035 void parse_in(const std::string& in, std::map<std::string, std::string>* out);
00036 
00037 int main(int argc, char* argv[])
00038 {
00039     if(argc < 2)
00040     {
00041         std::cout << "usage: abc_modem_simulator [tcp listen port]" << std::endl;
00042         exit(1);    
00043     }
00044 
00045     goby::util::TCPServer server(goby::util::as<unsigned>(argv[1]));
00046 
00047     server.start();
00048     while(server.active())
00049     {
00050         goby::util::protobuf::Datagram in;
00051         while(server.readline(&in))
00052         {
00053             // clear off \r\n and other whitespace at ends
00054             boost::trim(*in.mutable_data());
00055 
00056             std::cout << "Received: " << in.ShortDebugString() << std::endl;
00057             
00058             std::map<std::string, std::string> parsed;
00059             try
00060             {
00061                 parse_in(in.data(), &parsed);
00062                 if(parsed["KEY"] == "CONF")
00063                 {
00064                     std::cout << "Got configuration: " << in.data() << std::endl;
00065 
00066                     // register a modem id
00067                     if(parsed.count("MAC"))
00068                     {
00069                         int mac = goby::util::as<int>(parsed["MAC"]);
00070                         std::cout << "Set MAC address " << mac << " for endpoint " << in.src() << std::endl;
00071                         modem_id2endpoint[mac] = in.src();
00072                     }
00073                 }
00074                 else if(parsed["KEY"] == "SEND")
00075                 {
00076 
00077                     std::cout << "Got send: " << in.data() << std::endl;
00078                     
00079                     goby::util::protobuf::Datagram out;        
00080                     out.set_src(server.local_endpoint());
00081 
00082                     if(!parsed.count("HEX"))
00083                         throw(std::runtime_error("No DATA in SEND message"));
00084 
00085                     if(!parsed.count("FROM"))
00086                         throw(std::runtime_error("No FROM in SEND message"));
00087                     
00088                     if(!parsed.count("BITRATE"))
00089                         throw(std::runtime_error("No BITRATE in SEND message"));
00090                     
00091 
00092                     int src = goby::util::as<int>(parsed["FROM"]);
00093                     
00094                     if(parsed.count("TO"))
00095                     {
00096                         int dest = goby::util::as<int>(parsed["TO"]);
00097                         
00098                         std::stringstream out_ss;
00099                         out_ss << "RECV,FROM:" << src
00100                                << ",TO:" << dest
00101                                << ",HEX:" << parsed["HEX"]
00102                                << ",BITRATE:" << parsed["BITRATE"] << "\r\n";
00103                         out.set_data(out_ss.str());
00104                         
00105                         if(dest == goby::acomms::BROADCAST_ID)
00106                         {                            
00107                             typedef std::map<int, std::string>::const_iterator const_iterator;
00108                             for(const_iterator it = modem_id2endpoint.begin(), n =  modem_id2endpoint.end(); it !=n; ++it)
00109                             {
00110                                 // do not send it back to the originator
00111                                 if(it->first != src)
00112                                 {
00113                                     out.set_dest(it->second);
00114                                     std::cout << "Sending: " << out.ShortDebugString() << std::endl;
00115                                     server.write(out);
00116                                 }
00117                             }
00118                         }
00119                         else
00120                         {
00121                             if(!modem_id2endpoint.count(dest))
00122                                 throw(std::runtime_error("Unknown destination ID " + goby::util::as<std::string>(dest)));
00123 
00124                             out.set_dest(modem_id2endpoint[dest]);
00125                             std::cout << "Sending: " << out.ShortDebugString() << std::endl;
00126                             server.write(out);
00127 
00128                             if(parsed.count("ACK") && goby::util::as<bool>(parsed["ACK"]))
00129                             {
00130                                 out.set_dest(in.src());
00131                                 
00132                                 std::stringstream out_ss;
00133                                 out_ss << "ACKN,FROM:" << dest
00134                                        << ",TO:" << src << "\r\n";
00135                                 out.set_data(out_ss.str());
00136                                 std::cout << "Sending: " << out.ShortDebugString() << std::endl;
00137 
00138                                 server.write(out);
00139                             }
00140                         }
00141                         
00142                     }
00143                     else 
00144                         throw(std::runtime_error("No TO in SEND message"));
00145 
00146                 } 
00147             }
00148             catch(std::exception& e)
00149             {
00150                 std::cout << "Invalid line from modem: " << in.data() << std::endl;
00151                 std::cout << "Why: " << e.what() << std::endl;
00152             }
00153         }
00154         
00155         usleep(1000);
00156     }
00157 
00158     std::cout << "server failed..." << std::endl;
00159     exit(1);
00160 }
00161 
00162 
00163 void parse_in(const std::string& in, std::map<std::string, std::string>* out)
00164 {
00165     std::vector<std::string> comma_split;
00166     boost::split(comma_split, in, boost::is_any_of(","));
00167     out->insert(std::make_pair("KEY", comma_split.at(0)));
00168     for(int i = 1, n = comma_split.size(); i < n; ++i)
00169     {
00170         std::vector<std::string> colon_split;
00171         boost::split(colon_split, comma_split[i],
00172                      boost::is_any_of(":"));
00173         out->insert(std::make_pair(colon_split.at(0),
00174                                    colon_split.at(1)));
00175     }
00176 }
00177 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends