Subversion Repositories HomeAutomation

Rev

Rev 1598 | Go to most recent revision | Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1596 runge 1
/*
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License along
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 */
20
 
21
#include "Protocol.h"
22
 
23
#include <stdexcept>
24
 
25
#include <boost/lexical_cast.hpp>
26
 
27
namespace atom {
28
namespace can {
29
 
30
Protocol::Pointer Protocol::instance_ = Protocol::Pointer(new Protocol());
31
 
32
Protocol::Protocol() : LOG("can::Protocol")
33
{
34
}
35
 
36
Protocol::~Protocol()
37
{
38
}
39
 
40
Protocol::Pointer Protocol::Instance()
41
{
42
    return Protocol::instance_;
43
}
44
 
45
void Protocol::Delete()
46
{
47
    Protocol::instance_.reset();
48
}
49
 
50
bool Protocol::Load(std::string filename)
51
{
52
    try
53
    {
54
        this->root_node_.LoadFile(filename);
55
    }
56
    catch (std::runtime_error& e)
57
    {
58
        LOG.Error(e.what());
59
        return false;
60
    }
61
 
62
    LOG.Info("Protocol loaded successfully");
63
    return true;
64
}
65
 
66
std::string Protocol::LookupClassName(unsigned int class_id)
67
{
68
    try
69
    {
70
        return this->root_node_.FindChild("classes").SelectChild("id", boost::lexical_cast<std::string>(class_id)).GetAttributeValue("name");
71
    }
72
    catch (std::runtime_error& e)
73
    {
74
        LOG.Error(e.what());
75
        throw std::runtime_error("No such class_id found, " + boost::lexical_cast<std::string>(class_id));
76
    }
77
}
78
 
79
unsigned int Protocol::ResolveClassId(std::string class_name)
80
{
81
    try
82
    {
83
        return boost::lexical_cast<unsigned int>(this->root_node_.FindChild("classes").SelectChild("name", class_name).GetAttributeValue("id"));
84
    }
85
    catch (std::runtime_error& e)
86
    {
87
        LOG.Error(e.what());
88
        throw std::runtime_error("No such class_name found, " + class_name);
89
    }
90
}
91
 
92
std::string Protocol::LookupCommandName(unsigned int command_id, std::string module_name)
93
{
94
    try
95
    {
96
        if (command_id >= 128)
97
        {
98
            return this->root_node_.FindChild("commands").SelectChild("id", boost::lexical_cast<std::string>(command_id), "module", module_name).GetAttributeValue("name");
99
        }
100
 
101
        return this->root_node_.FindChild("commands").SelectChild("id", boost::lexical_cast<std::string>(command_id)).GetAttributeValue("name");
102
    }
103
    catch (std::runtime_error& e)
104
    {
105
        LOG.Error(e.what());
106
        throw std::runtime_error("No such command found, id = " + boost::lexical_cast<std::string>(command_id) + ", module = " + module_name);
107
    }
108
}
109
 
110
unsigned int Protocol::ResolveCommandId(std::string command_name, std::string module_name)
111
{
112
    try
113
    {
114
        return boost::lexical_cast<unsigned int >(this->root_node_.FindChild("commands").SelectChild("name", command_name, "module", module_name).GetAttributeValue("id"));
115
    }
116
    catch (std::runtime_error& e)
117
    {
118
    }
119
 
120
    try
121
    {
122
        return boost::lexical_cast<unsigned int >(this->root_node_.FindChild("commands").SelectChild("name", command_name).GetAttributeValue("id"));
123
    }
124
    catch (std::runtime_error& e)
125
    {
126
        LOG.Error(e.what());
127
        throw std::runtime_error("No such command found, name = " + command_name + ", module = " + module_name);
128
    }
129
}
130
 
131
std::string Protocol::LookupNMTCommandName(unsigned int command_id)
132
{
133
    try
134
    {
135
        return this->root_node_.FindChild("nmt_messages").SelectChild("id", boost::lexical_cast<std::string>(command_id)).GetAttributeValue("name");
136
    }
137
    catch (std::runtime_error& e)
138
    {
139
        LOG.Error(e.what());
140
        throw std::runtime_error("No such nmt command found, id = " + boost::lexical_cast<std::string>(command_id));
141
    }
142
}
143
 
144
unsigned int Protocol::ResolveNMTCommandId(std::string command_name)
145
{
146
    try
147
    {
148
        return boost::lexical_cast<unsigned int >(this->root_node_.FindChild("nmt_messages").SelectChild("name", command_name).GetAttributeValue("id"));
149
    }
150
    catch (std::runtime_error& e)
151
    {
152
        LOG.Error(e.what());
153
        throw std::runtime_error("No such nmt command found, name = " + command_name);
154
    }
155
}
156
 
157
std::string Protocol::GetDefineId(std::string name, std::string group)
158
{
159
    try
160
    {
161
        return this->root_node_.FindChild("defines").SelectChild("name", name, "group", group).GetAttributeValue("id");
162
    }
163
    catch (std::runtime_error& e)
164
    {
165
        LOG.Error(e.what());
166
        throw std::runtime_error("No such define found, name = " + name + ", group = " + group);
167
    }
168
}
169
 
170
std::string Protocol::LookupDirectionFlag(unsigned int direction_flag)
171
{
172
    try
173
    {
174
        return this->root_node_.FindChild("defines").SelectChild("id", boost::lexical_cast<std::string>(direction_flag), "group", "DirectionFlag").GetAttributeValue("name");
175
    }
176
    catch (std::runtime_error& e)
177
    {
178
        LOG.Error(e.what());
179
        throw std::runtime_error("No such direction flag found, direction_flag = " + boost::lexical_cast<std::string>(direction_flag));
180
    }
181
}
182
 
183
unsigned int Protocol::ResolveDirectionFlag(std::string direction_name)
184
{
185
    try
186
    {
187
        return boost::lexical_cast<unsigned int>(this->root_node_.FindChild("defines").SelectChild("name", direction_name, "group", "DirectionFlag").GetAttributeValue("id"));
188
    }
189
    catch (std::runtime_error& e)
190
    {
191
        LOG.Error(e.what());
192
        throw std::runtime_error("No such direction flag found, direction_name = " + direction_name);
193
    }
194
}
195
 
196
std::string Protocol::LookupModuleName(unsigned int module_id)
197
{
198
    try
199
    {
200
        return this->root_node_.FindChild("modules").SelectChild("id", boost::lexical_cast<std::string>(module_id)).GetAttributeValue("name");
201
    }
202
    catch (std::runtime_error& e)
203
    {
204
        LOG.Error(e.what());
205
        throw std::runtime_error("No such module id found, " + boost::lexical_cast<std::string>(module_id));
206
    }
207
}
208
 
209
unsigned int Protocol::ResolveModuleId(std::string module_name)
210
{
211
    try
212
    {
213
        return boost::lexical_cast<unsigned int>(this->root_node_.FindChild("modules").SelectChild("name", module_name).GetAttributeValue("id"));
214
    }
215
    catch (std::runtime_error& e)
216
    {
217
        LOG.Error(e.what());
218
        throw std::runtime_error("No such module name found, " + module_name);
219
    }
220
}
221
 
222
xml::Node::NodeList Protocol::GetCommandVariables(std::string command_name, std::string module_name)
223
{
224
    try
225
    {
226
        return this->root_node_.FindChild("commands").SelectChild("name", command_name, "module", module_name).FindChild("variables").GetChildren();
227
    }
228
    catch (std::runtime_error& e)
229
    {
230
    }
231
 
232
    try
233
    {
234
        return this->root_node_.FindChild("commands").SelectChild("name", command_name).FindChild("variables").GetChildren();
235
    }
236
    catch (std::runtime_error& e)
237
    {
238
        LOG.Error(e.what());
239
        throw std::runtime_error("No such command found, name = " + command_name + ", module = " + module_name);
240
    }
241
}
242
 
243
xml::Node::NodeList Protocol::GetNMTCommandVariables(std::string command_name)
244
{
245
    try
246
    {
247
        return this->root_node_.FindChild("nmt_messages").SelectChild("name", command_name).FindChild("variables").GetChildren();
248
    }
249
    catch (std::runtime_error& e)
250
    {
251
        LOG.Error(e.what());
252
        throw std::runtime_error("No such nmt command found, name = " + command_name);
253
    }
254
}
255
 
256
 
257
 
258
 
259
 
260
 
261
 
262
 
263
 
264
 
265
 
266
 
267
/*
268
 
269
 
270
 
271
 
272
 
273
void Protocol::makeNMTDataValid(std::string commandName, map<std::string, CanVariable> &data)
274
{
275
    std::vector<Node> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
276
 
277
    for (int n = 0; n < commandNodes.size(); n++)
278
    {
279
        map<std::string, std::string> attributes = commandNodes[n].getAttributes();
280
 
281
        if (attributes["name"] == commandName)
282
        {
283
            Node varablesNode = commandNodes[n].findChild("variables");
284
 
285
            makeDataValid(varablesNode.getChildren(), data);
286
 
287
            return;
288
        }
289
    }
290
}
291
 
292
void Protocol::makeDataValid(int commandId, std::string moduleName, map<std::string, CanVariable> &data)
293
{
294
    std::vector<Node> commandNodes = xmlNode.findChild("commands").getChildren();
295
 
296
    for (int n = 0; n < commandNodes.size(); n++)
297
    {
298
        map<std::string, std::string> attributes = commandNodes[n].getAttributes();
299
 
300
        bool correct = false;
301
 
302
        if (commandId >= 128)
303
        {
304
            if (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)
305
            {
306
                correct = true;
307
            }
308
        }
309
        else if (stoi(attributes["id"]) == commandId)
310
        {
311
            correct = true;
312
        }
313
 
314
        if (correct)
315
        {
316
            Node varablesNode = commandNodes[n].findChild("variables");
317
 
318
            makeDataValid(varablesNode.getChildren(), data);
319
 
320
            return;
321
        }
322
    }
323
}
324
 
325
void Protocol::makeDataValid(std::vector<Node> variableNodes, map<std::string, CanVariable> &data)
326
{
327
    ///FIXME: Remove variables that do not exist in the xmlfile
328
    for (int c = 0; c < variableNodes.size(); c++)
329
    {
330
        map<std::string, std::string> attributes = variableNodes[c].getAttributes();
331
 
332
        if (data.find(attributes["name"]) != data.end())
333
        {
334
            data[attributes["name"]].setType(attributes["type"]);
335
            data[attributes["name"]].setUnit(attributes["unit"]);
336
            data[attributes["name"]].setBitLength(stoi(attributes["bit_length"]));
337
            data[attributes["name"]].setStartBit(stoi(attributes["start_bit"]));
338
 
339
            if (attributes["type"] == "enum")
340
            {
341
                std::vector<Node> values = variableNodes[c].getChildren();
342
 
343
                for (int k = 0; k < values.size(); k++)
344
                {
345
                    map<std::string, std::string> valueAttributes = values[k].getAttributes();
346
                    data[attributes["name"]].addEnumValue(valueAttributes["id"], valueAttributes["name"]);
347
                }
348
            }
349
        }
350
    }
351
}
352
 
353
std::string Protocol::translateDataToHex(int commandId, std::string moduleName, map<std::string, CanVariable> &data)
354
{
355
    makeDataValid(commandId, moduleName, data);
356
 
357
    return translateValidDataToHex(data);
358
}
359
 
360
 
361
map<std::string, CanVariable> Protocol::translateData(int commandId, std::string moduleName, std::string dataHex)
362
{
363
    std::vector<Node> commandNodes = xmlNode.findChild("commands").getChildren();
364
 
365
    for (int n = 0; n < commandNodes.size(); n++)
366
    {
367
        map<std::string, std::string> attributes = commandNodes[n].getAttributes();
368
 
369
        bool correct = false;
370
 
371
        if (commandId >= 128)
372
        {
373
            if (stoi(attributes["id"]) == commandId && attributes["module"] == moduleName)
374
            {
375
                correct = true;
376
            }
377
        }
378
        else if (stoi(attributes["id"]) == commandId)
379
        {
380
            correct = true;
381
        }
382
 
383
        if (correct)
384
        {
385
            Node varablesNode = commandNodes[n].findChild("variables");
386
 
387
            return translateData(varablesNode.getChildren(), dataHex);
388
        }
389
    }
390
 
391
    map<std::string, CanVariable> variables;
392
    return variables;
393
}
394
 
395
map<std::string, CanVariable> Protocol::translateNMTData(int commandId, std::string dataHex)
396
{
397
    std::vector<Node> commandNodes = xmlNode.findChild("nmt_messages").getChildren();
398
 
399
    for (int n = 0; n < commandNodes.size(); n++)
400
    {
401
        map<std::string, std::string> attributes = commandNodes[n].getAttributes();
402
 
403
        if (stoi(attributes["id"]) == commandId)
404
        {
405
            Node varablesNode = commandNodes[n].findChild("variables");
406
 
407
            return translateData(varablesNode.getChildren(), dataHex);
408
        }
409
    }
410
 
411
    map<std::string, CanVariable> variables;
412
    return variables;
413
}
414
 
415
std::string Protocol::translateNMTDataToHex(std::string commandName, map<std::string, CanVariable> &data)
416
{
417
    makeNMTDataValid(commandName, data);
418
 
419
    return translateValidDataToHex(data);
420
}
421
 
422
 
423
template <class T>
424
bool from_std::string(T& t,
425
                const std::std::string& s,
426
                std::ios_base& (*f)(std::ios_base&))
427
{
428
    std::istd::stringstream iss(s);
429
    return !(iss >> f >> t).fail();
430
}
431
 
432
 
433
std::string Protocol::translateValidDataToHex(map<std::string, CanVariable> &data)
434
{
435
    std::string bin = "0000000000000000000000000000000000000000000000000000000000000000";
436
    int highestBit = 0;
437
 
438
    for (map<std::string, CanVariable>::iterator iter = data.begin(); iter != data.end(); iter++)
439
    {
440
        if (iter->second.getType() == "uint")
441
        {
442
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
443
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
444
 
445
            unsigned int a = stou(iter->second.getValue());
446
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
447
        }
448
        else if (iter->second.getType() == "int")
449
        {
450
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
451
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
452
 
453
            unsigned int a = stou(iter->second.getValue());
454
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(a, iter->second.getBitLength()));
455
 
456
        }
457
        else if (iter->second.getType() == "float")
458
        {
459
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
460
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
461
            bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), float2bin(stof(iter->second.getValue()), iter->second.getBitLength()));
462
 
463
        }
464
        else if (iter->second.getType() == "enum")
465
        {
466
            if (iter->second.getStartBit() + iter->second.getBitLength() > highestBit)
467
                highestBit = iter->second.getStartBit() + iter->second.getBitLength();
468
 
469
            std::string value = iter->second.getEnumIdValue();
470
 
471
            if (value == "")
472
            {
473
                throw new CanMessageException("Got enum that could not be converterd to a value. value = \"" + iter->second.getValue() + "\" enumString is \"" + iter->second.getEnumsString() + "\"\n");
474
            }
475
            else
476
            {
477
                bin.replace(iter->second.getStartBit(), iter->second.getBitLength(), uint2bin(stou(value), iter->second.getBitLength()));
478
            }
479
        }
480
        else if (iter->second.getType() == "ascii")
481
        {
482
            for (int n = 0; n < iter->second.getValue().length(); n++)
483
            {
484
                if (iter->second.getStartBit()+n*8 + 8 > highestBit)
485
                    highestBit = iter->second.getStartBit()+n*8 + 8;
486
 
487
                //bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin((unsigned int)iter->second.getValue()[n], 8));
488
                    unsigned int temp = iter->second.getValue()[n];
489
                    if (temp > 0xff)
490
                    {
491
                        temp &= 0xff;
492
                    }
493
                    bin.replace(iter->second.getStartBit()+n*8, 8, uint2bin(temp, 8));
494
            }
495
        }
496
        else if (iter->second.getType() == "hexstd::string")
497
        {
498
            for (int n = 0; n < iter->second.getValue().length(); n++)
499
            {
500
                if (iter->second.getStartBit()+n*4 + 4 > highestBit)
501
                    highestBit = iter->second.getStartBit()+n*4 + 4;
502
 
503
                std::string character;
504
                character += iter->second.getValue()[n];
505
 
506
                bin.replace(iter->second.getStartBit()+n*4, 4, hex2bin(character));
507
            }
508
        }
509
    }
510
 
511
    try
512
    {
513
        while (highestBit%8 != 0)
514
        {
515
            highestBit++;
516
        }
517
        bin = bin.substr(0, highestBit);
518
    }
519
    catch (std::out_of_range& e)
520
    {
521
        cout << "DEBUG: translateValidDataToHex exception: " << e.what() << "\n";
522
        cout << "DEBUG: A bin=" << bin << " :: highestBit=" << highestBit << endl;
523
    }
524
 
525
    return bin2hex(bin);
526
}
527
 
528
map<std::string, CanVariable> Protocol::translateData(std::vector<Node> variableNodes, std::string dataHex)
529
{
530
    map<std::string, CanVariable> variables;
531
    std::string dataBin = hex2bin(dataHex);
532
    //dataBin = rpad(dataBin, 64, '0');
533
 
534
    for (int c = 0; c < variableNodes.size(); c++)
535
    {
536
        map<std::string, std::string> attributes = variableNodes[c].getAttributes();
537
 
538
        int bitStart = stoi(attributes["start_bit"]);
539
        int bitLength = stoi(attributes["bit_length"]);
540
        std::string bits;
541
 
542
        try
543
        {
544
            bits = dataBin.substr(bitStart, bitLength);
545
        }
546
        catch (std::out_of_range& e)
547
        {
548
            return variables;
549
        }
550
 
551
        CanVariable variable;
552
 
553
        variable.setName(attributes["name"]);
554
        variable.setType(attributes["type"]);
555
        variable.setUnit(attributes["unit"]);
556
        variable.setStartBit(bitStart);
557
        variable.setBitLength(bitLength);
558
 
559
        if (attributes["type"] == "uint")
560
        {
561
            variable.setValue(utos(bin2uint(bits)));
562
        }
563
        else if (attributes["type"] == "int")
564
        {
565
            variable.setValue(itos(bin2int(bits)));
566
        }
567
        else if (attributes["type"] == "float")
568
        {
569
            variable.setValue(ftos(bin2float(bits)));
570
        }
571
        else if (attributes["type"] == "enum")
572
        {
573
            std::vector<Node> values = variableNodes[c].getChildren();
574
 
575
            std::string value = utos(bin2uint(bits));
576
 
577
            for (int k = 0; k < values.size(); k++)
578
            {
579
                map<std::string, std::string> valueAttributes = values[k].getAttributes();
580
                variable.addEnumValue(valueAttributes["id"], valueAttributes["name"]);
581
 
582
                if (valueAttributes["id"] == value)
583
                {
584
                    variable.setValue(valueAttributes["name"]);
585
                }
586
            }
587
        }
588
        else if (attributes["type"] == "ascii")
589
        {
590
            std::string str;
591
 
592
            for (int k = 0; k < bits.length(); k += 8)
593
            {
594
                try
595
                {
596
                    str += (char)bin2uint(bits.substr(k, 8));
597
                }
598
                catch (std::out_of_range& e)
599
                {
600
                    cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
601
                    cout << "DEBUG: B bits=" << bits << " :: k=" << k << endl;
602
                    continue;
603
                }
604
            }
605
 
606
            variable.setValue(str);
607
        }
608
        else if (attributes["type"] == "hexstd::string")
609
        {
610
            std::string str;
611
 
612
            for (int k = 0; k < bits.length(); k += 4)
613
            {
614
                try
615
                {
616
                    str += bin2hex(bits.substr(k, 4));
617
                }
618
                catch (std::out_of_range& e)
619
                {
620
                    cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
621
                    cout << "DEBUG: C bits=" << bits << " :: k=" << k << endl;
622
                    continue;
623
                }
624
            }
625
 
626
            variable.setValue(str);
627
        }
628
 
629
        variables[attributes["name"]] = variable;
630
    }
631
 
632
    return variables;
633
}
634
 
635
 
636
   */
637
 
638
 
639
 
640
 
641
 
642
 
643
 
644
 
645
 
646
}; // namespace can
647
}; // namespace atom