Subversion Repositories HomeAutomation

Rev

Details | 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
 
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
    SyslogStream &slog = SyslogStream::getInstance();
45
 
46
    string filename = Settings::get("CanIdXMLFile");
47
 
985 runge 48
    if (file_exists(filename))
49
    {
50
        xmlNode.load(filename.c_str());
969 runge 51
 
985 runge 52
        slog << "Loading definitions from " + filename + ".\n";
53
    }
54
    else
55
    {
56
        slog << "CanIdXMLFile is not defined in the config file, this will probably not work at all.\n";
57
    }
969 runge 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
 
981 runge 105
        if (commandId >= 128)
969 runge 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
 
981 runge 134
            if (commandId >= 128)
969 runge 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
 
986 runge 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
 
969 runge 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
 
991 runge 277
void CanIdTranslator::makeNMTDataValid(int commandId, map<string, CanVariable> &data)
969 runge 278
{
991 runge 279
    vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
969 runge 280
 
281
    for (int n = 0; n < commandNodes.size(); n++)
282
    {
283
        map<string, string> attributes = commandNodes[n].getAttributes();
284
 
991 runge 285
        if (stoi(attributes["id"]) == commandId)
969 runge 286
        {
287
            XmlNode varablesNode = commandNodes[n].findChild("variables");
288
 
991 runge 289
            makeDataValid(varablesNode.getChildren(), data);
969 runge 290
 
991 runge 291
            return;
969 runge 292
        }
293
    }
991 runge 294
}
969 runge 295
 
991 runge 296
void CanIdTranslator::makeDataValid(int commandId, string moduleName, map<string, CanVariable> &data)
297
{
298
    vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
969 runge 299
 
991 runge 300
    for (int n = 0; n < commandNodes.size(); n++)
969 runge 301
    {
991 runge 302
        map<string, string> attributes = commandNodes[n].getAttributes();
969 runge 303
 
1001 runge 304
        bool correct = false;
305
 
306
        if (commandId >= 128)
969 runge 307
        {
1001 runge 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
        {
991 runge 320
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 321
 
991 runge 322
            makeDataValid(varablesNode.getChildren(), data);
969 runge 323
 
991 runge 324
            return;
969 runge 325
        }
991 runge 326
    }
327
}
981 runge 328
 
991 runge 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();
981 runge 335
 
991 runge 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"]));
981 runge 342
        }
969 runge 343
    }
991 runge 344
}
969 runge 345
 
991 runge 346
string CanIdTranslator::translateDataToHex(int commandId, string moduleName, map<string, CanVariable> &data)
347
{
348
    makeDataValid(commandId, moduleName, data);
969 runge 349
 
991 runge 350
    return translateValidDataToHex(data);
969 runge 351
}
352
 
991 runge 353
 
969 runge 354
map<string, CanVariable> CanIdTranslator::translateData(int commandId, string moduleName, string dataHex)
355
{
991 runge 356
    vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
969 runge 357
 
358
    for (int n = 0; n < commandNodes.size(); n++)
359
    {
360
        map<string, string> attributes = commandNodes[n].getAttributes();
361
 
1001 runge 362
        bool correct = false;
363
 
364
        if (commandId >= 128)
969 runge 365
        {
1001 runge 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
        {
969 runge 378
            XmlNode varablesNode = commandNodes[n].findChild("variables");
379
 
991 runge 380
            return translateData(varablesNode.getChildren(), dataHex);
986 runge 381
        }
382
    }
969 runge 383
 
991 runge 384
    map<string, CanVariable> variables;
986 runge 385
    return variables;
386
}
969 runge 387
 
986 runge 388
map<string, CanVariable> CanIdTranslator::translateNMTData(int commandId, string dataHex)
389
{
991 runge 390
    vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
969 runge 391
 
986 runge 392
    for (int n = 0; n < commandNodes.size(); n++)
393
    {
394
        map<string, string> attributes = commandNodes[n].getAttributes();
969 runge 395
 
986 runge 396
        if (stoi(attributes["id"]) == commandId)
397
        {
398
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 399
 
991 runge 400
            return translateData(varablesNode.getChildren(), dataHex);
969 runge 401
        }
402
    }
403
 
991 runge 404
    map<string, CanVariable> variables;
969 runge 405
    return variables;
406
}
407
 
991 runge 408
string CanIdTranslator::translateNMTDataToHex(int commandId, map<string, CanVariable> &data)
969 runge 409
{
991 runge 410
    makeNMTDataValid(commandId, data);
969 runge 411
 
991 runge 412
    return translateValidDataToHex(data);
413
}
969 runge 414
 
991 runge 415
string CanIdTranslator::translateValidDataToHex(map<string, CanVariable> &data)
416
{
986 runge 417
    string bin = "0000000000000000000000000000000000000000000000000000000000000000";
991 runge 418
    int highestBit = 0;
986 runge 419
 
991 runge 420
    for (map<string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
986 runge 421
    {
422
        if (iter->second.getType() == "uint")
423
        {
991 runge 424
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
425
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 426
 
1002 runge 427
            unsigned int a = stou(iter->second.getValue());
986 runge 428
 
429
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
430
        }
431
        else if (iter->second.getType() == "float")
432
        {
991 runge 433
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
434
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 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
            {
991 runge 442
                if (iter->second.getStartBit()+n*8 + 8 > highestBit)
443
                    highestBit = iter->second.getStartBit()+n*8 + 8;
986 runge 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
            {
991 runge 452
                if (iter->second.getStartBit()+n*4 + 4 > highestBit)
453
                    highestBit = iter->second.getStartBit()+n*4 + 4;
986 runge 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
 
997 runge 463
    try
464
    {
465
        bin = bin.substr(0, highestBit);
466
    }
467
    catch (std::out_of_range& e)
468
    {
469
        cout << "DEBUG: translateValidDataToHex exception: " << e.what() << "\n";
470
        cout << "DEBUG: A bin=" << bin << " :: highestBit=" << highestBit << endl;
471
    }
986 runge 472
 
473
    return bin2hex(bin);
969 runge 474
}
986 runge 475
 
991 runge 476
map<string, CanVariable> CanIdTranslator::translateData(vector<XmlNode> variableNodes, string dataHex)
477
{
478
    map<string, CanVariable> variables;
479
    string dataBin = hex2bin(dataHex);
997 runge 480
    //dataBin = rpad(dataBin, 64, '0');
991 runge 481
 
482
    for (int c = 0; c < variableNodes.size(); c++)
483
    {
484
        map<string, string> attributes = variableNodes[c].getAttributes();
485
 
486
        int bitStart = stoi(attributes["start_bit"]);
487
        int bitLength = stoi(attributes["bit_length"]);
997 runge 488
        string bits;
991 runge 489
 
997 runge 490
        try
491
        {
492
            bits = dataBin.substr(bitStart, bitLength);
493
        }
494
        catch (std::out_of_range& e)
495
        {
496
            return variables;
497
        }
991 runge 498
 
499
        CanVariable variable;
500
 
501
        variable.setName(attributes["name"]);
502
        variable.setType(attributes["type"]);
503
        variable.setUnit(attributes["unit"]);
504
        variable.setStartBit(bitStart);
505
        variable.setBitLength(bitLength);
506
 
507
        if (attributes["type"] == "uint")
508
        {
1002 runge 509
            variable.setValue(utos(bin2uint(bits)));
991 runge 510
        }
511
        else if (attributes["type"] == "float")
512
        {
513
            variable.setValue(ftos(bin2float(bits)));
514
        }
515
        else if (attributes["type"] == "ascii")
516
        {
517
            string str;
518
 
519
            for (int k = 0; k < bits.length(); k += 8)
520
            {
997 runge 521
                try
522
                {
523
                    str += (char)bin2uint(bits.substr(k, 8));
524
                }
525
                catch (std::out_of_range& e)
526
                {
527
                    cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
528
                    cout << "DEBUG: B bits=" << bits << " :: k=" << k << endl;
529
                    continue;
530
                }
991 runge 531
            }
532
 
533
            variable.setValue(str);
534
        }
535
        else if (attributes["type"] == "hexstring")
536
        {
537
            string str;
538
 
539
            for (int k = 0; k < bits.length(); k += 4)
540
            {
997 runge 541
                try
542
                {
543
                    str += bin2hex(bits.substr(k, 4));
544
                }
545
                catch (std::out_of_range& e)
546
                {
547
                    cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
548
                    cout << "DEBUG: C bits=" << bits << " :: k=" << k << endl;
549
                    continue;
550
                }
991 runge 551
            }
552
 
553
            variable.setValue(str);
554
        }
555
 
556
        variables[attributes["name"]] = variable;
557
    }
558
 
559
    return variables;
560
}
561
 
562