Skip to content
Snippets Groups Projects
MyMessage.h 25 KiB
Newer Older
  • Learn to ignore specific revisions
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
    /*
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2019 Sensnology AB
     * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     */
    
    /**
     * @file MyMessage.h
     *
     * @brief API and type declarations for MySensors messages
     * @defgroup MyMessagegrp MyMessage
     * @ingroup publics
     * @{
     *
     * @brief Here you can find all message types used by the MySensors protocol as well as macros for
     * parsing and manipulating messages.
     */
    #ifndef MyMessage_h
    #define MyMessage_h
    
    #ifdef __cplusplus
    #include <Arduino.h>
    #include <stdint.h>
    #endif
    
    #define V2_MYS_HEADER_PROTOCOL_VERSION      (2u) //!< Protocol version
    #define V2_MYS_HEADER_SIZE                  (7u) //!< Header size
    #define V2_MYS_HEADER_MAX_MESSAGE_SIZE      (32u) //!< Max payload size
    
    #define V2_MYS_HEADER_VSL_VERSION_POS       (0) //!< bitfield position version
    #define V2_MYS_HEADER_VSL_VERSION_SIZE      (2u) //!< size version field
    #define V2_MYS_HEADER_VSL_SIGNED_POS        (2u) //!< bitfield position signed field
    #define V2_MYS_HEADER_VSL_SIGNED_SIZE       (1u) //!< size signed field
    #define V2_MYS_HEADER_VSL_LENGTH_POS        (3u) //!< bitfield position length field
    #define V2_MYS_HEADER_VSL_LENGTH_SIZE       (5u) //!< size length field
    
    #define V2_MYS_HEADER_CEP_COMMAND_POS       (0) //!< bitfield position command field
    #define V2_MYS_HEADER_CEP_COMMAND_SIZE      (3u) //!< size command field
    #define V2_MYS_HEADER_CEP_ECHOREQUEST_POS   (3u) //!< bitfield position echo request field
    #define V2_MYS_HEADER_CEP_ECHOREQUEST_SIZE   (1u) //!< size echo request field
    #define V2_MYS_HEADER_CEP_ECHO_POS          (4u) //!< bitfield position echo field
    #define V2_MYS_HEADER_CEP_ECHO_SIZE         (1u) //!< size echo field
    #define V2_MYS_HEADER_CEP_PAYLOADTYPE_POS   (5u) //!< bitfield position payload type field
    #define V2_MYS_HEADER_CEP_PAYLOADTYPE_SIZE  (3u) //!< size payload type field
    
    #define MAX_MESSAGE_SIZE                    V2_MYS_HEADER_MAX_MESSAGE_SIZE	//!< The maximum size of a message (including header)
    #define HEADER_SIZE                         V2_MYS_HEADER_SIZE	//!< The size of the header
    #define MAX_PAYLOAD_SIZE                    (MAX_MESSAGE_SIZE - HEADER_SIZE) //!< The maximum size of a payload depends on #MAX_MESSAGE_SIZE and #HEADER_SIZE
    
    // deprecated in 3.0.0
    #define MAX_PAYLOAD                         MAX_PAYLOAD_SIZE //!< \deprecated in 3.0.0 The maximum size of a payload depends on #MAX_MESSAGE_SIZE and #HEADER_SIZE
    
    /// @brief The command field (message-type) defines the overall properties of a message
    typedef enum {
    	C_PRESENTATION = 0,	//!< Sent by a node when they present attached sensors. This is usually done in presentation() at startup.
    	C_SET          = 1,	//!< This message is sent from or to a sensor when a sensor value should be updated.
    	C_REQ          = 2,	//!< Requests a variable value (usually from an actuator destined for controller).
    	C_INTERNAL     = 3,	//!< Internal MySensors messages (also include common messages provided/generated by the library).
    	C_STREAM       = 4,	//!< For firmware and other larger chunks of data that need to be divided into pieces.
    	C_RESERVED_5   = 5,	//!< C_RESERVED_5
    	C_RESERVED_6   = 6,	//!< C_RESERVED_6
    	C_INVALID_7    = 7	//!< C_INVALID_7
    } mysensors_command_t;
    
    #if !DOXYGEN // Hide until we migrate
    /// @brief Type of sensor (used when presenting sensors)
    typedef enum {
    	S_DOOR					= 0,	//!< Door sensor, V_TRIPPED, V_ARMED
    	S_MOTION				= 1,	//!< Motion sensor, V_TRIPPED, V_ARMED
    	S_SMOKE					= 2,	//!< Smoke sensor, V_TRIPPED, V_ARMED
    	S_BINARY				= 3,	//!< Binary light or relay, V_STATUS, V_WATT
    	S_LIGHT					= 3,	//!< \deprecated Same as S_BINARY
    	S_DIMMER				= 4,	//!< Dimmable light or fan device, V_STATUS (on/off), V_PERCENTAGE (dimmer level 0-100), V_WATT
    	S_COVER					= 5,	//!< Blinds or window cover, V_UP, V_DOWN, V_STOP, V_PERCENTAGE (open/close to a percentage)
    	S_TEMP					= 6,	//!< Temperature sensor, V_TEMP
    	S_HUM					= 7,	//!< Humidity sensor, V_HUM
    	S_BARO					= 8,	//!< Barometer sensor, V_PRESSURE, V_FORECAST
    	S_WIND					= 9,	//!< Wind sensor, V_WIND, V_GUST
    	S_RAIN					= 10,	//!< Rain sensor, V_RAIN, V_RAINRATE
    	S_UV					= 11,	//!< Uv sensor, V_UV
    	S_WEIGHT				= 12,	//!< Personal scale sensor, V_WEIGHT, V_IMPEDANCE
    	S_POWER					= 13,	//!< Power meter, V_WATT, V_KWH, V_VAR, V_VA, V_POWER_FACTOR
    	S_HEATER				= 14,	//!< Header device, V_HVAC_SETPOINT_HEAT, V_HVAC_FLOW_STATE, V_TEMP
    	S_DISTANCE				= 15,	//!< Distance sensor, V_DISTANCE
    	S_LIGHT_LEVEL			= 16,	//!< Light level sensor, V_LIGHT_LEVEL (uncalibrated in percentage),  V_LEVEL (light level in lux)
    	S_ARDUINO_NODE			= 17,	//!< Used (internally) for presenting a non-repeating Arduino node
    	S_ARDUINO_REPEATER_NODE	= 18,	//!< Used (internally) for presenting a repeating Arduino node
    	S_LOCK					= 19,	//!< Lock device, V_LOCK_STATUS
    	S_IR					= 20,	//!< IR device, V_IR_SEND, V_IR_RECEIVE
    	S_WATER					= 21,	//!< Water meter, V_FLOW, V_VOLUME
    	S_AIR_QUALITY			= 22,	//!< Air quality sensor, V_LEVEL
    	S_CUSTOM				= 23,	//!< Custom sensor
    	S_DUST					= 24,	//!< Dust sensor, V_LEVEL
    	S_SCENE_CONTROLLER		= 25,	//!< Scene controller device, V_SCENE_ON, V_SCENE_OFF.
    	S_RGB_LIGHT				= 26,	//!< RGB light. Send color component data using V_RGB. Also supports V_WATT
    	S_RGBW_LIGHT			= 27,	//!< RGB light with an additional White component. Send data using V_RGBW. Also supports V_WATT
    	S_COLOR_SENSOR			= 28,	//!< Color sensor, send color information using V_RGB
    	S_HVAC					= 29,	//!< Thermostat/HVAC device. V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE, V_TEMP
    	S_MULTIMETER			= 30,	//!< Multimeter device, V_VOLTAGE, V_CURRENT, V_IMPEDANCE
    	S_SPRINKLER				= 31,	//!< Sprinkler, V_STATUS (turn on/off), V_TRIPPED (if fire detecting device)
    	S_WATER_LEAK			= 32,	//!< Water leak sensor, V_TRIPPED, V_ARMED
    	S_SOUND					= 33,	//!< Sound sensor, V_TRIPPED, V_ARMED, V_LEVEL (sound level in dB)
    	S_VIBRATION				= 34,	//!< Vibration sensor, V_TRIPPED, V_ARMED, V_LEVEL (vibration in Hz)
    	S_MOISTURE				= 35,	//!< Moisture sensor, V_TRIPPED, V_ARMED, V_LEVEL (water content or moisture in percentage?)
    	S_INFO					= 36,	//!< LCD text device / Simple information device on controller, V_TEXT
    	S_GAS					= 37,	//!< Gas meter, V_FLOW, V_VOLUME
    	S_GPS					= 38,	//!< GPS Sensor, V_POSITION
    	S_WATER_QUALITY			= 39	//!< V_TEMP, V_PH, V_ORP, V_EC, V_STATUS
    } mysensors_sensor_t;
    
    /// @brief Type of sensor data (for set/req/echo messages)
    typedef enum {
    	V_TEMP					= 0,	//!< S_TEMP. Temperature S_TEMP, S_HEATER, S_HVAC
    	V_HUM					= 1,	//!< S_HUM. Humidity
    	V_STATUS				= 2,	//!< S_BINARY, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting/reporting binary (on/off) status. 1=on, 0=off
    	V_LIGHT					= 2,	//!< \deprecated Same as V_STATUS
    	V_PERCENTAGE			= 3,	//!< S_DIMMER. Used for sending a percentage value 0-100 (%).
    	V_DIMMER				= 3,	//!< \deprecated Same as V_PERCENTAGE
    	V_PRESSURE				= 4,	//!< S_BARO. Atmospheric Pressure
    	V_FORECAST				= 5,	//!< S_BARO. Whether forecast. string of "stable", "sunny", "cloudy", "unstable", "thunderstorm" or "unknown"
    	V_RAIN					= 6,	//!< S_RAIN. Amount of rain
    	V_RAINRATE				= 7,	//!< S_RAIN. Rate of rain
    	V_WIND					= 8,	//!< S_WIND. Wind speed
    	V_GUST					= 9,	//!< S_WIND. Gust
    	V_DIRECTION				= 10,	//!< S_WIND. Wind direction 0-360 (degrees)
    	V_UV					= 11,	//!< S_UV. UV light level
    	V_WEIGHT				= 12,	//!< S_WEIGHT. Weight(for scales etc)
    	V_DISTANCE				= 13,	//!< S_DISTANCE. Distance
    	V_IMPEDANCE				= 14,	//!< S_MULTIMETER, S_WEIGHT. Impedance value
    	V_ARMED					= 15,	//!< S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER. Armed status of a security sensor. 1 = Armed, 0 = Bypassed
    	V_TRIPPED				= 16,	//!< S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER, S_WATER_LEAK, S_SOUND, S_VIBRATION, S_MOISTURE. Tripped status of a security sensor. 1 = Tripped, 0
    	V_WATT					= 17,	//!< S_POWER, S_BINARY, S_DIMMER, S_RGB_LIGHT, S_RGBW_LIGHT. Watt value for power meters
    	V_KWH					= 18,	//!< S_POWER. Accumulated number of KWH for a power meter
    	V_SCENE_ON				= 19,	//!< S_SCENE_CONTROLLER. Turn on a scene
    	V_SCENE_OFF				= 20,	//!< S_SCENE_CONTROLLER. Turn of a scene
    	V_HVAC_FLOW_STATE		= 21,	//!< S_HEATER, S_HVAC. HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver")
    	V_HEATER				= 21,	//!< \deprecated Same as V_HVAC_FLOW_STATE
    	V_HVAC_SPEED			= 22,	//!< S_HVAC, S_HEATER. HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto")
    	V_LIGHT_LEVEL			= 23,	//!< S_LIGHT_LEVEL. Uncalibrated light level. 0-100%. Use V_LEVEL for light level in lux
    	V_VAR1					= 24,	//!< VAR1
    	V_VAR2					= 25,	//!< VAR2
    	V_VAR3					= 26,	//!< VAR3
    	V_VAR4					= 27,	//!< VAR4
    	V_VAR5					= 28,	//!< VAR5
    	V_UP					= 29,	//!< S_COVER. Window covering. Up
    	V_DOWN					= 30,	//!< S_COVER. Window covering. Down
    	V_STOP					= 31,	//!< S_COVER. Window covering. Stop
    	V_IR_SEND				= 32,	//!< S_IR. Send out an IR-command
    	V_IR_RECEIVE			= 33,	//!< S_IR. This message contains a received IR-command
    	V_FLOW					= 34,	//!< S_WATER. Flow of water (in meter)
    	V_VOLUME				= 35,	//!< S_WATER. Water volume
    	V_LOCK_STATUS			= 36,	//!< S_LOCK. Set or get lock status. 1=Locked, 0=Unlocked
    	V_LEVEL					= 37,	//!< S_DUST, S_AIR_QUALITY, S_SOUND (dB), S_VIBRATION (hz), S_LIGHT_LEVEL (lux)
    	V_VOLTAGE				= 38,	//!< S_MULTIMETER
    	V_CURRENT				= 39,	//!< S_MULTIMETER
    	V_RGB					= 40,	//!< S_RGB_LIGHT, S_COLOR_SENSOR. Sent as ASCII hex: RRGGBB (RR=red, GG=green, BB=blue component)
    	V_RGBW					= 41,	//!< S_RGBW_LIGHT. Sent as ASCII hex: RRGGBBWW (WW=white component)
    	V_ID					= 42,	//!< Used for sending in sensors hardware ids (i.e. OneWire DS1820b).
    	V_UNIT_PREFIX			= 43,	//!< Allows sensors to send in a string representing the unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch.
    	V_HVAC_SETPOINT_COOL	= 44,	//!< S_HVAC. HVAC cool setpoint (Integer between 0-100)
    	V_HVAC_SETPOINT_HEAT	= 45,	//!< S_HEATER, S_HVAC. HVAC/Heater setpoint (Integer between 0-100)
    	V_HVAC_FLOW_MODE		= 46,	//!< S_HVAC. Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn")
    	V_TEXT					= 47,	//!< S_INFO. Text message to display on LCD or controller device
    	V_CUSTOM				= 48,	//!< Custom messages used for controller/inter node specific commands, preferably using S_CUSTOM device type.
    	V_POSITION				= 49,	//!< GPS position and altitude. Payload: latitude;longitude;altitude(m). E.g. "55.722526;13.017972;18"
    	V_IR_RECORD				= 50,	//!< Record IR codes S_IR for playback
    	V_PH					= 51,	//!< S_WATER_QUALITY, water PH
    	V_ORP					= 52,	//!< S_WATER_QUALITY, water ORP : redox potential in mV
    	V_EC					= 53,	//!< S_WATER_QUALITY, water electric conductivity μS/cm (microSiemens/cm)
    	V_VAR					= 54,	//!< S_POWER, Reactive power: volt-ampere reactive (var)
    	V_VA					= 55,	//!< S_POWER, Apparent power: volt-ampere (VA)
    	V_POWER_FACTOR			= 56,	//!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1]
    } mysensors_data_t;
    #endif
    
    /// @brief Type of internal messages (for internal messages)
    typedef enum {
    	I_BATTERY_LEVEL				= 0,	//!< Battery level
    	I_TIME						= 1,	//!< Time (request/response)
    	I_VERSION					= 2,	//!< Version
    	I_ID_REQUEST				= 3,	//!< ID request
    	I_ID_RESPONSE				= 4,	//!< ID response
    	I_INCLUSION_MODE			= 5,	//!< Inclusion mode
    	I_CONFIG					= 6,	//!< Config (request/response)
    	I_FIND_PARENT_REQUEST		= 7,	//!< Find parent
    	I_FIND_PARENT_RESPONSE		= 8,	//!< Find parent response
    	I_LOG_MESSAGE				= 9,	//!< Log message
    	I_CHILDREN					= 10,	//!< Children
    	I_SKETCH_NAME				= 11,	//!< Sketch name
    	I_SKETCH_VERSION			= 12,	//!< Sketch version
    	I_REBOOT					= 13,	//!< Reboot request
    	I_GATEWAY_READY				= 14,	//!< Gateway ready
    	I_SIGNING_PRESENTATION		= 15,	//!< Provides signing related preferences (first byte is preference version)
    	I_NONCE_REQUEST				= 16,	//!< Request for a nonce
    	I_NONCE_RESPONSE			= 17,	//!< Payload is nonce data
    	I_HEARTBEAT_REQUEST			= 18,	//!< Heartbeat request
    	I_PRESENTATION				= 19,	//!< Presentation message
    	I_DISCOVER_REQUEST			= 20,	//!< Discover request
    	I_DISCOVER_RESPONSE			= 21,	//!< Discover response
    	I_HEARTBEAT_RESPONSE		= 22,	//!< Heartbeat response
    	I_LOCKED					= 23,	//!< Node is locked (reason in string-payload)
    	I_PING						= 24,	//!< Ping sent to node, payload incremental hop counter
    	I_PONG						= 25,	//!< In return to ping, sent back to sender, payload incremental hop counter
    	I_REGISTRATION_REQUEST		= 26,	//!< Register request to GW
    	I_REGISTRATION_RESPONSE		= 27,	//!< Register response from GW
    	I_DEBUG						= 28,	//!< Debug message
    	I_SIGNAL_REPORT_REQUEST		= 29,	//!< Device signal strength request
    	I_SIGNAL_REPORT_REVERSE		= 30,	//!< Internal
    	I_SIGNAL_REPORT_RESPONSE	= 31,	//!< Device signal strength response (RSSI)
    	I_PRE_SLEEP_NOTIFICATION	= 32,	//!< Message sent before node is going to sleep
    	I_POST_SLEEP_NOTIFICATION	= 33	//!< Message sent after node woke up (if enabled)
    } mysensors_internal_t;
    
    /// @brief Type of data stream (for streamed message)
    typedef enum {
    	ST_FIRMWARE_CONFIG_REQUEST	= 0,	//!< Request new FW, payload contains current FW details
    	ST_FIRMWARE_CONFIG_RESPONSE	= 1,	//!< New FW details to initiate OTA FW update
    	ST_FIRMWARE_REQUEST			= 2,	//!< Request FW block
    	ST_FIRMWARE_RESPONSE		= 3,	//!< Response FW block
    	ST_SOUND					= 4,	//!< Sound
    	ST_IMAGE					= 5,	//!< Image
    	ST_FIRMWARE_CONFIRM	= 6, //!< Mark running firmware as valid (MyOTAFirmwareUpdateNVM + mcuboot)
    	ST_FIRMWARE_RESPONSE_RLE = 7,	//!< Response FW block with run length encoded data
    } mysensors_stream_t;
    
    /// @brief Type of payload
    typedef enum {
    	P_STRING				= 0,	//!< Payload type is string
    	P_BYTE					= 1,	//!< Payload type is byte
    	P_INT16					= 2,	//!< Payload type is INT16
    	P_UINT16				= 3,	//!< Payload type is UINT16
    	P_LONG32				= 4,	//!< Payload type is INT32
    	P_ULONG32				= 5,	//!< Payload type is UINT32
    	P_CUSTOM				= 6,	//!< Payload type is binary
    	P_FLOAT32				= 7		//!< Payload type is float32
    } mysensors_payload_t;
    
    
    #ifndef BIT
    #define BIT(n)                  ( 1<<(n) ) //!< Bit indexing macro
    #endif
    #define BIT_MASK(len)           ( BIT(len)-1 ) //!< Create a bitmask of length 'len'
    #define BF_MASK(start, len)     ( BIT_MASK(len)<<(start) ) //!< Create a bitfield mask of length starting at bit 'start'
    
    #define BF_PREP(x, start, len)  ( ((x)&BIT_MASK(len)) << (start) ) //!< Prepare a bitmask for insertion or combining
    #define BF_GET(y, start, len)   ( ((y)>>(start)) & BIT_MASK(len) ) //!< Extract a bitfield of length 'len' starting at bit 'start' from 'y'
    #define BF_SET(y, x, start, len)    ( y= ((y) &~ BF_MASK(start, len)) | BF_PREP(x, start, len) ) //!< Insert a new bitfield value 'x' into 'y'
    
    // Getters/setters for special bit fields in header
    // deprecated in 3.0.0
    #define mSetVersion(_message, _version) _message.setVersion(_version) //!< \deprecated Set version field
    #define mGetVersion(_message) _message.getVersion() //!< \deprecated Get version field
    
    #define mSetSigned(_message, _signed) _message.setSigned(_signed) //!< \deprecated Set signed field
    #define mGetSigned(_message) _message.getSigned() //!< \deprecated Get signed field
    
    #define mSetLength(_message,_length) _message.setLength(_length) //!< \deprecated Set length field
    #define mGetLength(_message) _message.getLength() //!< \deprecated Get length field
    
    #define mSetCommand(_message, _command) _message.setCommand(_command) //!< \deprecated Set command field
    #define mGetCommand(_message) _message.getCommand() //!< \deprecated Get command field
    
    #define mSetRequestEcho(_message, _requestEcho) _message.setRequestEcho(_requestEcho) //!< \deprecated Set echo request field
    #define mGetRequestEcho(_message) _message.getRequestEcho() //!< \deprecated Get echo request field
    
    #define mSetEcho(_message, _echo) _message.setEcho(_echo) //!< \deprecated Set echo field
    #define mGetEcho(_message) _message.getEcho() //!< \deprecated Get echo field
    
    #define mSetPayloadType(_message, _payloadType) _message.setPayloadType(_payloadType) //!< \deprecated Set payload type field
    #define mGetPayloadType(_message) _message.getPayloadType() //!< \deprecated Get payload type field
    
    #if defined(__cplusplus) || defined(DOXYGEN)
    /**
     * @brief MyMessage is used to create, manipulate, send and read MySensors messages
     */
    class MyMessage
    {
    private:
    	char* getCustomString(char *buffer) const;
    
    public:
    
    	/**
    	 * Default constructor
    	 */
    	MyMessage(void);
    
    	/**
    	 * Constructor
    	 * @param sensorId id of the child sensor for this message
    	 * @param dataType
    	 */
    	MyMessage(const uint8_t sensorId, const mysensors_data_t dataType);
    
    	/**
    	 * @brief Clear message contents.
    	 */
    	void clear(void);
    
    	/**
    	 * If payload is something else than P_STRING you can have the payload value converted
    	 * into string representation by supplying a buffer with the minimum size of
    	 * 2 * MAX_PAYLOAD_SIZE + 1. This is to be able to fit hex-conversion of a full binary payload.
    	 * @param buffer pointer to a buffer that's at least 2 * MAX_PAYLOAD_SIZE + 1 bytes large
    	 */
    	char* getStream(char *buffer) const;
    
    	/**
    	 * @brief Copy the payload into the supplied buffer
    	 */
    	char* getString(char *buffer) const;
    
    	/**
    	 * @brief Get payload as string
    	 * @return pointer to a char array storing the string
    	 */
    	const char* getString(void) const;
    
    	/**
    	 * @brief Get custom payload
    	 * @return pointer to the raw payload
    	 */
    	void* getCustom(void) const;
    
    	/**
    	 * @brief Get bool payload
    	 * @return a bool with the value of the payload (true/false)
    	 */
    	bool getBool(void) const;
    
    	/**
    	 * @brief Get unsigned 8-bit integer payload
    	 * @return the value of the payload, 0 to 255
    	 */
    	uint8_t getByte(void) const;
    
    	/**
    	 * @brief Get float payload
    	 * @return the floating-point value of the payload
    	 */
    	float getFloat(void) const;
    
    	/**
    	 * @brief Get signed 16-bit integer payload
    	 * @return the value of the payload, –32768 to 32767
    	 */
    	int16_t getInt(void) const;
    
    	/**
    	 * @brief Get unsigned 16-bit integer payload
    	 * @return the value of the payload, 0 to 65535
    	 */
    	uint16_t getUInt(void) const;
    
    	/**
    	 * @brief Get signed 32-bit integer payload
    	 * @return the value of the payload, –2147483648 to 2147483647
    	 */
    	int32_t getLong(void) const;
    
    	/**
    	 * @brief Get unsigned 32-bit integer payload
    	 * @return the value of the payload, 0 to 4294967295
    	 */
    	uint32_t getULong(void) const;
    
    	/**
    	* @brief getHeaderSize
    	* @return the size of the header
    	*/
    	uint8_t getHeaderSize(void) const;
    
    	/**
    	* @brief getMaxPayloadSize
    	* @return the max. size of the payload
    	*/
    	uint8_t getMaxPayloadSize(void) const;
    
    	/**
    	* @brief getExpectedMessageSize
    	* @return the expected message size based on header information
    	*/
    	uint8_t getExpectedMessageSize(void) const;
    
    	/**
    	* @brief isProtocolVersionValid
    	* @return true if the protocol version is valid
    	*/
    	bool isProtocolVersionValid(void) const;
    
    	/**
    	 * @brief Getter for echo request
    	 * @return echo request
    	 */
    	bool getRequestEcho(void) const;
    
    	/**
    	 * @brief Setter for echo request
    	 * @param requestEcho
    	 */
    	MyMessage& setRequestEcho(const bool requestEcho);
    
    	/**
    	 * @brief Getter for version
    	 * @return version
    	 */
    	uint8_t getVersion(void) const;
    
    	/**
    	 * @brief Setter for version
    	 */
    	MyMessage& setVersion(void);
    
    	/**
    	* @brief Getter for length
    	* @return length
    	*/
    	uint8_t getLength(void) const;
    
    	/**
    	 * @brief Setter for length
    	 * @param length
    	 */
    	MyMessage& setLength(const uint8_t length);
    
    	/**
    	* @brief Getter for command type
    	* @return #mysensors_command_t
    	*/
    	mysensors_command_t getCommand(void) const;
    
    	/**
    	 * @brief Setter for command type
    	 * @param command
    	 */
    	MyMessage& setCommand(const mysensors_command_t command);
    
    	/**
    	* @brief Getter for payload type
    	* @return payload type
    	*/
    	mysensors_payload_t getPayloadType(void) const;
    
    	/**
    	 * @brief Setter for payload type
    	 * @param payloadType
    	 */
    	MyMessage& setPayloadType(const mysensors_payload_t payloadType);
    
    	/**
    	* @brief Getter for sign field
    	* @return sign field
    	*/
    	bool getSigned(void) const;
    
    	/**
    	 * @brief Setter for sign field
    	 * @param signedFlag
    	 */
    	MyMessage& setSigned(const bool signedFlag);
    
    	/**
    	 * \deprecated use isEcho()
    	 * @brief Getter for echo-flag.
    	 * @return true if this is an echoed message
    	 */
    	bool isAck(void) const;
    
    	/**
    	 * @brief Getter for echo-flag.
    	 * @return true if this is an echoed message
    	 */
    	bool isEcho(void) const;
    
    	/**
    	* @brief Setter for echo-flag.
    	* @param echo true if this an echo message
    	*/
    	MyMessage& setEcho(const bool echo);
    
    	/**
    	 * @brief Get message type
    	 * @return messageType
    	 */
    	uint8_t getType(void) const;
    
    	/**
    	 * @brief Set message type
    	 * @param messageType
    	 */
    	MyMessage& setType(const uint8_t messageType);
    
    	/**
    	* @brief Get last ID
    	* @return lastId
    	*/
    	uint8_t getLast(void) const;
    
    	/**
    	 * @brief Set last ID
    	 * @param lastId
    	 */
    	MyMessage& setLast(const uint8_t lastId);
    
    	/**
    	* @brief Get sender ID
    	* @return sender
    	*/
    	uint8_t getSender(void) const;
    
    	/**
    	 * @brief Set sender ID
    	 * @param senderId
    	 */
    	MyMessage& setSender(const uint8_t senderId);
    
    	/**
    	 * @brief Get sensor ID of message
    	 * @return sensorId
    	 */
    	uint8_t getSensor(void) const;
    
    	/**
    	 * @brief Set which child sensor this message belongs to
    	 * @param sensorId
    	 */
    	MyMessage& setSensor(const uint8_t sensorId);
    
    	/**
    	 * @brief Get destination
    	 * @return destinationId
    	 */
    	uint8_t getDestination(void) const;
    
    	/**
    	 * @brief Set final destination node id for this message
    	 * @param destinationId
    	 */
    	MyMessage& setDestination(const uint8_t destinationId);
    
    	/**
    	 * @brief Set entire payload
    	 * @param payload pointer to the buffer where the payload is stored
    	 * @param length of the payload
    	 */
    	MyMessage& set(const void* payload, const size_t length);
    
    	/**
    	 * @brief Set payload to character array
    	 * @param value pointer to the character array. The array must be null-terminated.
    	 */
    	MyMessage& set(const char* value);
    #if !defined(__linux__)
    	/**
    	 * @brief Set payload to character array from flash
    	 * @param value pointer to the character array. The array must be null-terminated.
    	 */
    	MyMessage& set(const __FlashStringHelper* value);
    #endif
    
    	/**
    	 * @brief Set payload to decimal number
    	 * @param value float
    	 * @param decimals number of decimals to include
    	 */
    	MyMessage& set(const float value, const uint8_t decimals);
    
    	/**
    	 * @brief Set payload to bool value
    	 * @param value true or false
    	 */
    	MyMessage& set(const bool value);
    
    	/**
    	 * @brief Set payload to unsigned 8-bit integer value
    	 * @param value (0 to 255)
    	 */
    	MyMessage& set(const uint8_t value);
    
    	/**
    	 * @brief Set payload to unsigned 32-bit integer value
    	 * @param value (0 to 4294967295)
    	 */
    	MyMessage& set(const uint32_t value);
    
    	/**
    	 * @brief Set payload to signed 32-bit integer value
    	 * @param value (–2147483648 to 2147483647)
    	 */
    	MyMessage& set(const int32_t value);
    
    	/**
    	 * @brief Set payload to unsigned 16-bit integer value
    	 * @param value (0 to 65535)
    	 */
    	MyMessage& set(const uint16_t value);
    
    	/**
    	 * @brief Set payload to signed 16-bit integer value
    	 * @param value (–32768 to 32767)
    	 */
    	MyMessage& set(const int16_t value);
    
    #else
    
    typedef union {
    	struct {
    
    #endif
    	uint8_t last;							//!< 8 bit - Id of last node this message passed
    	uint8_t sender;						//!< 8 bit - Id of sender node (origin)
    	uint8_t destination;			//!< 8 bit - Id of destination node
    
    	/**
    	 * 2 bit - Protocol version<br>
    	 * 1 bit - Signed flag<br>
    	 * 5 bit - Length of payload
    	 */
    	uint8_t version_length;
    
    	/**
    	 * 3 bit - Command type<br>
    	 * 1 bit - Request an echo - Indicator that receiver should echo the message back to the sender<br>
    	 * 1 bit - Is echo message - Indicator that this is the echoed message<br>
    	 * 3 bit - Payload data type
    	 */
    	uint8_t command_echo_payload;
    
    	uint8_t type; //!< 8 bit - Type varies depending on command
    	uint8_t sensor; //!< 8 bit - Id of sensor that this message concerns.
    
    	/*
    	 * Each message can transfer a payload. We add one extra byte for string
    	 * terminator \0 to be "printable" this is not transferred OTA
    	 * This union is used to simplify the construction of the binary data types transferred.
    	 */
    	union {
    		uint8_t bValue; //!< unsigned byte value (8-bit)
    		uint16_t uiValue; //!< unsigned integer value (16-bit)
    		int16_t iValue; //!< signed integer value (16-bit)
    		uint32_t ulValue; //!< unsigned long value (32-bit)
    		int32_t lValue; //!< signed long value (32-bit)
    		struct { //!< Float messages
    			float fValue;
    			uint8_t fPrecision; //!< Number of decimals when serializing
    		};
    		char data[MAX_PAYLOAD_SIZE + 1]; //!< Buffer for raw payload data
    	} __attribute__((packed)); //!< Doxygen will complain without this comment
    #if defined(__cplusplus) || defined(DOXYGEN)
    } __attribute__((packed));
    #else
    };
    uint8_t array[HEADER_SIZE + MAX_PAYLOAD_SIZE + 1]; //!< buffer for entire message
    } __attribute__((packed)) MyMessage;
    #endif
    
    #endif
    /** @}*/