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