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