Subversion Repositories HomeAutomation

Rev

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