Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

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