Subversion Repositories HomeAutomation

Rev

Rev 1596 | Rev 1598 | 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. #include "type/common.h"
  37.  
  38. namespace atom {
  39. namespace can {
  40.  
  41. enum
  42. {
  43.     PACKET_START = 253,
  44.     PACKET_END   = 250,
  45.     PACKET_PING  = 251
  46. };
  47.    
  48. Network::Network(std::string address): Subscriber(false), LOG("can::Network"), buffer_(2048)
  49. {
  50.     this->address_ = address;
  51.     this->client_id_ = 0;
  52.        
  53.     net::Manager::Instance()->ConnectSlots(net::Client::SignalOnNewState::slot_type(&Network::SlotOnNewState, this, _1, _2, _3).track(this->tracker_),
  54.                                            net::Client::SignalOnNewData::slot_type(&Network::SlotOnNewData, this, _1, _2, _3).track(this->tracker_));
  55.    
  56.     // Examples of address
  57.     // udp:192.168.1.250:1100
  58.     // serial:/dev/ttyUSB0:38400
  59.    
  60.     std::vector<std::string> parts;
  61.     boost::algorithm::split(parts, address, boost::is_any_of(":"), boost::algorithm::token_compress_off);
  62.    
  63.     if (parts.size() < 3)
  64.     {
  65.         LOG.Error("Malformed address string: " + address);
  66.         return;
  67.     }
  68.    
  69.     boost::algorithm::to_lower(parts[0]);
  70.    
  71.     if (parts[0] == "udp")
  72.     {
  73.         this->protocol_ = net::PROTOCOL_UDP;
  74.     }
  75.     else if (parts[0] == "serial")
  76.     {
  77.         this->protocol_ = net::PROTOCOL_SERIAL;
  78.     }
  79.     else
  80.     {
  81.         LOG.Error("Unknown protocol, only support udp and serial, got " + parts[0]);
  82.         return;
  83.     }
  84.    
  85.     this->address_ = parts[1];
  86.     this->port_or_baud_ = boost::lexical_cast<unsigned int>(parts[2]);
  87.    
  88.     try
  89.     {
  90.         this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
  91.         LOG.Info("Connected to " + address);
  92.        
  93.         LOG.Info("Sending ping.");
  94.         type::Byteset buffer(1);
  95.        
  96.         buffer[0] = PACKET_PING;
  97.        
  98.         net::Manager::Instance()->SendTo(this->client_id_, buffer);
  99.     }
  100.     catch (std::exception e)
  101.     {
  102.         LOG.Error(e.what());
  103.     }
  104. }
  105.  
  106. Network::~Network()
  107. {
  108.     net::Manager::Instance()->Disconnect(this->client_id_);
  109. }
  110.  
  111. void Network::SlotOnNewData(net::ClientId client_id, net::ServerId server_id, type::Byteset data)
  112. {
  113.     if (client_id == this->client_id_)
  114.     {
  115.         type::Byteset temp_buffer = data;
  116.         this->io_service_.post(boost::bind(&Network::SlotOnNewDataHandler, this, client_id, server_id, temp_buffer));
  117.     }
  118. }
  119.  
  120. void Network::SlotOnNewState(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
  121. {
  122.     if (client_id == this->client_id_)
  123.     {
  124.         this->io_service_.post(boost::bind(&Network::SlotOnNewStateHandler, this, client_id, server_id, client_state));
  125.     }
  126. }
  127.  
  128. void Network::SlotOnTimeout(timer::TimerId timer_id)
  129. {
  130.     if (timer_id == this->timer_id_)
  131.     {
  132.         this->io_service_.post(boost::bind(&Network::SlotOnTimeoutHandler, this, timer_id));
  133.     }
  134. }
  135.  
  136. void Network::SlotOnMessageHandler(broker::Message::Pointer message)
  137. {
  138.     if (message->GetType() == broker::Message::CAN_MESSAGE)
  139.     {
  140.         Message* payload = static_cast<Message*>(message->GetPayload().get());
  141.        
  142.        
  143.        
  144.     }
  145. }
  146.  
  147. void Network::SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, type::Byteset data)
  148. {
  149.     static bool have_start = false;
  150.    
  151.     for (unsigned int n = 0; n < data.GetSize(); n++)
  152.     {
  153.         if (have_start)
  154.         {
  155.             if (data[n] == PACKET_END && this->buffer_.GetSize() == 15)
  156.             {
  157.                 //LOG.Debug("Received packet end and size is 15.");
  158.                 this->ProcessBuffer();
  159.                 have_start = false;
  160.             }
  161.             else
  162.             {
  163.                 this->buffer_.Append(data[n]);
  164.             }
  165.         }
  166.         else if (data[n] == PACKET_START)
  167.         {
  168.             //LOG.Debug("Received packet start.");
  169.             this->buffer_.Clear();
  170.             have_start = true;
  171.         }
  172.         else if (data[n] == PACKET_PING)
  173.         {
  174.             LOG.Info("Received pong.");
  175.         }
  176.     }
  177. }
  178.  
  179. void Network::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
  180. {
  181.     if (client_state == net::CLIENT_STATE_DISCONNECTED)
  182.     {
  183.         LOG.Warning("Got disconnected, setting reconnect timer...");
  184.        
  185.         this->timer_id_ = timer::Manager::Instance()->Set(10000, true);
  186.         this->client_id_ = 0;
  187.     }
  188.     else
  189.     {
  190.         LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
  191.     }
  192. }
  193.  
  194. void Network::SlotOnTimeoutHandler(timer::TimerId timer_id)
  195. {
  196.     try
  197.     {
  198.         this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
  199.         LOG.Info("Connected again.");
  200.        
  201.         timer::Manager::Instance()->Cancel(timer_id);
  202.         this->timer_id_ = 0;
  203.     }
  204.     catch (std::exception e)
  205.     {
  206.         LOG.Error(e.what());
  207.         LOG.Warning("Will try again soon...");
  208.     }
  209. }
  210.  
  211. void Network::ProcessBuffer()
  212. {
  213.     try
  214.     {
  215.         std::string class_name = "";
  216.         std::string direction_name = "";
  217.         std::string module_name = "";
  218.         unsigned int id = 0;
  219.         std::string command_name = "";
  220.        
  221.         unsigned int class_id = (this->buffer_[3] >> 1) & 0x0F;
  222.        
  223.         //LOG.Debug("class_id=" + boost::lexical_cast<std::string>(class_id) + ", byte[3] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[3]));
  224.        
  225.         class_name = Protocol::Instance()->LookupClassName(class_id);
  226.        
  227.         //LOG.Debug("class_name=" + class_name);
  228.        
  229.         if (class_name == "nmt")
  230.         {
  231.             unsigned int command_id = this->buffer_[2];
  232.             //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id) + ", byte[2] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[2]));
  233.            
  234.             command_name = Protocol::Instance()->LookupNMTCommandName(command_id);
  235.             //LOG.Debug("command_name=" + command_name);
  236.         }
  237.         else
  238.         {
  239.             unsigned int direction_flag = this->buffer_[3] & 0x01;
  240.             //LOG.Debug("direction_flag=" + boost::lexical_cast<std::string>(direction_flag) + ", byte[3] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[3]));
  241.            
  242.             direction_name = Protocol::Instance()->LookupDirectionFlag(direction_flag);
  243.             //LOG.Debug("direction_name=" + direction_name);
  244.            
  245.             unsigned int module_id = this->buffer_[2];
  246.             //LOG.Debug("module_id=" + boost::lexical_cast<std::string>(module_id) + ", byte[2] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[2]));
  247.            
  248.             module_name = Protocol::Instance()->LookupModuleName(module_id);
  249.             //LOG.Debug("module_name=" + module_name);
  250.            
  251.             id = this->buffer_[1];
  252.             //LOG.Debug("id=" + boost::lexical_cast<std::string>(id) + ", byte[1] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[1]));
  253.            
  254.             unsigned int command_id = this->buffer_[0];
  255.             //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id) + ", byte[0] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[0]));
  256.            
  257.             command_name = Protocol::Instance()->LookupCommandName(command_id, module_name);
  258.             //LOG.Debug("command_name=" + command_name);
  259.         }
  260.  
  261.         Message* payload = new Message(class_name, direction_name, module_name, id, command_name);
  262.  
  263.         unsigned int length = this->buffer_[6];
  264.         //LOG.Debug("Data length = " + boost::lexical_cast<std::string>(length));
  265.        
  266.         type::Byteset data_set(length);
  267.        
  268.         for (unsigned int n = 0; n < length; n++)
  269.         {
  270.             //LOG.Debug("add byte[" + boost::lexical_cast<std::string>(n + 7) + "] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[n + 7]));
  271.             data_set.Append(this->buffer_[n + 7]);
  272.         }
  273.         /*
  274.         for (unsigned int n = 0; n < data_set.GetSize(); n++)
  275.         {
  276.             LOG.Debug("byte[" + boost::lexical_cast<std::string>(n) + "] = " + boost::lexical_cast<std::string>((unsigned int)data_set[n]));
  277.         }
  278.         */
  279.         type::Bitset databits(data_set);
  280.        
  281.         /*
  282.         std::string temp = "";
  283.         std::string temp2 = "";
  284.         for (unsigned int n = 0; n < databits.GetCount(); n ++)
  285.         {
  286.            
  287.             temp2 += boost::lexical_cast<std::string>((unsigned int)databits.bytes_[n/8]);
  288.             temp += boost::lexical_cast<std::string>(databits.Get(n));
  289.         }
  290.        
  291.         LOG.Debug("databits1 = " + temp);
  292.         LOG.Debug("databits2 = " + temp2);*/
  293.        
  294.         xml::Node::NodeList variable_nodes;
  295.        
  296.         if (class_name == "nmt")
  297.         {
  298.             variable_nodes = Protocol::Instance()->GetNMTCommandVariables(command_name);
  299.         }
  300.         else
  301.         {
  302.             variable_nodes = Protocol::Instance()->GetCommandVariables(command_name, module_name);
  303.         }
  304.        
  305.         for (unsigned int n = 0; n < variable_nodes.size(); n++)
  306.         {
  307.             unsigned int start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
  308.             unsigned int bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
  309.             std::string type = variable_nodes[n].GetAttributeValue("type");
  310.            
  311.             //LOG.Debug("name=" + variable_nodes[n].GetAttributeValue("name"));
  312.             //LOG.Debug("type=" + type);
  313.            
  314.             std::string value = "";
  315.            
  316.             if (type == "int")
  317.             {
  318.                 unsigned long raw_bit_value = databits.Read(start_bit, bit_length);
  319.                 int raw_value = 0;
  320.                
  321.                 memcpy(&raw_value, &raw_bit_value, sizeof(raw_value));
  322.                 value = boost::lexical_cast<std::string>(raw_value);
  323.             }
  324.             else if (type == "float")
  325.             {
  326.                 float raw_value = 0;
  327.                 bool negative = false;;
  328.                
  329.                 if (databits.Get(start_bit))
  330.                 {
  331.                     negative = true;
  332.                 }
  333.                
  334.                 for (int c = bit_length-1; c > 0; c--)
  335.                 {
  336.                     if (databits.Get(start_bit + c) != negative)
  337.                     {
  338.                         raw_value += pow(2.0f, (int)(bit_length-1-c));
  339.                     }
  340.                 }
  341.                
  342.                 raw_value /= 64.0f;
  343.                
  344.                 if (negative)
  345.                 {
  346.                     raw_value = -raw_value;
  347.                 }
  348.                
  349.                 value = boost::lexical_cast<std::string>(raw_value);
  350.                 //LOG.Debug("float:value="+value);
  351.             }
  352.             else if (type == "ascii")
  353.             {
  354.                 char c = 0;
  355.                
  356.                 for (unsigned int p = 0; p < bit_length; p += 8)
  357.                 {
  358.                     unsigned long raw_bit_value = databits.Read(start_bit + p, 8);
  359.                     memcpy(&c, &raw_bit_value, sizeof(c));
  360.                     value += c;
  361.                 }
  362.             }
  363.             else if (type == "hexstring")
  364.             {
  365.                 for (unsigned int p = 0; p < bit_length; p += 4)
  366.                 {
  367.                     unsigned long raw_bit_value = databits.Read(start_bit + p, 4);
  368.                    
  369.                     //value += boost::lexical_cast<std::string>(raw_bit_value);
  370.                 }
  371.             }
  372.             else if (type == "enum")
  373.             {
  374.                 value = boost::lexical_cast<std::string>(databits.Read(start_bit, bit_length));
  375.                 value = variable_nodes[n].SelectChild("id", value).GetAttributeValue("name");
  376.             }
  377.             else// if (type == "uint")
  378.             {
  379.                 unsigned long raw_bit_value = databits.Read(start_bit, bit_length);
  380.                 unsigned int raw_value = 0;
  381.                
  382.                 memcpy(&raw_value, &raw_bit_value, sizeof(raw_value));
  383.                 value = boost::lexical_cast<std::string>(raw_value);
  384.             }
  385.            
  386.             //LOG.Debug("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ",bit_length=" + boost::lexical_cast<std::string>(bit_length));
  387.            
  388.             payload->SetVariable(variable_nodes[n].GetAttributeValue("name"), value);
  389.             //LOG.Debug("Variable:" + variable_nodes[n].GetAttributeValue("name") + " = " + value);
  390.         }
  391.        
  392.         broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
  393.     }
  394.     catch (std::runtime_error& e)
  395.     {
  396.         std::string bytestring;
  397.        
  398.         for (unsigned int n = 0; n < this->buffer_.GetSize(); n++)
  399.         {
  400.             bytestring += boost::lexical_cast<std::string>((unsigned int)this->buffer_[n]) + ",";
  401.         }
  402.        
  403.         LOG.Debug("Bytes: " + bytestring);
  404.        
  405.         LOG.Error("Malformed message received, " + std::string(e.what()));
  406.     }
  407.    
  408.     this->buffer_.Clear();
  409. }
  410.    
  411. }; // namespace can
  412. }; // namespace atom
  413.