Subversion Repositories HomeAutomation

Rev

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