Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

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