Subversion Repositories HomeAutomation

Rev

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