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