Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

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