Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
11 andreas 1
/*
406 andreas 2
 * Copyright (C) 2018 to 2023 by Andreas Theofilu <andreas@theosys.at>
11 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
19
#ifndef __TAMXNET_H__
20
#define __TAMXNET_H__
21
 
86 andreas 22
//#include "asio.hpp"
11 andreas 23
 
87 andreas 24
#include <vector>
70 andreas 25
#include <map>
11 andreas 26
#include <functional>
27
#include <cstring>
28
#include <cstdio>
29
#include <atomic>
86 andreas 30
#include <thread>
11 andreas 31
 
86 andreas 32
#include "tsocket.h"
169 andreas 33
#include "tvector.h"
11 andreas 34
 
235 andreas 35
#if defined(__ANDROID__) || defined(__MACH__)
21 andreas 36
typedef unsigned long int ulong;
37
#endif
38
 
11 andreas 39
extern std::atomic<bool> killed;
21 andreas 40
extern bool prg_stopped;
11 andreas 41
 
42
namespace amx
43
{
15 andreas 44
#define MAX_CHUNK   0x07d0  // Maximum size a part of a file can have. The file will be splitted into this size of chunks.
45
#define BUF_SIZE    0x1000  // 4096 bytes
11 andreas 46
 
86 andreas 47
#define NSTATE_OFFLINE      0
406 andreas 48
#define NSTATE_OFFLINE1     1
86 andreas 49
#define NSTATE_ONLINE       6
406 andreas 50
#define NSTATE_ONLINE1      5
86 andreas 51
#define NSTATE_CONNECTING   9
52
 
93 andreas 53
#define WAIT_RESET          3   // Number of seconds to wait in case of connecting to another controller
54
#define WAIT_RECONNECT      15  // Number of seconds to wait in case of reconnecting to the same controller
55
 
326 andreas 56
#define DTSZ_STRING         0x01    // ASCII string (8 bit)
57
#define DTSZ_WSTRING        0x02    // Wide string (16 bit)
58
#define DTSZ_BYTE           0x10    // Byte (8 bit unsigned)
59
#define DTSZ_CHAR           0x11    // Byte (8 bit signed)
60
#define DTSZ_UINT           0x20    // Word (16 bit unsigned)
61
#define DTSZ_INT            0x21    // Word (16 bit signed)
62
#define DTSZ_LUINT          0x40    // DWORD (32 bit unsigned)
63
#define DTSZ_LINTT          0x41    // DWORD (32 bit signed)
64
#define DTSZ_FLOAT          0x4f    // FLOAT (32 bit)
65
#define DTSZ_DOUBLE         0x8f    // DOUBLE (32/64 bit)
66
 
11 andreas 67
    typedef struct ANET_SEND
15 andreas 68
    {
69
        uint16_t device{0};     // Device ID of panel
70
        uint16_t MC{0};         // message command number
71
        uint16_t port{0};       // port number
72
        uint16_t level{0};      // level number (if any)
73
        uint16_t channel{0};    // channel status
74
        uint16_t value{0};      // level value
75
        // this is for custom events
76
        uint16_t ID{0};         // ID of button
77
        uint16_t type{0};       // Type of event
78
        uint16_t flag{0};       // Flag
79
        uint32_t value1{0};     // Value 1
80
        uint32_t value2{0};     // Value 2
81
        uint32_t value3{0};     // Value 3
82
        unsigned char dtype{0}; // Type of data
83
        std::string msg;        // message string
84
    } ANET_SEND;
11 andreas 85
 
15 andreas 86
    typedef union
87
    {
88
        unsigned char byte; // type = 0x10
89
        char ch;            // type = 0x11
90
        uint16_t integer;   // type = 0x20 (also wide char)
91
        int16_t sinteger;   // type = 0x21
92
        uint32_t dword;     // type = 0x40
93
        int32_t sdword;     // type = 0x41
94
        float fvalue;       // type = 0x4f
95
        double dvalue;      // type = 0x8f
96
    } ANET_CONTENT;
11 andreas 97
 
15 andreas 98
    typedef struct ANET_MSG
99
    {
100
        uint16_t device;        // device number
101
        uint16_t port;          // port number
102
        uint16_t system;        // system number
103
        uint16_t value;         // value of command
104
        unsigned char type;     // defines how to interpret the content of cmd
105
        ANET_CONTENT content;
106
    } ANET_MSG;
11 andreas 107
 
15 andreas 108
    typedef struct ANET_MSG_STRING
109
    {
110
        uint16_t device;        // device number
111
        uint16_t port;          // port number
112
        uint16_t system;        // system number
113
        unsigned char type;     // Definnes the type of content (0x01 = 8 bit chars, 0x02 = 16 bit chars --> wide chars)
114
        uint16_t length;        // length of following content
115
        unsigned char content[1500];// content string
116
    } ANET_MSG_STRING;
11 andreas 117
 
15 andreas 118
    typedef struct ANET_ASIZE
119
    {
120
        uint16_t device;        // device number
121
        uint16_t port;          // port number
122
        uint16_t system;        // system number
123
        unsigned char type;     // Defines the type of content (0x01 = 8 bit chars, 0x02 = 16 bit chars --> wide chars)
124
        uint16_t length;        // length of following content
125
    } ANET_ASIZE;
11 andreas 126
 
15 andreas 127
    typedef struct ANET_LEVSUPPORT
128
    {
129
        uint16_t device;        // device number
130
        uint16_t port;          // port number
131
        uint16_t system;        // system number
132
        uint16_t level;         // level number
133
        unsigned char num;      // number of supported types
134
        unsigned char types[6]; // Type codes
135
    } ANET_LEVSUPPORT;
11 andreas 136
 
15 andreas 137
    typedef struct ANET_ASTATCODE
138
    {
139
        uint16_t device;        // device number
140
        uint16_t port;          // port number
141
        uint16_t system;        // system number
142
        uint16_t status;        // status code
143
        unsigned char type;     // defines how to interpret the content of cmd
144
        uint16_t length;        // length of following string
145
        unsigned char str[512];
146
    } ANET_ASTATCODE;
11 andreas 147
 
15 andreas 148
    typedef struct ANET_LEVEL
149
    {
150
        uint16_t device;        // device number
151
        uint16_t port;          // port number
152
        uint16_t system;        // system number
153
        uint16_t level;         // level number
154
    } ANET_LEVEL;
11 andreas 155
 
15 andreas 156
    typedef struct ANET_CHANNEL
157
    {
158
        uint16_t device;        // device number
159
        uint16_t port;          // port number
160
        uint16_t system;        // system number
161
        uint16_t channel;       // level number
162
    } ANET_CHANNEL;
11 andreas 163
 
15 andreas 164
    typedef struct ANET_RPCOUNT
165
    {
166
        uint16_t device;        // device number
167
        uint16_t system;        // system number
168
    } ANET_RPCOUNT;
11 andreas 169
 
15 andreas 170
    typedef struct ANET_APCOUNT // Answer to request for port count
171
    {
172
        uint16_t device;        // device number
173
        uint16_t system;        // system number
174
        uint16_t pcount;        // number of supported ports
175
    } ANET_APCOUNT;
11 andreas 176
 
15 andreas 177
    typedef struct ANET_ROUTCHAN    // Request for port count
178
    {
179
        uint16_t device;        // device number
180
        uint16_t port;          // system number
181
        uint16_t system;        // number of supported ports
182
    } ANET_ROUTCHAN;
11 andreas 183
 
15 andreas 184
    typedef struct ANET_AOUTCHAN    // Answer to request for port count
185
    {
186
        uint16_t device;        // device number
187
        uint16_t port;          // system number
188
        uint16_t system;        // number of supported ports
189
        uint16_t count;         // number of supported channels
190
    } ANET_AOUTCHAN;
11 andreas 191
 
15 andreas 192
    typedef struct ANET_ADEVINFO // Answer to "request device info"
193
    {
194
        uint16_t device;        // device number
195
        uint16_t system;        // system number
196
        uint16_t flag;          // Bit 8 - If set, this message was generated in response to a key press, during the identification mode is active.
197
        unsigned char objectID; // object ID
198
        unsigned char parentID; // parent ID
199
        uint16_t herstID;       // herst ID
200
        uint16_t deviceID;      // device ID
201
        unsigned char serial[16]; // serial number
202
        uint16_t fwid;          // firmware ID
203
        unsigned char info[512];// several NULL terminated informations
204
        int len;                // length of field info
205
    } ANET_ADEVINFO;
11 andreas 206
 
15 andreas 207
    typedef struct ANET_ASTATUS // Answer to "master status"
208
    {
209
        uint16_t system;        // number of system
210
        uint16_t status;        // Bit field
211
        unsigned char str[512]; // Null terminated status string
212
    } ANET_ASTATUS;
11 andreas 213
 
15 andreas 214
    typedef struct ANET_CUSTOM  // Custom event
215
    {
216
        uint16_t device;        // Device number
217
        uint16_t port;          // Port number
218
        uint16_t system;        // System number
219
        uint16_t ID;            // ID of event (button ID)
220
        uint16_t type;          // Type of event
221
        uint16_t flag;          // Flag
222
        uint32_t value1;        // Value 1
223
        uint32_t value2;        // Value 2
224
        uint32_t value3;        // Value 3
225
        unsigned char dtype;    // type of following data
226
        uint16_t length;        // length of following string
227
        unsigned char data[255];// Custom data
228
    } ANET_CUSTOM;
11 andreas 229
 
16 andreas 230
    typedef struct ANET_BLINK       // Blink message (contains date and time)
15 andreas 231
    {
16 andreas 232
        unsigned char heartBeat;    // Time between heart beats in 10th of seconds
233
        unsigned char LED;          // Bit 0: Bus-LED: 0 off, 1 on; Bits 1-6 reserved; Bit 7: 1 = force reset device
234
        unsigned char month;        // Month 1 - 12
235
        unsigned char day;          // Day 1 - 31
236
        uint16_t year;              // Year
237
        unsigned char hour;         // Hours 0 - 23
238
        unsigned char minute;       // Minutes 0 - 59
239
        unsigned char second;       // Seconds 0 - 59
240
        unsigned char weekday;      // 0 = Monday, 1 = Thuesday, ...
241
        uint16_t extTemp;           // External temperature, if available (0x8000 invalid value)
15 andreas 242
        unsigned char dateTime[64]; // Rest is a string containing the date and time.
16 andreas 243
 
244
        void clear()
245
        {
246
            heartBeat = 0;
247
            LED = 0;
248
            month = 0;
249
            day = 0;
250
            year = 0;
251
            hour = 0;
252
            minute = 0;
253
            second = 0;
254
            weekday = 0;
255
            extTemp = 0;
256
            dateTime[0] = 0;
257
        }
15 andreas 258
    } ANET_BLINK;
259
 
260
    typedef struct ANET_FILETRANSFER    // File transfer
261
    {
262
        uint16_t ftype;         // 0 = not used, 1=IR, 2=Firmware, 3=TP file, 4=Axcess2
263
        uint16_t function;      // The function to be performed, or length of data block
264
        uint16_t info1;
11 andreas 265
        uint16_t info2;
15 andreas 266
        uint32_t unk;           // ?
267
        uint32_t unk1;          // ?
268
        uint32_t unk2;          // ?
269
        uint32_t unk3;          // ?
270
        unsigned char data[2048];// Function specific data
271
    } ANET_FILETRANSFER;
11 andreas 272
 
15 andreas 273
    typedef union
274
    {
275
        ANET_CHANNEL chan_state;
276
        ANET_MSG message_value;
277
        ANET_MSG_STRING message_string;
278
        ANET_LEVEL level;
279
        ANET_CHANNEL channel;
280
        ANET_RPCOUNT reqPortCount;
281
        ANET_APCOUNT sendPortNumber;
282
        ANET_ROUTCHAN reqOutpChannels;
283
        ANET_AOUTCHAN sendOutpChannels;
284
        ANET_ASTATCODE sendStatusCode;
285
        ANET_ASIZE sendSize;
286
        ANET_LEVEL reqLevels;
287
        ANET_LEVSUPPORT sendLevSupport;
288
        ANET_ADEVINFO srDeviceInfo;     // send/receive device info
289
        ANET_CUSTOM customEvent;
290
        ANET_BLINK blinkMessage;
291
        ANET_FILETRANSFER filetransfer;
292
    } ANET_DATA;
11 andreas 293
 
15 andreas 294
    typedef struct ANET_COMMAND // Structure of type command (type = 0x00, status = 0x000c)
295
    {
296
        char ID{2};             // 0x00:        Always 0x02
297
        uint16_t hlen{0};       // 0x01 - 0x02: Header length (length + 3 for total length!)
298
        char sep1{2};           // 0x03:        Seperator always 0x02
299
        char type{0};           // 0x04:        Type of header
300
        uint16_t unk1{1};       // 0x05 - 0x06: always 0x0001
301
        uint16_t device1{0};    // 0x07 - 0x08: receive: device, send: 0x000
302
        uint16_t port1{0};      // 0x09 - 0x0a: receive: port,   send: 0x001
303
        uint16_t system{0};     // 0x0b - 0x0c: receive: system, send: 0x001
304
        uint16_t device2{0};    // 0x0d - 0x0e: send: device,    receive: 0x0000
305
        uint16_t port2{0};      // 0x0f - 0x10: send: port,      receive: 0x0001
306
        char unk6{0x0f};        // 0x11:        Always 0x0f
307
        uint16_t count{0};      // 0x12 - 0x13: Counter
308
        uint16_t MC{0};         // 0x14 - 0x15: Message command identifier
309
        ANET_DATA data;         // 0x16 - n     Data block
310
        unsigned char checksum{0};  // last byte:   Checksum
412 andreas 311
        bool intern{false};     // Internal command
11 andreas 312
 
15 andreas 313
        void clear()
314
        {
315
            ID = 0x02;
316
            hlen = 0;
317
            sep1 = 0x02;
318
            type = 0;
319
            unk1 = 1;
320
            device1 = 0;
321
            port1 = 0;
322
            system = 0;
323
            device2 = 0;
324
            port2 = 0;
325
            unk6 = 0x0f;
326
            count = 0;
327
            MC = 0;
328
            checksum = 0;
412 andreas 329
            intern = false;
15 andreas 330
        }
331
    } ANET_COMMAND;
11 andreas 332
 
15 andreas 333
    typedef struct
334
    {
335
        unsigned char objectID;     // Unique 8-bit identifier that identifies this structure of information
336
        unsigned char parentID;     // Refers to an existing object ID. If 0, has this object to any parent object (parent).
337
        uint16_t manufacturerID;    // Value that uniquely identifies the manufacture of the device.
338
        uint16_t deviceID;          // Value that uniquely identifies the device type.
339
        char serialNum[16];         // Fixed length of 16 bytes.
340
        uint16_t firmwareID;        // Value that uniquely identifies the object code that the device requires.
341
        // NULL terminated text field
342
        char versionInfo[16];       // A closed with NULL text string that specifies the version of the reprogrammable component.
343
        char deviceInfo[32];        // A closed with NULL text string that specifies the name or model number of the device.
344
        char manufacturerInfo[32];  // A closed with NULL text string that specifies the name of the device manufacturer.
345
        unsigned char format;       // Value that indicates the type of device specific addressing information following.
346
        unsigned char len;          // Value that indicates the length of the following device-specific addressing information.
347
        unsigned char addr[8];      // Extended address as indicated by the type and length of the extended address.
348
    } DEVICE_INFO;
11 andreas 349
 
15 andreas 350
    typedef struct FTRANSFER
351
    {
352
        int percent{0};             // Status indicating the percent done
353
        int maxFiles{0};            // Total available files
354
        int lengthFile{0};          // Total length of currently transfered file
355
        int actFileNum{0};          // Number of currently transfered file.
356
        int actDelFile{0};          // Number of currently deleted file.
357
    } FTRANSFER;
11 andreas 358
 
15 andreas 359
    typedef struct FUNC_NETWORK_t
360
    {
361
        ulong handle{0};
362
        std::function<void(int)> func{nullptr};
363
    }FUNC_NETWORK_t;
11 andreas 364
 
15 andreas 365
    typedef struct FUNC_TIMER_t
366
    {
367
        ulong handle{0};
368
        std::function<void(const ANET_BLINK&)> func{nullptr};
369
    }FUNC_TIMER_t;
11 andreas 370
 
92 andreas 371
    class TAmxNet
15 andreas 372
    {
373
        public:
374
            TAmxNet();
375
            explicit TAmxNet(const std::string& sn);
376
            explicit TAmxNet(const std::string& sn, const std::string& nm);
377
            ~TAmxNet();
11 andreas 378
 
15 andreas 379
            void Run();
88 andreas 380
            void stop(bool soft=false);
93 andreas 381
            bool reconnect();
11 andreas 382
 
15 andreas 383
            void setCallback(std::function<void(const ANET_COMMAND&)> func) { callback = func; }
384
            void registerNetworkState(std::function<void(int)> registerNetwork, ulong handle);
385
            void registerTimer(std::function<void(const ANET_BLINK&)> registerBlink, ulong handle);
386
            void deregNetworkState(ulong handle);
387
            void deregTimer(ulong handle);
388
 
389
            bool sendCommand(const ANET_SEND& s);
390
            bool isStopped() { return stopped_; }
92 andreas 391
            bool isConnected() { if (mSocket) return mSocket->isConnected(); return false; }
392
            bool close() { if (mSocket) return mSocket->close(); return false; }
88 andreas 393
            bool isNetRun();
15 andreas 394
            void setPanelID(int id) { panelID = id; }
395
            void setSerialNum(const std::string& sn);
396
            bool setupStatus() { return receiveSetup; }
397
            void setPanName(const std::string& nm) { panName.assign(nm); }
398
 
93 andreas 399
            void setWaitTime(int secs);
400
            int getWaitTime() { return mWaitTime; }
401
            int swapWaitTime();
402
 
88 andreas 403
        protected:
404
            void start();
405
 
15 andreas 406
        private:
407
            enum R_TOKEN
408
            {
409
                RT_NONE,
410
                RT_ID,
411
                RT_LEN,
412
                RT_SEP1,
413
                RT_TYPE,
414
                RT_WORD1,
415
                RT_DEVICE,
416
                RT_WORD2,
417
                RT_WORD3,
418
                RT_WORD4,
419
                RT_WORD5,
420
                RT_SEP2,
421
                RT_COUNT,
422
                RT_MC,
423
                RT_DATA
424
            };
425
 
92 andreas 426
            void init();
86 andreas 427
            void handle_connect();
169 andreas 428
            void runWrite();
15 andreas 429
            void start_read();
86 andreas 430
            void handle_read(size_t n, R_TOKEN tk);
15 andreas 431
            void start_write();
432
            void handleFTransfer(ANET_SEND& s, ANET_FILETRANSFER& ft);
433
            uint16_t swapWord(uint16_t w);
434
            uint32_t swapDWord(uint32_t dw);
435
            unsigned char calcChecksum(const unsigned char *buffer, size_t len);
436
            uint16_t makeWord(unsigned char b1, unsigned char b2);
437
            uint32_t makeDWord(unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4);
438
            unsigned char *makeBuffer(const ANET_COMMAND& s);
439
            int msg97fill(ANET_COMMAND *com);
440
            bool isCommand(const std::string& cmd);
70 andreas 441
            bool isRunning() { return !(stopped_ || killed || prg_stopped); }
15 andreas 442
            int countFiles();
443
            void sendAllFuncNetwork(int state);
444
            void sendAllFuncTimer(const ANET_BLINK& blink);
11 andreas 445
 
15 andreas 446
            std::function<void(const ANET_COMMAND&)> callback;
11 andreas 447
 
92 andreas 448
            TSocket *mSocket{nullptr};  // Pointer to socket class needed for communication
93 andreas 449
            FILE *rcvFile{nullptr};
450
            FILE *sndFile{nullptr};
451
            size_t posRcv{0};
452
            size_t lenRcv{0};
453
            size_t posSnd{0};
454
            size_t lenSnd{0};
455
            std::thread mThread;
169 andreas 456
            std::thread mWriteThread;   // Thread used to write to the Netlinx.
15 andreas 457
            std::string input_buffer_;
458
            std::string panName;        // The technical name of the panel
169 andreas 459
            TVector<ANET_COMMAND> comStack; // commands to answer
93 andreas 460
            std::vector<DEVICE_INFO> devInfo;
461
            std::string oldCmd;
462
            std::string serNum;
463
            std::string sndFileName;
464
            std::string rcvFileName;
465
            ANET_COMMAND comm;          // received command
466
            ANET_COMMAND mSend;         // answer / request
467
            int panelID{0};             // Panel ID of currently legalized panel.
468
            int mWaitTime{3};           // [seconds]: Wait by default for 3 seconds
469
            int mOldWaitTime{3};        // [seconds]: The previous wait time in case of change
470
            FTRANSFER ftransfer;
15 andreas 471
            uint16_t reqDevStatus{0};
472
            uint16_t sendCounter{0};    // Counter increment on every send
93 andreas 473
            std::atomic<bool> stopped_{false};
474
            std::atomic<bool> mSendReady{false};
475
            bool protError{false};      // true = error on receive --> disconnect
15 andreas 476
            bool initSend{false};       // TRUE = all init messages are send.
477
            bool ready{false};          // TRUE = ready for communication
169 andreas 478
            std::atomic<bool> write_busy{false};
15 andreas 479
            std::atomic<bool> receiveSetup{false};
480
            bool isOpenSnd{false};
481
            bool isOpenRcv{false};
85 andreas 482
            bool _retry{false};
93 andreas 483
            char buff_[BUF_SIZE];       // Internal used buffer for network communication
406 andreas 484
            int mLastOnlineState{NSTATE_OFFLINE};
15 andreas 485
    };
11 andreas 486
}
487
 
488
#endif