Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
11 andreas 1
/*
86 andreas 2
 * Copyright (C) 2018 to 2022 by Andreas Theofilu <andreas@theosys.at>
11 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
19
#include <sys/utsname.h>
86 andreas 20
/*
11 andreas 21
#ifdef __APPLE__
22
#include <boost/asio/buffer.hpp>
23
#include <boost/asio/io_context.hpp>
24
#include <boost/asio/ip/tcp.hpp>
25
#include <boost/asio/read_until.hpp>
26
#include <boost/asio/steady_timer.hpp>
27
#include <boost/asio/write.hpp>
28
#include <boost/asio/read.hpp>
29
#else
30
#include <asio/buffer.hpp>
31
#include <asio/io_context.hpp>
32
#include <asio/ip/tcp.hpp>
33
#include <asio/read_until.hpp>
34
#include <asio/steady_timer.hpp>
35
#include <asio/write.hpp>
36
#include <asio/read.hpp>
37
#endif
86 andreas 38
*/
11 andreas 39
#include <functional>
40
#include <iostream>
41
#include <fstream>
42
#include <cstring>
43
#include <string>
44
#include <chrono>
45
#include <thread>
15 andreas 46
#include <map>
11 andreas 47
 
48
#include <sys/stat.h>
49
#include <sys/types.h>
50
#include <unistd.h>
51
 
52
#include "tamxnet.h"
53
#include "terror.h"
54
#include "tconfig.h"
55
#include "tdirectory.h"
56
#include "tresources.h"
57
#include "texpand.h"
86 andreas 58
#include "tsocket.h"
89 andreas 59
#include "texcept.h"
11 andreas 60
 
61
using namespace amx;
62
using namespace std;
63
 
64
using placeholders::_1;
65
using placeholders::_2;
66
 
67
string cmdList[] =
68
{
69
    "@WLD-", "@AFP-", "@GCE-", "@APG-", "@CPG-", "@DPG-", "@PDR-", "@PHE-",
70
    "@PHP-", "@PHT-", "@PPA-", "@PPF-", "@PPG-", "@PPK-", "@PPM-", "@PPN-",
71
    "@PPT-", "@PPX", "@PSE-", "@PSP-", "@PST-", "PAGE-", "PPOF-", "PPOG-",
72
    "PPON-", "^ANI-", "^APF-", "^BAT-", "^BAU-", "^BCB-", "^BCF-", "^BCT-",
73
    "^BDO-", "^BFB-", "^BIM-", "^BLN-", "^BMC-", "^BMF-", "^BMI-", "^BML-",
74
    "^BMP-", "^BNC-", "^BNN-", "^BNT-", "^BOP-", "^BOR-", "^BOS-", "^BPP-",
75
    "^BRD-", "^BSF-", "^BSP-", "^BSM-", "^BSO-", "^BVL-", "^BVN-", "^BVP-",
76
    "^BVT-", "^BWW-", "^CPF-", "^DLD-", "^DPF-", "^ENA-", "^FON-", "^GDI-",
77
    "^GIV-", "^GLH-", "^GLL-", "^GRD-", "^GRU-", "^GSC-", "^GSN-", "^ICO-",
78
    "^IRM-", "^JSB-", "^JSI-", "^JST-", "^MBT-", "^MDC-", "^SHO-", "^TEC-",
79
    "^TEF-", "^TOP-", "^TXT-", "^UNI-", "^LPC-", "^LPR-", "^LPS-", "?BCB-",
80
    "?BCF-", "?BCT-", "?BMP-", "?BOP-", "?BRD-", "?BWW-", "?FON-", "?ICO-",
81
    "?JSB-", "?JSI-", "?JST-", "?TEC-", "?TEF-", "?TXT-", "ABEEP", "ADBEEP",
82
    "@AKB-", "AKEYB-", "AKEYP-", "AKEYR-", "@AKP-", "@AKR", "BEEP", "BRIT-",
83
    "@BRT-", "DBEEP", "@EKP-", "PKEYP-", "@PKP-", "SETUP", "SHUTDOWN", "SLEEP",
84
    "@SOU-", "@TKP-", "TPAGEON", "TPAGEOFF", "@VKB", "WAKE", "^CAL", "^KPS-",
85
    "^VKS-", "@PWD-", "^PWD-", "^BBR-", "^RAF-", "^RFR-", "^RMF-", "^RSR-",
86
    "^MODEL?", "^ICS-", "^ICE-", "^ICM-", "^PHN-", "?PHN-", "LEVON", "RXON",
15 andreas 87
    "BLINK", "\0"
11 andreas 88
};
89
 
90
#define NUMBER_CMDS     144
91
 
91 andreas 92
#ifndef __ANDROID__
90 andreas 93
std::atomic<bool> killed = false;
94
std::atomic<bool> _netRunning = false;
91 andreas 95
#else
96
std::atomic<bool> killed;
97
std::atomic<bool> _netRunning;
98
#endif
14 andreas 99
amx::TAmxNet *gAmxNet = nullptr;
92 andreas 100
static bool __CommValid = false;
87 andreas 101
std::map<ulong, FUNC_NETWORK_t> mFuncsNetwork;
102
std::map<ulong, FUNC_TIMER_t> mFuncsTimer;
103
 
11 andreas 104
TAmxNet::TAmxNet()
105
{
106
    DECL_TRACER("TAmxNet::TAmxNet()");
92 andreas 107
 
11 andreas 108
    init();
109
}
110
 
111
TAmxNet::TAmxNet(const string& sn)
86 andreas 112
    : serNum(sn)
11 andreas 113
{
114
    DECL_TRACER("TAmxNet::TAmxNet(const string& sn)");
92 andreas 115
 
11 andreas 116
    init();
117
}
118
 
119
TAmxNet::TAmxNet(const string& sn, const string& nm)
86 andreas 120
    : panName(nm),
11 andreas 121
      serNum(sn)
122
{
123
    DECL_TRACER("TAmxNet::TAmxNet(const string& sn)");
92 andreas 124
 
11 andreas 125
    size_t pos = nm.find(" (TPC)");
126
 
127
    if (pos != string::npos)
128
    {
129
        panName = nm.substr(0, pos) + "i";
130
        MSG_TRACE("Converted TP name: " << panName);
131
    }
132
 
133
    init();
134
}
135
 
136
TAmxNet::~TAmxNet()
137
{
138
    DECL_TRACER("TAmxNet::~TAmxNet()");
92 andreas 139
 
11 andreas 140
    callback = 0;
141
    stop();
92 andreas 142
 
143
    if (mSocket)
144
    {
145
        delete mSocket;
146
        mSocket = nullptr;
147
        __CommValid = false;
148
    }
149
 
70 andreas 150
    gAmxNet = nullptr;
11 andreas 151
}
152
 
92 andreas 153
void TAmxNet::init()
11 andreas 154
{
155
    DECL_TRACER("TAmxNet::init()");
156
 
157
    sendCounter = 0;
158
    initSend = false;
159
    ready = false;
89 andreas 160
 
92 andreas 161
    callback = 0;
162
    stopped_ = false;
163
    write_busy = false;
164
    gAmxNet = this;
165
 
166
    if (!mSocket)
89 andreas 167
    {
92 andreas 168
        mSocket = new TSocket;
169
        __CommValid = true;
89 andreas 170
    }
171
 
11 andreas 172
    string version = "v2.01.00";        // A version > 2.0 is needed for file transfer!
173
    int devID = 0x0163, fwID = 0x0290;
174
 
175
    if (TConfig::getPanelType().length() > 0)
176
        panName = TConfig::getPanelType();
177
    else if (panName.empty())
178
        panName.assign("TheoSys");
179
 
180
    if (panName.find("MVP") != string::npos && panName.find("5200") != string::npos)
181
    {
182
        devID = 0x0149;
183
        fwID = 0x0310;
184
    }
185
 
186
    // Initialize the devive info structure
187
    DEVICE_INFO di;
188
    // Answer to MC = 0x0017 --> MC = 0x0097
189
    di.objectID = 0;
190
    di.parentID = 0;
191
    di.manufacturerID = 1;
192
    di.deviceID = devID;
193
    memset(di.serialNum, 0x20, sizeof(di.serialNum));
194
 
195
    if (!serNum.empty())
196
        memcpy(di.serialNum, serNum.c_str(), serNum.length());
197
 
198
    di.firmwareID = fwID;
199
    memset(di.versionInfo, 0, sizeof(di.versionInfo));
200
    strncpy(di.versionInfo, version.c_str(), version.length());
201
    memset(di.deviceInfo, 0, sizeof(di.deviceInfo));
202
    strncpy(di.deviceInfo, panName.c_str(), min(panName.length(), sizeof(di.deviceInfo) - 1));
203
    memset(di.manufacturerInfo, 0, sizeof(di.manufacturerInfo));
204
    strncpy(di.manufacturerInfo, "TheoSys", 7);
205
    di.format = 2;
206
    di.len = 4;
207
    memset(di.addr, 0, sizeof(di.addr));
208
    devInfo.push_back(di);
209
    // Kernel info
210
    di.objectID = 2;
211
    di.firmwareID = fwID + 1;
212
    memset(di.serialNum, 0x20, sizeof(di.serialNum));
213
    memcpy(di.serialNum, "N/A", 3);
214
    memset(di.deviceInfo, 0, sizeof(di.deviceInfo));
215
    strncpy(di.deviceInfo, "Kernel", 6);
216
    memset(di.versionInfo, 0, sizeof(di.versionInfo));
217
#ifdef __linux__
218
    struct utsname kinfo;
219
    uname(&kinfo);
220
    strncpy(di.versionInfo, kinfo.release, sizeof(di.versionInfo));
221
#else
222
    strncpy(di.versionInfo, "4.00.00", 7);
223
#endif
224
    devInfo.push_back(di);
225
}
226
 
15 andreas 227
void TAmxNet::registerNetworkState(function<void (int)> registerNetwork, ulong handle)
228
{
229
    DECL_TRACER("TAmxNet::registerNetworkState(function<void (int)> registerNetwork, ulong handle)");
230
 
231
    map<ulong, FUNC_NETWORK_t>::iterator iter = mFuncsNetwork.find(handle);
232
 
83 andreas 233
    if (mFuncsNetwork.size() == 0 || iter == mFuncsNetwork.end())
15 andreas 234
    {
235
        FUNC_NETWORK_t fn;
236
        fn.handle = handle;
237
        fn.func = registerNetwork;
238
        mFuncsNetwork.insert(pair<ulong, FUNC_NETWORK_t>(handle, fn));
239
    }
240
 
88 andreas 241
    registerNetwork((isRunning() ? NSTATE_ONLINE : NSTATE_OFFLINE));
15 andreas 242
}
243
 
244
void TAmxNet::registerTimer(function<void (const ANET_BLINK &)> registerBlink, ulong handle)
245
{
246
    DECL_TRACER("TAmxNet::registerTimer(function<void (const ANET_BLINK &)> registerBlink, ulong handle)");
247
 
248
    map<ulong, FUNC_TIMER_t>::iterator iter = mFuncsTimer.find(handle);
249
 
83 andreas 250
    if (mFuncsTimer.size() == 0 || iter == mFuncsTimer.end())
15 andreas 251
    {
252
        FUNC_TIMER_t ft;
253
        ft.handle = handle;
254
        ft.func = registerBlink;
255
        mFuncsTimer.insert(pair<ulong, FUNC_TIMER_t>(handle, ft));
256
    }
257
}
258
 
259
void TAmxNet::deregNetworkState(ulong handle)
260
{
261
    DECL_TRACER("TAmxNet::deregNetworkState(ulong handle)");
262
 
83 andreas 263
    if (mFuncsNetwork.size() == 0)
264
        return;
265
 
15 andreas 266
    map<ulong, FUNC_NETWORK_t>::iterator iter = mFuncsNetwork.find(handle);
267
 
17 andreas 268
    if (iter != mFuncsNetwork.end())
15 andreas 269
        mFuncsNetwork.erase(iter);
270
}
271
 
272
void TAmxNet::deregTimer(ulong handle)
273
{
274
    DECL_TRACER("TAmxNet::deregTimer(ulong handle)");
275
 
83 andreas 276
    if (mFuncsTimer.size() == 0)
277
        return;
278
 
15 andreas 279
    map<ulong, FUNC_TIMER_t>::iterator iter = mFuncsTimer.find(handle);
280
 
17 andreas 281
    if (iter != mFuncsTimer.end())
15 andreas 282
        mFuncsTimer.erase(iter);
283
}
284
 
88 andreas 285
void TAmxNet::stop(bool soft)
11 andreas 286
{
86 andreas 287
    DECL_TRACER("TAmxNet::stop: Stopping the client...");
83 andreas 288
 
86 andreas 289
    if (stopped_)
83 andreas 290
        return;
291
 
88 andreas 292
    if (!soft)
293
        stopped_ = true;
294
 
92 andreas 295
    if (mSocket)
296
        mSocket->close();
11 andreas 297
}
298
 
93 andreas 299
bool TAmxNet::reconnect()
300
{
301
    DECL_TRACER("TAmxNet::reconnect()");
302
 
303
    if (!mSocket || !__CommValid)
304
        return false;
305
 
306
    mSocket->close();
307
    initSend = false;
308
    ready = false;
309
    return true;
310
}
311
 
88 andreas 312
bool TAmxNet::isNetRun()
313
{
314
    return _netRunning;
315
}
316
 
86 andreas 317
void TAmxNet::Run()
11 andreas 318
{
86 andreas 319
    DECL_TRACER("TAmxNet::Run()");
14 andreas 320
 
92 andreas 321
    if (_netRunning || !__CommValid)
11 andreas 322
        return;
323
 
88 andreas 324
    _netRunning = true;
86 andreas 325
    stopped_ = false;
326
    _retry = false;
11 andreas 327
 
328
    try
329
    {
86 andreas 330
        mThread = std::thread([=] { this->start(); });
331
        mThread.detach();
11 andreas 332
    }
333
    catch (std::exception& e)
334
    {
86 andreas 335
        MSG_ERROR("Error connecting to " << TConfig::getController() << ":" << to_string(TConfig::getPort()) << " [" << e.what() << "]");
336
        _netRunning = false;
11 andreas 337
    }
338
}
339
 
88 andreas 340
/*
341
 * This function is running as a thread. It is the main method connecting to
342
 * a controller and it handles all the communication with the controller.
343
 */
86 andreas 344
void TAmxNet::start()
11 andreas 345
{
86 andreas 346
    DECL_TRACER("TAmxNet::start()");
11 andreas 347
 
86 andreas 348
    sendAllFuncNetwork(NSTATE_CONNECTING);
44 andreas 349
 
92 andreas 350
    while (__CommValid && mSocket && isRunning())
11 andreas 351
    {
93 andreas 352
        initSend = false;
353
        ready = false;
354
 
92 andreas 355
        if (__CommValid && mSocket && !mSocket->connect(TConfig::getController(), TConfig::getPort()))
11 andreas 356
        {
87 andreas 357
            MSG_DEBUG("Connection failed. Retrying ...");
86 andreas 358
            sendAllFuncNetwork(NSTATE_OFFLINE);
93 andreas 359
            std::this_thread::sleep_for(std::chrono::seconds(mWaitTime));
360
            setWaitTime(WAIT_RESET);
86 andreas 361
            continue;
11 andreas 362
        }
92 andreas 363
        else if (!mSocket)
364
            break;
11 andreas 365
 
86 andreas 366
        sendAllFuncNetwork(NSTATE_ONLINE);
367
        handle_connect();
93 andreas 368
        std::this_thread::sleep_for(std::chrono::seconds(mWaitTime));
369
        setWaitTime(WAIT_RESET);
370
        MSG_INFO("Network will be reestablished ...");
11 andreas 371
    }
372
 
86 andreas 373
    _netRunning = false;
11 andreas 374
}
375
 
86 andreas 376
void TAmxNet::handle_connect()
11 andreas 377
{
86 andreas 378
    DECL_TRACER("TAmxNet::handle_connect()");
11 andreas 379
 
86 andreas 380
    try
11 andreas 381
    {
92 andreas 382
        while (__CommValid && mSocket && isRunning() && mSocket->isConnected())
86 andreas 383
        {
384
            // Start the input actor.
385
            start_read();
11 andreas 386
 
86 andreas 387
            // Start the output actor.
388
            if (isRunning())
389
                start_write();
390
        }
11 andreas 391
 
86 andreas 392
        if (!stopped_ && (killed || prg_stopped))
393
            stop();
11 andreas 394
    }
86 andreas 395
    catch (std::exception& e)
11 andreas 396
    {
86 andreas 397
        MSG_ERROR("Error: " << e.what());
92 andreas 398
 
399
        if (mSocket)
400
            mSocket->close();
11 andreas 401
    }
93 andreas 402
    catch (TXceptComm& e)
89 andreas 403
    {
92 andreas 404
        if (mSocket)
405
            mSocket->close();
89 andreas 406
    }
93 andreas 407
 
408
    sendAllFuncNetwork(NSTATE_CONNECTING);
409
    setWaitTime(WAIT_RECONNECT);
11 andreas 410
}
411
 
412
void TAmxNet::start_read()
413
{
414
    DECL_TRACER("TAmxNet::start_read()");
415
 
92 andreas 416
    if (!__CommValid || !mSocket || !isRunning() || !mSocket->isConnected())
11 andreas 417
        return;
418
 
88 andreas 419
    string _message = "TAmxNet::start_read(): Invalid argument received!";
11 andreas 420
    protError = false;
421
    comm.clear();
422
 
89 andreas 423
    try
88 andreas 424
    {
89 andreas 425
        // Read the first byte. It should be 0x02
92 andreas 426
        if (mSocket->readAbsolut(buff_, 1) == 1)
89 andreas 427
            handle_read(1, RT_ID);
92 andreas 428
        else if (mSocket->isConnected())
89 andreas 429
        {
430
            _message.append(" [RT_ID]");
431
            XCEPTCOMM(_message);
432
        }
433
        else
93 andreas 434
        {
435
            setWaitTime(WAIT_RECONNECT);
89 andreas 436
            return;
93 andreas 437
        }
11 andreas 438
 
92 andreas 439
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 440
            handle_read(2, RT_LEN);
92 andreas 441
        else if (mSocket->isConnected())
89 andreas 442
        {
443
            _message.append(" [RT_LEN]");
444
            XCEPTCOMM(_message);
445
        }
446
        else
93 andreas 447
        {
448
            setWaitTime(WAIT_RECONNECT);
89 andreas 449
            return;
93 andreas 450
        }
11 andreas 451
 
92 andreas 452
        if (mSocket->readAbsolut(buff_, 1) == 1)
89 andreas 453
            handle_read(1, RT_SEP1);
92 andreas 454
        else if (mSocket->isConnected())
89 andreas 455
        {
456
            _message.append(" [RT_SEP1]");
457
            XCEPTCOMM(_message);
458
        }
459
        else
93 andreas 460
        {
461
            setWaitTime(WAIT_RECONNECT);
89 andreas 462
            return;
93 andreas 463
        }
11 andreas 464
 
92 andreas 465
        if (mSocket->readAbsolut(buff_, 1) == 1)
89 andreas 466
            handle_read(1, RT_TYPE);
92 andreas 467
        else if (mSocket->isConnected())
89 andreas 468
        {
469
            _message.append(" [RT_TYPE]");
470
            XCEPTCOMM(_message);
471
        }
472
        else
93 andreas 473
        {
474
            setWaitTime(WAIT_RECONNECT);
89 andreas 475
            return;
93 andreas 476
        }
11 andreas 477
 
92 andreas 478
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 479
            handle_read(2, RT_WORD1);
92 andreas 480
        else if (mSocket->isConnected())
89 andreas 481
        {
482
            _message.append(" [RT_WORD1]");
483
            XCEPTCOMM(_message);
484
        }
485
        else
93 andreas 486
        {
487
            setWaitTime(30);
89 andreas 488
            return;
93 andreas 489
        }
11 andreas 490
 
92 andreas 491
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 492
            handle_read(2, RT_DEVICE);
92 andreas 493
        else if (mSocket->isConnected())
89 andreas 494
        {
495
            _message.append(" [RT_DEVIVE]");
496
            XCEPTCOMM(_message);
497
        }
498
        else
93 andreas 499
        {
500
            setWaitTime(WAIT_RECONNECT);
89 andreas 501
            return;
93 andreas 502
        }
11 andreas 503
 
92 andreas 504
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 505
            handle_read(2, RT_WORD2);
92 andreas 506
        else if (mSocket->isConnected())
89 andreas 507
        {
508
            _message.append(" [RT_WORD2]");
509
            XCEPTCOMM(_message);
510
        }
511
        else
93 andreas 512
        {
513
            setWaitTime(WAIT_RECONNECT);
89 andreas 514
            return;
93 andreas 515
        }
11 andreas 516
 
92 andreas 517
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 518
            handle_read(2, RT_WORD3);
92 andreas 519
        else if (mSocket->isConnected())
89 andreas 520
        {
521
            _message.append(" [RT_WORD3]");
522
            XCEPTCOMM(_message);
523
        }
524
        else
93 andreas 525
        {
526
            setWaitTime(WAIT_RECONNECT);
89 andreas 527
            return;
93 andreas 528
        }
11 andreas 529
 
92 andreas 530
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 531
            handle_read(2, RT_WORD4);
92 andreas 532
        else if (mSocket->isConnected())
89 andreas 533
        {
534
            _message.append(" [RT_WORD4]");
535
            XCEPTCOMM(_message);
536
        }
537
        else
93 andreas 538
        {
539
            setWaitTime(WAIT_RECONNECT);
89 andreas 540
            return;
93 andreas 541
        }
11 andreas 542
 
92 andreas 543
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 544
            handle_read(2, RT_WORD5);
92 andreas 545
        else if (mSocket->isConnected())
89 andreas 546
        {
547
            _message.append(" [RT_WORD5]");
548
            XCEPTCOMM(_message);
549
        }
550
        else
93 andreas 551
        {
552
            setWaitTime(WAIT_RECONNECT);
89 andreas 553
            return;
93 andreas 554
        }
11 andreas 555
 
92 andreas 556
        if (mSocket->readAbsolut(buff_, 1) == 1)
89 andreas 557
            handle_read(1, RT_SEP2);
92 andreas 558
        else if (mSocket->isConnected())
89 andreas 559
        {
560
            _message.append(" [RT_SEP2]");
561
            XCEPTCOMM(_message);
562
        }
563
        else
93 andreas 564
        {
565
            setWaitTime(WAIT_RECONNECT);
89 andreas 566
            return;
93 andreas 567
        }
11 andreas 568
 
92 andreas 569
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 570
            handle_read(2, RT_COUNT);
92 andreas 571
        else if (mSocket->isConnected())
89 andreas 572
        {
573
            _message.append(" [RT_COUNT]");
574
            XCEPTCOMM(_message);
575
        }
576
        else
93 andreas 577
        {
578
            setWaitTime(WAIT_RECONNECT);
89 andreas 579
            return;
93 andreas 580
        }
11 andreas 581
 
92 andreas 582
        if (mSocket->readAbsolut(buff_, 2) == 2)
89 andreas 583
            handle_read(2, RT_MC);
92 andreas 584
        else if (mSocket->isConnected())
89 andreas 585
        {
586
            _message.append(" [RT_MC]");
587
            XCEPTCOMM(_message);
588
        }
589
        else
93 andreas 590
        {
591
            setWaitTime(WAIT_RECONNECT);
89 andreas 592
            return;
93 andreas 593
        }
11 andreas 594
 
89 andreas 595
        // Calculate the length of the data block. This is the rest of the total length
596
        size_t len = (comm.hlen + 3) - 0x0015;
11 andreas 597
 
92 andreas 598
        if (mSocket->isConnected() && len > BUF_SIZE)
89 andreas 599
        {
600
            _message = "Length to read is " + to_string(len) + " bytes, but the buffer is only " + to_string(BUF_SIZE) + " bytes!";
601
            XCEPTCOMM(_message);
602
        }
92 andreas 603
        else if (!mSocket->isConnected())
93 andreas 604
        {
605
            setWaitTime(WAIT_RECONNECT);
89 andreas 606
            return;
93 andreas 607
        }
89 andreas 608
 
92 andreas 609
        if (mSocket->readAbsolut(buff_, len) == len)
89 andreas 610
            handle_read(len, RT_DATA);
92 andreas 611
        else if (mSocket->isConnected())
89 andreas 612
        {
613
            _message.append(" [RT_DATA]");
614
            XCEPTCOMM(_message);
615
        }
11 andreas 616
    }
89 andreas 617
    catch (TXceptNetwork& e)
88 andreas 618
    {
93 andreas 619
        setWaitTime(WAIT_RECONNECT);
88 andreas 620
    }
11 andreas 621
}
622
 
86 andreas 623
void TAmxNet::handle_read(size_t n, R_TOKEN tk)
11 andreas 624
{
625
    DECL_TRACER("TAmxNet::handle_read(const error_code& error, size_t n, R_TOKEN tk)");
626
 
92 andreas 627
    if (stopped_ || !__CommValid || !mSocket || !mSocket->isConnected())
11 andreas 628
        return;
629
 
21 andreas 630
    if (killed || prg_stopped)
11 andreas 631
    {
632
        stop();
633
        return;
634
    }
635
 
636
    uint32_t dw;
637
    int val, pos;
638
    size_t len;
639
    ANET_SEND s;        // Used to answer system requests
640
    string cmd;
641
 
86 andreas 642
    len = (n < BUF_SIZE) ? n : BUF_SIZE - 1;
643
    input_buffer_.assign((char *)&buff_[0], len);
11 andreas 644
 
86 andreas 645
    MSG_DEBUG("Token: " << tk << ", " << len << " bytes");
11 andreas 646
 
86 andreas 647
    switch (tk)
648
    {
649
        case RT_ID:
650
            if (buff_[0] != 0x02)
651
                protError = true;
652
            else
653
                comm.ID = buff_[0];
654
        break;
11 andreas 655
 
86 andreas 656
        case RT_LEN:    comm.hlen = makeWord(buff_[0], buff_[1]); break;
11 andreas 657
 
86 andreas 658
        case RT_SEP1:
659
            if (buff_[0] != 0x02)
660
                protError = true;
661
            else
662
                comm.sep1 = buff_[0];
663
        break;
11 andreas 664
 
86 andreas 665
        case RT_TYPE:   comm.type = buff_[0]; break;
666
        case RT_WORD1:  comm.unk1 = makeWord(buff_[0], buff_[1]); break;
667
        case RT_DEVICE: comm.device1 = makeWord(buff_[0], buff_[1]); break;
668
        case RT_WORD2:  comm.port1 = makeWord(buff_[0], buff_[1]); break;
669
        case RT_WORD3:  comm.system = makeWord(buff_[0], buff_[1]); break;
670
        case RT_WORD4:  comm.device2 = makeWord(buff_[0], buff_[1]); break;
671
        case RT_WORD5:  comm.port2 = makeWord(buff_[0], buff_[1]); break;
11 andreas 672
 
86 andreas 673
        case RT_SEP2:
674
            if (buff_[0] != 0x0f)
675
                protError = true;
676
            else
677
                comm.unk6 = buff_[0];
678
        break;
11 andreas 679
 
86 andreas 680
        case RT_COUNT:  comm.count = makeWord(buff_[0], buff_[1]); break;
681
        case RT_MC:     comm.MC = makeWord(buff_[0], buff_[1]); break;
11 andreas 682
 
86 andreas 683
        case RT_DATA:
684
            if (protError || !isRunning())
685
                break;
11 andreas 686
 
93 andreas 687
            MSG_DEBUG("Received message type: 0x" << std::setw(4) << std::setfill('0') << std::hex << comm.MC);
11 andreas 688
 
86 andreas 689
            switch (comm.MC)
690
            {
691
                case 0x0001:    // ACK
692
                case 0x0002:    // NAK
693
                    comm.checksum = buff_[0];
694
                break;
11 andreas 695
 
86 andreas 696
                case 0x0084:    // input channel ON
697
                case 0x0085:    // input channel OFF
698
                case 0x0006:    // output channel ON
699
                case 0x0086:    // output channel ON status
700
                case 0x0007:    // output channel OFF
701
                case 0x0087:    // output channel OFF status
702
                case 0x0088:    // input/output channel ON status
703
                case 0x0089:    // input/output channel OFF status
704
                case 0x0018:    // feedback channel ON
705
                case 0x0019:    // feedback channel OFF
706
                    comm.data.chan_state.device = makeWord(buff_[0], buff_[1]);
707
                    comm.data.chan_state.port = makeWord(buff_[2], buff_[3]);
708
                    comm.data.chan_state.system = makeWord(buff_[4], buff_[5]);
709
                    comm.data.chan_state.channel = makeWord(buff_[6], buff_[7]);
710
                    comm.checksum = buff_[8];
11 andreas 711
 
86 andreas 712
                    s.channel = comm.data.chan_state.channel;
713
                    s.level = 0;
714
                    s.port = comm.data.chan_state.port;
715
                    s.value = 0;
11 andreas 716
 
86 andreas 717
                    switch (comm.MC)
718
                    {
719
                        case 0x0006: s.MC = 0x0086; break;
720
                        case 0x0007: s.MC = 0x0087; break;
721
                    }
11 andreas 722
 
86 andreas 723
                    if (comm.MC < 0x0020)
724
                    {
11 andreas 725
                        if (callback)
726
                            callback(comm);
13 andreas 727
                        else
728
                            MSG_WARNING("Missing callback function!");
86 andreas 729
                    }
730
                    else
731
                        sendCommand(s);
732
                break;
11 andreas 733
 
86 andreas 734
                case 0x000a:    // level value change
735
                case 0x008a:
736
                    comm.data.message_value.device = makeWord(buff_[0], buff_[1]);
737
                    comm.data.message_value.port = makeWord(buff_[2], buff_[3]);
738
                    comm.data.message_value.system = makeWord(buff_[4], buff_[5]);
739
                    comm.data.message_value.value = makeWord(buff_[6], buff_[7]);
740
                    comm.data.message_value.type = buff_[8];
741
                    val = (int)buff_[8];
11 andreas 742
 
86 andreas 743
                    switch (val)
744
                    {
745
                        case 0x010: comm.data.message_value.content.byte = buff_[9]; comm.checksum = buff_[10]; break;
746
                        case 0x011: comm.data.message_value.content.ch = buff_[9]; comm.checksum = buff_[10]; break;
747
                        case 0x020: comm.data.message_value.content.integer = makeWord(buff_[9], buff_[10]); comm.checksum = buff_[11]; break;
748
                        case 0x021: comm.data.message_value.content.sinteger = makeWord(buff_[9], buff_[10]); comm.checksum = buff_[11]; break;
749
                        case 0x040: comm.data.message_value.content.dword = makeDWord(buff_[9], buff_[10], buff_[11], buff_[12]); comm.checksum = buff_[13]; break;
750
                        case 0x041: comm.data.message_value.content.sdword = makeDWord(buff_[9], buff_[10], buff_[11], buff_[12]); comm.checksum = buff_[13]; break;
11 andreas 751
 
86 andreas 752
                        case 0x04f:
753
                            dw = makeDWord(buff_[9], buff_[10], buff_[11], buff_[12]);
754
                            memcpy(&comm.data.message_value.content.fvalue, &dw, 4);
755
                            comm.checksum = buff_[13];
756
                        break;
11 andreas 757
 
86 andreas 758
                        case 0x08f:
759
                            memcpy(&comm.data.message_value.content.dvalue, &buff_[9], 8);  // FIXME: wrong byte order on Intel CPU?
760
                            comm.checksum = buff_[17];
761
                        break;
762
                    }
11 andreas 763
 
86 andreas 764
                    if (callback)
765
                        callback(comm);
766
                    else
767
                        MSG_WARNING("Missing callback function!");
768
                break;
11 andreas 769
 
86 andreas 770
                case 0x000b:    // string value change
771
                case 0x008b:
772
                case 0x000c:    // command string
773
                case 0x008c:
774
                    comm.data.message_string.device = makeWord(buff_[0], buff_[1]);
775
                    comm.data.message_string.port = makeWord(buff_[2], buff_[3]);
776
                    comm.data.message_string.system = makeWord(buff_[4], buff_[5]);
777
                    comm.data.message_string.type = buff_[6];
778
                    comm.data.message_string.length = makeWord(buff_[7], buff_[8]);
779
                    memset(&comm.data.message_string.content[0], 0, sizeof(comm.data.message_string.content));
780
                    len = (buff_[6] == 0x01) ? comm.data.message_string.length : comm.data.message_string.length * 2;
11 andreas 781
 
86 andreas 782
                    if (len >= sizeof(comm.data.message_string.content))
783
                    {
784
                        len = sizeof(comm.data.message_string.content) - 1;
785
                        comm.data.message_string.length = (buff_[6] == 0x01) ? len : len / 2;
786
                    }
11 andreas 787
 
86 andreas 788
                    memcpy(&comm.data.message_string.content[0], &buff_[9], len);
789
                    pos = (int)(len + 10);
790
                    comm.checksum = buff_[pos];
791
                    cmd.assign((char *)&comm.data.message_string.content[0], len);
792
                    MSG_DEBUG("cmd=" << cmd);
11 andreas 793
 
86 andreas 794
                    if (isCommand(cmd))
795
                    {
796
                        MSG_DEBUG("Command found!");
797
                        oldCmd.assign(cmd);
798
                    }
799
                    else
800
                    {
801
                        oldCmd.append(cmd);
802
                        MSG_DEBUG("Concatenated cmd=" << oldCmd);
803
                        memset(&comm.data.message_string.content[0], 0, sizeof(comm.data.message_string.content));
804
                        memcpy(&comm.data.message_string.content[0], oldCmd.c_str(), sizeof(comm.data.message_string.content) - 1);
805
                        comm.data.message_string.length = oldCmd.length();
806
                        oldCmd.clear();
807
                    }
11 andreas 808
 
86 andreas 809
                    if (callback)
810
                        callback(comm);
811
                    else
812
                        MSG_WARNING("Missing callback function!");
813
                break;
11 andreas 814
 
86 andreas 815
                case 0x000e:    // request level value
816
                    comm.data.level.device = makeWord(buff_[0], buff_[1]);
817
                    comm.data.level.port = makeWord(buff_[2], buff_[3]);
818
                    comm.data.level.system = makeWord(buff_[4], buff_[5]);
819
                    comm.data.level.level = makeWord(buff_[6], buff_[7]);
820
                    comm.checksum = buff_[8];
11 andreas 821
 
86 andreas 822
                    if (callback)
823
                        callback(comm);
824
                    else
825
                        MSG_WARNING("Missing callback function!");
826
                break;
11 andreas 827
 
86 andreas 828
                case 0x000f:    // request output channel status
829
                    comm.data.channel.device = makeWord(buff_[0], buff_[1]);
830
                    comm.data.channel.port = makeWord(buff_[2], buff_[3]);
831
                    comm.data.channel.system = makeWord(buff_[4], buff_[5]);
832
                    comm.data.channel.channel = makeWord(buff_[6], buff_[7]);
833
                    comm.checksum = buff_[8];
11 andreas 834
 
86 andreas 835
                    if (callback)
836
                        callback(comm);
837
                    else
838
                        MSG_WARNING("Missing callback function!");
839
                break;
11 andreas 840
 
86 andreas 841
                case 0x0010:    // request port count
842
                case 0x0017:    // request device info
843
                    comm.data.reqPortCount.device = makeWord(buff_[0], buff_[1]);
844
                    comm.data.reqPortCount.system = makeWord(buff_[2], buff_[3]);
845
                    comm.checksum = buff_[4];
846
                    s.channel = false;
847
                    s.level = 0;
848
                    s.port = 0;
849
                    s.value = 0x0015;
850
                    s.MC = (comm.MC == 0x0010) ? 0x0090 : 0x0097;
11 andreas 851
 
86 andreas 852
                    if (s.MC == 0x0097)
853
                    {
854
                        comm.data.srDeviceInfo.device = comm.device2;
855
                        comm.data.srDeviceInfo.system = comm.system;
856
                        comm.data.srDeviceInfo.flag = 0x0000;
857
                        comm.data.srDeviceInfo.parentID = 0;
858
                        comm.data.srDeviceInfo.herstID = 1;
859
                        msg97fill(&comm);
860
                    }
861
                    else
11 andreas 862
                        sendCommand(s);
86 andreas 863
                break;
11 andreas 864
 
86 andreas 865
                case 0x0011:    // request output channel count
866
                case 0x0012:    // request level count
867
                case 0x0013:    // request string size
868
                case 0x0014:    // request command size
869
                    comm.data.reqOutpChannels.device = makeWord(buff_[0], buff_[1]);
870
                    comm.data.reqOutpChannels.port = makeWord(buff_[2], buff_[3]);
871
                    comm.data.reqOutpChannels.system = makeWord(buff_[4], buff_[5]);
872
                    comm.checksum = buff_[6];
873
                    s.channel = false;
874
                    s.level = 0;
875
                    s.port = comm.data.reqOutpChannels.port;
876
                    s.value = 0;
11 andreas 877
 
86 andreas 878
                    switch (comm.MC)
879
                    {
880
                        case 0x0011:
11 andreas 881
                            s.MC = 0x0091;
882
                            s.value = 0x0f75;   // # channels
86 andreas 883
                        break;
884
 
885
                        case 0x0012:
11 andreas 886
                            s.MC = 0x0092;
887
                            s.value = 0x000d;   // # levels
86 andreas 888
                        break;
889
 
890
                        case 0x0013:
11 andreas 891
                            s.MC = 0x0093;
892
                            s.value = 0x00c7;   // string size
86 andreas 893
                        break;
894
 
895
                        case 0x0014:
11 andreas 896
                            s.MC = 0x0094;
897
                            s.value = 0x00c7;   // command size
86 andreas 898
                        break;
899
                    }
11 andreas 900
 
86 andreas 901
                    sendCommand(s);
902
                break;
903
 
904
                case 0x0015:    // request level size
905
                    comm.data.reqLevels.device = makeWord(buff_[0], buff_[1]);
906
                    comm.data.reqLevels.port = makeWord(buff_[2], buff_[3]);
907
                    comm.data.reqLevels.system = makeWord(buff_[4], buff_[5]);
908
                    comm.data.reqLevels.level = makeWord(buff_[6], buff_[7]);
909
                    comm.checksum = buff_[8];
910
                    s.channel = false;
911
                    s.level = comm.data.reqLevels.level;
912
                    s.port = comm.data.reqLevels.port;
913
                    s.value = 0;
914
                    s.MC = 0x0095;
915
                    sendCommand(s);
916
                break;
917
 
918
                case 0x0016:    // request status code
919
                    comm.data.sendStatusCode.device = makeWord(buff_[0], buff_[1]);
920
                    comm.data.sendStatusCode.port = makeWord(buff_[2], buff_[3]);
921
                    comm.data.sendStatusCode.system = makeWord(buff_[4], buff_[5]);
922
 
923
                    if (callback)
924
                        callback(comm);
925
                    else
926
                        MSG_WARNING("Missing callback function!");
927
                break;
928
 
929
                case 0x0097:    // receive device info
930
                    comm.data.srDeviceInfo.device = makeWord(buff_[0], buff_[1]);
931
                    comm.data.srDeviceInfo.system = makeWord(buff_[2], buff_[3]);
932
                    comm.data.srDeviceInfo.flag = makeWord(buff_[4], buff_[5]);
933
                    comm.data.srDeviceInfo.objectID = buff_[6];
934
                    comm.data.srDeviceInfo.parentID = buff_[7];
935
                    comm.data.srDeviceInfo.herstID = makeWord(buff_[8], buff_[9]);
936
                    comm.data.srDeviceInfo.deviceID = makeWord(buff_[10], buff_[11]);
937
                    memcpy(comm.data.srDeviceInfo.serial, &buff_[12], 16);
938
                    comm.data.srDeviceInfo.fwid = makeWord(buff_[28], buff_[29]);
939
                    memset(comm.data.srDeviceInfo.info, 0, sizeof(comm.data.srDeviceInfo.info));
940
                    memcpy(comm.data.srDeviceInfo.info, &buff_[30], comm.hlen - 0x0015 - 29);
941
                    comm.checksum = buff_[comm.hlen + 3];
942
                    // Prepare answer
943
                    s.channel = false;
944
                    s.level = 0;
945
                    s.port = 0;
946
                    s.value = 0;
947
 
948
                    if (!initSend)
949
                    {
950
                        s.MC = 0x0097;
951
                        initSend = true;
952
                    }
953
                    else if (!ready)
954
                    {
955
                        // Send counts
956
                        s.MC = 0x0090;
957
                        s.value = 0x0015;   // # ports
11 andreas 958
                        sendCommand(s);
86 andreas 959
                        s.MC = 0x0091;
960
                        s.value = 0x0f75;   // # channels
961
                        sendCommand(s);
962
                        s.MC = 0x0092;
963
                        s.value = 0x000d;   // # levels
964
                        sendCommand(s);
965
                        s.MC = 0x0093;
966
                        s.value = 0x00c7;   // string size
967
                        sendCommand(s);
968
                        s.MC = 0x0094;
969
                        s.value = 0x00c7;   // command size
970
                        sendCommand(s);
971
                        s.MC = 0x0098;
972
                        ready = true;
973
                    }
974
                    else
975
                        break;
11 andreas 976
 
86 andreas 977
                    sendCommand(s);
11 andreas 978
 
93 andreas 979
                    MSG_DEBUG("S/N: " << comm.data.srDeviceInfo.serial << " | " << comm.data.srDeviceInfo.info);
86 andreas 980
                break;
11 andreas 981
 
86 andreas 982
                case 0x00a1:    // request status
983
                    reqDevStatus = makeWord(buff_[0], buff_[1]);
984
                    comm.checksum = buff_[2];
985
                break;
11 andreas 986
 
86 andreas 987
                case 0x0204:    // file transfer
988
                    s.device = comm.device2;
989
                    comm.data.filetransfer.ftype = makeWord(buff_[0], buff_[1]);
990
                    comm.data.filetransfer.function = makeWord(buff_[2], buff_[3]);
991
                    pos = 4;
992
 
993
                    if (comm.data.filetransfer.ftype == 0 && comm.data.filetransfer.function == 0x0105)         // Directory exist?
994
                    {
995
                        for (size_t i = 0; i < 0x0104; i++)
11 andreas 996
                        {
86 andreas 997
                            comm.data.filetransfer.data[i] = buff_[pos];
998
                            pos++;
11 andreas 999
                        }
1000
 
86 andreas 1001
                        comm.data.filetransfer.data[0x0103] = 0;
1002
                        handleFTransfer(s, comm.data.filetransfer);
1003
                    }
1004
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0100)    // Controller have more files
1005
                        handleFTransfer(s, comm.data.filetransfer);
1006
                    else if (comm.data.filetransfer.ftype == 0 && comm.data.filetransfer.function == 0x0100)    // Request directory listing
1007
                    {
1008
                        comm.data.filetransfer.unk = makeWord(buff_[4], buff_[5]);
1009
                        pos = 6;
11 andreas 1010
 
86 andreas 1011
                        for (size_t i = 0; i < 0x0104; i++)
1012
                        {
1013
                            comm.data.filetransfer.data[i] = buff_[pos];
1014
                            pos++;
11 andreas 1015
                        }
1016
 
86 andreas 1017
                        comm.data.filetransfer.data[0x0103] = 0;
1018
                        handleFTransfer(s, comm.data.filetransfer);
1019
                    }
1020
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0102)    // controller will send a file
1021
                    {
1022
                        comm.data.filetransfer.unk = makeDWord(buff_[4], buff_[5], buff_[6], buff_[7]);
1023
                        comm.data.filetransfer.unk1 = makeDWord(buff_[8], buff_[9], buff_[10], buff_[11]);
1024
                        pos = 12;
11 andreas 1025
 
86 andreas 1026
                        for (size_t i = 0; i < 0x0104; i++)
1027
                        {
1028
                            comm.data.filetransfer.data[i] = buff_[pos];
1029
                            pos++;
11 andreas 1030
                        }
1031
 
86 andreas 1032
                        comm.data.filetransfer.data[0x0103] = 0;
1033
                        handleFTransfer(s, comm.data.filetransfer);
1034
                    }
1035
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0103)    // file or part of a file
1036
                    {
1037
                        comm.data.filetransfer.unk = makeWord(buff_[4], buff_[5]);
1038
                        pos = 6;
11 andreas 1039
 
86 andreas 1040
                        for (size_t i = 0; i < comm.data.filetransfer.unk; i++)
1041
                        {
1042
                            comm.data.filetransfer.data[i] = buff_[pos];
1043
                            pos++;
11 andreas 1044
                        }
86 andreas 1045
 
1046
                        handleFTransfer(s, comm.data.filetransfer);
1047
                    }
1048
                    else if (comm.data.filetransfer.ftype == 0 && comm.data.filetransfer.function == 0x0104)    // Does file exist;
1049
                    {
1050
                        for (size_t i = 0; i < 0x0104; i++)
11 andreas 1051
                        {
86 andreas 1052
                            comm.data.filetransfer.data[i] = buff_[pos];
1053
                            pos++;
11 andreas 1054
                        }
1055
 
86 andreas 1056
                        comm.data.filetransfer.data[0x0103] = 0;
1057
                        handleFTransfer(s, comm.data.filetransfer);
1058
                    }
1059
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0104)    // request a file
1060
                    {
1061
                        comm.data.filetransfer.unk = makeWord(buff_[4], buff_[5]);
1062
                        pos = 6;
11 andreas 1063
 
86 andreas 1064
                        for (size_t i = 0; i < 0x0104; i++)
11 andreas 1065
                        {
86 andreas 1066
                            comm.data.filetransfer.data[i] = buff_[pos];
1067
                            pos++;
11 andreas 1068
                        }
1069
 
86 andreas 1070
                        comm.data.filetransfer.data[0x0103] = 0;
1071
                        handleFTransfer(s, comm.data.filetransfer);
1072
                    }
1073
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0106)    // ACK for 0x0105
1074
                    {
1075
                        comm.data.filetransfer.unk = makeDWord(buff_[4], buff_[5], buff_[6], buff_[7]);
1076
                        pos = 8;
1077
                        handleFTransfer(s, comm.data.filetransfer);
1078
                    }
1079
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0002)    // request next part of file
1080
                        handleFTransfer(s, comm.data.filetransfer);
1081
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0003)    // File content from controller
1082
                    {
1083
                        comm.data.filetransfer.unk = makeWord(buff_[4], buff_[5]);  // length of data block
1084
                        pos = 6;
11 andreas 1085
 
86 andreas 1086
                        for (size_t i = 0; i < comm.data.filetransfer.unk; i++)
11 andreas 1087
                        {
86 andreas 1088
                            comm.data.filetransfer.data[i] = buff_[pos];
1089
                            pos++;
11 andreas 1090
                        }
1091
 
86 andreas 1092
                        handleFTransfer(s, comm.data.filetransfer);
1093
                    }
1094
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0004)    // End of file
1095
                        handleFTransfer(s, comm.data.filetransfer);
1096
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0005)    // End of file ACK
1097
                        handleFTransfer(s, comm.data.filetransfer);
1098
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0006)    // End of directory listing ACK
1099
                    {
1100
                        comm.data.filetransfer.unk = makeWord(buff_[4], buff_[5]);  // length of received data block
1101
                        pos = 6;
1102
                        handleFTransfer(s, comm.data.filetransfer);
1103
                    }
1104
                    else if (comm.data.filetransfer.ftype == 4 && comm.data.filetransfer.function == 0x0007)    // End of file transfer
1105
                        handleFTransfer(s, comm.data.filetransfer);
11 andreas 1106
 
86 andreas 1107
                break;
15 andreas 1108
 
86 andreas 1109
                case 0x0501:    // ping
1110
                    comm.data.chan_state.device = makeWord(buff_[0], buff_[1]);
1111
                    comm.data.chan_state.system = makeWord(buff_[2], buff_[3]);
1112
                    s.channel = 0;
1113
                    s.level = 0;
1114
                    s.port = 0;
1115
                    s.value = 0;
1116
                    s.MC = 0x0581;
1117
                    sendCommand(s);
1118
                break;
15 andreas 1119
 
86 andreas 1120
                case 0x0502:    // Date and time
1121
                    comm.data.blinkMessage.heartBeat = buff_[0];
1122
                    comm.data.blinkMessage.LED = buff_[1];
1123
                    comm.data.blinkMessage.month = buff_[2];
1124
                    comm.data.blinkMessage.day = buff_[3];
1125
                    comm.data.blinkMessage.year = makeWord(buff_[4], buff_[5]);
1126
                    comm.data.blinkMessage.hour = buff_[6];
1127
                    comm.data.blinkMessage.minute = buff_[7];
1128
                    comm.data.blinkMessage.second = buff_[8];
1129
                    comm.data.blinkMessage.weekday = buff_[9];
1130
                    comm.data.blinkMessage.extTemp = makeWord(buff_[10], buff_[11]);
1131
                    memset(comm.data.blinkMessage.dateTime, 0, sizeof(comm.data.blinkMessage.dateTime));
1132
                    memcpy(comm.data.blinkMessage.dateTime, &buff_[12], comm.hlen - 0x0015 - 11);
1133
                    comm.checksum = buff_[comm.hlen + 3];
1134
 
1135
                    sendAllFuncTimer(comm.data.blinkMessage);
15 andreas 1136
/*                        if (callback)
86 andreas 1137
                        callback(comm);
1138
                    else
1139
                        MSG_WARNING("Missing callback function!"); */
1140
                break;
1141
            }
1142
        break;
11 andreas 1143
 
86 andreas 1144
        default:        // Every unknown or unsupported command/request should be ignored.
1145
            ignore = true;
11 andreas 1146
    }
1147
}
1148
 
1149
bool TAmxNet::sendCommand(const ANET_SEND& s)
1150
{
1151
    DECL_TRACER("TAmxNet::sendCommand (const ANET_SEND& s)");
1152
 
1153
    size_t len, size;
1154
    ANET_COMMAND com;
1155
    com.clear();
1156
    com.MC = s.MC;
1157
 
1158
    if (s.MC == 0x0204)     // file transfer
1159
        com.device1 = s.device;
1160
    else
1161
        com.device1 = 0;
1162
 
1163
    com.device2 = panelID;
1164
    com.port1 = 1;
1165
    com.system = TConfig::getSystem();
1166
    com.port2 = s.port;
1167
    sendCounter++;
1168
    com.count = sendCounter;
1169
 
1170
    switch (s.MC)
1171
    {
1172
        case 0x0084:        // push button
1173
            com.data.channel.device = com.device2;
1174
            com.data.channel.port = s.port;
1175
            com.data.channel.system = com.system;
1176
            com.data.channel.channel = s.channel;
1177
            com.hlen = 0x0016 - 0x0003 + sizeof(ANET_CHANNEL);
93 andreas 1178
            MSG_DEBUG("SEND: BUTTON PUSH-" << s.channel << ":" << s.port << ":" << com.device2);
11 andreas 1179
            comStack.push_back(com);
14 andreas 1180
            mSendReady = true;
13 andreas 1181
        break;
11 andreas 1182
 
1183
        case 0x0085:        // release button
1184
            com.data.channel.device = com.device2;
1185
            com.data.channel.port = s.port;
1186
            com.data.channel.system = com.system;
1187
            com.data.channel.channel = s.channel;
1188
            com.hlen = 0x0016 - 0x0003 + sizeof(ANET_CHANNEL);
93 andreas 1189
            MSG_DEBUG("SEND: BUTTON RELEASE-" << s.channel << ":" << s.port << ":" << com.device2);
11 andreas 1190
            comStack.push_back(com);
14 andreas 1191
            mSendReady = true;
13 andreas 1192
        break;
11 andreas 1193
 
1194
        case 0x0086:    // output channel on
1195
        case 0x0088:    // feedback/input channel on
1196
            com.data.channel.device = com.device2;
1197
            com.data.channel.port = s.port;
1198
            com.data.channel.system = com.system;
1199
            com.data.channel.channel = s.channel;
1200
            com.hlen = 0x0016 - 0x0003 + sizeof(ANET_CHANNEL);
93 andreas 1201
            MSG_DEBUG("SEND: CHANNEL ON-" << s.channel << ":" << s.port << ":" << com.device2);
11 andreas 1202
            comStack.push_back(com);
14 andreas 1203
            mSendReady = true;
13 andreas 1204
        break;
11 andreas 1205
 
1206
        case 0x0087:    // output channel off
1207
        case 0x0089:    // feedback/input channel off
1208
            com.data.channel.device = com.device2;
1209
            com.data.channel.port = s.port;
1210
            com.data.channel.system = com.system;
1211
            com.data.channel.channel = s.channel;
1212
            com.hlen = 0x0016 - 0x0003 + sizeof(ANET_CHANNEL);
93 andreas 1213
            MSG_DEBUG("SEND: CHANNEL OFF-" << s.channel << ":" << s.port << ":" << com.device2);
11 andreas 1214
            comStack.push_back(com);
14 andreas 1215
            mSendReady = true;
13 andreas 1216
        break;
11 andreas 1217
 
1218
        case 0x008a:        // level value changed
1219
            com.data.message_value.device = com.device2;
1220
            com.data.message_value.port = s.port;
1221
            com.data.message_value.system = com.system;
1222
            com.data.message_value.value = s.level;
1223
            com.data.message_value.type = 0x20;     // unsigned integer
1224
            com.data.message_value.content.integer = s.value;
1225
            com.hlen = 0x0016 - 0x0003 + 11;
93 andreas 1226
            MSG_DEBUG("SEND: LEVEL-" << s.value << "," << s.level << ":" << s.port << ":" << com.device2);
11 andreas 1227
            comStack.push_back(com);
14 andreas 1228
            mSendReady = true;
13 andreas 1229
        break;
11 andreas 1230
 
1231
        case 0x008b:        // string command
1232
        case 0x008c:        // send command string
1233
            com.data.message_string.device = com.device2;
1234
            com.data.message_string.port = s.port;
1235
            com.data.message_string.system = com.system;
1236
            com.data.message_string.type = 0x01;    // char string
1237
 
1238
            if (s.msg.length() >= sizeof(com.data.message_string.content))
1239
                len = sizeof(com.data.message_string.content) - 1;
1240
            else
1241
                len = s.msg.length();
1242
 
1243
            com.data.message_string.length = len;
1244
            strncpy((char *)&com.data.message_string.content[0], s.msg.c_str(), len);
1245
            com.hlen = 0x0016 - 3 + 9 + len;
93 andreas 1246
            MSG_DEBUG("SEND: STRING-'" << s.msg << "'," << s.port << ":" << com.device2);
11 andreas 1247
            comStack.push_back(com);
14 andreas 1248
            mSendReady = true;
13 andreas 1249
        break;
11 andreas 1250
 
1251
        case 0x008d:    // Custom event
1252
            com.data.customEvent.device = com.device2;
1253
            com.data.customEvent.port = s.port;
1254
            com.data.customEvent.system = com.system;
1255
            com.data.customEvent.ID = s.ID;
1256
            com.data.customEvent.type = s.type;
1257
            com.data.customEvent.flag = s.flag;
1258
            com.data.customEvent.value1 = s.value1;
1259
            com.data.customEvent.value2 = s.value2;
1260
            com.data.customEvent.value3 = s.value3;
1261
            com.data.customEvent.dtype = s.dtype;
1262
 
1263
            if (s.msg.length() >= sizeof(com.data.customEvent.data))
1264
                len = sizeof(com.data.customEvent.data) - 1;
1265
            else
1266
                len = s.msg.length();
1267
 
1268
            com.data.customEvent.length = len;
1269
            memset(com.data.customEvent.data, 0, sizeof(com.data.customEvent.data));
1270
            memcpy(&com.data.customEvent.data[0], s.msg.c_str(), s.msg.length());
1271
            com.hlen = 0x0016 - 3 + 29 + s.msg.length();
1272
            comStack.push_back(com);
14 andreas 1273
            mSendReady = true;
13 andreas 1274
        break;
11 andreas 1275
 
1276
        case 0x0090:        // port count
1277
            com.data.sendPortNumber.device = com.device2;
1278
            com.data.sendPortNumber.system = com.system;
1279
            com.data.sendPortNumber.pcount = s.value;
1280
            com.hlen = 0x0016 - 3 + 6;
1281
            comStack.push_back(com);
14 andreas 1282
            mSendReady = true;
13 andreas 1283
        break;
11 andreas 1284
 
1285
        case 0x0091:        // output channel count
1286
        case 0x0092:        // send level count
1287
            com.data.sendOutpChannels.device = com.device2;
1288
            com.data.sendOutpChannels.port = s.port;
1289
            com.data.sendOutpChannels.system = com.system;
1290
            com.data.sendOutpChannels.count = s.value;
1291
            com.hlen = 0x0016 - 3 + 8;
1292
            comStack.push_back(com);
14 andreas 1293
            mSendReady = true;
13 andreas 1294
        break;
11 andreas 1295
 
1296
        case 0x0093:        // string size
1297
        case 0x0094:        // command size
1298
            com.data.sendSize.device = com.device2;
1299
            com.data.sendSize.port = s.port;
1300
            com.data.sendSize.system = com.system;
1301
            com.data.sendSize.type = 0x01;
1302
            com.data.sendSize.length = s.value;
1303
            com.hlen = 0x0016 - 3 + 9;
1304
            comStack.push_back(com);
14 andreas 1305
            mSendReady = true;
13 andreas 1306
        break;
11 andreas 1307
 
1308
        case 0x0095:        // suported level types
1309
            com.data.sendLevSupport.device = com.device2;
1310
            com.data.sendLevSupport.port = s.port;
1311
            com.data.sendLevSupport.system = com.system;
1312
            com.data.sendLevSupport.level = s.level;
1313
            com.data.sendLevSupport.num = 6;
1314
            com.data.sendLevSupport.types[0] = 0x10;
1315
            com.data.sendLevSupport.types[1] = 0x11;
1316
            com.data.sendLevSupport.types[2] = 0x20;
1317
            com.data.sendLevSupport.types[3] = 0x21;
1318
            com.data.sendLevSupport.types[4] = 0x40;
1319
            com.data.sendLevSupport.types[5] = 0x41;
1320
            com.hlen = 0x0016 - 0x0003 + sizeof(ANET_LEVSUPPORT);
1321
            comStack.push_back(com);
14 andreas 1322
            mSendReady = true;
13 andreas 1323
        break;
11 andreas 1324
 
1325
        case 0x0096:        // Status code
1326
            com.data.sendStatusCode.device = com.device2;
1327
            com.data.sendStatusCode.port = s.port;
1328
            com.data.sendStatusCode.system = com.system;
1329
            com.data.sendStatusCode.status = 0;
1330
            com.data.sendStatusCode.type = 0x11;
1331
            com.data.sendStatusCode.length = 2;
1332
            com.data.sendStatusCode.str[0] = 'O';
1333
            com.data.sendStatusCode.str[1] = 'K';
1334
            com.hlen = 0x0016 - 3 + 13;
1335
            comStack.push_back(com);
14 andreas 1336
            mSendReady = true;
13 andreas 1337
        break;
11 andreas 1338
 
1339
        case 0x0097:        // device info
1340
            com.data.srDeviceInfo.device = com.device2;
1341
            com.data.srDeviceInfo.system = com.system;
1342
            com.data.srDeviceInfo.flag = 0x0000;
1343
            com.data.srDeviceInfo.objectID = 0;
1344
            com.data.srDeviceInfo.parentID = 0;
1345
            com.data.srDeviceInfo.herstID = 1;
1346
            msg97fill(&com);
14 andreas 1347
            mSendReady = true;
13 andreas 1348
        break;
11 andreas 1349
 
1350
        case 0x0098:
1351
            com.data.reqPortCount.device = com.device2;
1352
            com.data.reqPortCount.system = com.system;
1353
            com.hlen = 0x0016 - 3 + 4;
1354
            comStack.push_back(com);
14 andreas 1355
            mSendReady = true;
13 andreas 1356
        break;
11 andreas 1357
 
1358
        case 0x0204:        // File transfer
1359
            com.port1 = 0;
1360
            com.port2 = 0;
1361
            com.data.filetransfer.ftype = s.dtype;
1362
            com.data.filetransfer.function = s.type;
1363
            com.data.filetransfer.info1 = s.value;
1364
            com.data.filetransfer.info2 = s.level;
1365
            com.data.filetransfer.unk = s.value1;
1366
            com.data.filetransfer.unk1 = s.value2;
1367
            com.data.filetransfer.unk2 = s.value3;
1368
            size = min(s.msg.length(), sizeof(com.data.filetransfer.data) - 1);
1369
            memcpy(com.data.filetransfer.data, s.msg.c_str(), size);
1370
            com.data.filetransfer.data[size] = 0;
1371
            len = 4;
1372
 
1373
            if (s.dtype == 0)
1374
            {
1375
                switch (s.type)
1376
                {
1377
                    case 0x0001: len += 2; break;
1378
                    case 0x0101: len += 16 + size + 1; break;
1379
                    case 0x0102: len += 19 + size + 1; break;
1380
                }
1381
            }
1382
            else
1383
            {
1384
                switch (s.type)
1385
                {
1386
                    case 0x0003: len += 2 + s.value1; break;
1387
                    case 0x0101: len += 8; break;
1388
                    case 0x0103: len += 6; break;
1389
                    case 0x0105: len += 8; break;
1390
                }
1391
            }
1392
 
1393
            com.hlen = 0x0016 - 3 + len;
1394
            comStack.push_back(com);
14 andreas 1395
            mSendReady = true;
13 andreas 1396
        break;
11 andreas 1397
 
1398
        case 0x0581:        // Pong
1399
            com.data.srDeviceInfo.device = panelID; // Configuration->getAMXChannel();
1400
            com.data.srDeviceInfo.system = TConfig::getSystem();
1401
            com.data.srDeviceInfo.herstID = devInfo[0].manufacturerID;
1402
            com.data.srDeviceInfo.deviceID = devInfo[0].deviceID;
1403
            com.data.srDeviceInfo.info[0] = 2;  // Type: IPv4 address
1404
            com.data.srDeviceInfo.info[1] = 4;  // length of following data
1405
 
1406
            {
92 andreas 1407
                string addr = mSocket->getMyIP();
11 andreas 1408
                vector<string> parts = StrSplit(addr, ".");
1409
 
1410
                for (size_t i = 0; i < parts.size(); i++)
1411
                    com.data.srDeviceInfo.info[i + 2] = (unsigned char)atoi(parts[i].c_str());
1412
            }
1413
 
1414
            com.hlen = 0x0016 - 3 + 14;
1415
            comStack.push_back(com);
14 andreas 1416
            mSendReady = true;
13 andreas 1417
        break;
11 andreas 1418
    }
1419
 
14 andreas 1420
    if (mSendReady)
11 andreas 1421
        start_write();
1422
 
14 andreas 1423
    return mSendReady;
11 andreas 1424
}
1425
 
1426
void TAmxNet::handleFTransfer(ANET_SEND &s, ANET_FILETRANSFER &ft)
1427
{
1428
    DECL_TRACER("TAmxNet::handleFTransfer (ANET_SEND &s, ANET_FILETRANSFER &ft)");
1429
 
1430
    int len;
1431
    ANET_COMMAND ftr;
1432
    ftr.MC = 0x1000;
1433
    ftr.device1 = s.device;
1434
    ftr.device2 = s.device;
1435
    ftr.port1 = 0;
1436
    ftr.port2 = 0;
1437
    ftr.count = 0;
1438
    ftr.data.filetransfer.ftype = ft.ftype;
1439
    ftr.data.filetransfer.function = ft.function;
1440
    ftr.data.filetransfer.data[0] = 0;
1441
 
1442
    if (ft.ftype == 0 && ft.function == 0x0105)     // Create directory
1443
    {
1444
        s.channel = 0;
1445
        s.level = 0;
1446
        s.port = 0;
1447
        s.value = 0;
1448
        s.MC = 0x0204;
1449
        s.dtype = 0;                // ftype --> function type
1450
        s.type = 0x0001;            // function
1451
        s.value1 = 0;               // 1st data byte 0x00
1452
        s.value2 = 0x10;            // 2nd data byte 0x10
1453
        string f((char *)&ft.data);
93 andreas 1454
        MSG_DEBUG("0x0000/0x0105: Directory " << f << " exist?");
88 andreas 1455
        string prjPath = TConfig::getProjectPath();
1456
        string newPath;
1457
        dir::TDirectory dir;
11 andreas 1458
 
1459
        if (f.compare(0, 8, "AMXPanel") == 0)
1460
        {
1461
            if (f.find("/images") > 0)
88 andreas 1462
            {
1463
                newPath = prjPath + "/images";
1464
                dir.createAllPath(newPath);
1465
//                mkdir(string(TConfig::getProjectPath() + "/images").c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
1466
            }
11 andreas 1467
            else if (f.find("/sounds") > 0)
88 andreas 1468
            {
1469
                newPath = prjPath + "/sounds";
1470
                dir.createAllPath(newPath);
1471
//                mkdir(string(TConfig::getProjectPath() + "/sounds").c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
1472
            }
11 andreas 1473
            else if (f.find("/fonts") > 0)
88 andreas 1474
            {
1475
                newPath = prjPath + "/fonts";
1476
                dir.createAllPath(newPath);
1477
//                mkdir(string(TConfig::getProjectPath() + "/fonts").c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
1478
            }
11 andreas 1479
        }
1480
        else if (f.compare(0, 8, "__system") == 0)
1481
        {
88 andreas 1482
            vector<string> subDirs = { "borders", "cursors", "fonts", "images", "sliders", "sounds" };
1483
            vector<string>::iterator iter;
1484
 
1485
            for (iter = subDirs.begin(); iter != subDirs.end(); ++iter)
11 andreas 1486
            {
88 andreas 1487
                newPath = prjPath + "/__system/graphics/" + *iter;
1488
                dir.createAllPath(newPath);
11 andreas 1489
            }
1490
        }
1491
 
1492
        sendCommand(s);
1493
 
1494
        if (!receiveSetup)
1495
        {
1496
            receiveSetup = true;
1497
            ftransfer.maxFiles = countFiles();
1498
 
1499
            if (callback)
1500
                callback(ftr);
13 andreas 1501
            else
1502
                MSG_WARNING("Missing callback function!");
11 andreas 1503
        }
1504
    }
1505
    else if (ft.ftype == 0 && ft.function == 0x0100)    // Request directory
1506
    {
1507
        string fname((char *)&ft.data);
1508
        string amxpath(fname);
1509
        string realPath;
1510
        size_t pos = 0;
1511
        len = 0;
1512
        dir::TDirectory dr;
1513
 
1514
        if (fname.compare("AMXPanel/") == 0)
1515
        {
1516
            realPath.assign(TConfig::getProjectPath());
1517
            amxpath.assign("/opt/amx/user/AMXPanel");
1518
        }
1519
        else if ((pos = fname.find("AMXPanel/")) != string::npos)
1520
        {
1521
            if (pos == 0)
1522
                amxpath = "/opt/amx/user/" + fname;
1523
 
1524
            realPath = dr.stripPath("AMXPanel", fname);
1525
            realPath = TConfig::getProjectPath() + "/" + realPath;
1526
 
1527
            if (dr.isFile(realPath))
1528
                len = dr.getFileSize(realPath);
1529
        }
1530
 
93 andreas 1531
        MSG_DEBUG("0x0000/0x0100: Request directory " << fname);
11 andreas 1532
        snprintf((char *)&ftr.data.filetransfer.data[0], sizeof(ftr.data.filetransfer.data), "Syncing %d files ...", ftransfer.maxFiles);
1533
 
1534
        if (callback)
1535
            callback(ftr);
13 andreas 1536
        else
1537
            MSG_WARNING("Missing callback function!");
14 andreas 1538
 
11 andreas 1539
        s.channel = 0;
1540
        s.level = 0;
1541
        s.port = 0;
1542
        s.value = 0;
1543
        s.MC = 0x0204;
1544
        s.dtype = 0x0000;
1545
        s.type = 0x0101;
1546
        s.value1 = len;     // File length
1547
        s.value2 = 0x0000be42;
1548
        s.value3 = 0x00003e75;
1549
        s.msg = amxpath;
1550
        sendCommand(s);
1551
        // Read the directory tree
1552
        dr.setStripPath(true);
1553
        dr.readDir(realPath);
1554
        amxpath = fname;
1555
 
1556
        if (amxpath.length() > 1 && amxpath.at(amxpath.length() - 1) == '/')
1557
            amxpath = amxpath.substr(0, amxpath.length() - 1);
1558
 
1559
        for (pos = 0; pos < dr.getNumEntries(); pos++)
1560
        {
1561
            dir::DFILES_T df = dr.getEntry(pos);
1562
            s.type = 0x0102;
1563
 
1564
            s.value = (dr.testDirectory(df.attr)) ? 1 : 0;  // Depends on type of entry
1565
            s.level = dr.getNumEntries();       // # entries
1566
            s.value1 = df.count;                // counter
1567
            s.value2 = df.size;                 // Size of file
1568
            s.value3 = df.date;                 // Last modification date (epoch)
1569
            s.msg.assign(amxpath + "/" + df.name);
1570
            sendCommand(s);
1571
        }
23 andreas 1572
 
1573
        if (dr.getNumEntries() == 0)
1574
        {
1575
            s.type = 0x0102;
1576
 
1577
            s.value = 0;
1578
            s.level = 0;       // # entries
1579
            s.value1 = 0;                // counter
1580
            s.value2 = 0;                 // Size of file
1581
            s.value3 = 0;                 // Last modification date (epoch)
1582
            s.msg.assign(amxpath + "/");
1583
            sendCommand(s);
1584
        }
11 andreas 1585
    }
1586
    else if (ft.ftype == 4 && ft.function == 0x0100)    // Have more files to send.
1587
    {
93 andreas 1588
        MSG_DEBUG("0x0004/0x0100: Have more files to send.");
11 andreas 1589
        s.channel = 0;
1590
        s.level = 0;
1591
        s.port = 0;
1592
        s.value = 0;
1593
        s.MC = 0x0204;
1594
        s.dtype = 4;                // ftype --> function type
1595
        s.type = 0x0101;            // function:
1596
        s.value1 = 0x01bb3000;      // ?
1597
        s.value2 = 0;               // ?
1598
        sendCommand(s);
1599
    }
1600
    else if (ft.ftype == 4 && ft.function == 0x0102)    // Controller will send a file
1601
    {
1602
        string f((char*)&ft.data);
1603
        size_t pos;
1604
        rcvFileName.assign(TConfig::getProjectPath());
1605
 
1606
        if (f.find("AMXPanel") != string::npos)
1607
        {
1608
            pos = f.find_first_of("/");
1609
            rcvFileName.append(f.substr(pos));
1610
        }
1611
        else
1612
        {
1613
            rcvFileName.append("/");
1614
            rcvFileName.append((char*)&ft.data);
1615
        }
1616
 
1617
        if (rcvFile != nullptr)
88 andreas 1618
        {
11 andreas 1619
            fclose(rcvFile);
88 andreas 1620
            rcvFile = nullptr;
1621
            isOpenRcv = false;
1622
        }
11 andreas 1623
 
43 andreas 1624
        // The file name is encoded as CP1250 (Windows). Because we use UTF-8 we
1625
        // must convert the file name to get rid of non ASCII characters.
1626
        rcvFileName = cp1250ToUTF8(rcvFileName);
65 andreas 1627
        dir::TDirectory dr;
1628
 
1629
        if (!dr.exists(rcvFileName))
1630
            dr.createAllPath(rcvFileName, true);
1631
        else
1632
            dr.drop(rcvFileName);
1633
 
11 andreas 1634
        rcvFile = fopen(rcvFileName.c_str(), "w+");
1635
 
1636
        if (!rcvFile)
1637
        {
65 andreas 1638
            MSG_ERROR("Error creating file " << rcvFileName << " (" << strerror(errno) << ")");
11 andreas 1639
            isOpenRcv = false;
1640
        }
1641
        else
65 andreas 1642
        {
11 andreas 1643
            isOpenRcv = true;
1644
 
65 andreas 1645
            if (!TStreamError::checkFilter(HLOG_TRACE))
1646
            {
1647
                MSG_INFO("Writing file: " << rcvFileName);
1648
            }
1649
        }
1650
 
93 andreas 1651
        MSG_DEBUG("0x0004/0x0102: Controller will send file " << rcvFileName);
65 andreas 1652
 
11 andreas 1653
        ftransfer.actFileNum++;
1654
        ftransfer.lengthFile = ft.unk;
1655
 
1656
        if (ftransfer.actFileNum > ftransfer.maxFiles)
1657
            ftransfer.maxFiles = ftransfer.actFileNum;
1658
 
1659
        ftransfer.percent = (int)(100.0 / (double)ftransfer.maxFiles * (double)ftransfer.actFileNum);
1660
        pos = rcvFileName.find_last_of("/");
1661
        string shfn;
1662
 
1663
        if (pos != string::npos)
43 andreas 1664
            shfn = rcvFileName.substr(pos + 1);
11 andreas 1665
        else
43 andreas 1666
            shfn = rcvFileName;
11 andreas 1667
 
43 andreas 1668
        snprintf((char*)&ftr.data.filetransfer.data[0], sizeof(ftr.data.filetransfer.data), "[%d/%d] %s", ftransfer.actFileNum, ftransfer.maxFiles, shfn.c_str());
11 andreas 1669
        ftr.count = ftransfer.percent;
1670
        ftr.data.filetransfer.info1 = 0;
1671
 
1672
        if (callback)
1673
            callback(ftr);
13 andreas 1674
        else
1675
            MSG_WARNING("Missing callback function!");
11 andreas 1676
 
1677
        posRcv = 0;
1678
        lenRcv = ft.unk;
1679
        s.channel = 0;
1680
        s.level = 0;
1681
        s.port = 0;
1682
        s.value = 0;
1683
        s.MC = 0x0204;
1684
        s.dtype = 4;                // ftype --> function type
1685
        s.type = 0x0103;            // function: ready for receiving file
1686
        s.value1 = MAX_CHUNK;       // Maximum length of a chunk
1687
        s.value2 = ft.unk1;         // ID?
1688
        sendCommand(s);
1689
    }
1690
    else if (ft.ftype == 0 && ft.function == 0x0104)    // Delete file <name>
1691
    {
1692
        dir::TDirectory dr;
1693
        s.channel = 0;
1694
        s.level = 0;
1695
        s.port = 0;
1696
        s.value = 0;
1697
        s.MC = 0x0204;
1698
        string f((char*)&ft.data[0]);
1699
        size_t pos = 0;
1700
 
1701
        if ((pos = f.find("AMXPanel/")) == string::npos)
1702
            pos = f.find("__system/");
1703
 
93 andreas 1704
        MSG_DEBUG("0x0000/0x0104: Delete file " << f);
11 andreas 1705
 
1706
        if (pos != string::npos)
1707
            f = TConfig::getProjectPath() + "/" + f.substr(pos + 9);
1708
        else
1709
            f = TConfig::getProjectPath() + "/" + f;
1710
 
1711
        if (dr.exists(f))
1712
        {
1713
            s.dtype = 0;                // ftype --> function type
1714
            s.type = 0x0002;            // function: yes file exists
1715
            remove(f.c_str());
1716
        }
1717
        else    // Send: file was deleted although it does not exist.
1718
        {
1719
            MSG_ERROR("[DELETE] File " << f << " not found!");
1720
            s.dtype = 0;                // ftype --> function type
1721
            s.type = 0x0002;            // function: yes file exists
1722
        }
1723
 
1724
        sendCommand(s);
1725
 
1726
        if (ftransfer.actDelFile == 0)
1727
        {
1728
            ftransfer.actDelFile++;
1729
            ftransfer.percent = (int)(100.0 / (double)ftransfer.maxFiles * (double)ftransfer.actDelFile);
1730
            ftr.count = ftransfer.percent;
1731
 
1732
            if (callback)
1733
                callback(ftr);
13 andreas 1734
            else
1735
                MSG_WARNING("Missing callback function!");
11 andreas 1736
        }
1737
        else
1738
        {
1739
            ftransfer.actDelFile++;
1740
            int prc = (int)(100.0 / (double)ftransfer.maxFiles * (double)ftransfer.actDelFile);
1741
 
1742
            if (prc != ftransfer.percent)
1743
            {
1744
                ftransfer.percent = prc;
1745
                ftr.count = prc;
1746
 
1747
                if (callback)
1748
                    callback(ftr);
13 andreas 1749
                else
1750
                    MSG_WARNING("Missing callback function!");
11 andreas 1751
            }
1752
        }
1753
    }
1754
    else if (ft.ftype == 4 && ft.function == 0x0104)    // request a file
1755
    {
1756
        string f((char*)&ft.data);
1757
        size_t pos;
1758
        len = 0;
1759
        sndFileName.assign(TConfig::getProjectPath());
93 andreas 1760
        MSG_DEBUG("0x0004/0x0104: Request file " << f);
11 andreas 1761
 
1762
        if (f.find("AMXPanel") != string::npos)
1763
        {
1764
            pos = f.find_first_of("/");
1765
            sndFileName.append(f.substr(pos));
1766
        }
1767
        else
1768
        {
1769
            sndFileName.append("/");
1770
            sndFileName.append(f);
1771
        }
1772
 
1773
        if (!access(sndFileName.c_str(), R_OK))
1774
        {
1775
            struct stat s;
1776
 
1777
            if (stat(sndFileName.c_str(), &s) == 0)
1778
                len = s.st_size;
1779
            else
1780
                len = 0;
1781
        }
1782
        else if (sndFileName.find("/version.xma") > 0)
1783
            len = 0x0015;
1784
        else
1785
            len = 0;
1786
 
93 andreas 1787
        MSG_DEBUG("0x0004/0x0104: (" << len << ") File: " << sndFileName);
11 andreas 1788
 
1789
        s.channel = 0;
1790
        s.level = 0;
1791
        s.port = 0;
1792
        s.value = 0;
1793
        s.MC = 0x0204;
1794
        s.dtype = 4;                // ftype --> function type
1795
        s.type = 0x0105;            // function
1796
        s.value1 = len;             // length of file to send
1797
        s.value2 = 0x00001388;      // ID for device when sending a file.
1798
        sendCommand(s);
1799
    }
1800
    else if (ft.ftype == 4 && ft.function == 0x0106)    // Controller is ready for receiving file
1801
    {
93 andreas 1802
        MSG_DEBUG("0x0004/0x0106: Controller is ready for receiving file.");
11 andreas 1803
 
1804
        if (!access(sndFileName.c_str(), R_OK))
1805
        {
1806
            struct stat st;
1807
            stat(sndFileName.c_str(), &st);
1808
            len = st.st_size;
1809
            lenSnd = len;
1810
            posSnd = 0;
1811
            sndFile = fopen(sndFileName.c_str(), "r");
1812
 
1813
            if (!sndFile)
1814
            {
1815
                MSG_ERROR("Error reading file " << sndFileName);
1816
                len = 0;
1817
                isOpenSnd = false;
1818
            }
1819
            else
1820
                isOpenSnd = true;
1821
 
1822
            if (isOpenSnd && len <= MAX_CHUNK)
1823
            {
1824
                char *buf = new char[len + 1];
1825
                fread(buf, 1, len, sndFile);
1826
                s.msg.assign(buf, len);
1827
                delete[] buf;
1828
                posSnd = len;
1829
            }
1830
            else if (isOpenSnd)
1831
            {
1832
                char *buf = new char[MAX_CHUNK + 1];
1833
                fread(buf, 1, MAX_CHUNK, sndFile);
1834
                s.msg.assign(buf, MAX_CHUNK);
1835
                delete[] buf;
1836
                posSnd = MAX_CHUNK;
1837
                len = MAX_CHUNK;
1838
            }
1839
        }
1840
        else if (sndFileName.find("/version.xma") > 0)
1841
        {
1842
            s.msg.assign("<version>9</version>\n");
1843
            len = s.msg.length();
1844
            posSnd = len;
1845
        }
1846
        else
1847
            len = 0;
1848
 
1849
        s.channel = 0;
1850
        s.level = 0;
1851
        s.port = 0;
1852
        s.value = 0;
1853
        s.MC = 0x0204;
1854
        s.dtype = 4;                // ftype --> function type
1855
        s.type = 0x0003;            // function: Sending file with length <len>
1856
        s.value1 = len;             // length of content to send
1857
        sendCommand(s);
1858
    }
1859
    else if (ft.ftype == 4 && ft.function == 0x0002)    // request next part of file
1860
    {
93 andreas 1861
        MSG_DEBUG("0x0004/0x0002: Request next part of file.");
11 andreas 1862
        s.channel = 0;
1863
        s.level = 0;
1864
        s.port = 0;
1865
        s.value = 0;
1866
        s.MC = 0x0204;
1867
        s.dtype = 4;                // ftype --> function type
1868
 
1869
        if (posSnd < lenSnd)
1870
        {
1871
            s.type = 0x0003;        // Next part of file
1872
 
1873
            if ((posSnd + MAX_CHUNK) > lenSnd)
1874
                len = lenSnd - posSnd;
1875
            else
1876
                len = MAX_CHUNK;
1877
 
1878
            s.value1 = len;
1879
 
1880
            if (isOpenSnd)
1881
            {
1882
                char *buf = new char[len + 1];
1883
                fread(buf, 1, len, sndFile);
1884
                s.msg.assign(buf, len);
1885
                delete[] buf;
1886
                posSnd += len;
1887
            }
1888
            else
1889
                s.value1 = 0;
1890
        }
1891
        else
1892
            s.type = 0x0004;        // function: End of file reached
1893
 
1894
        sendCommand(s);
1895
    }
1896
    else if (ft.ftype == 4 && ft.function == 0x0003)    // File content
1897
    {
93 andreas 1898
        MSG_DEBUG("0x0004/0x0003: Received (part of) file.");
11 andreas 1899
        len = ft.unk;
1900
 
1901
        if (isOpenRcv)
1902
        {
1903
            fwrite(ft.data, 1, len, rcvFile);
1904
            posRcv += ft.unk;
1905
        }
1906
        else
65 andreas 1907
            MSG_WARNING("No open file to write to! (" << rcvFileName << ")");
11 andreas 1908
 
1909
        s.channel = 0;
1910
        s.level = 0;
1911
        s.port = 0;
1912
        s.value = 0;
1913
        s.MC = 0x0204;
1914
        s.dtype = 4;                // ftype --> function type
1915
        s.type = 0x0002;            // function: Request next part of file
1916
        sendCommand(s);
1917
 
1918
        int prc = (int)(100.0 / (double)ftransfer.lengthFile * (double)posRcv);
1919
 
1920
        if (prc != ftr.data.filetransfer.info1)
1921
        {
1922
            ftr.data.filetransfer.info1 = (int)(100.0 / (double)ftransfer.lengthFile * (double)posRcv);
1923
            ftr.count = ftransfer.percent;
1924
 
1925
            if (callback)
1926
                callback(ftr);
13 andreas 1927
            else
1928
                MSG_WARNING("Missing callback function!");
11 andreas 1929
        }
1930
    }
1931
    else if (ft.ftype == 4 && ft.function == 0x0004)    // End of file
1932
    {
93 andreas 1933
        MSG_DEBUG("0x0004/0x0004: End of file.");
11 andreas 1934
 
1935
        if (isOpenRcv)
1936
        {
1937
            unsigned char buf[8];
1938
            fseek(rcvFile, 0, SEEK_SET);
1939
            fread(buf, 1, sizeof(buf), rcvFile);
1940
            fclose(rcvFile);
1941
            isOpenRcv = false;
1942
            rcvFile = nullptr;
1943
            posRcv = 0;
1944
 
1945
            if (buf[0] == 0x1f && buf[1] == 0x8b)   // GNUzip compressed?
1946
            {
1947
                TExpand exp(rcvFileName);
1948
                exp.unzip();
1949
            }
1950
        }
1951
 
1952
        ftr.count = ftransfer.percent;
1953
        ftr.data.filetransfer.info1 = 100;
1954
 
1955
        if (callback)
1956
            callback(ftr);
13 andreas 1957
        else
1958
            MSG_WARNING("Missing callback functiom!");
11 andreas 1959
 
1960
        s.channel = 0;
1961
        s.level = 0;
1962
        s.port = 0;
1963
        s.value = 0;
1964
        s.MC = 0x0204;
1965
        s.dtype = 4;                // ftype --> function type
1966
        s.type = 0x0005;            // function: ACK, file received. No answer expected.
1967
        sendCommand(s);
1968
    }
1969
    else if (ft.ftype == 4 && ft.function == 0x0005)    // ACK, controller received file, no answer
1970
    {
93 andreas 1971
        MSG_DEBUG("0x0004/0x0005: Controller received file.");
11 andreas 1972
        posSnd = 0;
1973
        lenSnd = 0;
1974
 
1975
        if (isOpenSnd && sndFile != nullptr)
1976
            fclose(sndFile);
1977
 
1978
        ftransfer.lengthFile = 0;
1979
        sndFile = nullptr;
1980
    }
1981
    else if (ft.ftype == 4 && ft.function == 0x0006)    // End of directory transfer ACK
1982
    {
93 andreas 1983
        MSG_DEBUG("0x0004/0x0006: End of directory transfer.");
11 andreas 1984
    }
1985
    else if (ft.ftype == 4 && ft.function == 0x0007)    // End of file transfer
1986
    {
93 andreas 1987
        MSG_DEBUG("0x0004/0x0007: End of file transfer.");
11 andreas 1988
 
1989
        if (callback)
1990
            callback(ftr);
13 andreas 1991
        else
1992
            MSG_WARNING("Missing callback function!");
11 andreas 1993
 
1994
        receiveSetup = false;
1995
    }
1996
}
1997
 
1998
int TAmxNet::msg97fill(ANET_COMMAND *com)
1999
{
2000
    DECL_TRACER("TAmxNet::msg97fill(ANET_COMMAND *com)");
2001
 
2002
    int pos = 0;
2003
    unsigned char buf[512];
2004
 
2005
    for (size_t i = 0; i < devInfo.size(); i++)
2006
    {
2007
        pos = 0;
2008
 
2009
        if (i == 0)
2010
            com->sep1 = 0x12;
2011
        else
2012
            com->sep1 = 0x02;
2013
 
2014
        memset(buf, 0, sizeof(buf));
2015
        com->data.srDeviceInfo.objectID = devInfo[i].objectID;
2016
        com->data.srDeviceInfo.parentID = devInfo[i].parentID;
2017
        com->data.srDeviceInfo.herstID = devInfo[i].manufacturerID;
2018
        com->data.srDeviceInfo.deviceID = devInfo[i].deviceID;
2019
        memcpy(com->data.srDeviceInfo.serial, devInfo[i].serialNum, 16);
2020
        com->data.srDeviceInfo.fwid = devInfo[i].firmwareID;
2021
        memcpy(buf, devInfo[i].versionInfo, strlen(devInfo[i].versionInfo));
2022
        pos = (int)strlen(devInfo[i].versionInfo) + 1;
2023
        memcpy(buf + pos, devInfo[i].deviceInfo, strlen(devInfo[i].deviceInfo));
2024
        pos += strlen(devInfo[i].deviceInfo) + 1;
2025
        memcpy(buf + pos, devInfo[i].manufacturerInfo, strlen(devInfo[i].manufacturerInfo));
2026
        pos += strlen(devInfo[i].manufacturerInfo) + 1;
2027
        *(buf + pos) = 0x02; // type IP address
2028
        pos++;
2029
        *(buf + pos) = 0x04; // field length: 4 bytes
2030
        // Now the IP Address
92 andreas 2031
        string addr = mSocket->getMyIP();
11 andreas 2032
        vector<string> parts = StrSplit(addr, ".");
2033
 
2034
        for (size_t i = 0; i < parts.size(); i++)
2035
        {
2036
            pos++;
2037
            *(buf + pos) = (unsigned char)atoi(parts[i].c_str());
2038
        }
2039
 
2040
        pos++;
2041
        com->data.srDeviceInfo.len = pos;
2042
        memcpy(com->data.srDeviceInfo.info, buf, pos);
2043
        com->hlen = 0x0016 - 3 + 31 + pos - 1;
2044
        comStack.push_back(*com);
2045
        sendCounter++;
2046
        com->count = sendCounter;
2047
    }
2048
 
2049
    return pos;
2050
}
2051
 
2052
void TAmxNet::start_write()
2053
{
2054
    DECL_TRACER("TAmxNet::start_write()");
2055
 
92 andreas 2056
    if (!__CommValid || !mSocket || !isRunning() || !mSocket->isConnected())
11 andreas 2057
        return;
2058
 
2059
    if (write_busy)
2060
        return;
2061
 
2062
    write_busy = true;
2063
 
2064
    while (comStack.size() > 0)
2065
    {
2066
        if (!isRunning())
2067
        {
2068
            comStack.clear();
2069
            write_busy = false;
2070
            return;
2071
        }
2072
 
89 andreas 2073
        mSend = comStack.at(0);
11 andreas 2074
        comStack.erase(comStack.begin());   // delete oldest element
89 andreas 2075
        unsigned char *buf = makeBuffer(mSend);
11 andreas 2076
 
89 andreas 2077
        if (buf == nullptr)
11 andreas 2078
        {
89 andreas 2079
            MSG_ERROR("Error creating a buffer! Token number: " << mSend.MC);
11 andreas 2080
            continue;
2081
        }
2082
 
89 andreas 2083
        MSG_DEBUG("Wrote buffer with " << (mSend.hlen + 4) << " bytes.");
92 andreas 2084
        mSocket->send((char *)buf, mSend.hlen + 4);
11 andreas 2085
        delete[] buf;
2086
    }
2087
 
14 andreas 2088
    mSendReady = false;
11 andreas 2089
    write_busy = false;
2090
}
2091
 
2092
uint16_t TAmxNet::swapWord(uint16_t w)
2093
{
2094
    uint16_t word = 0;
2095
    word = ((w << 8) & 0xff00) | ((w >> 8) & 0x00ff);
2096
    return word;
2097
}
2098
 
2099
uint32_t TAmxNet::swapDWord(uint32_t dw)
2100
{
2101
    uint32_t dword = 0;
2102
    dword = ((dw << 24) & 0xff000000) | ((dw << 8) & 0x00ff0000) | ((dw >> 8) & 0x0000ff00) | ((dw >> 24) & 0x000000ff);
2103
    return dword;
2104
}
2105
 
2106
unsigned char TAmxNet::calcChecksum(const unsigned char* buffer, size_t len)
2107
{
2108
    DECL_TRACER("TAmxNet::calcChecksum(const unsigned char* buffer, size_t len)");
2109
    unsigned long sum = 0;
2110
 
2111
    for (size_t i = 0; i < len; i++)
2112
        sum += (unsigned long)(*(buffer + i)) & 0x000000ff;
2113
 
2114
    sum &= 0x000000ff;
93 andreas 2115
    MSG_DEBUG("Checksum=" << std::setw(2) << std::setfill('0') << std::hex << sum << ", #bytes=" << len << " bytes.");
11 andreas 2116
    return (unsigned char)sum;
2117
}
2118
 
2119
uint16_t TAmxNet::makeWord(unsigned char b1, unsigned char b2)
2120
{
2121
    return ((b1 << 8) & 0xff00) | b2;
2122
}
2123
 
2124
uint32_t TAmxNet::makeDWord(unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4)
2125
{
2126
    return ((b1 << 24) & 0xff000000) | ((b2 << 16) & 0x00ff0000) | ((b3  << 8) & 0x0000ff00) | b4;
2127
}
2128
 
2129
bool TAmxNet::isCommand(const string& cmd)
2130
{
2131
    DECL_TRACER("TAmxNet::isCommand(string& cmd)");
2132
 
2133
    int i = 0;
2134
 
2135
    while (cmdList[i][0] != 0)
2136
    {
2137
        if (cmd.find(cmdList[i]) == 0)
2138
            return true;
2139
 
2140
        i++;
2141
    }
2142
 
2143
    return false;
2144
}
2145
 
2146
unsigned char *TAmxNet::makeBuffer(const ANET_COMMAND& s)
2147
{
2148
    DECL_TRACER("TAmxNet::makeBuffer (const ANET_COMMAND& s)");
2149
 
2150
    int pos = 0;
2151
    int len;
2152
    bool valid = false;
2153
    unsigned char *buf;
2154
 
2155
    try
2156
    {
2157
        buf = new unsigned char[s.hlen + 5];
2158
        memset(buf, 0, s.hlen + 5);
2159
    }
2160
    catch (std::exception& e)
2161
    {
2162
        MSG_ERROR("Error allocating memory: " << e.what());
2163
        return nullptr;
2164
    }
2165
 
2166
    *buf = s.ID;
2167
    *(buf + 1) = s.hlen >> 8;
2168
    *(buf + 2) = s.hlen;
2169
    *(buf + 3) = s.sep1;
2170
    *(buf + 4) = s.type;
2171
    *(buf + 5) = s.unk1 >> 8;
2172
    *(buf + 6) = s.unk1;
2173
    *(buf + 7) = s.device1 >> 8;
2174
    *(buf + 8) = s.device1;
2175
    *(buf + 9) = s.port1 >> 8;
2176
    *(buf + 10) = s.port1;
2177
    *(buf + 11) = s.system >> 8;
2178
    *(buf + 12) = s.system;
2179
    *(buf + 13) = s.device2 >> 8;
2180
    *(buf + 14) = s.device2;
2181
    *(buf + 15) = s.port2 >> 8;
2182
    *(buf + 16) = s.port2;
2183
    *(buf + 17) = s.unk6;
2184
    *(buf + 18) = s.count >> 8;
2185
    *(buf + 19) = s.count;
2186
    *(buf + 20) = s.MC >> 8;
2187
    *(buf + 21) = s.MC;
2188
 
2189
    // Here the fixed block is complete. The data are following.
2190
    switch (s.MC)
2191
    {
2192
        case 0x0006:
2193
        case 0x0007:
2194
        case 0x0018:
2195
        case 0x0019:
2196
        case 0x0084:
2197
        case 0x0085:
2198
        case 0x0086:
2199
        case 0x0087:
2200
        case 0x0088:
2201
        case 0x0089:
2202
            *(buf + 22) = s.data.chan_state.device >> 8;
2203
            *(buf + 23) = s.data.chan_state.device;
2204
            *(buf + 24) = s.data.chan_state.port >> 8;
2205
            *(buf + 25) = s.data.chan_state.port;
2206
            *(buf + 26) = s.data.chan_state.system >> 8;
2207
            *(buf + 27) = s.data.chan_state.system;
2208
            *(buf + 28) = s.data.chan_state.channel >> 8;
2209
            *(buf + 29) = s.data.chan_state.channel;
2210
            *(buf + 30) = calcChecksum(buf, 30);
2211
            valid = true;
2212
            break;
2213
 
2214
        case 0x000a:
2215
        case 0x008a:
2216
            *(buf + 22) = s.data.message_value.device >> 8;
2217
            *(buf + 23) = s.data.message_value.device;
2218
            *(buf + 24) = s.data.message_value.port >> 8;
2219
            *(buf + 25) = s.data.message_value.port;
2220
            *(buf + 26) = s.data.message_value.system >> 8;
2221
            *(buf + 27) = s.data.message_value.system;
2222
            *(buf + 28) = s.data.message_value.value >> 8;
2223
            *(buf + 29) = s.data.message_value.value;
2224
            *(buf + 30) = s.data.message_value.type;
2225
            pos = 31;
2226
 
2227
            switch (s.data.message_value.type)
2228
            {
2229
                case 0x10: *(buf + pos) = s.data.message_value.content.byte; break;
2230
 
2231
                case 0x11: *(buf + pos) = s.data.message_value.content.ch; break;
2232
 
2233
                case 0x20:
2234
                    *(buf + pos) = s.data.message_value.content.integer >> 8;
2235
                    pos++;
2236
                    *(buf + pos) = s.data.message_value.content.integer;
2237
                    break;
2238
 
2239
                case 0x21:
2240
                    *(buf + pos) = s.data.message_value.content.sinteger >> 8;
2241
                    pos++;
2242
                    *(buf + pos) = s.data.message_value.content.sinteger;
2243
                    break;
2244
 
2245
                case 0x40:
2246
                    *(buf + pos) = s.data.message_value.content.dword >> 24;
2247
                    pos++;
2248
                    *(buf + pos) = s.data.message_value.content.dword >> 16;
2249
                    pos++;
2250
                    *(buf + pos) = s.data.message_value.content.dword >> 8;
2251
                    pos++;
2252
                    *(buf + pos) = s.data.message_value.content.dword;
2253
                    break;
2254
 
2255
                case 0x41:
2256
                    *(buf + pos) = s.data.message_value.content.sdword >> 24;
2257
                    pos++;
2258
                    *(buf + pos) = s.data.message_value.content.sdword >> 16;
2259
                    pos++;
2260
                    *(buf + pos) = s.data.message_value.content.sdword >> 8;
2261
                    pos++;
2262
                    *(buf + pos) = s.data.message_value.content.sdword;
2263
                    break;
2264
 
2265
                case 0x4f:
2266
                    memcpy(buf + pos, &s.data.message_value.content.fvalue, 4);
2267
                    pos += 3;
2268
                    break;
2269
 
2270
                case 0x8f:
2271
                    memcpy(buf + pos, &s.data.message_value.content.fvalue, 8);
2272
                    pos += 3;
2273
                    break;
2274
            }
2275
 
2276
            pos++;
2277
            *(buf + pos) = calcChecksum(buf, pos);
2278
            valid = true;
13 andreas 2279
        break;
11 andreas 2280
 
2281
        case 0x000b:
2282
        case 0x000c:
2283
        case 0x008b:
2284
        case 0x008c:
2285
            *(buf + 22) = s.data.message_string.device >> 8;
2286
            *(buf + 23) = s.data.message_string.device;
2287
            *(buf + 24) = s.data.message_string.port >> 8;
2288
            *(buf + 25) = s.data.message_string.port;
2289
            *(buf + 26) = s.data.message_string.system >> 8;
2290
            *(buf + 27) = s.data.message_string.system;
2291
            *(buf + 28) = s.data.message_string.type;
2292
            *(buf + 29) = s.data.message_string.length >> 8;
2293
            *(buf + 30) = s.data.message_string.length;
2294
            pos = 31;
2295
            memcpy(buf + pos, s.data.message_string.content, s.data.message_string.length);
2296
            pos += s.data.message_string.length;
2297
            *(buf + pos) = calcChecksum(buf, pos);
2298
            valid = true;
13 andreas 2299
        break;
11 andreas 2300
 
2301
        case 0x008d:    // Custom event
2302
            *(buf + 22) = s.data.customEvent.device >> 8;
2303
            *(buf + 23) = s.data.customEvent.device;
2304
            *(buf + 24) = s.data.customEvent.port >> 8;
2305
            *(buf + 25) = s.data.customEvent.port;
2306
            *(buf + 26) = s.data.customEvent.system >> 8;
2307
            *(buf + 27) = s.data.customEvent.system;
2308
            *(buf + 28) = s.data.customEvent.ID >> 8;
2309
            *(buf + 29) = s.data.customEvent.ID;
2310
            *(buf + 30) = s.data.customEvent.type >> 8;
2311
            *(buf + 31) = s.data.customEvent.type;
2312
            *(buf + 32) = s.data.customEvent.flag >> 8;
2313
            *(buf + 33) = s.data.customEvent.flag;
2314
            *(buf + 34) = s.data.customEvent.value1 >> 24;
2315
            *(buf + 35) = s.data.customEvent.value1 >> 16;
2316
            *(buf + 36) = s.data.customEvent.value1 >> 8;
2317
            *(buf + 37) = s.data.customEvent.value1;
2318
            *(buf + 38) = s.data.customEvent.value2 >> 24;
2319
            *(buf + 39) = s.data.customEvent.value2 >> 16;
2320
            *(buf + 40) = s.data.customEvent.value2 >> 8;
2321
            *(buf + 41) = s.data.customEvent.value2;
2322
            *(buf + 42) = s.data.customEvent.value3 >> 24;
2323
            *(buf + 43) = s.data.customEvent.value3 >> 16;
2324
            *(buf + 44) = s.data.customEvent.value3 >> 8;
2325
            *(buf + 45) = s.data.customEvent.value3;
2326
            *(buf + 46) = s.data.customEvent.dtype;
2327
            *(buf + 47) = s.data.customEvent.length >> 8;
2328
            *(buf + 48) = s.data.customEvent.length;
2329
            pos = 49;
2330
 
2331
            if (s.data.customEvent.length > 0)
2332
            {
2333
                memcpy(buf + pos, s.data.customEvent.data, s.data.customEvent.length);
2334
                pos += s.data.customEvent.length;
2335
            }
2336
 
2337
            *(buf + pos) = 0;
2338
            *(buf + pos + 1) = 0;
2339
            pos += 2;
2340
            *(buf + pos) = calcChecksum(buf, pos);
2341
            valid = true;
13 andreas 2342
        break;
11 andreas 2343
 
2344
        case 0x0090:
2345
            *(buf + 22) = s.data.sendPortNumber.device >> 8;
2346
            *(buf + 23) = s.data.sendPortNumber.device;
2347
            *(buf + 24) = s.data.sendPortNumber.system >> 8;
2348
            *(buf + 25) = s.data.sendPortNumber.system;
2349
            *(buf + 26) = s.data.sendPortNumber.pcount >> 8;
2350
            *(buf + 27) = s.data.sendPortNumber.pcount;
2351
            *(buf + 28) = calcChecksum(buf, 28);
2352
            valid = true;
13 andreas 2353
        break;
11 andreas 2354
 
2355
        case 0x0091:
2356
        case 0x0092:
2357
            *(buf + 22) = s.data.sendOutpChannels.device >> 8;
2358
            *(buf + 23) = s.data.sendOutpChannels.device;
2359
            *(buf + 24) = s.data.sendOutpChannels.port >> 8;
2360
            *(buf + 25) = s.data.sendOutpChannels.port;
2361
            *(buf + 26) = s.data.sendOutpChannels.system >> 8;
2362
            *(buf + 27) = s.data.sendOutpChannels.system;
2363
            *(buf + 28) = s.data.sendOutpChannels.count >> 8;
2364
            *(buf + 29) = s.data.sendOutpChannels.count;
2365
            *(buf + 30) = calcChecksum(buf, 30);
2366
            valid = true;
13 andreas 2367
        break;
11 andreas 2368
 
2369
        case 0x0093:
2370
        case 0x0094:
2371
            *(buf + 22) = s.data.sendSize.device >> 8;
2372
            *(buf + 23) = s.data.sendSize.device;
2373
            *(buf + 24) = s.data.sendSize.port >> 8;
2374
            *(buf + 25) = s.data.sendSize.port;
2375
            *(buf + 26) = s.data.sendSize.system >> 8;
2376
            *(buf + 27) = s.data.sendSize.system;
2377
            *(buf + 28) = s.data.sendSize.type;
2378
            *(buf + 29) = s.data.sendSize.length >> 8;
2379
            *(buf + 30) = s.data.sendSize.length;
2380
            *(buf + 31) = calcChecksum(buf, 31);
2381
            valid = true;
13 andreas 2382
        break;
11 andreas 2383
 
2384
        case 0x0095:
2385
            *(buf + 22) = s.data.sendLevSupport.device >> 8;
2386
            *(buf + 23) = s.data.sendLevSupport.device;
2387
            *(buf + 24) = s.data.sendLevSupport.port >> 8;
2388
            *(buf + 25) = s.data.sendLevSupport.port;
2389
            *(buf + 26) = s.data.sendLevSupport.system >> 8;
2390
            *(buf + 27) = s.data.sendLevSupport.system;
2391
            *(buf + 28) = s.data.sendLevSupport.level >> 8;
2392
            *(buf + 29) = s.data.sendLevSupport.level;
2393
            *(buf + 30) = s.data.sendLevSupport.num;
2394
            *(buf + 31) = s.data.sendLevSupport.types[0];
2395
            *(buf + 32) = s.data.sendLevSupport.types[1];
2396
            *(buf + 33) = s.data.sendLevSupport.types[2];
2397
            *(buf + 34) = s.data.sendLevSupport.types[3];
2398
            *(buf + 35) = s.data.sendLevSupport.types[4];
2399
            *(buf + 36) = s.data.sendLevSupport.types[5];
2400
            *(buf + 37) = calcChecksum(buf, 37);
2401
            valid = true;
13 andreas 2402
        break;
11 andreas 2403
 
2404
        case 0x0096:
2405
            *(buf + 22) = s.data.sendStatusCode.device >> 8;
2406
            *(buf + 23) = s.data.sendStatusCode.device;
2407
            *(buf + 24) = s.data.sendStatusCode.port >> 8;
2408
            *(buf + 25) = s.data.sendStatusCode.port;
2409
            *(buf + 26) = s.data.sendStatusCode.system >> 8;
2410
            *(buf + 27) = s.data.sendStatusCode.system;
2411
            *(buf + 28) = s.data.sendStatusCode.status >> 8;
2412
            *(buf + 29) = s.data.sendStatusCode.status;
2413
            *(buf + 30) = s.data.sendStatusCode.type;
2414
            *(buf + 31) = s.data.sendStatusCode.length >> 8;
2415
            *(buf + 32) = s.data.sendStatusCode.length;
2416
            pos = 33;
2417
            memset((void*)&s.data.sendStatusCode.str[0], 0, sizeof(s.data.sendStatusCode.str));
2418
            memcpy(buf + pos, s.data.sendStatusCode.str, s.data.sendStatusCode.length);
2419
            pos += s.data.sendStatusCode.length;
2420
            *(buf + pos) = calcChecksum(buf, pos);
2421
            valid = true;
13 andreas 2422
        break;
11 andreas 2423
 
2424
        case 0x0097:
2425
            *(buf + 22) = s.data.srDeviceInfo.device >> 8;
2426
            *(buf + 23) = s.data.srDeviceInfo.device;
2427
            *(buf + 24) = s.data.srDeviceInfo.system >> 8;
2428
            *(buf + 25) = s.data.srDeviceInfo.system;
2429
            *(buf + 26) = s.data.srDeviceInfo.flag >> 8;
2430
            *(buf + 27) = s.data.srDeviceInfo.flag;
2431
            *(buf + 28) = s.data.srDeviceInfo.objectID;
2432
            *(buf + 29) = s.data.srDeviceInfo.parentID;
2433
            *(buf + 30) = s.data.srDeviceInfo.herstID >> 8;
2434
            *(buf + 31) = s.data.srDeviceInfo.herstID;
2435
            *(buf + 32) = s.data.srDeviceInfo.deviceID >> 8;
2436
            *(buf + 33) = s.data.srDeviceInfo.deviceID;
2437
            pos = 34;
2438
            memcpy(buf + pos, s.data.srDeviceInfo.serial, 16);
2439
            pos += 16;
2440
            *(buf + pos) = s.data.srDeviceInfo.fwid >> 8;
2441
            pos++;
2442
            *(buf + pos) = s.data.srDeviceInfo.fwid;
2443
            pos++;
2444
            memcpy(buf + pos, s.data.srDeviceInfo.info, s.data.srDeviceInfo.len);
2445
            pos += s.data.srDeviceInfo.len;
2446
            *(buf + pos) = calcChecksum(buf, pos);
2447
            valid = true;
13 andreas 2448
        break;
11 andreas 2449
 
2450
        case 0x0098:
2451
            *(buf + 22) = s.data.reqPortCount.device >> 8;
2452
            *(buf + 23) = s.data.reqPortCount.device;
2453
            *(buf + 24) = s.data.reqPortCount.system >> 8;
2454
            *(buf + 25) = s.data.reqPortCount.system;
2455
            *(buf + 26) = calcChecksum(buf, 26);
2456
            valid = true;
13 andreas 2457
        break;
11 andreas 2458
 
2459
        case 0x0204:    // file transfer
2460
            *(buf + 22) = s.data.filetransfer.ftype >> 8;
2461
            *(buf + 23) = s.data.filetransfer.ftype;
2462
            *(buf + 24) = s.data.filetransfer.function >> 8;
2463
            *(buf + 25) = s.data.filetransfer.function;
2464
            pos = 26;
2465
 
2466
            switch (s.data.filetransfer.function)
2467
            {
2468
                case 0x0001:
2469
                    *(buf + 26) = s.data.filetransfer.unk;
2470
                    *(buf + 27) = s.data.filetransfer.unk1;
2471
                    pos = 28;
13 andreas 2472
                break;
11 andreas 2473
 
2474
                case 0x0003:
2475
                    *(buf + 26) = s.data.filetransfer.unk >> 8;
2476
                    *(buf + 27) = s.data.filetransfer.unk;
2477
                    pos = 28;
2478
 
2479
                    for (uint32_t i = 0; i < s.data.filetransfer.unk && pos < (s.hlen + 3); i++)
2480
                    {
2481
                        *(buf + pos) = s.data.filetransfer.data[i];
2482
                        pos++;
2483
                    }
13 andreas 2484
                break;
11 andreas 2485
 
2486
                case 0x0101:
2487
                    if (s.data.filetransfer.ftype == 0)
2488
                    {
2489
                        *(buf + 26) = s.data.filetransfer.unk >> 24;
2490
                        *(buf + 27) = s.data.filetransfer.unk >> 16;
2491
                        *(buf + 28) = s.data.filetransfer.unk >> 8;
2492
                        *(buf + 29) = s.data.filetransfer.unk;
2493
                        *(buf + 30) = s.data.filetransfer.unk1 >> 24;
2494
                        *(buf + 31) = s.data.filetransfer.unk1 >> 16;
2495
                        *(buf + 32) = s.data.filetransfer.unk1 >> 8;
2496
                        *(buf + 33) = s.data.filetransfer.unk1;
2497
                        *(buf + 34) = s.data.filetransfer.unk2 >> 24;
2498
                        *(buf + 35) = s.data.filetransfer.unk2 >> 16;
2499
                        *(buf + 36) = s.data.filetransfer.unk2 >> 8;
2500
                        *(buf + 37) = s.data.filetransfer.unk2;
2501
                        *(buf + 38) = 0x00;
2502
                        *(buf + 39) = 0x00;
2503
                        *(buf + 40) = 0x3e;
2504
                        *(buf + 41) = 0x75;
2505
                        pos = 42;
2506
                        len = 0;
2507
 
2508
                        while (s.data.filetransfer.data[len] != 0)
2509
                        {
2510
                            *(buf + pos) = s.data.filetransfer.data[len];
2511
                            len++;
2512
                            pos++;
2513
                        }
2514
 
2515
                        *(buf + pos) = 0;
2516
                        pos++;
2517
                    }
2518
                    else
2519
                    {
2520
                        *(buf + 26) = s.data.filetransfer.unk >> 24;
2521
                        *(buf + 27) = s.data.filetransfer.unk >> 16;
2522
                        *(buf + 28) = s.data.filetransfer.unk >> 8;
2523
                        *(buf + 29) = s.data.filetransfer.unk;
2524
                        *(buf + 30) = 0x00;
2525
                        *(buf + 31) = 0x00;
2526
                        *(buf + 32) = 0x00;
2527
                        *(buf + 33) = 0x00;
2528
                        pos = 34;
2529
                    }
2530
 
13 andreas 2531
                break;
11 andreas 2532
 
2533
                case 0x0102:
2534
                    *(buf + 26) = 0x00;
2535
                    *(buf + 27) = 0x00;
2536
                    *(buf + 28) = 0x00;
2537
                    *(buf + 29) = s.data.filetransfer.info1;        // dir flag
2538
                    *(buf + 30) = s.data.filetransfer.info2 >> 8;   // # entries
2539
                    *(buf + 31) = s.data.filetransfer.info2;
2540
                    *(buf + 32) = s.data.filetransfer.unk >> 8;     // counter
2541
                    *(buf + 33) = s.data.filetransfer.unk;
2542
                    *(buf + 34) = s.data.filetransfer.unk1 >> 24;   // file size
2543
                    *(buf + 35) = s.data.filetransfer.unk1 >> 16;
2544
                    *(buf + 36) = s.data.filetransfer.unk1 >> 8;
2545
                    *(buf + 37) = s.data.filetransfer.unk1;
2546
                    *(buf + 38) = (s.data.filetransfer.info1 == 1) ? 0x0c : 0x0b;
2547
                    *(buf + 39) = (s.data.filetransfer.info1 == 1) ? 0x0e : 0x13;
2548
                    *(buf + 40) = 0x07;
2549
                    *(buf + 41) = s.data.filetransfer.unk2 >> 24;   // Date
2550
                    *(buf + 42) = s.data.filetransfer.unk2 >> 16;
2551
                    *(buf + 43) = s.data.filetransfer.unk2 >> 8;
2552
                    *(buf + 44) = s.data.filetransfer.unk2;
2553
                    pos = 45;
2554
                    len = 0;
2555
 
2556
                    while (s.data.filetransfer.data[len] != 0)
2557
                    {
2558
                        *(buf + pos) = s.data.filetransfer.data[len];
2559
                        pos++;
2560
                        len++;
2561
                    }
2562
 
2563
                    *(buf + pos) = 0;
2564
                    pos++;
13 andreas 2565
                break;
11 andreas 2566
 
2567
                case 0x0103:
2568
                    *(buf + 26) = s.data.filetransfer.unk >> 8;
2569
                    *(buf + 27) = s.data.filetransfer.unk;
2570
                    *(buf + 28) = s.data.filetransfer.unk1 >> 24;
2571
                    *(buf + 29) = s.data.filetransfer.unk1 >> 16;
2572
                    *(buf + 30) = s.data.filetransfer.unk1 >> 8;
2573
                    *(buf + 31) = s.data.filetransfer.unk1;
2574
                    pos = 32;
13 andreas 2575
                break;
11 andreas 2576
 
2577
                case 0x105:
2578
                    *(buf + 26) = s.data.filetransfer.unk >> 24;
2579
                    *(buf + 27) = s.data.filetransfer.unk >> 16;
2580
                    *(buf + 28) = s.data.filetransfer.unk >> 8;
2581
                    *(buf + 29) = s.data.filetransfer.unk;
2582
                    *(buf + 30) = s.data.filetransfer.unk1 >> 24;
2583
                    *(buf + 31) = s.data.filetransfer.unk1 >> 16;
2584
                    *(buf + 32) = s.data.filetransfer.unk1 >> 8;
2585
                    *(buf + 33) = s.data.filetransfer.unk1;
2586
                    pos = 34;
13 andreas 2587
                break;
11 andreas 2588
            }
2589
 
2590
            *(buf + pos) = calcChecksum(buf, pos);
2591
            valid = true;
13 andreas 2592
        break;
11 andreas 2593
 
2594
        case 0x0581:    // Pong
2595
            *(buf + 22) = s.data.srDeviceInfo.device >> 8;
2596
            *(buf + 23) = s.data.srDeviceInfo.device;
2597
            *(buf + 24) = s.data.srDeviceInfo.system >> 8;
2598
            *(buf + 25) = s.data.srDeviceInfo.system;
2599
            *(buf + 26) = s.data.srDeviceInfo.herstID >> 8;
2600
            *(buf + 27) = s.data.srDeviceInfo.herstID;
2601
            *(buf + 28) = s.data.srDeviceInfo.deviceID >> 8;
2602
            *(buf + 29) = s.data.srDeviceInfo.deviceID;
2603
            *(buf + 30) = s.data.srDeviceInfo.info[0];
2604
            *(buf + 31) = s.data.srDeviceInfo.info[1];
2605
            *(buf + 32) = s.data.srDeviceInfo.info[2];
2606
            *(buf + 33) = s.data.srDeviceInfo.info[3];
2607
            *(buf + 34) = s.data.srDeviceInfo.info[4];
2608
            *(buf + 35) = s.data.srDeviceInfo.info[5];
2609
            *(buf + 36) = calcChecksum(buf, 36);
2610
            valid = true;
13 andreas 2611
        break;
11 andreas 2612
    }
2613
 
2614
    if (!valid)
2615
    {
2616
        delete[] buf;
2617
        return 0;
2618
    }
2619
 
13 andreas 2620
//    MSG_TRACE("Buffer:");
2621
//    TError::logHex((char *)buf, s.hlen + 4);
11 andreas 2622
    return buf;
2623
}
2624
 
2625
void TAmxNet::setSerialNum(const string& sn)
2626
{
2627
    DECL_TRACER("TAmxNet::setSerialNum(const string& sn)");
2628
 
2629
    serNum = sn;
2630
    size_t len = (sn.length() > 15) ? 15 : sn.length();
2631
 
2632
    for (size_t i = 0; i < devInfo.size(); i++)
89 andreas 2633
        strncpy(devInfo[i].serialNum, sn.c_str(), len);
11 andreas 2634
}
2635
 
2636
int TAmxNet::countFiles()
2637
{
2638
    DECL_TRACER("TAmxNet::countFiles()");
2639
 
2640
    int count = 0;
2641
    ifstream in;
2642
 
2643
    try
2644
    {
2645
        in.open(TConfig::getProjectPath() + "/manifest.xma", fstream::in);
2646
 
2647
        if (!in)
2648
            return 0;
2649
 
2650
        for (string line; getline(in, line);)
2651
            count++;
2652
 
2653
        in.close();
2654
    }
2655
    catch (exception& e)
2656
    {
2657
        MSG_ERROR("Error: " << e.what());
2658
        return 0;
2659
    }
2660
 
2661
    return count;
2662
}
15 andreas 2663
 
2664
void TAmxNet::sendAllFuncNetwork(int state)
2665
{
2666
    DECL_TRACER("TAmxNet::sendAllFuncNetwork(int state)");
2667
 
17 andreas 2668
    if (mFuncsNetwork.empty())
2669
        return;
2670
 
83 andreas 2671
    MSG_DEBUG("Setting network state to " << state);
15 andreas 2672
    map<ulong, FUNC_NETWORK_t>::iterator iter;
2673
 
2674
    for (iter = mFuncsNetwork.begin(); iter != mFuncsNetwork.end(); iter++)
2675
        iter->second.func(state);
2676
}
2677
 
2678
void TAmxNet::sendAllFuncTimer(const ANET_BLINK& blink)
2679
{
2680
    DECL_TRACER("TAmxNet::sendAllFuncTimer(const ANET_BLINK& blink)");
2681
 
17 andreas 2682
    if (mFuncsTimer.empty())
2683
        return;
2684
 
15 andreas 2685
    map<ulong, FUNC_TIMER_t>::iterator iter;
2686
 
2687
    for (iter = mFuncsTimer.begin(); iter != mFuncsTimer.end(); iter++)
2688
        iter->second.func(blink);
2689
}
93 andreas 2690
 
2691
void TAmxNet::setWaitTime(int secs)
2692
{
2693
    DECL_TRACER("TAmxNet::setWaitTime(int secs)");
2694
 
2695
    if (secs <= 0 || secs > 300)    // Maximal 5 minutes
2696
        return;
2697
 
2698
    mOldWaitTime = mWaitTime;
2699
    mWaitTime = secs;
2700
}
2701
 
2702
int TAmxNet::swapWaitTime()
2703
{
2704
    DECL_TRACER("TAmxNet::restoreWaitTime()");
2705
 
2706
    int wt = mWaitTime;
2707
 
2708
    mWaitTime = mOldWaitTime;
2709
    mOldWaitTime = wt;
2710
    return mWaitTime;
2711
}