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