Subversion Repositories HomeAutomation

Rev

Rev 1595 | Rev 1597 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  *
  3.  *  Copyright (C) 2010  Mattias Runge
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License along
  16.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  17.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18.  *
  19.  */
  20.  
  21. #include "Network.h"
  22.  
  23. #include <vector>
  24.  
  25. #include <boost/algorithm/string.hpp>
  26. #include <boost/lexical_cast.hpp>
  27.  
  28. #include "net/Manager.h"
  29.  
  30. #include "broker/Manager.h"
  31.  
  32. #include "Protocol.h"
  33. #include "Message.h"
  34.  
  35. #include "type/Bitset.h"
  36.  
  37. namespace atom {
  38. namespace can {
  39.  
  40. enum
  41. {
  42.     PACKET_START = 253,
  43.     PACKET_END   = 250,
  44.     PACKET_PING  = 251
  45. };
  46.    
  47. Network::Network(std::string address): Subscriber(false), LOG("can::Network"), buffer_(2048)
  48. {
  49.     this->address_ = address;
  50.     this->client_id_ = 0;
  51.        
  52.     net::Manager::Instance()->ConnectSlots(net::Client::SignalOnNewState::slot_type(&Network::SlotOnNewState, this, _1, _2, _3).track(this->tracker_),
  53.                                            net::Client::SignalOnNewData::slot_type(&Network::SlotOnNewData, this, _1, _2, _3).track(this->tracker_));
  54.    
  55.     // Examples of address
  56.     // udp:192.168.1.250:1100
  57.     // serial:/dev/ttyUSB0:38400
  58.    
  59.     std::vector<std::string> parts;
  60.     boost::algorithm::split(parts, address, boost::is_any_of(":"), boost::algorithm::token_compress_off);
  61.    
  62.     if (parts.size() < 3)
  63.     {
  64.         LOG.Error("Malformed address string: " + address);
  65.         return;
  66.     }
  67.    
  68.     boost::algorithm::to_lower(parts[0]);
  69.    
  70.     if (parts[0] == "udp")
  71.     {
  72.         this->protocol_ = net::PROTOCOL_UDP;
  73.     }
  74.     else if (parts[0] == "serial")
  75.     {
  76.         this->protocol_ = net::PROTOCOL_SERIAL;
  77.     }
  78.     else
  79.     {
  80.         LOG.Error("Unknown protocol, only support udp and serial, got " + parts[0]);
  81.         return;
  82.     }
  83.    
  84.     this->address_ = parts[1];
  85.     this->port_or_baud_ = boost::lexical_cast<unsigned int>(parts[2]);
  86.    
  87.     try
  88.     {
  89.         this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
  90.         LOG.Info("Connected to " + address);
  91.        
  92.         LOG.Info("Sending ping.");
  93.         type::Byteset buffer(1);
  94.        
  95.         buffer[0] = PACKET_PING;
  96.        
  97.         net::Manager::Instance()->SendTo(this->client_id_, buffer);
  98.     }
  99.     catch (std::exception e)
  100.     {
  101.         LOG.Error(e.what());
  102.     }
  103. }
  104.  
  105. Network::~Network()
  106. {
  107.     net::Manager::Instance()->Disconnect(this->client_id_);
  108. }
  109.  
  110. void Network::SlotOnNewData(net::ClientId client_id, net::ServerId server_id, type::Byteset data)
  111. {
  112.     if (client_id == this->client_id_)
  113.     {
  114.         type::Byteset temp_buffer = data;
  115.         this->io_service_.post(boost::bind(&Network::SlotOnNewDataHandler, this, client_id, server_id, temp_buffer));
  116.     }
  117. }
  118.  
  119. void Network::SlotOnNewState(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
  120. {
  121.     if (client_id == this->client_id_)
  122.     {
  123.         this->io_service_.post(boost::bind(&Network::SlotOnNewStateHandler, this, client_id, server_id, client_state));
  124.     }
  125. }
  126.  
  127. void Network::SlotOnTimeout(timer::TimerId timer_id)
  128. {
  129.     if (timer_id == this->timer_id_)
  130.     {
  131.         this->io_service_.post(boost::bind(&Network::SlotOnTimeoutHandler, this, timer_id));
  132.     }
  133. }
  134.  
  135. void Network::SlotOnMessageHandler(broker::Message::Pointer message)
  136. {
  137.     if (message->GetType() == broker::Message::CAN_MESSAGE)
  138.     {
  139.         Message* payload = static_cast<Message*>(message->GetPayload().get());
  140.        
  141.        
  142.        
  143.     }
  144. }
  145.  
  146. void Network::SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, type::Byteset data)
  147. {
  148.     static bool have_start = false;
  149.    
  150.     for (unsigned int n = 0; n < data.GetSize(); n++)
  151.     {
  152.         if (have_start)
  153.         {
  154.             if (data[n] == PACKET_END && this->buffer_.GetSize() == 15)
  155.             {
  156.                 //LOG.Debug("Received packet end and size is 15.");
  157.                 this->ProcessBuffer();
  158.                 have_start = false;
  159.             }
  160.             else
  161.             {
  162.                 this->buffer_.Append(data[n]);
  163.             }
  164.         }
  165.         else if (data[n] == PACKET_START)
  166.         {
  167.             //LOG.Debug("Received packet start.");
  168.             this->buffer_.Clear();
  169.             have_start = true;
  170.         }
  171.         else if (data[n] == PACKET_PING)
  172.         {
  173.             LOG.Info("Received pong.");
  174.         }
  175.     }
  176. }
  177.  
  178. void Network::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
  179. {
  180.     if (client_state == net::CLIENT_STATE_DISCONNECTED)
  181.     {
  182.         LOG.Warning("Got disconnected, setting reconnect timer...");
  183.        
  184.         this->timer_id_ = timer::Manager::Instance()->Set(10000, true);
  185.         this->client_id_ = 0;
  186.     }
  187.     else
  188.     {
  189.         LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
  190.     }
  191. }
  192.  
  193. void Network::SlotOnTimeoutHandler(timer::TimerId timer_id)
  194. {
  195.     try
  196.     {
  197.         this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
  198.         LOG.Info("Connected again.");
  199.        
  200.         timer::Manager::Instance()->Cancel(timer_id);
  201.         this->timer_id_ = 0;
  202.     }
  203.     catch (std::exception e)
  204.     {
  205.         LOG.Error(e.what());
  206.         LOG.Warning("Will try again soon...");
  207.     }
  208. }
  209.  
  210. void Network::ProcessBuffer()
  211. {
  212.     try
  213.     {
  214.         std::string class_name = "";
  215.         std::string direction_name = "";
  216.         std::string module_name = "";
  217.         unsigned int id = 0;
  218.         std::string command_name = "";
  219.        
  220.         unsigned int class_id = (this->buffer_[3] >> 1) & 0x0F;
  221.        
  222.         //LOG.Debug("class_id=" + boost::lexical_cast<std::string>(class_id) + ", byte[3] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[3]));
  223.        
  224.         class_name = Protocol::Instance()->LookupClassName(class_id);
  225.        
  226.         //LOG.Debug("class_name=" + class_name);
  227.        
  228.         if (class_name == "nmt")
  229.         {
  230.             unsigned int command_id = this->buffer_[2];
  231.             //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id) + ", byte[2] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[2]));
  232.            
  233.             command_name = Protocol::Instance()->LookupNMTCommandName(command_id);
  234.             //LOG.Debug("command_name=" + command_name);
  235.         }
  236.         else
  237.         {
  238.             unsigned int direction_flag = this->buffer_[3] & 0x01;
  239.             //LOG.Debug("direction_flag=" + boost::lexical_cast<std::string>(direction_flag) + ", byte[3] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[3]));
  240.            
  241.             direction_name = Protocol::Instance()->LookupDirectionFlag(direction_flag);
  242.             //LOG.Debug("direction_name=" + direction_name);
  243.            
  244.             unsigned int module_id = this->buffer_[2];
  245.             //LOG.Debug("module_id=" + boost::lexical_cast<std::string>(module_id) + ", byte[2] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[2]));
  246.            
  247.             module_name = Protocol::Instance()->LookupModuleName(module_id);
  248.             //LOG.Debug("module_name=" + module_name);
  249.            
  250.             id = this->buffer_[1];
  251.             //LOG.Debug("id=" + boost::lexical_cast<std::string>(id) + ", byte[1] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[1]));
  252.            
  253.             unsigned int command_id = this->buffer_[0];
  254.             //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id) + ", byte[0] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[0]));
  255.            
  256.             command_name = Protocol::Instance()->LookupCommandName(command_id, module_name);
  257.             //LOG.Debug("command_name=" + command_name);
  258.         }
  259.  
  260.         Message* payload = new Message(class_name, direction_name, module_name, id, command_name);
  261.  
  262.         unsigned int length = this->buffer_[6];
  263.         //LOG.Debug("Data length = " + boost::lexical_cast<std::string>(length));
  264.        
  265.         type::Byteset data_set(length);
  266.        
  267.         for (unsigned int n = 0; n < length; n++)
  268.         {
  269.             //LOG.Debug("add byte[" + boost::lexical_cast<std::string>(n + 7) + "] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[n + 7]));
  270.             data_set.Append(this->buffer_[n + 7]);
  271.         }
  272.        
  273.         /*for (unsigned int n = 0; n < this->buffer_.GetSize(); n++)
  274.         {
  275.             LOG.Debug("byte[" + boost::lexical_cast<std::string>(n) + "] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[n]));
  276.         }*/
  277.        
  278.         type::Bitset databits(data_set);
  279.        
  280.        
  281.         std::string temp = "";
  282.         for (unsigned int n = 0; n < databits.GetCount(); n ++)
  283.         {
  284.             temp += boost::lexical_cast<std::string>(databits.Get(n));
  285.         }
  286.        
  287.         //LOG.Debug("databits = " + temp);
  288.        
  289.         xml::Node::NodeList variable_nodes;
  290.        
  291.         if (class_name == "nmt")
  292.         {
  293.             variable_nodes = Protocol::Instance()->GetNMTCommandVariables(command_name);
  294.         }
  295.         else
  296.         {
  297.             variable_nodes = Protocol::Instance()->GetCommandVariables(command_name, module_name);
  298.         }
  299.        
  300.         for (unsigned int n = 0; n < variable_nodes.size(); n++)
  301.         {
  302.             unsigned int start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
  303.             unsigned int bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
  304.             std::string type = variable_nodes[n].GetAttributeValue("type");
  305.            
  306.             std::string value = boost::lexical_cast<std::string>(databits.Read(start_bit, bit_length));
  307.  
  308.             if (type == "enum")
  309.             {
  310.                 value = variable_nodes[n].SelectChild("id", value).GetAttributeValue("name");
  311.             }
  312.            
  313.             // TODO handle all datatypes!
  314.            
  315.             //LOG.Debug("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ",bit_length=" + boost::lexical_cast<std::string>(bit_length));
  316.            
  317.             payload->SetVariable(variable_nodes[n].GetAttributeValue("name"), value);
  318.             //LOG.Debug("Variable:" + variable_nodes[n].GetAttributeValue("name") + " = " + value);
  319.         }
  320.        
  321.         broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
  322.     }
  323.     catch (std::runtime_error& e)
  324.     {
  325.         LOG.Error("Malformed message received, " + std::string(e.what()));
  326.     }
  327.    
  328.     this->buffer_.Clear();
  329. }
  330.    
  331. }; // namespace can
  332. }; // namespace atom
  333.