Subversion Repositories HomeAutomation

Rev

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 "Protocol.h"
  22.  
  23. #include <stdexcept>
  24.  
  25. #include <boost/lexical_cast.hpp>
  26.  
  27. namespace atom {
  28. namespace can {
  29.  
  30. Protocol::Pointer Protocol::instance_ = Protocol::Pointer(new Protocol());
  31.  
  32. Protocol::Protocol() : LOG("can::Protocol")
  33. {
  34. }
  35.  
  36. Protocol::~Protocol()
  37. {
  38. }
  39.  
  40. Protocol::Pointer Protocol::Instance()
  41. {
  42.     return Protocol::instance_;
  43. }
  44.  
  45. void Protocol::Delete()
  46. {
  47.     Protocol::instance_.reset();
  48. }
  49.    
  50. bool Protocol::Load(std::string filename)
  51. {
  52.     try
  53.     {
  54.         this->root_node_.LoadFile(filename);
  55.     }
  56.     catch (std::runtime_error& e)
  57.     {
  58.         LOG.Error(e.what());
  59.         return false;
  60.     }
  61.    
  62.     LOG.Info("Protocol loaded successfully");
  63.     return true;
  64. }
  65.  
  66. std::string Protocol::LookupClassName(unsigned int class_id)
  67. {
  68.     try
  69.     {
  70.         return this->root_node_.FindChild("classes").SelectChild("id", boost::lexical_cast<std::string>(class_id)).GetAttributeValue("name");
  71.     }
  72.     catch (std::runtime_error& e)
  73.     {
  74.         LOG.Error(e.what());
  75.         throw std::runtime_error("No such class_id found, " + boost::lexical_cast<std::string>(class_id));
  76.     }
  77. }
  78.  
  79. unsigned int Protocol::ResolveClassId(std::string class_name)
  80. {
  81.     try
  82.     {
  83.         return boost::lexical_cast<unsigned int>(this->root_node_.FindChild("classes").SelectChild("name", class_name).GetAttributeValue("id"));
  84.     }
  85.     catch (std::runtime_error& e)
  86.     {
  87.         LOG.Error(e.what());
  88.         throw std::runtime_error("No such class_name found, " + class_name);
  89.     }
  90. }
  91.  
  92. std::string Protocol::LookupCommandName(unsigned int command_id, std::string module_name)
  93. {
  94.     try
  95.     {
  96.         if (command_id >= 128)
  97.         {
  98.             return this->root_node_.FindChild("commands").SelectChild("id", boost::lexical_cast<std::string>(command_id), "module", module_name).GetAttributeValue("name");
  99.         }
  100.    
  101.         return this->root_node_.FindChild("commands").SelectChild("id", boost::lexical_cast<std::string>(command_id)).GetAttributeValue("name");
  102.     }
  103.     catch (std::runtime_error& e)
  104.     {
  105.         LOG.Error(e.what());
  106.         throw std::runtime_error("No such command found, id = " + boost::lexical_cast<std::string>(command_id) + ", module = " + module_name);
  107.     }
  108. }
  109.  
  110. unsigned int Protocol::ResolveCommandId(std::string command_name, std::string module_name)
  111. {
  112.     try
  113.     {
  114.         return boost::lexical_cast<unsigned int >(this->root_node_.FindChild("commands").SelectChild("name", command_name, "module", module_name).GetAttributeValue("id"));
  115.     }
  116.     catch (std::runtime_error& e)
  117.     {
  118.     }
  119.    
  120.     try
  121.     {
  122.         return boost::lexical_cast<unsigned int >(this->root_node_.FindChild("commands").SelectChild("name", command_name).GetAttributeValue("id"));
  123.     }
  124.     catch (std::runtime_error& e)
  125.     {
  126.         LOG.Error(e.what());
  127.         throw std::runtime_error("No such command found, name = " + command_name + ", module = " + module_name);
  128.     }
  129. }
  130.  
  131. std::string Protocol::LookupNMTCommandName(unsigned int command_id)
  132. {
  133.     try
  134.     {
  135.         return this->root_node_.FindChild("nmt_messages").SelectChild("id", boost::lexical_cast<std::string>(command_id)).GetAttributeValue("name");
  136.     }
  137.     catch (std::runtime_error& e)
  138.     {
  139.         LOG.Error(e.what());
  140.         throw std::runtime_error("No such nmt command found, id = " + boost::lexical_cast<std::string>(command_id));
  141.     }
  142. }
  143.  
  144. unsigned int Protocol::ResolveNMTCommandId(std::string command_name)
  145. {
  146.     try
  147.     {
  148.         return boost::lexical_cast<unsigned int >(this->root_node_.FindChild("nmt_messages").SelectChild("name", command_name).GetAttributeValue("id"));
  149.     }
  150.     catch (std::runtime_error& e)
  151.     {
  152.         LOG.Error(e.what());
  153.         throw std::runtime_error("No such nmt command found, name = " + command_name);
  154.     }
  155. }
  156.  
  157. std::string Protocol::GetDefineId(std::string name, std::string group)
  158. {
  159.     try
  160.     {
  161.         return this->root_node_.FindChild("defines").SelectChild("name", name, "group", group).GetAttributeValue("id");
  162.     }
  163.     catch (std::runtime_error& e)
  164.     {
  165.         LOG.Error(e.what());
  166.         throw std::runtime_error("No such define found, name = " + name + ", group = " + group);
  167.     }
  168. }
  169.  
  170. std::string Protocol::LookupDirectionFlag(unsigned int direction_flag)
  171. {
  172.     try
  173.     {
  174.         return this->root_node_.FindChild("defines").SelectChild("id", boost::lexical_cast<std::string>(direction_flag), "group", "DirectionFlag").GetAttributeValue("name");
  175.     }
  176.     catch (std::runtime_error& e)
  177.     {
  178.         LOG.Error(e.what());
  179.         throw std::runtime_error("No such direction flag found, direction_flag = " + boost::lexical_cast<std::string>(direction_flag));
  180.     }
  181. }
  182.  
  183. unsigned int Protocol::ResolveDirectionFlag(std::string direction_name)
  184. {
  185.     try
  186.     {
  187.         return boost::lexical_cast<unsigned int>(this->root_node_.FindChild("defines").SelectChild("name", direction_name, "group", "DirectionFlag").GetAttributeValue("id"));
  188.     }
  189.     catch (std::runtime_error& e)
  190.     {
  191.         LOG.Error(e.what());
  192.         throw std::runtime_error("No such direction flag found, direction_name = " + direction_name);
  193.     }
  194. }
  195.  
  196. std::string Protocol::LookupModuleName(unsigned int module_id)
  197. {
  198.     try
  199.     {
  200.         return this->root_node_.FindChild("modules").SelectChild("id", boost::lexical_cast<std::string>(module_id)).GetAttributeValue("name");
  201.     }
  202.     catch (std::runtime_error& e)
  203.     {
  204.         LOG.Error(e.what());
  205.         throw std::runtime_error("No such module id found, " + boost::lexical_cast<std::string>(module_id));
  206.     }
  207. }
  208.  
  209. unsigned int Protocol::ResolveModuleId(std::string module_name)
  210. {
  211.     try
  212.     {
  213.         return boost::lexical_cast<unsigned int>(this->root_node_.FindChild("modules").SelectChild("name", module_name).GetAttributeValue("id"));
  214.     }
  215.     catch (std::runtime_error& e)
  216.     {
  217.         LOG.Error(e.what());
  218.         throw std::runtime_error("No such module name found, " + module_name);
  219.     }
  220. }
  221.  
  222. xml::Node::NodeList Protocol::GetCommandVariables(std::string command_name, std::string module_name)
  223. {
  224.     try
  225.     {
  226.         return this->root_node_.FindChild("commands").SelectChild("name", command_name, "module", module_name).FindChild("variables").GetChildren();
  227.     }
  228.     catch (std::runtime_error& e)
  229.     {
  230.     }
  231.    
  232.     try
  233.     {
  234.         return this->root_node_.FindChild("commands").SelectChild("name", command_name).FindChild("variables").GetChildren();
  235.     }
  236.     catch (std::runtime_error& e)
  237.     {
  238.         LOG.Error(e.what());
  239.         throw std::runtime_error("No such command found, name = " + command_name + ", module = " + module_name);
  240.     }
  241. }
  242.  
  243. xml::Node::NodeList Protocol::GetNMTCommandVariables(std::string command_name)
  244. {
  245.     try
  246.     {
  247.         return this->root_node_.FindChild("nmt_messages").SelectChild("name", command_name).FindChild("variables").GetChildren();
  248.     }
  249.     catch (std::runtime_error& e)
  250.     {
  251.         LOG.Error(e.what());
  252.         throw std::runtime_error("No such nmt command found, name = " + command_name);
  253.     }
  254. }
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267. /*
  268.  
  269.  
  270.  
  271.  
  272.  
  273. void Protocol::makeNMTDataValid(std::string commandName, map<std::string, CanVariable> &data)
  274. {
  275.     std::vector<Node> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
  276.    
  277.     for (int n = 0; n < commandNodes.size(); n++)
  278.     {
  279.         map<std::string, std::string> attributes = commandNodes[n].getAttributes();
  280.        
  281.         if (attributes["name"] == commandName)
  282.         {
  283.             Node varablesNode = commandNodes[n].findChild("variables");
  284.            
  285.             makeDataValid(varablesNode.getChildren(), data);
  286.            
  287.             return;
  288.         }
  289.     }
  290. }
  291.  
  292. void Protocol::makeDataValid(int commandId, std::string moduleName, map<std::string, CanVariable> &data)
  293. {
  294.     std::vector<Node> commandNodes = xmlNode.findChild("commands").getChildren();
  295.    
  296.     for (int n = 0; n < commandNodes.size(); n++)
  297.     {
  298.         map<std::string, std::string> attributes = commandNodes[n].getAttributes();
  299.        
  300.         bool correct = false;
  301.        
  302.         if (commandId >= 128)
  303.         {
  304.             if (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)
  305.             {
  306.                 correct = true;
  307.             }
  308.         }
  309.         else if (stoi(attributes["id"]) == commandId)
  310.         {
  311.             correct = true;
  312.         }
  313.        
  314.         if (correct)
  315.         {
  316.             Node varablesNode = commandNodes[n].findChild("variables");
  317.            
  318.             makeDataValid(varablesNode.getChildren(), data);
  319.            
  320.             return;
  321.         }
  322.     }
  323. }
  324.  
  325. void Protocol::makeDataValid(std::vector<Node> variableNodes, map<std::string, CanVariable> &data)
  326. {
  327.     ///FIXME: Remove variables that do not exist in the xmlfile
  328.     for (int c = 0; c < variableNodes.size(); c++)
  329.     {
  330.         map<std::string, std::string> attributes = variableNodes[c].getAttributes();
  331.        
  332.         if (data.find(attributes["name"]) != data.end())
  333.         {
  334.             data[attributes["name"]].setType(attributes["type"]);
  335.             data[attributes["name"]].setUnit(attributes["unit"]);
  336.             data[attributes["name"]].setBitLength(stoi(attributes["bit_length"]));
  337.             data[attributes["name"]].setStartBit(stoi(attributes["start_bit"]));
  338.            
  339.             if (attributes["type"] == "enum")
  340.             {
  341.                 std::vector<Node> values = variableNodes[c].getChildren();
  342.                
  343.                 for (int k = 0; k < values.size(); k++)
  344.                 {
  345.                     map<std::string, std::string> valueAttributes = values[k].getAttributes();
  346.                     data[attributes["name"]].addEnumValue(valueAttributes["id"], valueAttributes["name"]);
  347.                 }
  348.             }
  349.         }
  350.     }
  351. }
  352.  
  353. std::string Protocol::translateDataToHex(int commandId, std::string moduleName, map<std::string, CanVariable> &data)
  354. {
  355.     makeDataValid(commandId, moduleName, data);
  356.    
  357.     return translateValidDataToHex(data);
  358. }
  359.  
  360.  
  361. map<std::string, CanVariable> Protocol::translateData(int commandId, std::string moduleName, std::string dataHex)
  362. {
  363.     std::vector<Node> commandNodes = xmlNode.findChild("commands").getChildren();
  364.    
  365.     for (int n = 0; n < commandNodes.size(); n++)
  366.     {
  367.         map<std::string, std::string> attributes = commandNodes[n].getAttributes();
  368.        
  369.         bool correct = false;
  370.        
  371.         if (commandId >= 128)
  372.         {
  373.             if (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)
  374.             {
  375.                 correct = true;
  376.             }
  377.         }
  378.         else if (stoi(attributes["id"]) == commandId)
  379.         {
  380.             correct = true;
  381.         }
  382.        
  383.         if (correct)
  384.         {
  385.             Node varablesNode = commandNodes[n].findChild("variables");
  386.            
  387.             return translateData(varablesNode.getChildren(), dataHex);
  388.         }
  389.     }
  390.    
  391.     map<std::string, CanVariable> variables;
  392.     return variables;
  393. }
  394.  
  395. map<std::string, CanVariable> Protocol::translateNMTData(int commandId, std::string dataHex)
  396. {
  397.     std::vector<Node> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
  398.    
  399.     for (int n = 0; n < commandNodes.size(); n++)
  400.     {
  401.         map<std::string, std::string> attributes = commandNodes[n].getAttributes();
  402.        
  403.         if (stoi(attributes["id"]) == commandId)
  404.         {
  405.             Node varablesNode = commandNodes[n].findChild("variables");
  406.            
  407.             return translateData(varablesNode.getChildren(), dataHex);
  408.         }
  409.     }
  410.    
  411.     map<std::string, CanVariable> variables;
  412.     return variables;
  413. }
  414.  
  415. std::string Protocol::translateNMTDataToHex(std::string commandName, map<std::string, CanVariable> &data)
  416. {
  417.     makeNMTDataValid(commandName, data);
  418.    
  419.     return translateValidDataToHex(data);
  420. }
  421.  
  422.  
  423. template <class T>
  424. bool from_std::string(T& t,
  425.                 const std::std::string& s,
  426.                 std::ios_base& (*f)(std::ios_base&))
  427. {
  428.     std::istd::stringstream iss(s);
  429.     return !(iss >> f >> t).fail();
  430. }
  431.  
  432.  
  433. std::string Protocol::translateValidDataToHex(map<std::string, CanVariable> &data)
  434. {
  435.     std::string bin = "0000000000000000000000000000000000000000000000000000000000000000";
  436.     int highestBit = 0;
  437.    
  438.     for (map<std::string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
  439.     {
  440.         if (iter->second.getType() == "uint")
  441.         {
  442.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  443.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  444.            
  445.             unsigned int a = stou(iter->second.getValue());
  446.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
  447.         }
  448.         else if (iter->second.getType() == "int")
  449.         {
  450.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  451.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  452.            
  453.             unsigned int a = stou(iter->second.getValue());
  454.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
  455.  
  456.         }
  457.         else if (iter->second.getType() == "float")
  458.         {
  459.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  460.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  461.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), float2bin(stof(iter->second.getValue()), iter->second.getBitLength()));
  462.            
  463.         }
  464.         else if (iter->second.getType() == "enum")
  465.         {
  466.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  467.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  468.            
  469.             std::string value = iter->second.getEnumIdValue();
  470.            
  471.             if (value == "")
  472.             {
  473.                 throw new CanMessageException("Got enum that could not be converterd to a value. value = \"" + iter->second.getValue() + "\" enumString is \"" + iter->second.getEnumsString() + "\"\n");
  474.             }
  475.             else
  476.             {
  477.                 bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(stou(value), iter->second.getBitLength()));
  478.             }
  479.         }
  480.         else if (iter->second.getType() == "ascii")
  481.         {
  482.             for (int n = 0; n < iter->second.getValue().length(); n++)
  483.             {
  484.                 if (iter->second.getStartBit()+n*8 + 8 > highestBit)
  485.                     highestBit = iter->second.getStartBit()+n*8 + 8;
  486.                
  487.                 //bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin((unsigned int)iter->second.getValue()[n], 8));
  488.                     unsigned int temp = iter->second.getValue()[n];
  489.                     if (temp > 0xff)
  490.                     {
  491.                         temp &= 0xff;
  492.                     }
  493.                     bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin(temp, 8));
  494.             }
  495.         }
  496.         else if (iter->second.getType() == "hexstd::string")
  497.         {
  498.             for (int n = 0; n < iter->second.getValue().length(); n++)
  499.             {
  500.                 if (iter->second.getStartBit()+n*4 + 4 > highestBit)
  501.                     highestBit = iter->second.getStartBit()+n*4 + 4;
  502.                
  503.                 std::string character;
  504.                 character += iter->second.getValue()[n];
  505.                
  506.                 bin.replace(iter->second.getStartBit()+n*4, 4, hex2bin(character));
  507.             }
  508.         }
  509.     }
  510.    
  511.     try
  512.     {
  513.         while (highestBit%8 != 0)
  514.         {
  515.             highestBit++;
  516.         }
  517.         bin = bin.substr(0, highestBit);
  518.     }
  519.     catch (std::out_of_range& e)
  520.     {
  521.         cout << "DEBUG: translateValidDataToHex exception: " << e.what() << "\n";
  522.         cout << "DEBUG: A bin=" << bin << " :: highestBit=" << highestBit << endl;
  523.     }
  524.    
  525.     return bin2hex(bin);
  526. }
  527.  
  528. map<std::string, CanVariable> Protocol::translateData(std::vector<Node> variableNodes, std::string dataHex)
  529. {
  530.     map<std::string, CanVariable> variables;
  531.     std::string dataBin = hex2bin(dataHex);
  532.     //dataBin = rpad(dataBin, 64, '0');
  533.    
  534.     for (int c = 0; c < variableNodes.size(); c++)
  535.     {
  536.         map<std::string, std::string> attributes = variableNodes[c].getAttributes();
  537.        
  538.         int bitStart = stoi(attributes["start_bit"]);
  539.         int bitLength = stoi(attributes["bit_length"]);
  540.         std::string bits;
  541.        
  542.         try
  543.         {
  544.             bits = dataBin.substr(bitStart, bitLength);
  545.         }
  546.         catch (std::out_of_range& e)
  547.         {
  548.             return variables;
  549.         }
  550.        
  551.         CanVariable variable;
  552.        
  553.         variable.setName(attributes["name"]);
  554.         variable.setType(attributes["type"]);
  555.         variable.setUnit(attributes["unit"]);
  556.         variable.setStartBit(bitStart);
  557.         variable.setBitLength(bitLength);
  558.        
  559.         if (attributes["type"] == "uint")
  560.         {
  561.             variable.setValue(utos(bin2uint(bits)));
  562.         }
  563.         else if (attributes["type"] == "int")
  564.         {
  565.             variable.setValue(itos(bin2int(bits)));
  566.         }
  567.         else if (attributes["type"] == "float")
  568.         {
  569.             variable.setValue(ftos(bin2float(bits)));
  570.         }
  571.         else if (attributes["type"] == "enum")
  572.         {
  573.             std::vector<Node> values = variableNodes[c].getChildren();
  574.            
  575.             std::string value = utos(bin2uint(bits));
  576.            
  577.             for (int k = 0; k < values.size(); k++)
  578.             {
  579.                 map<std::string, std::string> valueAttributes = values[k].getAttributes();
  580.                 variable.addEnumValue(valueAttributes["id"], valueAttributes["name"]);
  581.                
  582.                 if (valueAttributes["id"] == value)
  583.                 {
  584.                     variable.setValue(valueAttributes["name"]);
  585.                 }
  586.             }
  587.         }
  588.         else if (attributes["type"] == "ascii")
  589.         {
  590.             std::string str;
  591.            
  592.             for (int k = 0; k < bits.length(); k += 8)
  593.             {
  594.                 try
  595.                 {
  596.                     str += (char)bin2uint(bits.substr(k, 8));
  597.                 }
  598.                 catch (std::out_of_range& e)
  599.                 {
  600.                     cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
  601.                     cout << "DEBUG: B bits=" << bits << " :: k=" << k << endl;
  602.                     continue;
  603.                 }
  604.             }
  605.            
  606.             variable.setValue(str);
  607.         }
  608.         else if (attributes["type"] == "hexstd::string")
  609.         {
  610.             std::string str;
  611.            
  612.             for (int k = 0; k < bits.length(); k += 4)
  613.             {
  614.                 try
  615.                 {
  616.                     str += bin2hex(bits.substr(k, 4));
  617.                 }
  618.                 catch (std::out_of_range& e)
  619.                 {
  620.                     cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
  621.                     cout << "DEBUG: C bits=" << bits << " :: k=" << k << endl;
  622.                     continue;
  623.                 }
  624.             }
  625.            
  626.             variable.setValue(str);
  627.         }
  628.        
  629.         variables[attributes["name"]] = variable;
  630.     }
  631.    
  632.     return variables;
  633. }
  634.    
  635.    
  636.    */
  637.    
  638.    
  639.    
  640.    
  641.    
  642.    
  643.    
  644.    
  645.    
  646. }; // namespace can
  647. }; // namespace atom
  648.