Subversion Repositories tpanel

Rev

Rev 446 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
446 andreas 1
/*
464 andreas 2
 * Copyright (C) 2018 to 2024 by Andreas Theofilu <andreas@theosys.at>
446 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
 
22
//#include "asio.hpp"
23
 
24
#include <vector>
25
#include <map>
26
#include <functional>
27
#include <cstring>
28
#include <cstdio>
29
#include <atomic>
30
#include <thread>
31
 
32
#include "tsocket.h"
33
#include "tvector.h"
34
 
35
#if defined(__ANDROID__) || defined(__MACH__)
36
typedef unsigned long int ulong;
37
#endif
38
 
39
extern std::atomic<bool> killed;
40
extern bool prg_stopped;
41
 
42
namespace amx
43
{
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
46
 
47
#define NSTATE_OFFLINE      0
48
#define NSTATE_OFFLINE1     1
49
#define NSTATE_ONLINE       6
50
#define NSTATE_ONLINE1      5
51
#define NSTATE_CONNECTING   9
52
 
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
 
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
 
67
    typedef struct ANET_SEND
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;
85
 
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;
97
 
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;
107
 
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;
117
 
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;
126
 
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;
136
 
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;
147
 
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;
155
 
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;
163
 
164
    typedef struct ANET_RPCOUNT
165
    {
166
        uint16_t device;        // device number
167
        uint16_t system;        // system number
168
    } ANET_RPCOUNT;
169
 
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;
176
 
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;
183
 
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;
191
 
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;
206
 
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;
213
 
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;
229
 
230
    typedef struct ANET_BLINK       // Blink message (contains date and time)
231
    {
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)
242
        unsigned char dateTime[64]; // Rest is a string containing the date and time.
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
        }
258
    } ANET_BLINK;
259
 
464 andreas 260
    typedef struct ANET_NETWORK     // Setting the IP address, subnet mask and gateway of the Ethernet interface of the unit.
261
    {
262
        unsigned char bf;
263
        char data[1024];
264
        size_t len;
265
    }ANET_NETWORK;
266
 
446 andreas 267
    typedef struct ANET_FILETRANSFER    // File transfer
268
    {
269
        uint16_t ftype;         // 0 = not used, 1=IR, 2=Firmware, 3=TP file, 4=Axcess2
270
        uint16_t function;      // The function to be performed, or length of data block
271
        uint16_t info1;
272
        uint16_t info2;
273
        uint32_t unk;           // ?
274
        uint32_t unk1;          // ?
275
        uint32_t unk2;          // ?
276
        uint32_t unk3;          // ?
277
        unsigned char data[2048];// Function specific data
278
    } ANET_FILETRANSFER;
279
 
280
    typedef union
281
    {
282
        ANET_CHANNEL chan_state;
283
        ANET_MSG message_value;
284
        ANET_MSG_STRING message_string;
285
        ANET_LEVEL level;
286
        ANET_CHANNEL channel;
287
        ANET_RPCOUNT reqPortCount;
288
        ANET_APCOUNT sendPortNumber;
289
        ANET_ROUTCHAN reqOutpChannels;
290
        ANET_AOUTCHAN sendOutpChannels;
291
        ANET_ASTATCODE sendStatusCode;
292
        ANET_ASIZE sendSize;
293
        ANET_LEVEL reqLevels;
294
        ANET_LEVSUPPORT sendLevSupport;
295
        ANET_ADEVINFO srDeviceInfo;     // send/receive device info
296
        ANET_CUSTOM customEvent;
297
        ANET_BLINK blinkMessage;
464 andreas 298
        ANET_NETWORK network;
446 andreas 299
        ANET_FILETRANSFER filetransfer;
300
    } ANET_DATA;
301
 
302
    typedef struct ANET_COMMAND // Structure of type command (type = 0x00, status = 0x000c)
303
    {
304
        char ID{2};             // 0x00:        Always 0x02
305
        uint16_t hlen{0};       // 0x01 - 0x02: Header length (length + 3 for total length!)
306
        char sep1{2};           // 0x03:        Seperator always 0x02
307
        char type{0};           // 0x04:        Type of header
308
        uint16_t unk1{1};       // 0x05 - 0x06: always 0x0001
309
        uint16_t device1{0};    // 0x07 - 0x08: receive: device, send: 0x000
310
        uint16_t port1{0};      // 0x09 - 0x0a: receive: port,   send: 0x001
311
        uint16_t system{0};     // 0x0b - 0x0c: receive: system, send: 0x001
312
        uint16_t device2{0};    // 0x0d - 0x0e: send: device,    receive: 0x0000
313
        uint16_t port2{0};      // 0x0f - 0x10: send: port,      receive: 0x0001
314
        char unk6{0x0f};        // 0x11:        Always 0x0f
315
        uint16_t count{0};      // 0x12 - 0x13: Counter
316
        uint16_t MC{0};         // 0x14 - 0x15: Message command identifier
317
        ANET_DATA data;         // 0x16 - n     Data block
318
        unsigned char checksum{0};  // last byte:   Checksum
319
        bool intern{false};     // Internal command
320
 
321
        void clear()
322
        {
323
            ID = 0x02;
324
            hlen = 0;
325
            sep1 = 0x02;
326
            type = 0;
327
            unk1 = 1;
328
            device1 = 0;
329
            port1 = 0;
330
            system = 0;
331
            device2 = 0;
332
            port2 = 0;
333
            unk6 = 0x0f;
334
            count = 0;
335
            MC = 0;
336
            checksum = 0;
337
            intern = false;
338
        }
339
    } ANET_COMMAND;
340
 
341
    typedef struct
342
    {
343
        unsigned char objectID;     // Unique 8-bit identifier that identifies this structure of information
344
        unsigned char parentID;     // Refers to an existing object ID. If 0, has this object to any parent object (parent).
345
        uint16_t manufacturerID;    // Value that uniquely identifies the manufacture of the device.
346
        uint16_t deviceID;          // Value that uniquely identifies the device type.
347
        char serialNum[16];         // Fixed length of 16 bytes.
348
        uint16_t firmwareID;        // Value that uniquely identifies the object code that the device requires.
349
        // NULL terminated text field
350
        char versionInfo[16];       // A closed with NULL text string that specifies the version of the reprogrammable component.
351
        char deviceInfo[32];        // A closed with NULL text string that specifies the name or model number of the device.
352
        char manufacturerInfo[32];  // A closed with NULL text string that specifies the name of the device manufacturer.
353
        unsigned char format;       // Value that indicates the type of device specific addressing information following.
354
        unsigned char len;          // Value that indicates the length of the following device-specific addressing information.
355
        unsigned char addr[8];      // Extended address as indicated by the type and length of the extended address.
356
    } DEVICE_INFO;
357
 
358
    typedef struct FTRANSFER
359
    {
360
        int percent{0};             // Status indicating the percent done
361
        int maxFiles{0};            // Total available files
362
        int lengthFile{0};          // Total length of currently transfered file
363
        int actFileNum{0};          // Number of currently transfered file.
364
        int actDelFile{0};          // Number of currently deleted file.
365
    } FTRANSFER;
366
 
367
    typedef struct FUNC_NETWORK_t
368
    {
369
        ulong handle{0};
370
        std::function<void(int)> func{nullptr};
371
    }FUNC_NETWORK_t;
372
 
373
    typedef struct FUNC_TIMER_t
374
    {
375
        ulong handle{0};
376
        std::function<void(const ANET_BLINK&)> func{nullptr};
377
    }FUNC_TIMER_t;
378
 
379
    class TAmxNet
380
    {
381
        public:
382
            TAmxNet();
383
            explicit TAmxNet(const std::string& sn);
384
            explicit TAmxNet(const std::string& sn, const std::string& nm);
385
            ~TAmxNet();
386
 
387
            void Run();
388
            void stop(bool soft=false);
389
            bool reconnect();
390
 
391
            void setCallback(std::function<void(const ANET_COMMAND&)> func) { callback = func; }
392
            void registerNetworkState(std::function<void(int)> registerNetwork, ulong handle);
393
            void registerTimer(std::function<void(const ANET_BLINK&)> registerBlink, ulong handle);
394
            void deregNetworkState(ulong handle);
395
            void deregTimer(ulong handle);
396
 
397
            bool sendCommand(const ANET_SEND& s);
398
            bool isStopped() { return stopped_; }
399
            bool isConnected() { if (mSocket) return mSocket->isConnected(); return false; }
400
            bool close() { if (mSocket) return mSocket->close(); return false; }
401
            bool isNetRun();
402
            void setPanelID(int id) { panelID = id; }
403
            void setSerialNum(const std::string& sn);
404
            bool setupStatus() { return receiveSetup; }
405
            void setPanName(const std::string& nm) { panName.assign(nm); }
406
 
407
            void setWaitTime(int secs);
408
            int getWaitTime() { return mWaitTime; }
409
            int swapWaitTime();
410
 
411
        protected:
412
            void start();
413
 
414
        private:
415
            enum R_TOKEN
416
            {
417
                RT_NONE,
418
                RT_ID,
419
                RT_LEN,
420
                RT_SEP1,
421
                RT_TYPE,
422
                RT_WORD1,
423
                RT_DEVICE,
424
                RT_WORD2,
425
                RT_WORD3,
426
                RT_WORD4,
427
                RT_WORD5,
428
                RT_SEP2,
429
                RT_COUNT,
430
                RT_MC,
431
                RT_DATA
432
            };
433
 
434
            void init();
435
            void handle_connect();
436
            void runWrite();
437
            void start_read();
438
            void handle_read(size_t n, R_TOKEN tk);
439
            void start_write();
440
            void handleFTransfer(ANET_SEND& s, ANET_FILETRANSFER& ft);
441
            uint16_t swapWord(uint16_t w);
442
            uint32_t swapDWord(uint32_t dw);
443
            unsigned char calcChecksum(const unsigned char *buffer, size_t len);
444
            uint16_t makeWord(unsigned char b1, unsigned char b2);
445
            uint32_t makeDWord(unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4);
446
            unsigned char *makeBuffer(const ANET_COMMAND& s);
447
            int msg97fill(ANET_COMMAND *com);
448
            bool isCommand(const std::string& cmd);
449
            bool isRunning() { return !(stopped_ || killed || prg_stopped); }
450
            int countFiles();
451
            void sendAllFuncNetwork(int state);
452
            void sendAllFuncTimer(const ANET_BLINK& blink);
453
 
454
            std::function<void(const ANET_COMMAND&)> callback;
455
 
456
            TSocket *mSocket{nullptr};  // Pointer to socket class needed for communication
457
            FILE *rcvFile{nullptr};
458
            FILE *sndFile{nullptr};
459
            size_t posRcv{0};
460
            size_t lenRcv{0};
461
            size_t posSnd{0};
462
            size_t lenSnd{0};
463
            std::thread mThread;
464
            std::thread mWriteThread;   // Thread used to write to the Netlinx.
465
            std::string input_buffer_;
466
            std::string panName;        // The technical name of the panel
467
            TVector<ANET_COMMAND> comStack; // commands to answer
468
            std::vector<DEVICE_INFO> devInfo;
469
            std::string oldCmd;
470
            std::string serNum;
471
            std::string sndFileName;
472
            std::string rcvFileName;
473
            ANET_COMMAND comm;          // received command
474
            ANET_COMMAND mSend;         // answer / request
475
            int panelID{0};             // Panel ID of currently legalized panel.
476
            int mWaitTime{3};           // [seconds]: Wait by default for 3 seconds
477
            int mOldWaitTime{3};        // [seconds]: The previous wait time in case of change
478
            FTRANSFER ftransfer;
479
            uint16_t reqDevStatus{0};
480
            uint16_t sendCounter{0};    // Counter increment on every send
481
            std::atomic<bool> stopped_{false};
482
            std::atomic<bool> mSendReady{false};
483
            bool protError{false};      // true = error on receive --> disconnect
484
            bool initSend{false};       // TRUE = all init messages are send.
485
            bool ready{false};          // TRUE = ready for communication
486
            std::atomic<bool> write_busy{false};
487
            std::atomic<bool> receiveSetup{false};
488
            bool isOpenSnd{false};
489
            bool isOpenRcv{false};
490
            bool _retry{false};
491
            char buff_[BUF_SIZE];       // Internal used buffer for network communication
492
            int mLastOnlineState{NSTATE_OFFLINE};
493
    };
494
}
495
 
496
#endif