fixes
[public/netxms.git] / doc / misc / embedded_nxcp.c
CommitLineData
050f5603
VK
1/**
2 * NXCP message builder for embedded systems
3 *
4 * Copyright (c) 2014 Raden Solutions
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/**
20 * Configuration
21 */
22#define MAX_MSG_SIZE 512
23#define KEEP_MESSAGE_ID 1
24#define ALLOW_STRING_FIELDS 1
25#define ALLOW_INT64_FIELDS 0
26#define ALLOW_FLOAT_FIELDS 0
27#define ALLOW_BINARY_FIELDS 0
28
29/**
30 * Data types
31 */
32#define CSCP_DT_INTEGER 0
33#define CSCP_DT_STRING 1
34#define CSCP_DT_INT64 2
35#define CSCP_DT_INT16 3
36#define CSCP_DT_BINARY 4
37#define CSCP_DT_FLOAT 5
38
39/**
40 * Message flags
41 */
42#define MF_BINARY 0x0001
43#define MF_END_OF_FILE 0x0002
44#define MF_DONT_ENCRYPT 0x0004
45#define MF_END_OF_SEQUENCE 0x0008
46#define MF_REVERSE_ORDER 0x0010
47#define MF_CONTROL 0x0020
48
49
50#pragma pack(1)
51
52/**
53 * Data field structure
54 */
55typedef struct
56{
57 uint32_t id; // Variable identifier
58 char type; // Data type
59 char padding; // Padding
60 uint16_t wInt16;
61 union
62 {
63 uint32_t dwInteger;
64 uint64_t qwInt64;
65 double dFloat;
66 struct
67 {
68 uint32_t len;
69 uint16_t value[1];
70 } string;
71 } data;
72} NXCP_DF;
73
74#define df_int16 wInt16
75#define df_int32 data.dwInteger
76#define df_int64 data.qwInt64
77#define df_real data.dFloat
78#define df_string data.string
79
80/**
81 * Message structure
82 */
83typedef struct
84{
85 uint16_t code; // Message (command) code
86 uint16_t flags; // Message flags
87 uint32_t size; // Message size (including header) in bytes
88 uint32_t id; // Unique message identifier
89 uint32_t numFields; // Number of fields in message
90} NXCP_MESSAGE_HEADER;
91
92#pragma pack()
93
94/**
95 * NXCP message buffer
96 */
97char nxcp_message[MAX_MSG_SIZE] = "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
98
99#if KEEP_MESSAGE_ID
100static uint32_t nxcp_message_id = 1;
101#endif
102static char *curr;
103
104/**
105 * Initialize message
106 */
107void nxcp_init_message()
108{
109 ((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields = 0;
110 curr = nxcp_message + 16;
111}
112
113/**
114 * Add INT16 field
115 */
116void nxcp_add_int16(uint32_t id, uint16_t value)
117{
118 NXCP_DF *df = (NXCP_DF *)curr;
119 df->id = htonl(id);
120 df->type = CSCP_DT_INT16;
121 df->df_int16 = htons(value);
122 curr += 8;
123 ((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields++;
124}
125
126/**
127 * Add INT32 field
128 */
129void nxcp_add_int32(uint32_t id, uint32_t value)
130{
131 NXCP_DF *df = (NXCP_DF *)curr;
132 df->id = htonl(id);
133 df->type = CSCP_DT_INTEGER;
134 df->df_int32 = htonl(value);
135 curr += 16;
136 ((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields++;
137}
138
139#if ALLOW_INT64_FIELDS
140
141/**
142 * Add INT64 field
143 */
144void nxcp_add_int64(uint32_t id, uint64_t value)
145{
146 NXCP_DF *df = (NXCP_DF *)curr;
147 df->id = htonl(id);
148 df->type = CSCP_DT_INT64;
149 df->df_int64 = htonll(value);
150 curr += 16;
151 ((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields++;
152}
153
154#endif
155
156#if ALLOW_STRING_FIELDS
157
158/**
159 * Add string field
160 */
161void nxcp_add_string(uint32_t id, const char *value)
162{
163 uint32_t l;
164 const char *p;
165 NXCP_DF *df = (NXCP_DF *)curr;
166 df->id = htonl(id);
167 df->type = CSCP_DT_STRING;
0402dbc0 168 for(l = 0, p = value, curr += 12; *p != 0; l += 2, p++)
050f5603
VK
169 {
170 *(curr++) = 0;
171 *(curr++) = *p;
172 }
173 df->df_string.len = htonl(l);
174 int padding = 8 - (l + 12) % 8;
175 curr += (padding < 8) ? padding : 0;
176 ((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields++;
177}
178
179#endif
180
181#if ALLOW_BINARY_FIELDS
182
183/**
184 * Add binary field
185 */
186void nxcp_add_binary(uint32_t id, const char *value, uint32_t len)
187{
188 NXCP_DF *df = (NXCP_DF *)curr;
189 df->id = htonl(id);
190 df->type = CSCP_DT_BINARY;
191 df->df_string.len = htonl(len);
192 curr += 12;
193 memcpy(curr, value, len);
194 curr += len;
195 int padding = 8 - (len + 12) % 8;
196 curr += (padding < 8) ? padding : 0;
197 ((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields++;
198}
199
200#endif
201
202/**
203 * Finalize message. Returns number of bytes to be sent from nxcp_message array.
204 */
205uint32_t nxcp_finalize()
206{
207 uint32_t l = (uint32_t)(curr - nxcp_message);
208 ((NXCP_MESSAGE_HEADER *)nxcp_message)->size = htonl(l);
209 ((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields = htonl(((NXCP_MESSAGE_HEADER *)nxcp_message)->numFields);
210#if KEEP_MESSAGE_ID
211 ((NXCP_MESSAGE_HEADER *)nxcp_message)->id = htonl(nxcp_message_id++);
212#endif
213 return l;
214}
215
216#if 0
217
218/**
219 * Example
220 */
221void example()
222{
223 nxcp_init_message();
224 nxcp_add_int16(1, 120);
225 nxcp_add_string(2, "test message");
226 uint32_t l = nxcp_finalize();
227 /* now send l bytes from nxcp_message to the network */
228 send(sock, nxcp_message, l, 0);
229}
230
231#endif