Subversion Repositories HomeAutomation

Rev

Rev 1959 | Rev 1987 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1595 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 "Network.h"
22
 
23
#include <vector>
24
 
25
#include <boost/algorithm/string.hpp>
26
#include <boost/lexical_cast.hpp>
27
 
28
#include "net/Manager.h"
29
 
1596 runge 30
#include "broker/Manager.h"
31
 
32
#include "Protocol.h"
33
#include "Message.h"
34
 
1642 runge 35
#include "common/Bitset.h"
36
#include "common/common.h"
1596 runge 37
 
1595 runge 38
namespace atom {
39
namespace can {
40
 
1596 runge 41
enum
1595 runge 42
{
1596 runge 43
    PACKET_START = 253,
44
    PACKET_END   = 250,
45
    PACKET_PING  = 251
46
};
47
 
1916 runge 48
Network::Network(std::string address): broker::Subscriber(false), buffer_(2048), LOG("can::Network")
1596 runge 49
{
1595 runge 50
    this->address_ = address;
51
    this->client_id_ = 0;
52
 
53
    // Examples of address
54
    // udp:192.168.1.250:1100
55
    // serial:/dev/ttyUSB0:38400
56
 
1642 runge 57
    common::StringList parts;
1595 runge 58
    boost::algorithm::split(parts, address, boost::is_any_of(":"), boost::algorithm::token_compress_off);
59
 
60
    if (parts.size() < 3)
61
    {
62
        LOG.Error("Malformed address string: " + address);
63
        return;
64
    }
65
 
66
    boost::algorithm::to_lower(parts[0]);
67
 
68
    if (parts[0] == "udp")
69
    {
70
        this->protocol_ = net::PROTOCOL_UDP;
71
    }
72
    else if (parts[0] == "serial")
73
    {
74
        this->protocol_ = net::PROTOCOL_SERIAL;
75
    }
76
    else
77
    {
78
        LOG.Error("Unknown protocol, only support udp and serial, got " + parts[0]);
79
        return;
80
    }
81
 
82
    this->address_ = parts[1];
83
    this->port_or_baud_ = boost::lexical_cast<unsigned int>(parts[2]);
84
 
85
    try
86
    {
87
        this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
1596 runge 88
        LOG.Info("Connected to " + address);
1595 runge 89
 
1599 runge 90
        LOG.Info("Sending ping...");
91
 
1642 runge 92
        common::Byteset buffer(1);
1596 runge 93
        buffer[0] = PACKET_PING;
94
 
95
        net::Manager::Instance()->SendTo(this->client_id_, buffer);
1595 runge 96
    }
1606 runge 97
    catch (std::runtime_error& e)
1595 runge 98
    {
99
        LOG.Error(e.what());
100
    }
101
}
102
 
103
Network::~Network()
104
{
105
    net::Manager::Instance()->Disconnect(this->client_id_);
106
}
107
 
1596 runge 108
void Network::SlotOnTimeout(timer::TimerId timer_id)
109
{
110
    if (timer_id == this->timer_id_)
111
    {
112
        this->io_service_.post(boost::bind(&Network::SlotOnTimeoutHandler, this, timer_id));
113
    }
114
}
115
 
1595 runge 116
void Network::SlotOnMessageHandler(broker::Message::Pointer message)
117
{
1596 runge 118
    if (message->GetType() == broker::Message::CAN_MESSAGE)
119
    {
120
        Message* payload = static_cast<Message*>(message->GetPayload().get());
1642 runge 121
        common::Byteset data(17);
1596 runge 122
 
1598 runge 123
        data[0] = PACKET_START;
1596 runge 124
 
1598 runge 125
        unsigned int class_id = Protocol::Instance()->ResolveClassId(payload->GetClassName());
126
        data[4] = class_id << 1;
127
 
128
        if (payload->GetClassName() == "nmt")
129
        {
130
            unsigned int command_id = Protocol::Instance()->ResolveNMTCommandId(payload->GetCommandName());
131
            data[3] = command_id;
132
        }
133
        else
134
        {
135
            unsigned int direction_flag = Protocol::Instance()->ResolveDirectionFlag(payload->GetDirectionName());
136
            data[4] |= (direction_flag & 0x01);
137
 
138
            unsigned int module_id = Protocol::Instance()->ResolveModuleId(payload->GetModuleName());
139
            data[3] = module_id;
140
 
141
            data[2] = payload->GetId();
142
 
143
            unsigned int command_id = Protocol::Instance()->ResolveCommandId(payload->GetCommandName(), payload->GetModuleName());
144
            data[1] = command_id;
145
        }
1596 runge 146
 
1598 runge 147
        unsigned int highest_bit = 0;
1642 runge 148
        common::Bitset databits(64);
1598 runge 149
 
150
        xml::Node::NodeList variable_nodes;
151
        unsigned int start_bit;
152
        unsigned int bit_length;
153
        std::string type;
154
        std::string value;
155
 
156
        if (payload->GetClassName() == "nmt")
157
        {
158
            variable_nodes = Protocol::Instance()->GetNMTCommandVariables(payload->GetCommandName());
159
        }
160
        else
161
        {
162
            variable_nodes = Protocol::Instance()->GetCommandVariables(payload->GetCommandName(), payload->GetModuleName());
163
        }
164
 
165
        for (unsigned int n = 0; n < variable_nodes.size(); n++)
166
        {
167
            value = payload->GetVariable(variable_nodes[n].GetAttributeValue("name"));
1607 runge 168
            //LOG.Debug(variable_nodes[n].GetAttributeValue("name") + "=" + value); 
1598 runge 169
            if (value == "")
170
            {
171
                continue;
172
            }
173
 
174
            start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
175
            bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
176
            type = variable_nodes[n].GetAttributeValue("type");
177
 
178
            if (type == "int")
179
            {
180
                Protocol::Instance()->EncodeInt(databits, start_bit, bit_length, value);
181
            }
182
            else if (type == "float")
183
            {
184
                Protocol::Instance()->EncodeFloat(databits, start_bit, bit_length, value);
185
            }
186
            else if (type == "ascii")
187
            {
188
                Protocol::Instance()->EncodeAscii(databits, start_bit, bit_length, value);
1610 runge 189
                bit_length = value.length() * 8;
1598 runge 190
            }
191
            else if (type == "hexstring")
192
            {
193
                Protocol::Instance()->EncodeHexstring(databits, start_bit, bit_length, value);
1610 runge 194
                bit_length = value.length() * 4;
1598 runge 195
            }
196
            else if (type == "enum")
197
            {
198
                value = variable_nodes[n].SelectChild("name", value).GetAttributeValue("id");
199
                Protocol::Instance()->EncodeUint(databits, start_bit, bit_length, value);
200
            }
201
            else// if (type == "uint")
202
            {
203
                Protocol::Instance()->EncodeUint(databits, start_bit, bit_length, value);
204
            }
1840 linlun 205
 
206
            if (highest_bit < start_bit + bit_length)
1610 runge 207
            {
1840 linlun 208
                highest_bit = start_bit + bit_length;
1610 runge 209
            }
1598 runge 210
        }
211
 
212
        //LOG.Debug(databits.ToDebugString());
213
 
1646 runge 214
        unsigned int length = std::min((int)ceil((float)highest_bit / 8.0f), 8);
1598 runge 215
 
216
        data[5] = 1;
217
        data[6] = 0;
218
 
219
        data[7] = length;
220
 
221
        for (unsigned int n = 0; n < 8; n++)
222
        {
223
            data[8 + n] = databits.GetBytes()[n];
224
        }
225
 
226
        data[16] = PACKET_END;
227
 
228
        data.SetSize(17);
229
 
230
        //LOG.Debug("Bytes: " + data.ToDebugString());
231
        net::Manager::Instance()->SendTo(this->client_id_, data);
1917 linlun 232
    } else if (message->GetType() == broker::Message::CAN_RAW_MESSAGE)
233
    {
1918 linlun 234
 
1917 linlun 235
        std::string* payload_str;
236
    payload_str = static_cast<std::string*>(message->GetPayload().get());
237
    std::string line = *payload_str;
238
        common::Byteset data(17);
1919 linlun 239
        //LOG.Info("Got "+ line + "end");
1918 linlun 240
 
1917 linlun 241
        data[0] = PACKET_START;
242
        std::string value = line.substr(4,2);
1918 linlun 243
    //LOG.Info("<"+ value + ">");
1919 linlun 244
    data[4] = common::FromHex(value);
1918 linlun 245
    //LOG.Info("id1: " + value + " data: ");//+ data[1]);
1917 linlun 246
 
247
    value = line.substr(6,2);
1918 linlun 248
    //LOG.Info("<"+ value + ">");
1917 linlun 249
 
1919 linlun 250
    data[3] = common::FromHex(value);
1918 linlun 251
    //LOG.Info("id2: " + value + " data: ");//+ data[2]);
252
 
1917 linlun 253
    value = line.substr(8,2);
1919 linlun 254
    data[2] = common::FromHex(value);
1918 linlun 255
    //LOG.Info("id3: " + value + " data: ");//+ data[3]);
1917 linlun 256
 
257
    value = line.substr(10,2);
1919 linlun 258
    data[1] = common::FromHex(value);
1918 linlun 259
    //LOG.Info("id4: " + value + " data: ");//+ data[4]);
1917 linlun 260
 
261
    value = line.substr(13,1);
1918 linlun 262
    data[5] = common::FromHex(value);
263
    //LOG.Info("1: " + value + " data: ");//+ data[5]);
1917 linlun 264
 
265
    value = line.substr(15,1);
1918 linlun 266
    data[6] = common::FromHex(value);
267
    //LOG.Info("1: " + value + " data: ");//+ data[6]);
1917 linlun 268
 
269
        unsigned char length = 0;
1919 linlun 270
        unsigned char index = 0;
1917 linlun 271
        while (length < 8 && index + 16 < (unsigned char)line.length())
272
        {
1918 linlun 273
            value = line.substr(index+17,2);
274
        data[8+length] = common::FromHex(value);
275
        //LOG.Info("data: " + value + " data: ");//+ data[6]);
1917 linlun 276
        index += 3;
277
        length++;
278
        }
279
 
280
        data[7] = length;
281
        data[16] = PACKET_END;
282
 
283
        data.SetSize(17);
284
 
1919 linlun 285
        //LOG.Info("Bytes: " + data.ToDebugString());
1917 linlun 286
        net::Manager::Instance()->SendTo(this->client_id_, data);
1596 runge 287
    }
1595 runge 288
}
289
 
1986 runge 290
void Network::SlotOnNewDataHandler(net::SocketId client_id, common::Byteset data)
1595 runge 291
{
1598 runge 292
    if (client_id != this->client_id_)
293
    {
1986 runge 294
      return;
1598 runge 295
    }
296
 
1596 runge 297
    static bool have_start = false;
298
 
299
    for (unsigned int n = 0; n < data.GetSize(); n++)
300
    {
301
        if (have_start)
302
        {
303
            if (data[n] == PACKET_END && this->buffer_.GetSize() == 15)
304
            {
305
                this->ProcessBuffer();
306
                have_start = false;
307
            }
308
            else
309
            {
310
                this->buffer_.Append(data[n]);
311
            }
312
        }
313
        else if (data[n] == PACKET_START)
314
        {
315
            this->buffer_.Clear();
316
            have_start = true;
317
        }
318
        else if (data[n] == PACKET_PING)
319
        {
320
            LOG.Info("Received pong.");
321
        }
322
    }
1595 runge 323
}
324
 
1986 runge 325
void Network::SlotOnNewClientHandler(net::SocketId id, net::SocketId server_id)
1595 runge 326
{
1986 runge 327
 
328
}
329
 
330
void Network::SlotOnNewStateHandler(net::SocketId client_id, net::ClientState client_state)
331
{
1598 runge 332
    if (client_id != this->client_id_)
333
    {
334
        return;
335
    }
336
 
1595 runge 337
    if (client_state == net::CLIENT_STATE_DISCONNECTED)
338
    {
1596 runge 339
        LOG.Warning("Got disconnected, setting reconnect timer...");
340
 
1646 runge 341
        this->timer_id_ = timer::Manager::Instance()->SetTimer(10000, true);
1595 runge 342
        this->client_id_ = 0;
1596 runge 343
    }
344
    else
345
    {
346
        LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
347
    }
348
}
349
 
350
void Network::SlotOnTimeoutHandler(timer::TimerId timer_id)
351
{
352
    try
353
    {
354
        this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
355
        LOG.Info("Connected again.");
1595 runge 356
 
1596 runge 357
        timer::Manager::Instance()->Cancel(timer_id);
358
        this->timer_id_ = 0;
359
    }
1606 runge 360
    catch (std::runtime_error& e)
1596 runge 361
    {
362
        LOG.Error(e.what());
363
        LOG.Warning("Will try again soon...");
364
    }
365
}
366
 
367
void Network::ProcessBuffer()
368
{
369
    try
370
    {
371
        std::string class_name = "";
372
        std::string direction_name = "";
373
        std::string module_name = "";
374
        unsigned int id = 0;
375
        std::string command_name = "";
376
 
1916 runge 377
    std::string PKTstring = "PKT " +
378
                atom::common::ToHex8bit((unsigned int)this->buffer_[3]) +
379
                atom::common::ToHex8bit((unsigned int)this->buffer_[2]) +
380
                atom::common::ToHex8bit((unsigned int)this->buffer_[1]) +
381
                atom::common::ToHex8bit((unsigned int)this->buffer_[0]) +
382
                " " +
383
                atom::common::ToHex4bit((unsigned int)this->buffer_[4]) +
384
                " " +
385
                atom::common::ToHex4bit((unsigned int)this->buffer_[5]);
386
 
387
    for (unsigned int index = 7; index < 7 + (unsigned int)this->buffer_[6]; index++)
388
    {
389
        PKTstring += " " + atom::common::ToHex8bit((unsigned int)this->buffer_[index]) ;
1914 linlun 390
    }
1916 runge 391
 
1914 linlun 392
    PKTstring += "\n";
1916 runge 393
 
1915 linlun 394
    //LOG.Info(PKTstring);
1916 runge 395
 
1914 linlun 396
    std::string* payload_str = new std::string(PKTstring);
397
    broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_RAW_MESSAGE, broker::Message::PayloadPointer(payload_str), this)));
1916 runge 398
 
1914 linlun 399
 
1596 runge 400
        unsigned int class_id = (this->buffer_[3] >> 1) & 0x0F;
1607 runge 401
        //LOG.Debug("class_id=" + boost::lexical_cast<std::string>(class_id));
1596 runge 402
        class_name = Protocol::Instance()->LookupClassName(class_id);
403
 
404
        if (class_name == "nmt")
1595 runge 405
        {
1596 runge 406
            unsigned int command_id = this->buffer_[2];
1607 runge 407
            //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id));
1596 runge 408
            command_name = Protocol::Instance()->LookupNMTCommandName(command_id);
1595 runge 409
        }
1596 runge 410
        else
1595 runge 411
        {
1596 runge 412
            unsigned int direction_flag = this->buffer_[3] & 0x01;
1607 runge 413
            //LOG.Debug("direction_flag=" + boost::lexical_cast<std::string>(direction_flag));
1596 runge 414
            direction_name = Protocol::Instance()->LookupDirectionFlag(direction_flag);
415
 
416
            unsigned int module_id = this->buffer_[2];
1607 runge 417
            //LOG.Debug("module_id=" + boost::lexical_cast<std::string>(module_id));
1596 runge 418
            module_name = Protocol::Instance()->LookupModuleName(module_id);
1646 runge 419
            //LOG.Debug("module_name=" + module_name);
1596 runge 420
            id = this->buffer_[1];
421
 
422
            unsigned int command_id = this->buffer_[0];
1607 runge 423
            //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id));
1596 runge 424
            command_name = Protocol::Instance()->LookupCommandName(command_id, module_name);
1646 runge 425
            //LOG.Debug("command_name=" + command_name);
1595 runge 426
        }
1596 runge 427
 
428
        Message* payload = new Message(class_name, direction_name, module_name, id, command_name);
429
 
430
        unsigned int length = this->buffer_[6];
431
 
1642 runge 432
        common::Byteset data_set(length);
1596 runge 433
 
434
        for (unsigned int n = 0; n < length; n++)
435
        {
436
            data_set.Append(this->buffer_[n + 7]);
437
        }
1598 runge 438
 
1642 runge 439
        common::Bitset databits(data_set);
1596 runge 440
        xml::Node::NodeList variable_nodes;
1598 runge 441
        unsigned int start_bit;
1607 runge 442
        int bit_length;
1598 runge 443
        std::string type;
444
        std::string value;
1607 runge 445
        std::string name;
1596 runge 446
 
447
        if (class_name == "nmt")
448
        {
449
            variable_nodes = Protocol::Instance()->GetNMTCommandVariables(command_name);
450
        }
451
        else
452
        {
453
            variable_nodes = Protocol::Instance()->GetCommandVariables(command_name, module_name);
454
        }
455
 
456
        for (unsigned int n = 0; n < variable_nodes.size(); n++)
457
        {
1607 runge 458
            name = variable_nodes[n].GetAttributeValue("name");
1598 runge 459
            start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
460
            bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
1607 runge 461
 
462
            if (databits.GetCount() < start_bit + bit_length)
463
            {
464
                bit_length = databits.GetCount() - start_bit;
465
 
466
                if (bit_length <= 0)
467
                {
1610 runge 468
                    LOG.Warning("Can not read variable " + name + " for command " + command_name + ", message is to short, is there a match between the module and the protocol XML file?");
1607 runge 469
                    //LOG.Debug("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ", bit_length=" + boost::lexical_cast<std::string>(bit_length) + ", databits.GetCount()=" + boost::lexical_cast<std::string>(databits.GetCount()));
470
                    continue;
471
                }
472
            }
473
 
1598 runge 474
            type = variable_nodes[n].GetAttributeValue("type");
1596 runge 475
 
1597 runge 476
            if (type == "int")
1596 runge 477
            {
1598 runge 478
                value = Protocol::Instance()->DecodeInt(databits, start_bit, bit_length);
1597 runge 479
            }
480
            else if (type == "float")
481
            {
1598 runge 482
                value = Protocol::Instance()->DecodeFloat(databits, start_bit, bit_length);
1597 runge 483
            }
484
            else if (type == "ascii")
485
            {
1598 runge 486
                value = Protocol::Instance()->DecodeAscii(databits, start_bit, bit_length);
1597 runge 487
            }
488
            else if (type == "hexstring")
489
            {
1598 runge 490
                value = Protocol::Instance()->DecodeHexstring(databits, start_bit, bit_length);
1597 runge 491
            }
492
            else if (type == "enum")
493
            {
1607 runge 494
                //LOG.Debug("Enum: command name=" + command_name);
1598 runge 495
                value = Protocol::Instance()->DecodeUint(databits, start_bit, bit_length);
1607 runge 496
                //LOG.Debug("Enum: value=" + boost::lexical_cast<std::string>(value));
497
                //LOG.Debug("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ", bit_length=" + boost::lexical_cast<std::string>(bit_length));
498
 
1596 runge 499
                value = variable_nodes[n].SelectChild("id", value).GetAttributeValue("name");
500
            }
1597 runge 501
            else// if (type == "uint")
502
            {
1607 runge 503
                //LOG.Debug("type: type=" + type);
1598 runge 504
                value = Protocol::Instance()->DecodeUint(databits, start_bit, bit_length);
1597 runge 505
            }
1596 runge 506
 
1607 runge 507
            payload->SetVariable(name, value);
1596 runge 508
        }
509
 
510
        broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
1595 runge 511
    }
1596 runge 512
    catch (std::runtime_error& e)
1595 runge 513
    {
1596 runge 514
        LOG.Error("Malformed message received, " + std::string(e.what()));
1598 runge 515
        LOG.Debug("Bytes: " + this->buffer_.ToDebugString());
1595 runge 516
    }
1596 runge 517
 
518
    this->buffer_.Clear();
1595 runge 519
}
520
 
521
}; // namespace can
522
}; // namespace atom