dfb2f538ec21fbfefc628ae3b1a0e3cb864038e8
[public/netxms.git] / doc / misc / embedded_nxcp.c
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 */
55 typedef 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 */
83 typedef 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 */
97 char 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
100 static uint32_t nxcp_message_id = 1;
101 #endif
102 static char *curr;
103
104 /**
105 * Initialize message
106 */
107 void 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 */
116 void 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 */
129 void 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 */
144 void 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 */
161 void 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;
168 for(l = 0, p = value, curr += 12; *p != 0; l += 2, p++)
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 */
186 void 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 */
205 uint32_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 * Login
220 */
221 void login(const char *login, const char *passwd, const char *deviceId)
222 {
223 nxcp_init_message();
224 nxcp_add_string(1, login);
225 nxcp_add_string(2, password);
226 nxcp_add_string(433, deviceId);
227 uint32_t l = nxcp_finalize();
228 /* now send l bytes from nxcp_message to the network */
229 send(sock, nxcp_message, l, 0);
230 }
231
232 /**
233 * Data push example
234 */
235 void data_push()
236 {
237 nxcp_init_message();
238
239 uint32_t id = 0x10000000;
240
241 // first parameter
242 nxcp_add_int32(id++, 0);
243 nxcp_add_string(id++, "Parameter1");
244 nxcp_add_string(id++, "value1");
245
246 // second parameter
247 nxcp_add_int32(id++, 0);
248 nxcp_add_string(id++, "Parameter2");
249 nxcp_add_string(id++, "value2");
250
251 // parameter count
252 nxcp_add_int32(111, 2);
253
254 send(sock, nxcp_message, l, 0);
255 }
256
257 #endif