Subversion Repositories HomeAutomation

Rev

Rev 1030 | Rev 1048 | Go to most recent revision | 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
 
1046 runge 22
#include "canvariable.h"
23
 
24
 
25
#include <vector>
26
 
27
 
969 runge 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
{
1024 runge 50
    Logger &log = Logger::getInstance();
969 runge 51
 
52
    string filename = Settings::get("CanIdXMLFile");
53
 
985 runge 54
    if (file_exists(filename))
55
    {
56
        xmlNode.load(filename.c_str());
969 runge 57
 
1024 runge 58
        log.add("Loading definitions from " + filename + ".\n");
985 runge 59
    }
60
    else
61
    {
1024 runge 62
        log.add("CanIdXMLFile is not defined in the config file, this will probably not work at all.\n");
985 runge 63
    }
969 runge 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
 
981 runge 111
        if (commandId >= 128)
969 runge 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
 
981 runge 140
            if (commandId >= 128)
969 runge 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
 
986 runge 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
 
969 runge 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
 
1021 runge 283
void CanIdTranslator::makeNMTDataValid(string commandName, map<string, CanVariable> &data)
969 runge 284
{
991 runge 285
    vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
969 runge 286
 
287
    for (int n = 0; n < commandNodes.size(); n++)
288
    {
289
        map<string, string> attributes = commandNodes[n].getAttributes();
290
 
1021 runge 291
        if (attributes["name"] == commandName)
969 runge 292
        {
293
            XmlNode varablesNode = commandNodes[n].findChild("variables");
294
 
991 runge 295
            makeDataValid(varablesNode.getChildren(), data);
969 runge 296
 
991 runge 297
            return;
969 runge 298
        }
299
    }
991 runge 300
}
969 runge 301
 
991 runge 302
void CanIdTranslator::makeDataValid(int commandId, string moduleName, map<string, CanVariable> &data)
303
{
304
    vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
969 runge 305
 
991 runge 306
    for (int n = 0; n < commandNodes.size(); n++)
969 runge 307
    {
991 runge 308
        map<string, string> attributes = commandNodes[n].getAttributes();
969 runge 309
 
1001 runge 310
        bool correct = false;
311
 
312
        if (commandId >= 128)
969 runge 313
        {
1001 runge 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
        {
991 runge 326
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 327
 
991 runge 328
            makeDataValid(varablesNode.getChildren(), data);
969 runge 329
 
991 runge 330
            return;
969 runge 331
        }
991 runge 332
    }
333
}
981 runge 334
 
991 runge 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();
981 runge 341
 
991 runge 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"]));
1046 runge 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
            }
981 runge 359
        }
969 runge 360
    }
991 runge 361
}
969 runge 362
 
991 runge 363
string CanIdTranslator::translateDataToHex(int commandId, string moduleName, map<string, CanVariable> &data)
364
{
365
    makeDataValid(commandId, moduleName, data);
969 runge 366
 
991 runge 367
    return translateValidDataToHex(data);
969 runge 368
}
369
 
991 runge 370
 
969 runge 371
map<string, CanVariable> CanIdTranslator::translateData(int commandId, string moduleName, string dataHex)
372
{
991 runge 373
    vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
969 runge 374
 
375
    for (int n = 0; n < commandNodes.size(); n++)
376
    {
377
        map<string, string> attributes = commandNodes[n].getAttributes();
378
 
1001 runge 379
        bool correct = false;
380
 
381
        if (commandId >= 128)
969 runge 382
        {
1001 runge 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
        {
969 runge 395
            XmlNode varablesNode = commandNodes[n].findChild("variables");
396
 
991 runge 397
            return translateData(varablesNode.getChildren(), dataHex);
986 runge 398
        }
399
    }
969 runge 400
 
991 runge 401
    map<string, CanVariable> variables;
986 runge 402
    return variables;
403
}
969 runge 404
 
986 runge 405
map<string, CanVariable> CanIdTranslator::translateNMTData(int commandId, string dataHex)
406
{
991 runge 407
    vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
969 runge 408
 
986 runge 409
    for (int n = 0; n < commandNodes.size(); n++)
410
    {
411
        map<string, string> attributes = commandNodes[n].getAttributes();
969 runge 412
 
986 runge 413
        if (stoi(attributes["id"]) == commandId)
414
        {
415
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 416
 
991 runge 417
            return translateData(varablesNode.getChildren(), dataHex);
969 runge 418
        }
419
    }
420
 
991 runge 421
    map<string, CanVariable> variables;
969 runge 422
    return variables;
423
}
424
 
1021 runge 425
string CanIdTranslator::translateNMTDataToHex(string commandName, map<string, CanVariable> &data)
969 runge 426
{
1021 runge 427
    makeNMTDataValid(commandName, data);
969 runge 428
 
991 runge 429
    return translateValidDataToHex(data);
430
}
969 runge 431
 
991 runge 432
string CanIdTranslator::translateValidDataToHex(map<string, CanVariable> &data)
433
{
986 runge 434
    string bin = "0000000000000000000000000000000000000000000000000000000000000000";
991 runge 435
    int highestBit = 0;
986 runge 436
 
991 runge 437
    for (map<string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
986 runge 438
    {
439
        if (iter->second.getType() == "uint")
440
        {
991 runge 441
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
442
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 443
 
1002 runge 444
            unsigned int a = stou(iter->second.getValue());
986 runge 445
 
446
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
447
        }
448
        else if (iter->second.getType() == "float")
449
        {
991 runge 450
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
451
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 452
 
453
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), float2bin(stof(iter->second.getValue()), iter->second.getBitLength()));
454
        }
1046 runge 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
        }
986 runge 463
        else if (iter->second.getType() == "ascii")
464
        {
465
            for (int n = 0; n < iter->second.getValue().length(); n++)
466
            {
991 runge 467
                if (iter->second.getStartBit()+n*8 + 8 > highestBit)
468
                    highestBit = iter->second.getStartBit()+n*8 + 8;
986 runge 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
            {
991 runge 477
                if (iter->second.getStartBit()+n*4 + 4 > highestBit)
478
                    highestBit = iter->second.getStartBit()+n*4 + 4;
986 runge 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
 
997 runge 488
    try
489
    {
1030 linlun 490
        while (highestBit%8 != 0)
491
        {
492
            highestBit++;
493
        }
494
        bin = bin.substr(0, highestBit);
997 runge 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
    }
986 runge 501
 
502
    return bin2hex(bin);
969 runge 503
}
986 runge 504
 
991 runge 505
map<string, CanVariable> CanIdTranslator::translateData(vector<XmlNode> variableNodes, string dataHex)
506
{
507
    map<string, CanVariable> variables;
508
    string dataBin = hex2bin(dataHex);
997 runge 509
    //dataBin = rpad(dataBin, 64, '0');
991 runge 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"]);
997 runge 517
        string bits;
991 runge 518
 
997 runge 519
        try
520
        {
521
            bits = dataBin.substr(bitStart, bitLength);
522
        }
523
        catch (std::out_of_range& e)
524
        {
525
            return variables;
526
        }
991 runge 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
        {
1002 runge 538
            variable.setValue(utos(bin2uint(bits)));
991 runge 539
        }
540
        else if (attributes["type"] == "float")
541
        {
542
            variable.setValue(ftos(bin2float(bits)));
543
        }
1046 runge 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
        }
991 runge 561
        else if (attributes["type"] == "ascii")
562
        {
563
            string str;
564
 
565
            for (int k = 0; k < bits.length(); k += 8)
566
            {
997 runge 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
                }
991 runge 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
            {
997 runge 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
                }
991 runge 597
            }
598
 
599
            variable.setValue(str);
600
        }
601
 
602
        variables[attributes["name"]] = variable;
603
    }
604
 
605
    return variables;
606
}
607
 
608