Subversion Repositories HomeAutomation

Rev

Rev 1046 | 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 "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. string CanIdTranslator::translateValidDataToHex(map<string, CanVariable> &data)
  436. {
  437.     string bin = "0000000000000000000000000000000000000000000000000000000000000000";
  438.     int highestBit = 0;
  439.  
  440.     for (map<string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
  441.     {
  442.         if (iter->second.getType() == "uint")
  443.         {
  444.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  445.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  446.  
  447.             unsigned int a = stou(iter->second.getValue());
  448.  
  449.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
  450.         }
  451.         else if (iter->second.getType() == "float")
  452.         {
  453.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  454.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  455.  
  456.             bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), float2bin(stof(iter->second.getValue()), iter->second.getBitLength()));
  457.         }
  458.         else if (iter->second.getType() == "enum")
  459.         {
  460.             if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
  461.                 highestBit = iter->second.getStartBit() + iter->second.getBitLength();
  462.  
  463.             string value = iter->second.getEnumIdValue();
  464.  
  465.             if (value == "")
  466.             {
  467.                 throw new CanMessageException("Got enum that could not be converterd to a value. value = \"" + iter->second.getValue() + "\" enumString is \"" + iter->second.getEnumsString() + "\"\n");
  468.             }
  469.             else
  470.             {
  471.                 bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(stou(value), iter->second.getBitLength()));
  472.             }
  473.         }
  474.         else if (iter->second.getType() == "ascii")
  475.         {
  476.             for (int n = 0; n < iter->second.getValue().length(); n++)
  477.             {
  478.                 if (iter->second.getStartBit()+n*8 + 8 > highestBit)
  479.                     highestBit = iter->second.getStartBit()+n*8 + 8;
  480.  
  481.                 bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin((unsigned int)iter->second.getValue()[n], 8));
  482.             }
  483.         }
  484.         else if (iter->second.getType() == "hexstring")
  485.         {
  486.             for (int n = 0; n < iter->second.getValue().length(); n++)
  487.             {
  488.                 if (iter->second.getStartBit()+n*4 + 4 > highestBit)
  489.                     highestBit = iter->second.getStartBit()+n*4 + 4;
  490.  
  491.                 string character;
  492.                 character += iter->second.getValue()[n];
  493.  
  494.                 bin.replace(iter->second.getStartBit()+n*4, 4, hex2bin(character));
  495.             }
  496.         }
  497.     }
  498.  
  499.     try
  500.     {
  501.         while (highestBit%8 != 0)
  502.         {
  503.             highestBit++;
  504.         }
  505.         bin = bin.substr(0, highestBit);
  506.     }
  507.     catch (std::out_of_range& e)
  508.     {
  509.         cout << "DEBUG: translateValidDataToHex exception: " << e.what() << "\n";
  510.         cout << "DEBUG: A bin=" << bin << " :: highestBit=" << highestBit << endl;
  511.     }
  512.  
  513.     return bin2hex(bin);
  514. }
  515.  
  516. map<string, CanVariable> CanIdTranslator::translateData(vector<XmlNode> variableNodes, string dataHex)
  517. {
  518.     map<string, CanVariable> variables;
  519.     string dataBin = hex2bin(dataHex);
  520.     //dataBin = rpad(dataBin, 64, '0');
  521.  
  522.     for (int c = 0; c < variableNodes.size(); c++)
  523.     {
  524.         map<string, string> attributes = variableNodes[c].getAttributes();
  525.  
  526.         int bitStart = stoi(attributes["start_bit"]);
  527.         int bitLength = stoi(attributes["bit_length"]);
  528.         string bits;
  529.  
  530.         try
  531.         {
  532.             bits = dataBin.substr(bitStart, bitLength);
  533.         }
  534.         catch (std::out_of_range& e)
  535.         {
  536.             return variables;
  537.         }
  538.  
  539.         CanVariable variable;
  540.  
  541.         variable.setName(attributes["name"]);
  542.         variable.setType(attributes["type"]);
  543.         variable.setUnit(attributes["unit"]);
  544.         variable.setStartBit(bitStart);
  545.         variable.setBitLength(bitLength);
  546.  
  547.         if (attributes["type"] == "uint")
  548.         {
  549.             variable.setValue(utos(bin2uint(bits)));
  550.         }
  551.         else if (attributes["type"] == "float")
  552.         {
  553.             variable.setValue(ftos(bin2float(bits)));
  554.         }
  555.         else if (attributes["type"] == "enum")
  556.         {
  557.             vector<XmlNode> values = variableNodes[c].getChildren();
  558.  
  559.             string value = utos(bin2uint(bits));
  560.  
  561.             for (int k = 0; k < values.size(); k++)
  562.             {
  563.                 map<string, string> valueAttributes = values[k].getAttributes();
  564.                 variable.addEnumValue(valueAttributes["id"], valueAttributes["name"]);
  565.  
  566.                 if (valueAttributes["id"] == value)
  567.                 {
  568.                     variable.setValue(valueAttributes["name"]);
  569.                 }
  570.             }
  571.         }
  572.         else if (attributes["type"] == "ascii")
  573.         {
  574.             string str;
  575.  
  576.             for (int k = 0; k < bits.length(); k += 8)
  577.             {
  578.                 try
  579.                 {
  580.                     str += (char)bin2uint(bits.substr(k, 8));
  581.                 }
  582.                 catch (std::out_of_range& e)
  583.                 {
  584.                     cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
  585.                     cout << "DEBUG: B bits=" << bits << " :: k=" << k << endl;
  586.                     continue;
  587.                 }
  588.             }
  589.  
  590.             variable.setValue(str);
  591.         }
  592.         else if (attributes["type"] == "hexstring")
  593.         {
  594.             string str;
  595.  
  596.             for (int k = 0; k < bits.length(); k += 4)
  597.             {
  598.                 try
  599.                 {
  600.                     str += bin2hex(bits.substr(k, 4));
  601.                 }
  602.                 catch (std::out_of_range& e)
  603.                 {
  604.                     cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
  605.                     cout << "DEBUG: C bits=" << bits << " :: k=" << k << endl;
  606.                     continue;
  607.                 }
  608.             }
  609.  
  610.             variable.setValue(str);
  611.         }
  612.  
  613.         variables[attributes["name"]] = variable;
  614.     }
  615.  
  616.     return variables;
  617. }
  618.  
  619.  
  620.