Subversion Repositories HomeAutomation

Rev

Rev 1596 | Rev 1598 | 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
 
35
#include "type/Bitset.h"
1597 runge 36
#include "type/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
 
48
Network::Network(std::string address): Subscriber(false), LOG("can::Network"), buffer_(2048)
49
{
1595 runge 50
    this->address_ = address;
51
    this->client_id_ = 0;
52
 
53
    net::Manager::Instance()->ConnectSlots(net::Client::SignalOnNewState::slot_type(&Network::SlotOnNewState, this, _1, _2, _3).track(this->tracker_),
54
                                           net::Client::SignalOnNewData::slot_type(&Network::SlotOnNewData, this, _1, _2, _3).track(this->tracker_));
55
 
56
    // Examples of address
57
    // udp:192.168.1.250:1100
58
    // serial:/dev/ttyUSB0:38400
59
 
60
    std::vector<std::string> parts;
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
    {
73
        this->protocol_ = net::PROTOCOL_UDP;
74
    }
75
    else if (parts[0] == "serial")
76
    {
77
        this->protocol_ = net::PROTOCOL_SERIAL;
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
 
1596 runge 93
        LOG.Info("Sending ping.");
94
        type::Byteset buffer(1);
95
 
96
        buffer[0] = PACKET_PING;
97
 
98
        net::Manager::Instance()->SendTo(this->client_id_, buffer);
1595 runge 99
    }
100
    catch (std::exception e)
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::SlotOnNewData(net::ClientId client_id, net::ServerId server_id, type::Byteset data)
1595 runge 112
{
113
    if (client_id == this->client_id_)
114
    {
1596 runge 115
        type::Byteset temp_buffer = data;
116
        this->io_service_.post(boost::bind(&Network::SlotOnNewDataHandler, this, client_id, server_id, temp_buffer));
1595 runge 117
    }
118
}
119
 
120
void Network::SlotOnNewState(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
121
{
122
    if (client_id == this->client_id_)
123
    {
124
        this->io_service_.post(boost::bind(&Network::SlotOnNewStateHandler, this, client_id, server_id, client_state));
125
    }
126
}
127
 
1596 runge 128
void Network::SlotOnTimeout(timer::TimerId timer_id)
129
{
130
    if (timer_id == this->timer_id_)
131
    {
132
        this->io_service_.post(boost::bind(&Network::SlotOnTimeoutHandler, this, timer_id));
133
    }
134
}
135
 
1595 runge 136
void Network::SlotOnMessageHandler(broker::Message::Pointer message)
137
{
1596 runge 138
    if (message->GetType() == broker::Message::CAN_MESSAGE)
139
    {
140
        Message* payload = static_cast<Message*>(message->GetPayload().get());
141
 
142
 
143
 
144
    }
1595 runge 145
}
146
 
1596 runge 147
void Network::SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, type::Byteset data)
1595 runge 148
{
1596 runge 149
    static bool have_start = false;
150
 
151
    for (unsigned int n = 0; n < data.GetSize(); n++)
152
    {
153
        if (have_start)
154
        {
155
            if (data[n] == PACKET_END && this->buffer_.GetSize() == 15)
156
            {
157
                //LOG.Debug("Received packet end and size is 15.");
158
                this->ProcessBuffer();
159
                have_start = false;
160
            }
161
            else
162
            {
163
                this->buffer_.Append(data[n]);
164
            }
165
        }
166
        else if (data[n] == PACKET_START)
167
        {
168
            //LOG.Debug("Received packet start.");
169
            this->buffer_.Clear();
170
            have_start = true;
171
        }
172
        else if (data[n] == PACKET_PING)
173
        {
174
            LOG.Info("Received pong.");
175
        }
176
    }
1595 runge 177
}
178
 
179
void Network::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
180
{
181
    if (client_state == net::CLIENT_STATE_DISCONNECTED)
182
    {
1596 runge 183
        LOG.Warning("Got disconnected, setting reconnect timer...");
184
 
185
        this->timer_id_ = timer::Manager::Instance()->Set(10000, true);
1595 runge 186
        this->client_id_ = 0;
1596 runge 187
    }
188
    else
189
    {
190
        LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
191
    }
192
}
193
 
194
void Network::SlotOnTimeoutHandler(timer::TimerId timer_id)
195
{
196
    try
197
    {
198
        this->client_id_ = net::Manager::Instance()->Connect(this->protocol_, this->address_, this->port_or_baud_);
199
        LOG.Info("Connected again.");
1595 runge 200
 
1596 runge 201
        timer::Manager::Instance()->Cancel(timer_id);
202
        this->timer_id_ = 0;
203
    }
204
    catch (std::exception e)
205
    {
206
        LOG.Error(e.what());
207
        LOG.Warning("Will try again soon...");
208
    }
209
}
210
 
211
void Network::ProcessBuffer()
212
{
213
    try
214
    {
215
        std::string class_name = "";
216
        std::string direction_name = "";
217
        std::string module_name = "";
218
        unsigned int id = 0;
219
        std::string command_name = "";
220
 
221
        unsigned int class_id = (this->buffer_[3] >> 1) & 0x0F;
222
 
223
        //LOG.Debug("class_id=" + boost::lexical_cast<std::string>(class_id) + ", byte[3] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[3]));
224
 
225
        class_name = Protocol::Instance()->LookupClassName(class_id);
226
 
227
        //LOG.Debug("class_name=" + class_name);
228
 
229
        if (class_name == "nmt")
1595 runge 230
        {
1596 runge 231
            unsigned int command_id = this->buffer_[2];
232
            //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id) + ", byte[2] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[2]));
233
 
234
            command_name = Protocol::Instance()->LookupNMTCommandName(command_id);
235
            //LOG.Debug("command_name=" + command_name);
1595 runge 236
        }
1596 runge 237
        else
1595 runge 238
        {
1596 runge 239
            unsigned int direction_flag = this->buffer_[3] & 0x01;
240
            //LOG.Debug("direction_flag=" + boost::lexical_cast<std::string>(direction_flag) + ", byte[3] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[3]));
241
 
242
            direction_name = Protocol::Instance()->LookupDirectionFlag(direction_flag);
243
            //LOG.Debug("direction_name=" + direction_name);
244
 
245
            unsigned int module_id = this->buffer_[2];
246
            //LOG.Debug("module_id=" + boost::lexical_cast<std::string>(module_id) + ", byte[2] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[2]));
247
 
248
            module_name = Protocol::Instance()->LookupModuleName(module_id);
249
            //LOG.Debug("module_name=" + module_name);
250
 
251
            id = this->buffer_[1];
252
            //LOG.Debug("id=" + boost::lexical_cast<std::string>(id) + ", byte[1] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[1]));
253
 
254
            unsigned int command_id = this->buffer_[0];
255
            //LOG.Debug("command_id=" + boost::lexical_cast<std::string>(command_id) + ", byte[0] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[0]));
256
 
257
            command_name = Protocol::Instance()->LookupCommandName(command_id, module_name);
258
            //LOG.Debug("command_name=" + command_name);
1595 runge 259
        }
1596 runge 260
 
261
        Message* payload = new Message(class_name, direction_name, module_name, id, command_name);
262
 
263
        unsigned int length = this->buffer_[6];
264
        //LOG.Debug("Data length = " + boost::lexical_cast<std::string>(length));
265
 
266
        type::Byteset data_set(length);
267
 
268
        for (unsigned int n = 0; n < length; n++)
269
        {
270
            //LOG.Debug("add byte[" + boost::lexical_cast<std::string>(n + 7) + "] = " + boost::lexical_cast<std::string>((unsigned int)this->buffer_[n + 7]));
271
            data_set.Append(this->buffer_[n + 7]);
272
        }
1597 runge 273
        /*
274
        for (unsigned int n = 0; n < data_set.GetSize(); n++)
1596 runge 275
        {
1597 runge 276
            LOG.Debug("byte[" + boost::lexical_cast<std::string>(n) + "] = " + boost::lexical_cast<std::string>((unsigned int)data_set[n]));
277
        }
278
        */
1596 runge 279
        type::Bitset databits(data_set);
280
 
1597 runge 281
        /*
1596 runge 282
        std::string temp = "";
1597 runge 283
        std::string temp2 = "";
1596 runge 284
        for (unsigned int n = 0; n < databits.GetCount(); n ++)
285
        {
1597 runge 286
 
287
            temp2 += boost::lexical_cast<std::string>((unsigned int)databits.bytes_[n/8]);
1596 runge 288
            temp += boost::lexical_cast<std::string>(databits.Get(n));
289
        }
290
 
1597 runge 291
        LOG.Debug("databits1 = " + temp);
292
        LOG.Debug("databits2 = " + temp2);*/
1596 runge 293
 
294
        xml::Node::NodeList variable_nodes;
295
 
296
        if (class_name == "nmt")
297
        {
298
            variable_nodes = Protocol::Instance()->GetNMTCommandVariables(command_name);
299
        }
300
        else
301
        {
302
            variable_nodes = Protocol::Instance()->GetCommandVariables(command_name, module_name);
303
        }
304
 
305
        for (unsigned int n = 0; n < variable_nodes.size(); n++)
306
        {
307
            unsigned int start_bit = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("start_bit"));
308
            unsigned int bit_length = boost::lexical_cast<unsigned int>(variable_nodes[n].GetAttributeValue("bit_length"));
309
            std::string type = variable_nodes[n].GetAttributeValue("type");
310
 
1597 runge 311
            //LOG.Debug("name=" + variable_nodes[n].GetAttributeValue("name"));
312
            //LOG.Debug("type=" + type);
313
 
314
            std::string value = "";
315
 
316
            if (type == "int")
1596 runge 317
            {
1597 runge 318
                unsigned long raw_bit_value = databits.Read(start_bit, bit_length);
319
                int raw_value = 0;
320
 
321
                memcpy(&raw_value, &raw_bit_value, sizeof(raw_value));
322
                value = boost::lexical_cast<std::string>(raw_value);
323
            }
324
            else if (type == "float")
325
            {
326
                float raw_value = 0;
327
                bool negative = false;;
328
 
329
                if (databits.Get(start_bit))
330
                {
331
                    negative = true;
332
                }
333
 
334
                for (int c = bit_length-1; c > 0; c--)
335
                {
336
                    if (databits.Get(start_bit + c) != negative)
337
                    {
338
                        raw_value += pow(2.0f, (int)(bit_length-1-c));
339
                    }
340
                }
341
 
342
                raw_value /= 64.0f;
343
 
344
                if (negative)
345
                {
346
                    raw_value = -raw_value;
347
                }
348
 
349
                value = boost::lexical_cast<std::string>(raw_value);
350
                //LOG.Debug("float:value="+value);
351
            }
352
            else if (type == "ascii")
353
            {
354
                char c = 0;
355
 
356
                for (unsigned int p = 0; p < bit_length; p += 8)
357
                {
358
                    unsigned long raw_bit_value = databits.Read(start_bit + p, 8);
359
                    memcpy(&c, &raw_bit_value, sizeof(c));
360
                    value += c;
361
                }
362
            }
363
            else if (type == "hexstring")
364
            {
365
                for (unsigned int p = 0; p < bit_length; p += 4)
366
                {
367
                    unsigned long raw_bit_value = databits.Read(start_bit + p, 4);
368
 
369
                    //value += boost::lexical_cast<std::string>(raw_bit_value);
370
                }
371
            }
372
            else if (type == "enum")
373
            {
374
                value = boost::lexical_cast<std::string>(databits.Read(start_bit, bit_length));
1596 runge 375
                value = variable_nodes[n].SelectChild("id", value).GetAttributeValue("name");
376
            }
1597 runge 377
            else// if (type == "uint")
378
            {
379
                unsigned long raw_bit_value = databits.Read(start_bit, bit_length);
380
                unsigned int raw_value = 0;
381
 
382
                memcpy(&raw_value, &raw_bit_value, sizeof(raw_value));
383
                value = boost::lexical_cast<std::string>(raw_value);
384
            }
1596 runge 385
 
386
            //LOG.Debug("start_bit=" + boost::lexical_cast<std::string>(start_bit) + ",bit_length=" + boost::lexical_cast<std::string>(bit_length));
387
 
388
            payload->SetVariable(variable_nodes[n].GetAttributeValue("name"), value);
389
            //LOG.Debug("Variable:" + variable_nodes[n].GetAttributeValue("name") + " = " + value);
390
        }
391
 
392
        broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
1595 runge 393
    }
1596 runge 394
    catch (std::runtime_error& e)
1595 runge 395
    {
1597 runge 396
        std::string bytestring;
397
 
398
        for (unsigned int n = 0; n < this->buffer_.GetSize(); n++)
399
        {
400
            bytestring += boost::lexical_cast<std::string>((unsigned int)this->buffer_[n]) + ",";
401
        }
402
 
403
        LOG.Debug("Bytes: " + bytestring);
404
 
1596 runge 405
        LOG.Error("Malformed message received, " + std::string(e.what()));
1595 runge 406
    }
1596 runge 407
 
408
    this->buffer_.Clear();
1595 runge 409
}
410
 
411
}; // namespace can
412
}; // namespace atom