Subversion Repositories HomeAutomation

Rev

Rev 1959 | Rev 1987 | 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 "common/Bitset.h"
  36. #include "common/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): broker::Subscriber(false), buffer_(2048), LOG("can::Network")
  49. {
  50.     this->address_ = address;
  51.     this->client_id_ = 0;
  52.        
  53.     // Examples of address
  54.     // udp:192.168.1.250:1100
  55.     // serial:/dev/ttyUSB0:38400
  56.    
  57.     common::StringList parts;
  58.     boost::algorithm::split(parts, address, boost::is_any_of(":"), boost::algorithm::token_compress_off);
  59.    
  60.     if (parts.size() < 3)
  61.     {
  62.         LOG.Error("Malformed address string: " + address);
  63.         return;
  64.     }
  65.    
  66.     boost::algorithm::to_lower(parts[0]);
  67.    
  68.     if (parts[0] == "udp")
  69.     {
  70.         this->protocol_ = net::PROTOCOL_UDP;
  71.     }
  72.     else if (parts[0] == "serial")
  73.     {
  74.         this->protocol_ = net::PROTOCOL_SERIAL;
  75.     }
  76.     else
  77.     {
  78.         LOG.Error("Unknown protocol, only support udp and serial, got " + parts[0]);
  79.         return;
  80.     }
  81.    
  82.     this->address_ = parts[1];
  83.     this->port_or_baud_ = boost::lexical_cast<unsigned int>(parts[2]);
  84.    
  85.     try
  86.     {
  87.         this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
  88.         LOG.Info("Connected to " + address);
  89.        
  90.         LOG.Info("Sending ping...");
  91.  
  92.         common::Byteset buffer(1);
  93.         buffer[0] = PACKET_PING;
  94.        
  95.         net::Manager::Instance()->SendTo(this->client_id_, buffer);
  96.     }
  97.     catch (std::runtime_error& e)
  98.     {
  99.         LOG.Error(e.what());
  100.     }
  101. }
  102.  
  103. Network::~Network()
  104. {
  105.     net::Manager::Instance()->Disconnect(this->client_id_);
  106. }
  107.  
  108. void Network::SlotOnTimeout(timer::TimerId timer_id)
  109. {
  110.     if (timer_id == this->timer_id_)
  111.     {
  112.         this->io_service_.post(boost::bind(&Network::SlotOnTimeoutHandler, this, timer_id));
  113.     }
  114. }
  115.  
  116. void Network::SlotOnMessageHandler(broker::Message::Pointer message)
  117. {
  118.     if (message->GetType() == broker::Message::CAN_MESSAGE)
  119.     {
  120.         Message* payload = static_cast<Message*>(message->GetPayload().get());
  121.         common::Byteset data(17);
  122.        
  123.         data[0] = PACKET_START;
  124.        
  125.         unsigned int class_id = Protocol::Instance()->ResolveClassId(payload->GetClassName());
  126.         data[4] = class_id << 1;
  127.  
  128.         if (payload->GetClassName() == "nmt")
  129.         {
  130.             unsigned int command_id = Protocol::Instance()->ResolveNMTCommandId(payload->GetCommandName());
  131.             data[3] = command_id;
  132.         }
  133.         else
  134.         {
  135.             unsigned int direction_flag = Protocol::Instance()->ResolveDirectionFlag(payload->GetDirectionName());
  136.             data[4] |= (direction_flag & 0x01);
  137.            
  138.             unsigned int module_id = Protocol::Instance()->ResolveModuleId(payload->GetModuleName());
  139.             data[3] = module_id;
  140.            
  141.             data[2] = payload->GetId();
  142.            
  143.             unsigned int command_id = Protocol::Instance()->ResolveCommandId(payload->GetCommandName(), payload->GetModuleName());
  144.             data[1] = command_id;
  145.         }
  146.        
  147.         unsigned int highest_bit = 0;
  148.         common::Bitset databits(64);
  149.        
  150.         xml::Node::NodeList variable_nodes;
  151.         unsigned int start_bit;
  152.         unsigned int bit_length;
  153.         std::string type;
  154.         std::string value;
  155.        
  156.         if (payload->GetClassName() == "nmt")
  157.         {
  158.             variable_nodes = Protocol::Instance()->GetNMTCommandVariables(payload->GetCommandName());
  159.         }
  160.         else
  161.         {
  162.             variable_nodes = Protocol::Instance()->GetCommandVariables(payload->GetCommandName(), payload->GetModuleName());
  163.         }
  164.        
  165.         for (unsigned int n = 0; n < variable_nodes.size(); n++)
  166.         {
  167.             value = payload->GetVariable(variable_nodes[n].GetAttributeValue("name"));
  168.             //LOG.Debug(variable_nodes[n].GetAttributeValue("name") + "=" + value);
  169.             if (value == "")
  170.             {
  171.                 continue;
  172.             }
  173.            
  174.             start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
  175.             bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
  176.             type = variable_nodes[n].GetAttributeValue("type");
  177.            
  178.             if (type == "int")
  179.             {
  180.                 Protocol::Instance()->EncodeInt(databits, start_bit, bit_length, value);
  181.             }
  182.             else if (type == "float")
  183.             {
  184.                 Protocol::Instance()->EncodeFloat(databits, start_bit, bit_length, value);
  185.             }
  186.             else if (type == "ascii")
  187.             {
  188.                 Protocol::Instance()->EncodeAscii(databits, start_bit, bit_length, value);
  189.                 bit_length = value.length() * 8;
  190.             }
  191.             else if (type == "hexstring")
  192.             {
  193.                 Protocol::Instance()->EncodeHexstring(databits, start_bit, bit_length, value);
  194.                 bit_length = value.length() * 4;
  195.             }
  196.             else if (type == "enum")
  197.             {
  198.                 value = variable_nodes[n].SelectChild("name", value).GetAttributeValue("id");
  199.                 Protocol::Instance()->EncodeUint(databits, start_bit, bit_length, value);
  200.             }
  201.             else// if (type == "uint")
  202.             {
  203.                 Protocol::Instance()->EncodeUint(databits, start_bit, bit_length, value);
  204.             }
  205.  
  206.             if (highest_bit < start_bit + bit_length)
  207.             {
  208.                 highest_bit = start_bit + bit_length;
  209.             }
  210.         }
  211.        
  212.         //LOG.Debug(databits.ToDebugString());
  213.        
  214.         unsigned int length = std::min((int)ceil((float)highest_bit / 8.0f), 8);
  215.        
  216.         data[5] = 1;
  217.         data[6] = 0;
  218.        
  219.         data[7] = length;
  220.        
  221.         for (unsigned int n = 0; n < 8; n++)
  222.         {
  223.             data[8 + n] = databits.GetBytes()[n];
  224.         }
  225.        
  226.         data[16] = PACKET_END;
  227.        
  228.         data.SetSize(17);
  229.        
  230.         //LOG.Debug("Bytes: " + data.ToDebugString());
  231.         net::Manager::Instance()->SendTo(this->client_id_, data);
  232.     } else if (message->GetType() == broker::Message::CAN_RAW_MESSAGE)
  233.     {
  234.    
  235.         std::string* payload_str;
  236.     payload_str = static_cast<std::string*>(message->GetPayload().get());
  237.     std::string line = *payload_str;
  238.         common::Byteset data(17);
  239.         //LOG.Info("Got "+ line + "end");
  240.    
  241.         data[0] = PACKET_START;
  242.         std::string value = line.substr(4,2);
  243.     //LOG.Info("<"+ value + ">");
  244.     data[4] = common::FromHex(value);
  245.     //LOG.Info("id1: " + value + " data: ");//+ data[1]);
  246.    
  247.     value = line.substr(6,2);
  248.     //LOG.Info("<"+ value + ">");
  249.    
  250.     data[3] = common::FromHex(value);
  251.     //LOG.Info("id2: " + value + " data: ");//+ data[2]);
  252.    
  253.     value = line.substr(8,2);
  254.     data[2] = common::FromHex(value);
  255.     //LOG.Info("id3: " + value + " data: ");//+ data[3]);
  256.    
  257.     value = line.substr(10,2);
  258.     data[1] = common::FromHex(value);
  259.     //LOG.Info("id4: " + value + " data: ");//+ data[4]);
  260.    
  261.     value = line.substr(13,1);
  262.     data[5] = common::FromHex(value);
  263.     //LOG.Info("1: " + value + " data: ");//+ data[5]);
  264.    
  265.     value = line.substr(15,1);
  266.     data[6] = common::FromHex(value);
  267.     //LOG.Info("1: " + value + " data: ");//+ data[6]);
  268.  
  269.         unsigned char length = 0;
  270.         unsigned char index = 0;
  271.         while (length < 8 && index + 16 < (unsigned char)line.length())
  272.         {
  273.             value = line.substr(index+17,2);
  274.         data[8+length] = common::FromHex(value);
  275.         //LOG.Info("data: " + value + " data: ");//+ data[6]);
  276.         index += 3;
  277.         length++;
  278.         }
  279.        
  280.         data[7] = length;
  281.         data[16] = PACKET_END;
  282.        
  283.         data.SetSize(17);
  284.        
  285.         //LOG.Info("Bytes: " + data.ToDebugString());
  286.         net::Manager::Instance()->SendTo(this->client_id_, data);
  287.     }
  288. }
  289.  
  290. void Network::SlotOnNewDataHandler(net::SocketId client_id, common::Byteset data)
  291. {
  292.     if (client_id != this->client_id_)
  293.     {
  294.       return;
  295.     }
  296.    
  297.     static bool have_start = false;
  298.    
  299.     for (unsigned int n = 0; n < data.GetSize(); n++)
  300.     {
  301.         if (have_start)
  302.         {
  303.             if (data[n] == PACKET_END && this->buffer_.GetSize() == 15)
  304.             {
  305.                 this->ProcessBuffer();
  306.                 have_start = false;
  307.             }
  308.             else
  309.             {
  310.                 this->buffer_.Append(data[n]);
  311.             }
  312.         }
  313.         else if (data[n] == PACKET_START)
  314.         {
  315.             this->buffer_.Clear();
  316.             have_start = true;
  317.         }
  318.         else if (data[n] == PACKET_PING)
  319.         {
  320.             LOG.Info("Received pong.");
  321.         }
  322.     }
  323. }
  324.  
  325. void Network::SlotOnNewClientHandler(net::SocketId id, net::SocketId server_id)
  326. {
  327.  
  328. }
  329.  
  330. void Network::SlotOnNewStateHandler(net::SocketId client_id, net::ClientState client_state)
  331. {
  332.     if (client_id != this->client_id_)
  333.     {
  334.         return;
  335.     }
  336.    
  337.     if (client_state == net::CLIENT_STATE_DISCONNECTED)
  338.     {
  339.         LOG.Warning("Got disconnected, setting reconnect timer...");
  340.        
  341.         this->timer_id_ = timer::Manager::Instance()->SetTimer(10000, true);
  342.         this->client_id_ = 0;
  343.     }
  344.     else
  345.     {
  346.         LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
  347.     }
  348. }
  349.  
  350. void Network::SlotOnTimeoutHandler(timer::TimerId timer_id)
  351. {
  352.     try
  353.     {
  354.         this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
  355.         LOG.Info("Connected again.");
  356.        
  357.         timer::Manager::Instance()->Cancel(timer_id);
  358.         this->timer_id_ = 0;
  359.     }
  360.     catch (std::runtime_error& e)
  361.     {
  362.         LOG.Error(e.what());
  363.         LOG.Warning("Will try again soon...");
  364.     }
  365. }
  366.  
  367. void Network::ProcessBuffer()
  368. {
  369.     try
  370.     {
  371.         std::string class_name = "";
  372.         std::string direction_name = "";
  373.         std::string module_name = "";
  374.         unsigned int id = 0;
  375.         std::string command_name = "";
  376.        
  377.     std::string PKTstring = "PKT " +
  378.                 atom::common::ToHex8bit((unsigned int)this->buffer_[3]) +
  379.                 atom::common::ToHex8bit((unsigned int)this->buffer_[2]) +
  380.                 atom::common::ToHex8bit((unsigned int)this->buffer_[1]) +
  381.                 atom::common::ToHex8bit((unsigned int)this->buffer_[0]) +
  382.                 " " +
  383.                 atom::common::ToHex4bit((unsigned int)this->buffer_[4]) +
  384.                 " " +
  385.                 atom::common::ToHex4bit((unsigned int)this->buffer_[5]);
  386.    
  387.     for (unsigned int index = 7; index < 7 + (unsigned int)this->buffer_[6]; index++)
  388.     {
  389.         PKTstring += " " + atom::common::ToHex8bit((unsigned int)this->buffer_[index]) ;
  390.     }
  391.    
  392.     PKTstring += "\n";
  393.    
  394.     //LOG.Info(PKTstring);
  395.    
  396.     std::string* payload_str = new std::string(PKTstring);
  397.     broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_RAW_MESSAGE, broker::Message::PayloadPointer(payload_str), this)));
  398.  
  399.    
  400.         unsigned int class_id = (this->buffer_[3] >> 1) & 0x0F;
  401.         //LOG.Debug("class_id=" + boost::lexical_cast<std::string>(class_id));
  402.         class_name = Protocol::Instance()->LookupClassName(class_id);
  403.        
  404.         if (class_name == "nmt")
  405.         {
  406.             unsigned int command_id = this->buffer_[2];
  407.             //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id));
  408.             command_name = Protocol::Instance()->LookupNMTCommandName(command_id);
  409.         }
  410.         else
  411.         {
  412.             unsigned int direction_flag = this->buffer_[3] & 0x01;
  413.             //LOG.Debug("direction_flag=" + boost::lexical_cast<std::string>(direction_flag));
  414.             direction_name = Protocol::Instance()->LookupDirectionFlag(direction_flag);
  415.            
  416.             unsigned int module_id = this->buffer_[2];
  417.             //LOG.Debug("module_id=" + boost::lexical_cast<std::string>(module_id));
  418.             module_name = Protocol::Instance()->LookupModuleName(module_id);
  419.             //LOG.Debug("module_name=" + module_name);
  420.             id = this->buffer_[1];
  421.            
  422.             unsigned int command_id = this->buffer_[0];
  423.             //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id));
  424.             command_name = Protocol::Instance()->LookupCommandName(command_id, module_name);
  425.             //LOG.Debug("command_name=" + command_name);
  426.         }
  427.  
  428.         Message* payload = new Message(class_name, direction_name, module_name, id, command_name);
  429.  
  430.         unsigned int length = this->buffer_[6];
  431.        
  432.         common::Byteset data_set(length);
  433.        
  434.         for (unsigned int n = 0; n < length; n++)
  435.         {
  436.             data_set.Append(this->buffer_[n + 7]);
  437.         }
  438.  
  439.         common::Bitset databits(data_set);
  440.         xml::Node::NodeList variable_nodes;
  441.         unsigned int start_bit;
  442.         int bit_length;
  443.         std::string type;
  444.         std::string value;
  445.         std::string name;
  446.        
  447.         if (class_name == "nmt")
  448.         {
  449.             variable_nodes = Protocol::Instance()->GetNMTCommandVariables(command_name);
  450.         }
  451.         else
  452.         {
  453.             variable_nodes = Protocol::Instance()->GetCommandVariables(command_name, module_name);
  454.         }
  455.        
  456.         for (unsigned int n = 0; n < variable_nodes.size(); n++)
  457.         {
  458.             name = variable_nodes[n].GetAttributeValue("name");
  459.             start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
  460.             bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
  461.            
  462.             if (databits.GetCount() < start_bit + bit_length)
  463.             {
  464.                 bit_length = databits.GetCount() - start_bit;
  465.                
  466.                 if (bit_length <= 0)
  467.                 {
  468.                     LOG.Warning("Can not read variable " + name + " for command " + command_name + ", message is to short, is there a match between the module and the protocol XML file?");
  469.                     //LOG.Debug("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ", bit_length=" + boost::lexical_cast<std::string>(bit_length) + ", databits.GetCount()=" + boost::lexical_cast<std::string>(databits.GetCount()));
  470.                     continue;
  471.                 }
  472.             }
  473.            
  474.             type = variable_nodes[n].GetAttributeValue("type");
  475.            
  476.             if (type == "int")
  477.             {
  478.                 value = Protocol::Instance()->DecodeInt(databits, start_bit, bit_length);
  479.             }
  480.             else if (type == "float")
  481.             {
  482.                 value = Protocol::Instance()->DecodeFloat(databits, start_bit, bit_length);
  483.             }
  484.             else if (type == "ascii")
  485.             {
  486.                 value = Protocol::Instance()->DecodeAscii(databits, start_bit, bit_length);
  487.             }
  488.             else if (type == "hexstring")
  489.             {
  490.                 value = Protocol::Instance()->DecodeHexstring(databits, start_bit, bit_length);
  491.             }
  492.             else if (type == "enum")
  493.             {
  494.                 //LOG.Debug("Enum: command name=" + command_name);
  495.                 value = Protocol::Instance()->DecodeUint(databits, start_bit, bit_length);
  496.                 //LOG.Debug("Enum: value=" + boost::lexical_cast<std::string>(value));
  497.                 //LOG.Debug("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ", bit_length=" + boost::lexical_cast<std::string>(bit_length));
  498.                
  499.                 value = variable_nodes[n].SelectChild("id", value).GetAttributeValue("name");
  500.             }
  501.             else// if (type == "uint")
  502.             {
  503.                 //LOG.Debug("type: type=" + type);
  504.                 value = Protocol::Instance()->DecodeUint(databits, start_bit, bit_length);
  505.             }
  506.            
  507.             payload->SetVariable(name, value);
  508.         }
  509.        
  510.         broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
  511.     }
  512.     catch (std::runtime_error& e)
  513.     {
  514.         LOG.Error("Malformed message received, " + std::string(e.what()));
  515.         LOG.Debug("Bytes: " + this->buffer_.ToDebugString());
  516.     }
  517.    
  518.     this->buffer_.Clear();
  519. }
  520.    
  521. }; // namespace can
  522. }; // namespace atom
  523.