| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* GATE PROJECT LICENSE: | ||
| 2 | +----------------------------------------------------------------------------+ | ||
| 3 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
| 4 | | All rights reserved. | | ||
| 5 | | | | ||
| 6 | | Redistribution and use in source and binary forms, with or without | | ||
| 7 | | modification, are permitted provided that the following conditions are met:| | ||
| 8 | | | | ||
| 9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
| 10 | | this list of conditions and the following disclaimer. | | ||
| 11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
| 12 | | notice, this list of conditions and the following disclaimer in the | | ||
| 13 | | documentation and/or other materials provided with the distribution. | | ||
| 14 | | | | ||
| 15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
| 16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
| 17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
| 18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
| 19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
| 20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
| 21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
| 22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
| 23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
| 24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
| 25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
| 26 | +----------------------------------------------------------------------------+ | ||
| 27 | */ | ||
| 28 | |||
| 29 | /* | ||
| 30 | SENACT - SENsor & ACTor access protocol | ||
| 31 | ======================================= | ||
| 32 | |||
| 33 | */ | ||
| 34 | |||
| 35 | #ifndef SENACT_H_INCLUDED | ||
| 36 | #define SENACT_H_INCLUDED | ||
| 37 | |||
| 38 | #if defined(__cplusplus) | ||
| 39 | extern "C" { | ||
| 40 | #endif | ||
| 41 | |||
| 42 | /* | ||
| 43 | Communication protocol: | ||
| 44 | |||
| 45 | A message based on ASCII-text fields, beginning with a defined ID-Token and | ||
| 46 | terminated with a LINE-FEED (ASCII code 10) | ||
| 47 | |||
| 48 | this ID-Token is the message header to define which content data fields will | ||
| 49 | follow. | ||
| 50 | A KEY is a text | ||
| 51 | |||
| 52 | message: | ||
| 53 | "[ID]:[KEY]=[VALUE],[KEY]=[VALUE],...\n" | ||
| 54 | |||
| 55 | |||
| 56 | |||
| 57 | */ | ||
| 58 | |||
| 59 | #define SENACT_DATA_TYPE_INT 0x01 /* integer (32 bit, big endian) */ | ||
| 60 | #define SENACT_DATA_TYPE_FLOAT 0x02 /* floating point (32 bit, big endian) */ | ||
| 61 | #define SENACT_DATA_TYPE_TEXT 0x03 /* 8-bit TEXT characters (surrounded by quotes, C-style escaped)*/ | ||
| 62 | |||
| 63 | typedef unsigned char senact_device_id_t; | ||
| 64 | typedef unsigned char senact_data_type_t; | ||
| 65 | typedef unsigned char senact_data_category_t; | ||
| 66 | typedef unsigned char senact_data_unit_t; | ||
| 67 | |||
| 68 | |||
| 69 | typedef struct senact_device_type | ||
| 70 | { | ||
| 71 | senact_device_id_t device_id; | ||
| 72 | senact_data_type_t data_type; | ||
| 73 | senact_data_category_t data_category; | ||
| 74 | senact_data_unit_t data_unit; | ||
| 75 | } senact_device_type_t; | ||
| 76 | |||
| 77 | #define SENACT_DATA_CATEGORY_UNKNOWN 0x00 | ||
| 78 | #define SENACT_DATA_CATEGORY_RAW 0x01 /* generic raw data, unspecified */ | ||
| 79 | #define SENACT_DATA_CATEGORY_POS_X 0x10 /* position X coordinate */ | ||
| 80 | #define SENACT_DATA_CATEGORY_POS_Y 0x11 /* position Y coordinate */ | ||
| 81 | #define SENACT_DATA_CATEGORY_POS_Z 0x12 /* position Z coordinate */ | ||
| 82 | #define SENACT_DATA_CATEGORY_VELOCITY 0x13 /* movement speed */ | ||
| 83 | #define SENACT_DATA_CATEGORY_ACCEL_X 0x14 | ||
| 84 | #define SENACT_DATA_CATEGORY_ACCEL_Y 0x15 | ||
| 85 | #define SENACT_DATA_CATEGORY_ACCEL_Z 0x16 | ||
| 86 | #define SENACT_DATA_CATEGORY_LENGTH 0x17 /* length measurement */ | ||
| 87 | #define SENACT_DATA_CATEGORY_DISTANCE 0x18 /* distance measurement */ | ||
| 88 | #define SENACT_DATA_CATEGORY_WEIGHT 0x19 /* weight measurement */ | ||
| 89 | #define SENACT_DATA_CATEGORY_LOAD_CAPACITY 0x1a /* load capacity (e.g. battery capacity) */ | ||
| 90 | #define SENACT_DATA_CATEGORY_LOAD 0x1b /* load amount (e.g. battery capacity) */ | ||
| 91 | #define SENACT_DATA_CATEGORY_BUTTON 0x20 | ||
| 92 | #define SENACT_DATA_CATEGORY_TEMPERATURE 0x21 | ||
| 93 | #define SENACT_DATA_CATEGORY_PRESSURE 0x22 | ||
| 94 | |||
| 95 | |||
| 96 | #define SENACT_DATA_UNIT_UNKNOWN 0x00 | ||
| 97 | #define SENACT_DATA_UNIT_MILLIMETER 0x01 /* millimeters (position/distance) */ | ||
| 98 | #define SENACT_DATA_UNIT_INCH 0x02 /* inch (position/distance) */ | ||
| 99 | #define SENACT_DATA_UNIT_KMH 0x03 /* kilometers per hour (speed) */ | ||
| 100 | #define SENACT_DATA_UNIT_MPH 0x04 /* miles per hour (speed) */ | ||
| 101 | #define SENACT_DATA_UNIT_GRAMM 0x05 /* gramm (weight) */ | ||
| 102 | #define SENACT_DATA_UNIT_PERCENT 0x05 /* percentage (0 - 100) */ | ||
| 103 | |||
| 104 | |||
| 105 | ✗ | static unsigned senact_strlen(char const* text) | |
| 106 | { | ||
| 107 | ✗ | unsigned length = 0; | |
| 108 | ✗ | if (text) | |
| 109 | { | ||
| 110 | ✗ | while (*text) | |
| 111 | { | ||
| 112 | ✗ | ++length; | |
| 113 | ✗ | ++text; | |
| 114 | } | ||
| 115 | } | ||
| 116 | ✗ | return length; | |
| 117 | } | ||
| 118 | |||
| 119 | ✗ | static unsigned senact_check_token(char const* target, unsigned target_len, char const* token, unsigned token_len) | |
| 120 | { | ||
| 121 | ✗ | unsigned ret = 0; | |
| 122 | ✗ | if (target_len >= token_len) | |
| 123 | { | ||
| 124 | ✗ | ret = token_len; | |
| 125 | ✗ | while (token_len-- != 0) | |
| 126 | { | ||
| 127 | ✗ | if (*token != *target) | |
| 128 | { | ||
| 129 | ✗ | ret = 0; | |
| 130 | ✗ | break; | |
| 131 | } | ||
| 132 | ✗ | ++target; | |
| 133 | ✗ | ++token; | |
| 134 | } | ||
| 135 | } | ||
| 136 | ✗ | return ret; | |
| 137 | } | ||
| 138 | |||
| 139 | #ifndef SENACT_MAX_TEXT_LENGTH | ||
| 140 | #define SENACT_MAX_TEXT_LENGTH 62 | ||
| 141 | #endif | ||
| 142 | |||
| 143 | typedef struct senact_value | ||
| 144 | { | ||
| 145 | unsigned char value_type; | ||
| 146 | union | ||
| 147 | { | ||
| 148 | long int_value; | ||
| 149 | float float_value; | ||
| 150 | char text_value[SENACT_MAX_TEXT_LENGTH + 1]; | ||
| 151 | }; | ||
| 152 | } senact_value_t; | ||
| 153 | |||
| 154 | ✗ | static int senact_parse_digit(char chr) | |
| 155 | { | ||
| 156 | ✗ | if ((chr >= '0') && (chr <= '9')) | |
| 157 | { | ||
| 158 | ✗ | return (int)(chr - '0'); | |
| 159 | } | ||
| 160 | ✗ | return -1; | |
| 161 | } | ||
| 162 | |||
| 163 | ✗ | static unsigned senact_parse_value(char const* source, unsigned source_len, senact_value_t* value) | |
| 164 | { | ||
| 165 | ✗ | unsigned chars_parsed = 0; | |
| 166 | int digit; | ||
| 167 | ✗ | int sign = 1; | |
| 168 | ✗ | int escape_mode = 0; | |
| 169 | ✗ | char* text_ptr = &value->text_value[0]; | |
| 170 | ✗ | unsigned text_len = sizeof(value->text_value) - 1; | |
| 171 | float decimal_factor; | ||
| 172 | |||
| 173 | do | ||
| 174 | { | ||
| 175 | ✗ | if (source_len == 0) | |
| 176 | { | ||
| 177 | ✗ | break; | |
| 178 | } | ||
| 179 | |||
| 180 | ✗ | if (*source == '\"') | |
| 181 | { | ||
| 182 | /* text value */ | ||
| 183 | ✗ | value->value_type = SENACT_DATA_TYPE_TEXT; | |
| 184 | ✗ | ++source; | |
| 185 | ✗ | --source_len; | |
| 186 | ✗ | ++chars_parsed; | |
| 187 | ✗ | while ((source_len != 0) && (text_len != 0)) | |
| 188 | { | ||
| 189 | ✗ | if (escape_mode) | |
| 190 | { | ||
| 191 | ✗ | switch (*source) | |
| 192 | { | ||
| 193 | ✗ | case 'r': *text_ptr = '\r'; break; | |
| 194 | ✗ | case 'n': *text_ptr = '\r'; break; | |
| 195 | ✗ | case '\\': *text_ptr = '\r'; break; | |
| 196 | ✗ | case '\"': *text_ptr = '\"'; break; | |
| 197 | ✗ | case '\'': *text_ptr = '\''; break; | |
| 198 | ✗ | case 't': *text_ptr = '\r'; break; | |
| 199 | ✗ | case 'b': *text_ptr = '\r'; break; | |
| 200 | ✗ | default: *text_ptr = *source; break; | |
| 201 | } | ||
| 202 | ✗ | ++text_ptr; | |
| 203 | ✗ | --text_len; | |
| 204 | ✗ | ++source; | |
| 205 | ✗ | --source_len; | |
| 206 | ✗ | ++chars_parsed; | |
| 207 | ✗ | escape_mode = 0; | |
| 208 | } | ||
| 209 | else | ||
| 210 | { | ||
| 211 | ✗ | if (*source == '\"') | |
| 212 | { | ||
| 213 | /* end of string found */ | ||
| 214 | ✗ | ++chars_parsed; | |
| 215 | ✗ | break; | |
| 216 | } | ||
| 217 | ✗ | else if (*source == '\\') | |
| 218 | { | ||
| 219 | ✗ | escape_mode = 1; | |
| 220 | } | ||
| 221 | else | ||
| 222 | { | ||
| 223 | ✗ | value->text_value[text_len] = *source; | |
| 224 | ✗ | ++text_len; | |
| 225 | } | ||
| 226 | ✗ | ++chars_parsed; | |
| 227 | ✗ | ++source; | |
| 228 | ✗ | --source_len; | |
| 229 | } | ||
| 230 | |||
| 231 | } | ||
| 232 | ✗ | *text_ptr = 0; | |
| 233 | ✗ | break; | |
| 234 | } | ||
| 235 | |||
| 236 | /* expect a number */ | ||
| 237 | ✗ | value->value_type = SENACT_DATA_TYPE_INT; | |
| 238 | ✗ | value->int_value = 0; | |
| 239 | |||
| 240 | ✗ | if (*source == '-') | |
| 241 | { | ||
| 242 | ✗ | sign = -1; | |
| 243 | ✗ | ++source; | |
| 244 | ✗ | --source_len; | |
| 245 | ✗ | ++chars_parsed; | |
| 246 | } | ||
| 247 | |||
| 248 | ✗ | while (source_len != 0) | |
| 249 | { | ||
| 250 | ✗ | digit = senact_parse_digit(*source); | |
| 251 | ✗ | if (digit < 0) | |
| 252 | { | ||
| 253 | ✗ | break; | |
| 254 | } | ||
| 255 | ✗ | value->int_value *= 10; | |
| 256 | ✗ | value->int_value += (digit * sign); | |
| 257 | |||
| 258 | ✗ | ++source; | |
| 259 | ✗ | --source_len; | |
| 260 | ✗ | ++chars_parsed; | |
| 261 | } | ||
| 262 | ✗ | if (source_len == 0) break; | |
| 263 | |||
| 264 | ✗ | if (*source == '.') | |
| 265 | { | ||
| 266 | /* seems to be a floating point value*/ | ||
| 267 | ✗ | value->float_value = (float)value->int_value; | |
| 268 | ✗ | value->value_type = SENACT_DATA_TYPE_FLOAT; | |
| 269 | ✗ | ++source; | |
| 270 | ✗ | --source_len; | |
| 271 | ✗ | ++chars_parsed; | |
| 272 | |||
| 273 | ✗ | decimal_factor = 0.1f * (float)sign; | |
| 274 | ✗ | while (source_len != 0) | |
| 275 | { | ||
| 276 | ✗ | digit = senact_parse_digit(*source); | |
| 277 | ✗ | if (digit < 0) | |
| 278 | { | ||
| 279 | ✗ | break; | |
| 280 | } | ||
| 281 | ✗ | value->float_value += (decimal_factor * (float)digit); | |
| 282 | ✗ | decimal_factor *= 0.1f; | |
| 283 | |||
| 284 | ✗ | ++source; | |
| 285 | ✗ | --source_len; | |
| 286 | ✗ | ++chars_parsed; | |
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | } while (0); | ||
| 291 | |||
| 292 | ✗ | return chars_parsed; | |
| 293 | } | ||
| 294 | |||
| 295 | ✗ | static void senact_revert_string(char* target, unsigned target_len) | |
| 296 | { | ||
| 297 | unsigned ndx, cnt; | ||
| 298 | char tmp; | ||
| 299 | |||
| 300 | ✗ | cnt = target_len / 2; | |
| 301 | ✗ | for (ndx = 0; ndx != cnt; ++ndx) | |
| 302 | { | ||
| 303 | ✗ | tmp = target[ndx]; | |
| 304 | ✗ | target[ndx] = target[target_len - 1 - ndx]; | |
| 305 | ✗ | target[target_len - 1 - ndx] = tmp; | |
| 306 | } | ||
| 307 | ✗ | } | |
| 308 | |||
| 309 | ✗ | static unsigned senact_print_int(char* target, unsigned target_capacity, long value) | |
| 310 | { | ||
| 311 | ✗ | unsigned ret = 0; | |
| 312 | unsigned long ul; | ||
| 313 | int digit; | ||
| 314 | unsigned index; | ||
| 315 | |||
| 316 | |||
| 317 | do | ||
| 318 | { | ||
| 319 | ✗ | if (target_capacity < 2) break; | |
| 320 | ✗ | --target_capacity; | |
| 321 | |||
| 322 | /* | ||
| 323 | if(value == 0) | ||
| 324 | { | ||
| 325 | *target = '0'; | ||
| 326 | ++target; | ||
| 327 | ++ret; | ||
| 328 | *target = 0; | ||
| 329 | --target_capacity; | ||
| 330 | break; | ||
| 331 | } | ||
| 332 | */ | ||
| 333 | |||
| 334 | ✗ | if (value < 0) | |
| 335 | { | ||
| 336 | ✗ | *target = '-'; | |
| 337 | ✗ | ++target; | |
| 338 | ✗ | ++ret; | |
| 339 | ✗ | --target_capacity; | |
| 340 | ✗ | ul = (unsigned long)-value; | |
| 341 | } | ||
| 342 | else | ||
| 343 | { | ||
| 344 | ✗ | ul = (unsigned long)value; | |
| 345 | } | ||
| 346 | |||
| 347 | ✗ | index = 0; | |
| 348 | do | ||
| 349 | { | ||
| 350 | ✗ | if (index >= target_capacity) | |
| 351 | { | ||
| 352 | ✗ | break; | |
| 353 | } | ||
| 354 | ✗ | digit = (int)(ul % 10); | |
| 355 | ✗ | ul /= 10; | |
| 356 | ✗ | target[index] = (char)('0' + digit); | |
| 357 | |||
| 358 | ✗ | ++index; | |
| 359 | ✗ | } while (ul != 0); | |
| 360 | |||
| 361 | ✗ | senact_revert_string(target, index); | |
| 362 | ✗ | target[index] = 0; | |
| 363 | ✗ | ret += index; | |
| 364 | } while (0); | ||
| 365 | ✗ | return ret; | |
| 366 | } | ||
| 367 | ✗ | static unsigned senact_print_float(char* target, unsigned target_capacity, float value, unsigned decimal_len) | |
| 368 | { | ||
| 369 | ✗ | unsigned ret = 0; | |
| 370 | ✗ | long int_value = (long)value; | |
| 371 | ✗ | float decimal = value - (float)int_value; | |
| 372 | unsigned index; | ||
| 373 | ✗ | float factor = 1.0f; | |
| 374 | int digit; | ||
| 375 | |||
| 376 | do | ||
| 377 | { | ||
| 378 | ✗ | if (decimal < 0.0f) decimal *= -1.0f; | |
| 379 | |||
| 380 | ✗ | ret = senact_print_int(target, target_capacity, int_value); | |
| 381 | ✗ | if (ret == 0) break; | |
| 382 | |||
| 383 | ✗ | target += ret; | |
| 384 | ✗ | target_capacity -= ret; | |
| 385 | |||
| 386 | ✗ | if (target_capacity < 2) break; | |
| 387 | ✗ | --target_capacity; | |
| 388 | |||
| 389 | ✗ | *target = '.'; | |
| 390 | ✗ | ++target; | |
| 391 | ✗ | ++ret; | |
| 392 | ✗ | --target_capacity; | |
| 393 | |||
| 394 | ✗ | for (index = 0; (index < decimal_len) && (target_capacity != 0); ++index) | |
| 395 | { | ||
| 396 | ✗ | factor *= 10.0f; | |
| 397 | ✗ | digit = (int)(decimal * factor); | |
| 398 | ✗ | *target = (char)('0' + digit); | |
| 399 | ✗ | decimal -= (float)digit / factor; | |
| 400 | |||
| 401 | ✗ | ++target; | |
| 402 | ✗ | ++ret; | |
| 403 | ✗ | --target_capacity; | |
| 404 | } | ||
| 405 | |||
| 406 | ✗ | *target = 0; | |
| 407 | } while (0); | ||
| 408 | |||
| 409 | ✗ | return ret; | |
| 410 | |||
| 411 | } | ||
| 412 | ✗ | static unsigned senact_print_text(char* target, unsigned target_capacity, char const* text, unsigned text_len) | |
| 413 | { | ||
| 414 | ✗ | unsigned ret = 0; | |
| 415 | char chr; | ||
| 416 | do | ||
| 417 | { | ||
| 418 | ✗ | if (target_capacity < 4) | |
| 419 | { | ||
| 420 | ✗ | break; | |
| 421 | } | ||
| 422 | ✗ | target_capacity -= 4; | |
| 423 | |||
| 424 | ✗ | *target = '\"'; | |
| 425 | ✗ | ++target; | |
| 426 | |||
| 427 | ✗ | while ((target_capacity != 0) && (text_len != 0)) | |
| 428 | { | ||
| 429 | ✗ | chr = *text; | |
| 430 | ✗ | switch (chr) | |
| 431 | { | ||
| 432 | ✗ | case '\r': | |
| 433 | { | ||
| 434 | ✗ | *target = '\\'; | |
| 435 | ✗ | ++target; | |
| 436 | ✗ | --target_capacity; | |
| 437 | ✗ | chr = 'r'; | |
| 438 | ✗ | break; | |
| 439 | } | ||
| 440 | ✗ | case '\n': | |
| 441 | { | ||
| 442 | ✗ | *target = '\\'; | |
| 443 | ✗ | ++target; | |
| 444 | ✗ | --target_capacity; | |
| 445 | ✗ | chr = 'n'; | |
| 446 | ✗ | break; | |
| 447 | } | ||
| 448 | ✗ | case '\t': | |
| 449 | { | ||
| 450 | ✗ | *target = '\\'; | |
| 451 | ✗ | ++target; | |
| 452 | ✗ | --target_capacity; | |
| 453 | ✗ | chr = 't'; | |
| 454 | ✗ | break; | |
| 455 | } | ||
| 456 | ✗ | case '\\': | |
| 457 | { | ||
| 458 | ✗ | *target = '\\'; | |
| 459 | ✗ | ++target; | |
| 460 | ✗ | --target_capacity; | |
| 461 | ✗ | chr = '\\'; | |
| 462 | ✗ | break; | |
| 463 | } | ||
| 464 | ✗ | case '\"': | |
| 465 | { | ||
| 466 | ✗ | *target = '\\'; | |
| 467 | ✗ | ++target; | |
| 468 | ✗ | --target_capacity; | |
| 469 | ✗ | chr = '\"'; | |
| 470 | ✗ | break; | |
| 471 | } | ||
| 472 | ✗ | case '\'': | |
| 473 | { | ||
| 474 | ✗ | *target = '\\'; | |
| 475 | ✗ | ++target; | |
| 476 | ✗ | --target_capacity; | |
| 477 | ✗ | chr = '\''; | |
| 478 | ✗ | break; | |
| 479 | } | ||
| 480 | ✗ | default: | |
| 481 | { | ||
| 482 | ✗ | break; | |
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 486 | ✗ | *target = chr; | |
| 487 | ✗ | ++target; | |
| 488 | ✗ | ++text; | |
| 489 | ✗ | if (target_capacity != 0) | |
| 490 | { | ||
| 491 | ✗ | --target_capacity; | |
| 492 | } | ||
| 493 | ✗ | --text_len; | |
| 494 | } | ||
| 495 | } while (0); | ||
| 496 | |||
| 497 | ✗ | *target = '\"'; | |
| 498 | ✗ | ++target; | |
| 499 | ✗ | ++ret; | |
| 500 | ✗ | *target = '\0'; | |
| 501 | |||
| 502 | ✗ | return ret; | |
| 503 | } | ||
| 504 | |||
| 505 | ✗ | static unsigned senact_print_value(senact_value_t const* value, char* target, unsigned target_capacity) | |
| 506 | { | ||
| 507 | ✗ | unsigned ret = 0; | |
| 508 | ✗ | switch (value->value_type) | |
| 509 | { | ||
| 510 | ✗ | case SENACT_DATA_TYPE_INT: | |
| 511 | { | ||
| 512 | ✗ | ret = senact_print_int(target, target_capacity, value->int_value); | |
| 513 | ✗ | break; | |
| 514 | } | ||
| 515 | ✗ | case SENACT_DATA_TYPE_FLOAT: | |
| 516 | { | ||
| 517 | ✗ | ret = senact_print_float(target, target_capacity, value->float_value, 6); | |
| 518 | ✗ | break; | |
| 519 | } | ||
| 520 | ✗ | case SENACT_DATA_TYPE_TEXT: | |
| 521 | { | ||
| 522 | ✗ | ret = senact_print_text(target, target_capacity, value->text_value, senact_strlen(value->text_value)); | |
| 523 | ✗ | break; | |
| 524 | } | ||
| 525 | ✗ | default: | |
| 526 | { | ||
| 527 | ✗ | break; | |
| 528 | } | ||
| 529 | } | ||
| 530 | ✗ | return ret; | |
| 531 | } | ||
| 532 | |||
| 533 | |||
| 534 | typedef int (*senact_function_inspect_sensor_t)(senact_device_id_t id, void* device_param, | ||
| 535 | senact_data_type_t* output_data_type, | ||
| 536 | senact_data_category_t* output_data_category, | ||
| 537 | senact_data_unit_t* output_data_unit); | ||
| 538 | |||
| 539 | typedef int (*senact_function_read_sensor_t)(senact_device_id_t id, senact_value_t* output_value); | ||
| 540 | |||
| 541 | |||
| 542 | typedef int (*senact_function_inspect_actor_t)(senact_device_id_t id, void* device_param, | ||
| 543 | senact_data_type_t* output_data_type, | ||
| 544 | senact_data_category_t* output_data_category, | ||
| 545 | senact_data_unit_t* output_data_unit); | ||
| 546 | |||
| 547 | typedef int (*senact_function_update_actor_t)(senact_device_id_t id, senact_value_t const* value); | ||
| 548 | |||
| 549 | typedef struct | ||
| 550 | { | ||
| 551 | senact_device_id_t sensor_id; | ||
| 552 | void* sensor_param; | ||
| 553 | senact_function_inspect_sensor_t inspect_sensor; | ||
| 554 | senact_function_read_sensor_t read_sensor; | ||
| 555 | |||
| 556 | } senact_sensor_t; | ||
| 557 | |||
| 558 | typedef struct | ||
| 559 | { | ||
| 560 | senact_device_id_t actor_id; | ||
| 561 | void* actor_param; | ||
| 562 | senact_function_inspect_actor_t inspect_actor; | ||
| 563 | senact_function_update_actor_t update_actor; | ||
| 564 | } senact_actor_t; | ||
| 565 | |||
| 566 | #ifndef SENACT_MAX_SENSOR_COUNT | ||
| 567 | #define SENACT_MAX_SENSOR_COUNT 16 | ||
| 568 | #endif | ||
| 569 | #ifndef SENACT_MAX_ACTOR_COUNT | ||
| 570 | #define SENACT_MAX_ACTOR_COUNT 16 | ||
| 571 | #endif | ||
| 572 | |||
| 573 | static senact_sensor_t sensors[SENACT_MAX_SENSOR_COUNT]; | ||
| 574 | static senact_actor_t actors[SENACT_MAX_ACTOR_COUNT]; | ||
| 575 | |||
| 576 | |||
| 577 | |||
| 578 | |||
| 579 | |||
| 580 | |||
| 581 | |||
| 582 | #define SENACT_MSG_TYPE_QUERY_SENSOR_COUNT 0x10 | ||
| 583 | #define SENACT_MSG_TYPE_RESPONSE_SENSOR_COUNT 0x11 | ||
| 584 | static char senact_id_query_sensor_count[] = { 'Q', 'S', 'C', ':' }; | ||
| 585 | static char senact_id_response_sensors_count[] = { 'R', 'S', 'C', ':' }; | ||
| 586 | |||
| 587 | typedef struct senact_query_sensor_count | ||
| 588 | { | ||
| 589 | unsigned char msg_type; | ||
| 590 | } senact_query_sensor_count_t; | ||
| 591 | |||
| 592 | ✗ | static unsigned senact_print_query_sensor_count(senact_query_sensor_count_t const* msg, char* target, unsigned target_capacity) | |
| 593 | { | ||
| 594 | ✗ | unsigned ret = 0; | |
| 595 | /* TODO implementation */ | ||
| 596 | ✗ | return ret; | |
| 597 | } | ||
| 598 | ✗ | static unsigned senact_parse_query_sensor_count(char const* source, unsigned source_length, senact_query_sensor_count_t* msg) | |
| 599 | { | ||
| 600 | ✗ | unsigned ret = 0; | |
| 601 | /* TODO implementation */ | ||
| 602 | ✗ | return ret; | |
| 603 | } | ||
| 604 | |||
| 605 | |||
| 606 | |||
| 607 | typedef struct senact_msg_header | ||
| 608 | { | ||
| 609 | unsigned char msg_type; | ||
| 610 | } senact_msg_header_t; | ||
| 611 | |||
| 612 | |||
| 613 | typedef struct senact_response_sensor_count | ||
| 614 | { | ||
| 615 | senact_msg_header_t header; | ||
| 616 | long sensor_count; | ||
| 617 | } senact_response_sensor_count_t; | ||
| 618 | |||
| 619 | |||
| 620 | static char senact_id_query_list_actors[] = { 'Q', 'L', 'A' }; | ||
| 621 | static char senact_id_response_list_actors[] = { 'R', 'L', 'A' }; | ||
| 622 | |||
| 623 | static char senact_id_query_sensor_value[] = { 'Q', 'S', 'V' }; | ||
| 624 | static char senact_id_response_sensor_value[] = { 'R', 'S', 'V' }; | ||
| 625 | |||
| 626 | |||
| 627 | typedef struct senact_msg_request_list_sensors | ||
| 628 | { | ||
| 629 | unsigned char msg_type[4]; | ||
| 630 | unsigned short msg_length; | ||
| 631 | } senact_msg_request_list_sensors_t; | ||
| 632 | |||
| 633 | |||
| 634 | |||
| 635 | typedef union senact_msg | ||
| 636 | { | ||
| 637 | senact_msg_header_t header; | ||
| 638 | |||
| 639 | } senact_msg_t; | ||
| 640 | |||
| 641 | typedef struct senact_field_reflector | ||
| 642 | { | ||
| 643 | char key; | ||
| 644 | unsigned char data_type; | ||
| 645 | unsigned offset; | ||
| 646 | } senact_field_reflector_t; | ||
| 647 | |||
| 648 | typedef struct senact_msg_reflector | ||
| 649 | { | ||
| 650 | unsigned char msg_type; | ||
| 651 | char msg_id_token[3]; | ||
| 652 | senact_field_reflector_t values[4]; | ||
| 653 | } senact_msg_reflector_t; | ||
| 654 | |||
| 655 | static senact_msg_reflector_t senact_msg_reflectors[] = | ||
| 656 | { | ||
| 657 | { | ||
| 658 | SENACT_MSG_TYPE_QUERY_SENSOR_COUNT, | ||
| 659 | { 'Q', 'S', 'C' }, | ||
| 660 | { 0 } | ||
| 661 | }, | ||
| 662 | { | ||
| 663 | SENACT_MSG_TYPE_RESPONSE_SENSOR_COUNT, | ||
| 664 | { 'R', 'S', 'C' }, | ||
| 665 | { | ||
| 666 | { 'V', SENACT_DATA_TYPE_INT, offsetof(senact_response_sensor_count_t, sensor_count) } | ||
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | }; | ||
| 671 | |||
| 672 | |||
| 673 | #if defined(__cplusplus) | ||
| 674 | } | ||
| 675 | #endif | ||
| 676 | |||
| 677 | #endif | ||
| 678 | |||
| 679 |