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
 
991 runge 304
        if ((stoi(attributes["id"]) == commandId) || (commandId >= 128 && (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)))
969 runge 305
        {
991 runge 306
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 307
 
991 runge 308
            makeDataValid(varablesNode.getChildren(), data);
969 runge 309
 
991 runge 310
            return;
969 runge 311
        }
991 runge 312
    }
313
}
981 runge 314
 
991 runge 315
void CanIdTranslator::makeDataValid(vector<XmlNode> variableNodes, map<string, CanVariable> &data)
316
{
317
    ///FIXME: Remove variables that do not exist in the xmlfile
318
    for (int c = 0; c < variableNodes.size(); c++)
319
    {
320
        map<string, string> attributes = variableNodes[c].getAttributes();
981 runge 321
 
991 runge 322
        if (data.find(attributes["name"]) != data.end())
323
        {
324
            data[attributes["name"]].setType(attributes["type"]);
325
            data[attributes["name"]].setUnit(attributes["unit"]);
326
            data[attributes["name"]].setBitLength(stoi(attributes["bit_length"]));
327
            data[attributes["name"]].setStartBit(stoi(attributes["start_bit"]));
981 runge 328
        }
969 runge 329
    }
991 runge 330
}
969 runge 331
 
991 runge 332
string CanIdTranslator::translateDataToHex(int commandId, string moduleName, map<string, CanVariable> &data)
333
{
334
    makeDataValid(commandId, moduleName, data);
969 runge 335
 
991 runge 336
    return translateValidDataToHex(data);
969 runge 337
}
338
 
991 runge 339
 
969 runge 340
map<string, CanVariable> CanIdTranslator::translateData(int commandId, string moduleName, string dataHex)
341
{
991 runge 342
    vector<XmlNode> commandNodes = xmlNode.findChild("commands").getChildren();
969 runge 343
 
344
    for (int n = 0; n < commandNodes.size(); n++)
345
    {
346
        map<string, string> attributes = commandNodes[n].getAttributes();
347
 
991 runge 348
        if ((stoi(attributes["id"]) == commandId) || (commandId >= 128 && (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)))
969 runge 349
        {
350
            XmlNode varablesNode = commandNodes[n].findChild("variables");
351
 
991 runge 352
            return translateData(varablesNode.getChildren(), dataHex);
986 runge 353
        }
354
    }
969 runge 355
 
991 runge 356
    map<string, CanVariable> variables;
986 runge 357
    return variables;
358
}
969 runge 359
 
986 runge 360
map<string, CanVariable> CanIdTranslator::translateNMTData(int commandId, string dataHex)
361
{
991 runge 362
    vector<XmlNode> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
969 runge 363
 
986 runge 364
    for (int n = 0; n < commandNodes.size(); n++)
365
    {
366
        map<string, string> attributes = commandNodes[n].getAttributes();
969 runge 367
 
986 runge 368
        if (stoi(attributes["id"]) == commandId)
369
        {
370
            XmlNode varablesNode = commandNodes[n].findChild("variables");
969 runge 371
 
991 runge 372
            return translateData(varablesNode.getChildren(), dataHex);
969 runge 373
        }
374
    }
375
 
991 runge 376
    map<string, CanVariable> variables;
969 runge 377
    return variables;
378
}
379
 
991 runge 380
string CanIdTranslator::translateNMTDataToHex(int commandId, map<string, CanVariable> &data)
969 runge 381
{
991 runge 382
    makeNMTDataValid(commandId, data);
969 runge 383
 
991 runge 384
    return translateValidDataToHex(data);
385
}
969 runge 386
 
991 runge 387
string CanIdTranslator::translateValidDataToHex(map<string, CanVariable> &data)
388
{
986 runge 389
    string bin = "0000000000000000000000000000000000000000000000000000000000000000";
991 runge 390
    int highestBit = 0;
986 runge 391
 
991 runge 392
    for (map<string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
986 runge 393
    {
394
        if (iter->second.getType() == "uint")
395
        {
991 runge 396
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
397
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 398
 
399
            unsigned int a = stoi(iter->second.getValue());
400
 
401
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
402
        }
403
        else if (iter->second.getType() == "float")
404
        {
991 runge 405
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
406
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
986 runge 407
 
408
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), float2bin(stof(iter->second.getValue()), iter->second.getBitLength()));
409
        }
410
        else if (iter->second.getType() == "ascii")
411
        {
412
            for (int n = 0; n < iter->second.getValue().length(); n++)
413
            {
991 runge 414
                if (iter->second.getStartBit()+n*8 + 8 > highestBit)
415
                    highestBit = iter->second.getStartBit()+n*8 + 8;
986 runge 416
 
417
                bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin((unsigned int)iter->second.getValue()[n], 8));
418
            }
419
        }
420
        else if (iter->second.getType() == "hexstring")
421
        {
422
            for (int n = 0; n < iter->second.getValue().length(); n++)
423
            {
991 runge 424
                if (iter->second.getStartBit()+n*4 + 4 > highestBit)
425
                    highestBit = iter->second.getStartBit()+n*4 + 4;
986 runge 426
 
427
                string character;
428
                character += iter->second.getValue()[n];
429
 
430
                bin.replace(iter->second.getStartBit()+n*4, 4, hex2bin(character));
431
            }
432
        }
433
    }
434
 
997 runge 435
    try
436
    {
437
        bin = bin.substr(0, highestBit);
438
    }
439
    catch (std::out_of_range& e)
440
    {
441
        cout << "DEBUG: translateValidDataToHex exception: " << e.what() << "\n";
442
        cout << "DEBUG: A bin=" << bin << " :: highestBit=" << highestBit << endl;
443
    }
986 runge 444
 
445
    return bin2hex(bin);
969 runge 446
}
986 runge 447
 
991 runge 448
map<string, CanVariable> CanIdTranslator::translateData(vector<XmlNode> variableNodes, string dataHex)
449
{
450
    map<string, CanVariable> variables;
451
    string dataBin = hex2bin(dataHex);
997 runge 452
    //dataBin = rpad(dataBin, 64, '0');
991 runge 453
 
454
    for (int c = 0; c < variableNodes.size(); c++)
455
    {
456
        map<string, string> attributes = variableNodes[c].getAttributes();
457
 
458
        int bitStart = stoi(attributes["start_bit"]);
459
        int bitLength = stoi(attributes["bit_length"]);
997 runge 460
        string bits;
991 runge 461
 
997 runge 462
        try
463
        {
464
            bits = dataBin.substr(bitStart, bitLength);
465
        }
466
        catch (std::out_of_range& e)
467
        {
468
            return variables;
469
        }
991 runge 470
 
471
        CanVariable variable;
472
 
473
        variable.setName(attributes["name"]);
474
        variable.setType(attributes["type"]);
475
        variable.setUnit(attributes["unit"]);
476
        variable.setStartBit(bitStart);
477
        variable.setBitLength(bitLength);
478
 
479
        if (attributes["type"] == "uint")
480
        {
481
            variable.setValue(itos(bin2uint(bits)));
482
        }
483
        else if (attributes["type"] == "float")
484
        {
485
            variable.setValue(ftos(bin2float(bits)));
486
        }
487
        else if (attributes["type"] == "ascii")
488
        {
489
            string str;
490
 
491
            for (int k = 0; k < bits.length(); k += 8)
492
            {
997 runge 493
                try
494
                {
495
                    str += (char)bin2uint(bits.substr(k, 8));
496
                }
497
                catch (std::out_of_range& e)
498
                {
499
                    cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
500
                    cout << "DEBUG: B bits=" << bits << " :: k=" << k << endl;
501
                    continue;
502
                }
991 runge 503
            }
504
 
505
            variable.setValue(str);
506
        }
507
        else if (attributes["type"] == "hexstring")
508
        {
509
            string str;
510
 
511
            for (int k = 0; k < bits.length(); k += 4)
512
            {
997 runge 513
                try
514
                {
515
                    str += bin2hex(bits.substr(k, 4));
516
                }
517
                catch (std::out_of_range& e)
518
                {
519
                    cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
520
                    cout << "DEBUG: C bits=" << bits << " :: k=" << k << endl;
521
                    continue;
522
                }
991 runge 523
            }
524
 
525
            variable.setValue(str);
526
        }
527
 
528
        variables[attributes["name"]] = variable;
529
    }
530
 
531
    return variables;
532
}
533
 
534