Subversion Repositories HomeAutomation

Rev

Rev 2216 | 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. #include "common/log.h"
  38.  
  39. namespace atom {
  40. namespace can {
  41.  
  42. enum
  43. {
  44.     PACKET_START = 253,
  45.     PACKET_END   = 250,
  46.     PACKET_PING  = 251
  47. };
  48.  
  49. static const std::string log_module_ = "can::network";
  50.  
  51. Network::Network(std::string address): broker::Subscriber(false), LOG("can::Network")
  52. {
  53.     this->address_ = address;
  54.     this->client_id_ = 0;
  55.  
  56.     // Examples of address
  57.     // udp:192.168.1.250:1100
  58.     // serial:/dev/ttyUSB0:38400
  59.  
  60.     common::StringList 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::TRANSPORT_PROTOCOL_UDP;
  74.     }
  75.     else if (parts[0] == "serial")
  76.     {
  77.         this->protocol_ = net::TRANSPORT_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.  
  95.         common::Byteset buffer(1);
  96.         buffer[0] = PACKET_PING;
  97.  
  98.         net::Manager::Instance()->SendTo(this->client_id_, buffer);
  99.     }
  100.     catch (std::runtime_error& 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::SlotOnTimeout(timer::TimerId timer_id)
  112. {
  113.     if (timer_id == this->timer_id_)
  114.     {
  115.         this->io_service_.post(boost::bind(&Network::SlotOnTimeoutHandler, this, timer_id));
  116.     }
  117. }
  118.  
  119. void Network::SlotOnMessageHandler(broker::Message::Pointer message)
  120. {
  121.     if (message->GetType() == broker::Message::CAN_RAW_BYTES)
  122.     {
  123.       net::Manager::Instance()->SendTo(this->client_id_, message->GetRawData());
  124.     }
  125.     else if (message->GetType() == broker::Message::CAN_MESSAGE)
  126.     {
  127.         Message* payload = static_cast<Message*>(message->GetPayload().get());
  128.         common::Byteset data(17);
  129.  
  130.         data[0] = PACKET_START;
  131.  
  132.         unsigned int class_id = Protocol::Instance()->ResolveClassId(payload->GetClassName());
  133.         data[4] = class_id << 1;
  134.  
  135.         if (payload->GetClassName() == "nmt")
  136.         {
  137.             unsigned int command_id = Protocol::Instance()->ResolveNMTCommandId(payload->GetCommandName());
  138.             data[3] = command_id;
  139.         }
  140.         else
  141.         {
  142.             unsigned int direction_flag = Protocol::Instance()->ResolveDirectionFlag(payload->GetDirectionName());
  143.             data[4] |= (direction_flag & 0x01);
  144.  
  145.             unsigned int module_id = Protocol::Instance()->ResolveModuleId(payload->GetModuleName());
  146.             data[3] = module_id;
  147.  
  148.             data[2] = payload->GetId();
  149.  
  150.             unsigned int command_id = Protocol::Instance()->ResolveCommandId(payload->GetCommandName(), payload->GetModuleName());
  151.             data[1] = command_id;
  152.         }
  153.  
  154.         unsigned int highest_bit = 0;
  155.         common::Bitset databits(64);
  156.  
  157.         xml::Node::NodeList variable_nodes;
  158.         unsigned int start_bit;
  159.         unsigned int bit_length;
  160.         std::string type;
  161.         std::string value;
  162.  
  163.         if (payload->GetClassName() == "nmt")
  164.         {
  165.             variable_nodes = Protocol::Instance()->GetNMTCommandVariables(payload->GetCommandName());
  166.         }
  167.         else
  168.         {
  169.             variable_nodes = Protocol::Instance()->GetCommandVariables(payload->GetCommandName(), payload->GetModuleName());
  170.         }
  171.  
  172.         for (unsigned int n = 0; n < variable_nodes.size(); n++)
  173.         {
  174.             value = payload->GetVariable(variable_nodes[n].GetAttributeValue("name"));
  175.             //LOG.Debug(variable_nodes[n].GetAttributeValue("name") + "=" + value);
  176.             if (value == "")
  177.             {
  178.                 continue;
  179.             }
  180.  
  181.             start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
  182.             bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
  183.             type = variable_nodes[n].GetAttributeValue("type");
  184.  
  185.             if (type == "int")
  186.             {
  187.                 Protocol::Instance()->EncodeInt(databits, start_bit, bit_length, value);
  188.             }
  189.             else if (type == "float")
  190.             {
  191.                 Protocol::Instance()->EncodeFloat(databits, start_bit, bit_length, value);
  192.             }
  193.             else if (type == "IEEE32")
  194.             {
  195.                 Protocol::Instance()->EncodeIEEE32(databits, start_bit, bit_length, value);
  196.             }
  197.             else if (type == "ascii")
  198.             {
  199.                 Protocol::Instance()->EncodeAscii(databits, start_bit, bit_length, value);
  200.                 bit_length = value.length() * 8;
  201.             }
  202.             else if (type == "hexstring")
  203.             {
  204.                 Protocol::Instance()->EncodeHexstring(databits, start_bit, bit_length, value);
  205.                 bit_length = value.length() * 4;
  206.             }
  207.             else if (type == "enum")
  208.             {
  209.                 value = variable_nodes[n].SelectChild("name", value).GetAttributeValue("id");
  210.                 Protocol::Instance()->EncodeUint(databits, start_bit, bit_length, value);
  211.             }
  212.             else// if (type == "uint")
  213.             {
  214.                 Protocol::Instance()->EncodeUint(databits, start_bit, bit_length, value);
  215.             }
  216.  
  217.             if (highest_bit < start_bit + bit_length)
  218.             {
  219.                 highest_bit = start_bit + bit_length;
  220.             }
  221.         }
  222.  
  223.         //LOG.Debug(databits.ToDebugString());
  224.  
  225.         unsigned int length = std::min((int)ceil((float)highest_bit / 8.0f), 8);
  226.  
  227.         data[5] = 1;
  228.         data[6] = 0;
  229.  
  230.         data[7] = length;
  231.  
  232.         for (unsigned int n = 0; n < 8; n++)
  233.         {
  234.             data[8 + n] = databits.GetBytes()[n];
  235.         }
  236.  
  237.         data[16] = PACKET_END;
  238.  
  239.         //LOG.Debug("Bytes: " + data.ToDebugString());
  240.         net::Manager::Instance()->SendTo(this->client_id_, data);
  241.     }
  242.     else if (message->GetType() == broker::Message::CAN_RAW_MESSAGE)
  243.     {
  244.         std::string* payload_str;
  245.     payload_str = static_cast<std::string*>(message->GetPayload().get());
  246.     std::string line = *payload_str;
  247.  
  248.         if (line.length() < 16)
  249.         {
  250.           log::Error(log_module_, "Packet was to short: \"%s\", length was %u.", line.data(), line.length());
  251.           return;
  252.         }
  253.  
  254.  
  255.         common::Byteset data(17);
  256.         //LOG.Info("Got "+ line + "end");
  257.  
  258.         data[0] = PACKET_START;
  259.         std::string value = line.substr(4,2);
  260.     //LOG.Info("<"+ value + ">");
  261.     data[4] = common::FromHex(value);
  262.     //LOG.Info("id1: " + value + " data: ");//+ data[1]);
  263.  
  264.     value = line.substr(6,2);
  265.     //LOG.Info("<"+ value + ">");
  266.  
  267.     data[3] = common::FromHex(value);
  268.     //LOG.Info("id2: " + value + " data: ");//+ data[2]);
  269.  
  270.     value = line.substr(8,2);
  271.     data[2] = common::FromHex(value);
  272.     //LOG.Info("id3: " + value + " data: ");//+ data[3]);
  273.  
  274.     value = line.substr(10,2);
  275.     data[1] = common::FromHex(value);
  276.     //LOG.Info("id4: " + value + " data: ");//+ data[4]);
  277.  
  278.     value = line.substr(13,1);
  279.     data[5] = common::FromHex(value);
  280.     //LOG.Info("1: " + value + " data: ");//+ data[5]);
  281.  
  282.     value = line.substr(15,1);
  283.     data[6] = common::FromHex(value);
  284.     //LOG.Info("1: " + value + " data: ");//+ data[6]);
  285.  
  286.         unsigned char length = 0;
  287.         unsigned char index = 0;
  288.         while (length < 8 && index + 16 < (unsigned char)line.length())
  289.         {
  290.             value = line.substr(index+17,2);
  291.         data[8+length] = common::FromHex(value);
  292.         //LOG.Info("data: " + value + " data: ");//+ data[6]);
  293.         index += 3;
  294.         length++;
  295.         }
  296.  
  297.         data[7] = length;
  298.         data[16] = PACKET_END;
  299.  
  300.  
  301.         //LOG.Info("Bytes: " + data.ToDebugString());
  302.         net::Manager::Instance()->SendTo(this->client_id_, data);
  303.     }
  304. }
  305.  
  306. void Network::SlotOnNewDataHandler(net::SocketId client_id, common::Byteset data)
  307. {
  308.   if (client_id != this->client_id_)
  309.   {
  310.     return;
  311.   }
  312.  
  313.   broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_RAW_BYTES, data, this)));
  314.  
  315.   static bool have_start = false;
  316.  
  317.   for (unsigned int n = 0; n < data.size(); n++)
  318.   {
  319.     log::Extreme(log_module_, "data[%u] = %u, have_start = %s, this->buffer_.size() = %u", n, (unsigned int)data[n], have_start ? "true" : "false", this->buffer_.size());
  320.  
  321.     if (have_start)
  322.     {
  323.       if (data[n] == PACKET_END && this->buffer_.size() >= 15)
  324.       {
  325.         log::Extreme(log_module_, "PACKET_END");
  326.  
  327.         while (this->buffer_.size() < 15)
  328.         {
  329.           this->buffer_.push_back(0);
  330.         }
  331.  
  332.         for (unsigned int k = 0; k < this->buffer_.size(); k++)
  333.         {
  334.           log::Extreme(log_module_, "this->buffer_[%u]=%u", k, (unsigned int)this->buffer_[k]);
  335.         }
  336.  
  337.         this->ProcessBuffer();
  338.  
  339.         have_start = false;
  340.       }
  341.       else
  342.       {
  343.         this->buffer_.push_back(data[n]);
  344.       }
  345.     }
  346.     else if (data[n] == PACKET_START)
  347.     {
  348.       log::Extreme(log_module_, "PACKET_START");
  349.  
  350.       common::Byteset empty_vector;
  351.       this->buffer_.swap(empty_vector);
  352.  
  353.       have_start = true;
  354.     }
  355.     else if (data[n] == PACKET_PING)
  356.     {
  357.       log::Info(log_module_, "Got Pong!");
  358.     }
  359.   }
  360. }
  361.  
  362. void Network::SlotOnNewClientHandler(net::SocketId id, net::SocketId server_id)
  363. {
  364.  
  365. }
  366.  
  367. void Network::SlotOnNewStateHandler(net::SocketId client_id, net::ClientState client_state)
  368. {
  369.     if (client_id != this->client_id_)
  370.     {
  371.         return;
  372.     }
  373.  
  374.     if (client_state == net::CLIENT_STATE_DISCONNECTED)
  375.     {
  376.         LOG.Warning("Got disconnected, setting reconnect timer...");
  377.  
  378.         this->timer_id_ = timer::Manager::Instance()->SetTimer(10000, true);
  379.         this->client_id_ = 0;
  380.     }
  381.     else
  382.     {
  383.         LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
  384.     }
  385. }
  386.  
  387. void Network::SlotOnTimeoutHandler(timer::TimerId timer_id)
  388. {
  389.     try
  390.     {
  391.         this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
  392.         LOG.Info("Connected again.");
  393.  
  394.         timer::Manager::Instance()->Cancel(timer_id);
  395.         this->timer_id_ = 0;
  396.     }
  397.     catch (std::runtime_error& e)
  398.     {
  399.         LOG.Error(e.what());
  400.         LOG.Warning("Will try again soon...");
  401.     }
  402. }
  403.  
  404. void Network::ProcessBuffer()
  405. {
  406.   LOG_DEBUG_ENTER;
  407.  
  408.     try
  409.     {
  410.         std::string class_name = "";
  411.         std::string direction_name = "";
  412.         std::string module_name = "";
  413.         unsigned int id = 0;
  414.         std::string command_name = "";
  415.  
  416.     std::string PKTstring = "PKT " +
  417.                 atom::common::ToHex8bit((unsigned int)this->buffer_[3]) +
  418.                 atom::common::ToHex8bit((unsigned int)this->buffer_[2]) +
  419.                 atom::common::ToHex8bit((unsigned int)this->buffer_[1]) +
  420.                 atom::common::ToHex8bit((unsigned int)this->buffer_[0]) +
  421.                 " " +
  422.                 atom::common::ToHex4bit((unsigned int)this->buffer_[4]) +
  423.                 " " +
  424.                 atom::common::ToHex4bit((unsigned int)this->buffer_[5]);
  425.  
  426.     for (unsigned int index = 7; index < 7 + (unsigned int)this->buffer_[6]; index++)
  427.     {
  428.         PKTstring += " " + atom::common::ToHex8bit((unsigned int)this->buffer_[index]) ;
  429.     }
  430.  
  431.     PKTstring += "\n";
  432.  
  433.     LOG.Extreme(PKTstring);
  434.  
  435.   for (unsigned int n = 0; n < this->buffer_.size(); n++)
  436.   {
  437.      log::Extreme(log_module_, "this->buffer_[%u]=%u", n, (unsigned int)this->buffer_[n]);
  438.   }
  439.  
  440.     std::string* payload_str = new std::string(PKTstring);
  441.     broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_RAW_MESSAGE, broker::Message::PayloadPointer(payload_str), this)));
  442.  
  443.  
  444.         unsigned int class_id = (this->buffer_[3] >> 1) & 0x0F;
  445.         LOG.Extreme("class_id=" + boost::lexical_cast<std::string>(class_id));
  446.         class_name = Protocol::Instance()->LookupClassName(class_id);
  447.  
  448.         if (class_name == "nmt")
  449.         {
  450.             unsigned int command_id = this->buffer_[2];
  451.             LOG.Extreme("command_id=" + boost::lexical_cast<std::string>(command_id));
  452.             command_name = Protocol::Instance()->LookupNMTCommandName(command_id);
  453.         }
  454.         else
  455.         {
  456.             unsigned int direction_flag = this->buffer_[3] & 0x01;
  457.             LOG.Extreme("direction_flag=" + boost::lexical_cast<std::string>(direction_flag));
  458.             direction_name = Protocol::Instance()->LookupDirectionFlag(direction_flag);
  459.  
  460.             unsigned int module_id = this->buffer_[2];
  461.             LOG.Extreme("module_id=" + boost::lexical_cast<std::string>(module_id));
  462.             module_name = Protocol::Instance()->LookupModuleName(module_id);
  463.             LOG.Extreme("module_name=" + module_name);
  464.             id = this->buffer_[1];
  465.  
  466.             unsigned int command_id = this->buffer_[0];
  467.             LOG.Extreme("command_id=" + boost::lexical_cast<std::string>(command_id));
  468.             command_name = Protocol::Instance()->LookupCommandName(command_id, module_name);
  469.             LOG.Extreme("command_name=" + command_name);
  470.         }
  471.  
  472.         Message* payload = new Message(class_name, direction_name, module_name, id, command_name);
  473.  
  474.         unsigned int length = this->buffer_[6];
  475.  
  476.         common::Byteset data_set;
  477.         data_set.reserve(length);
  478.  
  479.         for (unsigned int n = 0; n < length; n++)
  480.         {
  481.             data_set.push_back(this->buffer_[n + 7]);
  482.         }
  483.  
  484.         for (unsigned int n = 0; n < data_set.size(); n++)
  485.         {
  486.            log::Extreme(log_module_, "data_set[%u]=%u", n, (unsigned int)data_set[n]);
  487.         }
  488.  
  489.         common::Bitset databits(data_set);
  490.         xml::Node::NodeList variable_nodes;
  491.         unsigned int start_bit;
  492.         int bit_length;
  493.         std::string type;
  494.         std::string value;
  495.         std::string name;
  496.  
  497.         if (class_name == "nmt")
  498.         {
  499.             variable_nodes = Protocol::Instance()->GetNMTCommandVariables(command_name);
  500.         }
  501.         else
  502.         {
  503.             variable_nodes = Protocol::Instance()->GetCommandVariables(command_name, module_name);
  504.         }
  505.  
  506.         for (unsigned int n = 0; n < variable_nodes.size(); n++)
  507.         {
  508.             name = variable_nodes[n].GetAttributeValue("name");
  509.             start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
  510.             bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
  511.  
  512.             if (databits.GetCount() < start_bit + bit_length)
  513.             {
  514.                 bit_length = databits.GetCount() - start_bit;
  515.  
  516.                 if (bit_length <= 0)
  517.                 {
  518.                     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?");
  519.                     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()));
  520.                     continue;
  521.                 }
  522.             }
  523.  
  524.             type = variable_nodes[n].GetAttributeValue("type");
  525.             LOG.Extreme("type: type=" + type);
  526.  
  527.             if (type == "int")
  528.             {
  529.                 value = Protocol::Instance()->DecodeInt(databits, start_bit, bit_length);
  530.             }
  531.             else if (type == "float")
  532.             {
  533.                 value = Protocol::Instance()->DecodeFloat(databits, start_bit, bit_length);
  534.             }
  535.             else if (type == "IEEE32")
  536.             {
  537.                 value = Protocol::Instance()->DecodeIEEE32(databits, start_bit, bit_length);
  538.             }
  539.             else if (type == "ascii")
  540.             {
  541.                 value = Protocol::Instance()->DecodeAscii(databits, start_bit, bit_length);
  542.             }
  543.             else if (type == "hexstring")
  544.             {
  545.                 value = Protocol::Instance()->DecodeHexstring(databits, start_bit, bit_length);
  546.             }
  547.             else if (type == "enum")
  548.             {
  549.                 LOG.Extreme("Enum: command name=" + command_name);
  550.                 value = Protocol::Instance()->DecodeUint(databits, start_bit, bit_length);
  551.                 LOG.Extreme("Enum: value=" + boost::lexical_cast<std::string>(value));
  552.                 LOG.Extreme("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ", bit_length=" + boost::lexical_cast<std::string>(bit_length));
  553.  
  554.                 value = variable_nodes[n].SelectChild("id", value).GetAttributeValue("name");
  555.             }
  556.             else// if (type == "uint")
  557.             {
  558.                 value = Protocol::Instance()->DecodeUint(databits, start_bit, bit_length);
  559.             }
  560.  
  561.             LOG.Extreme("value=\"" + value + "\"");
  562.  
  563.             payload->SetVariable(name, value);
  564.         }
  565.  
  566.         broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
  567.     }
  568.     catch (std::runtime_error& e)
  569.     {
  570.         LOG.Error("Malformed message received, " + std::string(e.what()));
  571.         LOG.Debug("Bytes: " + std::string(this->buffer_.begin(), this->buffer_.end()));
  572.     }
  573.  
  574.     common::Byteset empty_vector;
  575.     this->buffer_.swap(empty_vector);
  576.  
  577.  
  578.     LOG_DEBUG_EXIT;
  579. }
  580.  
  581. }; // namespace can
  582. }; // namespace atom
  583.