Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
969 runge 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
 
1048 runge 22
#include "canmessageexception.h"
23
 
24
 
1046 runge 25
#include "canvariable.h"
26
 
27
 
28
#include <vector>
29
 
30
 
969 runge 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
{
1024 runge 53
    Logger &log = Logger::getInstance();
969 runge 54
 
55
    string filename = Settings::get("CanIdXMLFile");
56
 
985 runge 57
    if (file_exists(filename))
58
    {
59
        xmlNode.load(filename.c_str());
969 runge 60
 
1024 runge 61
        log.add("Loading definitions from " + filename + ".\n");
985 runge 62
    }
63
    else
64
    {
1024 runge 65
        log.add("CanIdXMLFile is not defined in the config file, this will probably not work at all.\n");
985 runge 66
    }
969 runge 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
 
981 runge 114
        if (commandId >= 128)
969 runge 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
 
981 runge 143
            if (commandId >= 128)
969 runge 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
 
986 runge 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
 
969 runge 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
 
1021 runge 286
void CanIdTranslator::makeNMTDataValid(string commandName, map<string, CanVariable> &data)
969 runge 287
{
991 runge 288
    vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
969 runge 289
 
290
    for (int n = 0; n < commandNodes.size(); n++)
291
    {
292
        map<string, string> attributes = commandNodes[n].getAttributes();
293
 
1021 runge 294
        if (attributes["name"] == commandName)
969 runge 295
        {
296
            XmlNode varablesNode = commandNodes[n].findChild("variables");
297
 
991 runge 298
            makeDataValid(varablesNode.getChildren(), data);
969 runge 299
 
991 runge 300
            return;
969 runge 301
        }
302
    }
991 runge 303
}
969 runge 304
 
991 runge 305
void CanIdTranslator::makeDataValid(int commandId, string moduleName, map<string, CanVariable> &data)
306
{
307
    vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
969 runge 308
 
991 runge 309
    for (int n = 0; n < commandNodes.size(); n++)
969 runge 310
    {
991 runge 311
        map<string, string> attributes = commandNodes[n].getAttributes();
969 runge 312
 
1001 runge 313
        bool correct = false;
314
 
315
        if (commandId >= 128)
969 runge 316
        {
1001 runge 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
        {
991 runge 329
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 330
 
991 runge 331
            makeDataValid(varablesNode.getChildren(), data);
969 runge 332
 
991 runge 333
            return;
969 runge 334
        }
991 runge 335
    }
336
}
981 runge 337
 
991 runge 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();
981 runge 344
 
991 runge 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"]));
1046 runge 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
            }
981 runge 362
        }
969 runge 363
    }
991 runge 364
}
969 runge 365
 
991 runge 366
string CanIdTranslator::translateDataToHex(int commandId, string moduleName, map<string, CanVariable> &data)
367
{
368
    makeDataValid(commandId, moduleName, data);
969 runge 369
 
991 runge 370
    return translateValidDataToHex(data);
969 runge 371
}
372
 
991 runge 373
 
969 runge 374
map<string, CanVariable> CanIdTranslator::translateData(int commandId, string moduleName, string dataHex)
375
{
991 runge 376
    vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
969 runge 377
 
378
    for (int n = 0; n < commandNodes.size(); n++)
379
    {
380
        map<string, string> attributes = commandNodes[n].getAttributes();
381
 
1001 runge 382
        bool correct = false;
383
 
384
        if (commandId >= 128)
969 runge 385
        {
1001 runge 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
        {
969 runge 398
            XmlNode varablesNode = commandNodes[n].findChild("variables");
399
 
991 runge 400
            return translateData(varablesNode.getChildren(), dataHex);
986 runge 401
        }
402
    }
969 runge 403
 
991 runge 404
    map<string, CanVariable> variables;
986 runge 405
    return variables;
406
}
969 runge 407
 
986 runge 408
map<string, CanVariable> CanIdTranslator::translateNMTData(int commandId, string dataHex)
409
{
991 runge 410
    vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
969 runge 411
 
986 runge 412
    for (int n = 0; n < commandNodes.size(); n++)
413
    {
414
        map<string, string> attributes = commandNodes[n].getAttributes();
969 runge 415
 
986 runge 416
        if (stoi(attributes["id"]) == commandId)
417
        {
418
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 419
 
991 runge 420
            return translateData(varablesNode.getChildren(), dataHex);
969 runge 421
        }
422
    }
423
 
991 runge 424
    map<string, CanVariable> variables;
969 runge 425
    return variables;
426
}
427
 
1021 runge 428
string CanIdTranslator::translateNMTDataToHex(string commandName, map<string, CanVariable> &data)
969 runge 429
{
1021 runge 430
    makeNMTDataValid(commandName, data);
969 runge 431
 
991 runge 432
    return translateValidDataToHex(data);
433
}
969 runge 434
 
1380 linlun 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
 
991 runge 446
string CanIdTranslator::translateValidDataToHex(map<string, CanVariable> &data)
447
{
986 runge 448
    string bin = "0000000000000000000000000000000000000000000000000000000000000000";
991 runge 449
    int highestBit = 0;
986 runge 450
 
991 runge 451
    for (map<string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
986 runge 452
    {
453
        if (iter->second.getType() == "uint")
454
        {
991 runge 455
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
456
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 457
 
1002 runge 458
            unsigned int a = stou(iter->second.getValue());
1380 linlun 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();
986 runge 465
 
1380 linlun 466
            unsigned int a = stou(iter->second.getValue());
986 runge 467
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
1380 linlun 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()));*/
986 runge 475
        }
476
        else if (iter->second.getType() == "float")
477
        {
991 runge 478
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
479
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 480
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), float2bin(stof(iter->second.getValue()), iter->second.getBitLength()));
1380 linlun 481
 
986 runge 482
        }
1380 linlun 483
    else if (iter->second.getType() == "enum")
1046 runge 484
        {
485
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
486
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
487
 
1048 runge 488
            string value = iter->second.getEnumIdValue();
1046 runge 489
 
1048 runge 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
            }
1046 runge 498
        }
986 runge 499
        else if (iter->second.getType() == "ascii")
500
        {
501
            for (int n = 0; n < iter->second.getValue().length(); n++)
502
            {
991 runge 503
                if (iter->second.getStartBit()+n*8 + 8 > highestBit)
504
                    highestBit = iter->second.getStartBit()+n*8 + 8;
986 runge 505
 
1227 arune 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));
986 runge 513
            }
514
        }
515
        else if (iter->second.getType() == "hexstring")
516
        {
517
            for (int n = 0; n < iter->second.getValue().length(); n++)
518
            {
991 runge 519
                if (iter->second.getStartBit()+n*4 + 4 > highestBit)
520
                    highestBit = iter->second.getStartBit()+n*4 + 4;
986 runge 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
 
997 runge 530
    try
531
    {
1030 linlun 532
        while (highestBit%8 != 0)
533
        {
534
            highestBit++;
535
        }
536
        bin = bin.substr(0, highestBit);
997 runge 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
    }
986 runge 543
 
544
    return bin2hex(bin);
969 runge 545
}
986 runge 546
 
991 runge 547
map<string, CanVariable> CanIdTranslator::translateData(vector<XmlNode> variableNodes, string dataHex)
548
{
549
    map<string, CanVariable> variables;
550
    string dataBin = hex2bin(dataHex);
997 runge 551
    //dataBin = rpad(dataBin, 64, '0');
991 runge 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"]);
997 runge 559
        string bits;
991 runge 560
 
997 runge 561
        try
562
        {
563
            bits = dataBin.substr(bitStart, bitLength);
564
        }
565
        catch (std::out_of_range& e)
566
        {
567
            return variables;
568
        }
991 runge 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
        {
1002 runge 580
            variable.setValue(utos(bin2uint(bits)));
991 runge 581
        }
1380 linlun 582
        else if (attributes["type"] == "int")
583
        {
584
            variable.setValue(itos(bin2int(bits)));
585
        }
991 runge 586
        else if (attributes["type"] == "float")
587
        {
588
            variable.setValue(ftos(bin2float(bits)));
589
        }
1046 runge 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
        }
991 runge 607
        else if (attributes["type"] == "ascii")
608
        {
609
            string str;
610
 
611
            for (int k = 0; k < bits.length(); k += 8)
612
            {
997 runge 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
                }
991 runge 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
            {
997 runge 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
                }
991 runge 643
            }
644
 
645
            variable.setValue(str);
646
        }
647
 
648
        variables[attributes["name"]] = variable;
649
    }
650
 
651
    return variables;
652
}
653
 
654