Subversion Repositories HomeAutomation

Rev

Rev 1227 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /***************************************************************************
  2.  *   Copyright (C) November 28, 2008 by Mattias Runge                             *
  3.  *   mattias@runge.se                                                      *
  4.  *   canidtranslator.cpp                                            *
  5.  *                                                                         *
  6.  *   This program is free software; you can redistribute it and/or modify  *
  7.  *   it under the terms of the GNU General Public License as published by  *
  8.  *   the Free Software Foundation; either version 2 of the License, or     *
  9.  *   (at your option) any later version.                                   *
  10.  *                                                                         *
  11.  *   This program is distributed in the hope that it will be useful,       *
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  14.  *   GNU General Public License for more details.                          *
  15.  *                                                                         *
  16.  *   You should have received a copy of the GNU General Public License     *
  17.  *   along with this program; if not, write to the                         *
  18.  *   Free Software Foundation, Inc.,                                       *
  19.  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  20.  ***************************************************************************/
  21.  
  22. #include "canmessageexception.h"
  23.  
  24.  
  25. #include "canvariable.h"
  26.  
  27.  
  28. #include <vector>
  29.  
  30.  
  31. #include "canidtranslator.h"
  32.  
  33. CanIdTranslator* CanIdTranslator::myInstance = NULL;
  34.  
  35. CanIdTranslator& CanIdTranslator::getInstance()
  36. {
  37.     if (myInstance == NULL)
  38.     {
  39.         myInstance = new CanIdTranslator();
  40.     }
  41.  
  42.     return *myInstance;
  43. }
  44.  
  45. void CanIdTranslator::deleteInstance()
  46. {
  47.     delete myInstance;
  48.     myInstance = NULL;
  49. }
  50.  
  51. CanIdTranslator::CanIdTranslator()
  52. {
  53.     Logger &log = Logger::getInstance();
  54.  
  55.     string filename = Settings::get("CanIdXMLFile");
  56.  
  57.     if (file_exists(filename))
  58.     {
  59.         xmlNode.load(filename.c_str());
  60.  
  61.         log.add("Loading definitions from " + filename + ".\n");
  62.     }
  63.     else
  64.     {
  65.         log.add("CanIdXMLFile is not defined in the config file, this will probably not work at all.\n");
  66.     }
  67. }
  68.  
  69. string CanIdTranslator::lookupClassName(int classId)
  70. {
  71.     XmlNode classesNode = xmlNode.findChild("classes");
  72.     vector<XmlNode> classNodes = classesNode.getChildren();
  73.  
  74.     for (int n = 0; n < classNodes.size(); n++)
  75.     {
  76.         map<string, string> attributes = classNodes[n].getAttributes();
  77.  
  78.         if (stoi(attributes["id"]) == classId)
  79.         {
  80.             return attributes["name"];
  81.         }
  82.     }
  83.  
  84.     return "";
  85. }
  86.  
  87. int CanIdTranslator::resolveClassId(string className)
  88. {
  89.     XmlNode classesNode = xmlNode.findChild("classes");
  90.     vector<XmlNode> classNodes = classesNode.getChildren();
  91.  
  92.     for (int n = 0; n < classNodes.size(); n++)
  93.     {
  94.         map<string, string> attributes = classNodes[n].getAttributes();
  95.  
  96.         if (attributes["name"].compare(className) == 0)
  97.         {
  98.             return stoi(attributes["id"]);
  99.         }
  100.     }
  101.  
  102.     return -1;
  103. }
  104.  
  105. string CanIdTranslator::lookupCommandName(int commandId, string moduleName)
  106. {
  107.     XmlNode commandsNode = xmlNode.findChild("commands");
  108.     vector<XmlNode> commandNodes = commandsNode.getChildren();
  109.  
  110.     for (int n = 0; n < commandNodes.size(); n++)
  111.     {
  112.         map<string, string> attributes = commandNodes[n].getAttributes();
  113.  
  114.         if (commandId >= 128)
  115.         {
  116.             if (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)
  117.             {
  118.                 return attributes["name"];
  119.             }
  120.         }
  121.         else if (stoi(attributes["id"]) == commandId)
  122.         {
  123.             return attributes["name"];
  124.         }
  125.     }
  126.  
  127.     return "";
  128. }
  129.  
  130. int CanIdTranslator::resolveCommandId(string commandName, string moduleName)
  131. {
  132.     XmlNode commandsNode = xmlNode.findChild("commands");
  133.     vector<XmlNode> commandNodes = commandsNode.getChildren();
  134.  
  135.     for (int n = 0; n < commandNodes.size(); n++)
  136.     {
  137.         map<string, string> attributes = commandNodes[n].getAttributes();
  138.  
  139.         if (attributes["name"].compare(commandName) == 0)
  140.         {
  141.             int commandId = stoi(attributes["id"]);
  142.  
  143.             if (commandId >= 128)
  144.             {
  145.                 if (attributes["module"] == moduleName)
  146.                 {
  147.                     return commandId;
  148.                 }
  149.             }
  150.             else
  151.             {
  152.                 return commandId;
  153.             }
  154.         }
  155.     }
  156.  
  157.     return -1;
  158. }
  159.  
  160. string CanIdTranslator::lookupNMTCommandName(int commandId)
  161. {
  162.     XmlNode commandsNode = xmlNode.findChild("nmt_messages");
  163.     vector<XmlNode> commandNodes = commandsNode.getChildren();
  164.  
  165.     for (int n = 0; n < commandNodes.size(); n++)
  166.     {
  167.         map<string, string> attributes = commandNodes[n].getAttributes();
  168.  
  169.         if (stoi(attributes["id"]) == commandId)
  170.         {
  171.             return attributes["name"];
  172.         }
  173.     }
  174.  
  175.     return "";
  176. }
  177.  
  178. int CanIdTranslator::resolveNMTCommandId(string commandName)
  179. {
  180.     XmlNode commandsNode = xmlNode.findChild("nmt_messages");
  181.     vector<XmlNode> commandNodes = commandsNode.getChildren();
  182.  
  183.     for (int n = 0; n < commandNodes.size(); n++)
  184.     {
  185.         map<string, string> attributes = commandNodes[n].getAttributes();
  186.  
  187.         if (attributes["name"].compare(commandName) == 0)
  188.         {
  189.             return stoi(attributes["id"]);
  190.         }
  191.     }
  192.  
  193.     return -1;
  194. }
  195.  
  196. string CanIdTranslator::getDefineId(string name, string group)
  197. {
  198.     XmlNode definesNode = xmlNode.findChild("defines");
  199.     vector<XmlNode> defineNodes = definesNode.getChildren();
  200.  
  201.     for (int n = 0; n < defineNodes.size(); n++)
  202.     {
  203.         map<string, string> attributes = defineNodes[n].getAttributes();
  204.  
  205.         if (attributes["group"] == group && attributes["name"] == name)
  206.         {
  207.             return attributes["id"];
  208.         }
  209.     }
  210.  
  211.     return "";
  212. }
  213.  
  214. string CanIdTranslator::lookupDirectionFlag(int directionFlag)
  215. {
  216.     XmlNode definesNode = xmlNode.findChild("defines");
  217.     vector<XmlNode> defineNodes = definesNode.getChildren();
  218.  
  219.     for (int n = 0; n < defineNodes.size(); n++)
  220.     {
  221.         map<string, string> attributes = defineNodes[n].getAttributes();
  222.  
  223.         if (attributes["group"].compare("DirectionFlag") == 0 && stoi(attributes["id"]) == directionFlag)
  224.         {
  225.             return attributes["name"];
  226.         }
  227.     }
  228.  
  229.     return "";
  230. }
  231.  
  232. int CanIdTranslator::resolveDirectionFlag(string directionName)
  233. {
  234.     XmlNode definesNode = xmlNode.findChild("defines");
  235.     vector<XmlNode> defineNodes = definesNode.getChildren();
  236.  
  237.     for (int n = 0; n < defineNodes.size(); n++)
  238.     {
  239.         map<string, string> attributes = defineNodes[n].getAttributes();
  240.  
  241.         if (attributes["group"].compare("DirectionFlag") == 0 && attributes["name"].compare(directionName) == 0)
  242.         {
  243.             return stoi(attributes["id"]);
  244.         }
  245.     }
  246.  
  247.     return -1;
  248. }
  249.  
  250. string CanIdTranslator::lookupModuleName(int moduleId)
  251. {
  252.     XmlNode modulesNode = xmlNode.findChild("modules");
  253.     vector<XmlNode> moduleNodes = modulesNode.getChildren();
  254.  
  255.     for (int n = 0; n < moduleNodes.size(); n++)
  256.     {
  257.         map<string, string> attributes = moduleNodes[n].getAttributes();
  258.  
  259.         if (stoi(attributes["id"]) == moduleId)
  260.         {
  261.             return attributes["name"];
  262.         }
  263.     }
  264.  
  265.     return "";
  266. }
  267.  
  268. int CanIdTranslator::resolveModuleId(string moduleName)
  269. {
  270.     XmlNode modulesNode = xmlNode.findChild("modules");
  271.     vector<XmlNode> moduleNodes = modulesNode.getChildren();
  272.  
  273.     for (int n = 0; n < moduleNodes.size(); n++)
  274.     {
  275.         map<string, string> attributes = moduleNodes[n].getAttributes();
  276.  
  277.         if (attributes["name"].compare(moduleName) == 0)
  278.         {
  279.             return stoi(attributes["id"]);
  280.         }
  281.     }
  282.  
  283.     return -1;
  284. }
  285.  
  286. void CanIdTranslator::makeNMTDataValid(string commandName, map<string, CanVariable> &data)
  287. {
  288.     vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
  289.  
  290.     for (int n = 0; n < commandNodes.size(); n++)
  291.     {
  292.         map<string, string> attributes = commandNodes[n].getAttributes();
  293.  
  294.         if (attributes["name"] == commandName)
  295.         {
  296.             XmlNode varablesNode = commandNodes[n].findChild("variables");
  297.  
  298.             makeDataValid(varablesNode.getChildren(), data);
  299.  
  300.             return;
  301.         }
  302.     }
  303. }
  304.  
  305. void CanIdTranslator::makeDataValid(int commandId, string moduleName, map<string, CanVariable> &data)
  306. {
  307.     vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
  308.  
  309.     for (int n = 0; n < commandNodes.size(); n++)
  310.     {
  311.         map<string, string> attributes = commandNodes[n].getAttributes();
  312.  
  313.         bool correct = false;
  314.  
  315.         if (commandId >= 128)
  316.         {
  317.             if (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)
  318.             {
  319.                 correct = true;
  320.             }
  321.         }
  322.         else if (stoi(attributes["id"]) == commandId)
  323.         {
  324.             correct = true;
  325.         }
  326.  
  327.         if (correct)
  328.         {
  329.             XmlNode varablesNode = commandNodes[n].findChild("variables");
  330.  
  331.             makeDataValid(varablesNode.getChildren(), data);
  332.  
  333.             return;
  334.         }
  335.     }
  336. }
  337.  
  338. void CanIdTranslator::makeDataValid(vector<XmlNode> variableNodes, map<string, CanVariable> &data)
  339. {
  340.     ///FIXME: Remove variables that do not exist in the xmlfile
  341.     for (int c = 0; c < variableNodes.size(); c++)
  342.     {
  343.         map<string, string> attributes = variableNodes[c].getAttributes();
  344.  
  345.         if (data.find(attributes["name"]) != data.end())
  346.         {
  347.             data[attributes["name"]].setType(attributes["type"]);
  348.             data[attributes["name"]].setUnit(attributes["unit"]);
  349.             data[attributes["name"]].setBitLength(stoi(attributes["bit_length"]));
  350.             data[attributes["name"]].setStartBit(stoi(attributes["start_bit"]));
  351.  
  352.             if (attributes["type"] == "enum")
  353.             {
  354.                 vector<XmlNode> values = variableNodes[c].getChildren();
  355.  
  356.                 for (int k = 0; k < values.size(); k++)
  357.                 {
  358.                     map<string, string> valueAttributes = values[k].getAttributes();
  359.                     data[attributes["name"]].addEnumValue(valueAttributes["id"], valueAttributes["name"]);
  360.                 }
  361.             }
  362.         }
  363.     }
  364. }
  365.  
  366. string CanIdTranslator::translateDataToHex(int commandId, string moduleName, map<string, CanVariable> &data)
  367. {
  368.     makeDataValid(commandId, moduleName, data);
  369.  
  370.     return translateValidDataToHex(data);
  371. }
  372.  
  373.  
  374. map<string, CanVariable> CanIdTranslator::translateData(int commandId, string moduleName, string dataHex)
  375. {
  376.     vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
  377.  
  378.     for (int n = 0; n < commandNodes.size(); n++)
  379.     {
  380.         map<string, string> attributes = commandNodes[n].getAttributes();
  381.  
  382.         bool correct = false;
  383.  
  384.         if (commandId >= 128)
  385.         {
  386.             if (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)
  387.             {
  388.                 correct = true;
  389.             }
  390.         }
  391.         else if (stoi(attributes["id"]) == commandId)
  392.         {
  393.             correct = true;
  394.         }
  395.  
  396.         if (correct)
  397.         {
  398.             XmlNode varablesNode = commandNodes[n].findChild("variables");
  399.  
  400.             return translateData(varablesNode.getChildren(), dataHex);
  401.         }
  402.     }
  403.  
  404.     map<string, CanVariable> variables;
  405.     return variables;
  406. }
  407.  
  408. map<string, CanVariable> CanIdTranslator::translateNMTData(int commandId, string dataHex)
  409. {
  410.     vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
  411.  
  412.     for (int n = 0; n < commandNodes.size(); n++)
  413.     {
  414.         map<string, string> attributes = commandNodes[n].getAttributes();
  415.  
  416.         if (stoi(attributes["id"]) == commandId)
  417.         {
  418.             XmlNode varablesNode = commandNodes[n].findChild("variables");
  419.  
  420.             return translateData(varablesNode.getChildren(), dataHex);
  421.         }
  422.     }
  423.  
  424.     map<string, CanVariable> variables;
  425.     return variables;
  426. }
  427.  
  428. string CanIdTranslator::translateNMTDataToHex(string commandName, map<string, CanVariable> &data)
  429. {
  430.     makeNMTDataValid(commandName, data);
  431.  
  432.     return translateValidDataToHex(data);
  433. }
  434.  
  435.  
  436. template <class T>
  437. bool from_string(T& t,
  438.                  const std::string& s,
  439.                  std::ios_base& (*f)(std::ios_base&))
  440. {
  441.   std::istringstream iss(s);
  442.   return !(iss >> f >> t).fail();
  443. }
  444.  
  445.  
  446. string CanIdTranslator::translateValidDataToHex(map<string, CanVariable> &data)
  447. {
  448.     string bin = "0000000000000000000000000000000000000000000000000000000000000000";
  449.     int highestBit = 0;
  450.  
  451.     for (map<string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
  452.     {
  453.         if (iter->second.getType() == "uint")
  454.         {
  455.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  456.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  457.  
  458.             unsigned int a = stou(iter->second.getValue());
  459.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
  460.         }
  461.         else if (iter->second.getType() == "int")
  462.         {
  463. if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  464.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  465.  
  466.             unsigned int a = stou(iter->second.getValue());
  467.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
  468.             /*if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  469.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  470. cout << iter->second.getValue() << endl;
  471.  
  472.             int a = stoi(iter->second.getValue());
  473. cout << a << endl;
  474.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));*/
  475.         }
  476.         else if (iter->second.getType() == "float")
  477.         {
  478.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  479.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  480.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), float2bin(stof(iter->second.getValue()), iter->second.getBitLength()));
  481.            
  482.         }
  483.     else if (iter->second.getType() == "enum")
  484.         {
  485.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  486.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  487.  
  488.             string value = iter->second.getEnumIdValue();
  489.  
  490.             if (value == "")
  491.             {
  492.                 throw new CanMessageException("Got enum that could not be converterd to a value. value = \"" + iter->second.getValue() + "\" enumString is \"" + iter->second.getEnumsString() + "\"\n");
  493.             }
  494.             else
  495.             {
  496.                 bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(stou(value), iter->second.getBitLength()));
  497.             }
  498.         }
  499.         else if (iter->second.getType() == "ascii")
  500.         {
  501.             for (int n = 0; n < iter->second.getValue().length(); n++)
  502.             {
  503.                 if (iter->second.getStartBit()+n*8 + 8 > highestBit)
  504.                     highestBit = iter->second.getStartBit()+n*8 + 8;
  505.  
  506.                 //bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin((unsigned int)iter->second.getValue()[n], 8));
  507.                 unsigned int temp = iter->second.getValue()[n];
  508.                 if (temp > 0xff)
  509.                 {
  510.                     temp &= 0xff;
  511.                 }
  512.                 bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin(temp, 8));
  513.             }
  514.         }
  515.         else if (iter->second.getType() == "hexstring")
  516.         {
  517.             for (int n = 0; n < iter->second.getValue().length(); n++)
  518.             {
  519.                 if (iter->second.getStartBit()+n*4 + 4 > highestBit)
  520.                     highestBit = iter->second.getStartBit()+n*4 + 4;
  521.  
  522.                 string character;
  523.                 character += iter->second.getValue()[n];
  524.  
  525.                 bin.replace(iter->second.getStartBit()+n*4, 4, hex2bin(character));
  526.             }
  527.         }
  528.     }
  529.  
  530.     try
  531.     {
  532.         while (highestBit%8 != 0)
  533.         {
  534.             highestBit++;
  535.         }
  536.         bin = bin.substr(0, highestBit);
  537.     }
  538.     catch (std::out_of_range& e)
  539.     {
  540.         cout << "DEBUG: translateValidDataToHex exception: " << e.what() << "\n";
  541.         cout << "DEBUG: A bin=" << bin << " :: highestBit=" << highestBit << endl;
  542.     }
  543.  
  544.     return bin2hex(bin);
  545. }
  546.  
  547. map<string, CanVariable> CanIdTranslator::translateData(vector<XmlNode> variableNodes, string dataHex)
  548. {
  549.     map<string, CanVariable> variables;
  550.     string dataBin = hex2bin(dataHex);
  551.     //dataBin = rpad(dataBin, 64, '0');
  552.  
  553.     for (int c = 0; c < variableNodes.size(); c++)
  554.     {
  555.         map<string, string> attributes = variableNodes[c].getAttributes();
  556.  
  557.         int bitStart = stoi(attributes["start_bit"]);
  558.         int bitLength = stoi(attributes["bit_length"]);
  559.         string bits;
  560.  
  561.         try
  562.         {
  563.             bits = dataBin.substr(bitStart, bitLength);
  564.         }
  565.         catch (std::out_of_range& e)
  566.         {
  567.             return variables;
  568.         }
  569.  
  570.         CanVariable variable;
  571.  
  572.         variable.setName(attributes["name"]);
  573.         variable.setType(attributes["type"]);
  574.         variable.setUnit(attributes["unit"]);
  575.         variable.setStartBit(bitStart);
  576.         variable.setBitLength(bitLength);
  577.  
  578.         if (attributes["type"] == "uint")
  579.         {
  580.             variable.setValue(utos(bin2uint(bits)));
  581.         }
  582.         else if (attributes["type"] == "int")
  583.         {
  584.             variable.setValue(itos(bin2int(bits)));
  585.         }
  586.         else if (attributes["type"] == "float")
  587.         {
  588.             variable.setValue(ftos(bin2float(bits)));
  589.         }
  590.         else if (attributes["type"] == "enum")
  591.         {
  592.             vector<XmlNode> values = variableNodes[c].getChildren();
  593.  
  594.             string value = utos(bin2uint(bits));
  595.  
  596.             for (int k = 0; k < values.size(); k++)
  597.             {
  598.                 map<string, string> valueAttributes = values[k].getAttributes();
  599.                 variable.addEnumValue(valueAttributes["id"], valueAttributes["name"]);
  600.  
  601.                 if (valueAttributes["id"] == value)
  602.                 {
  603.                     variable.setValue(valueAttributes["name"]);
  604.                 }
  605.             }
  606.         }
  607.         else if (attributes["type"] == "ascii")
  608.         {
  609.             string str;
  610.  
  611.             for (int k = 0; k < bits.length(); k += 8)
  612.             {
  613.                 try
  614.                 {
  615.                     str += (char)bin2uint(bits.substr(k, 8));
  616.                 }
  617.                 catch (std::out_of_range& e)
  618.                 {
  619.                     cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
  620.                     cout << "DEBUG: B bits=" << bits << " :: k=" << k << endl;
  621.                     continue;
  622.                 }
  623.             }
  624.  
  625.             variable.setValue(str);
  626.         }
  627.         else if (attributes["type"] == "hexstring")
  628.         {
  629.             string str;
  630.  
  631.             for (int k = 0; k < bits.length(); k += 4)
  632.             {
  633.                 try
  634.                 {
  635.                     str += bin2hex(bits.substr(k, 4));
  636.                 }
  637.                 catch (std::out_of_range& e)
  638.                 {
  639.                     cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
  640.                     cout << "DEBUG: C bits=" << bits << " :: k=" << k << endl;
  641.                     continue;
  642.                 }
  643.             }
  644.  
  645.             variable.setValue(str);
  646.         }
  647.  
  648.         variables[attributes["name"]] = variable;
  649.     }
  650.  
  651.     return variables;
  652. }
  653.  
  654.  
  655.