Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Proof-of-concept for establishing design bassis for an extremely compact
- * data transfer protocol for wireless data transmission
- *
- * The idea is to have a protocol that is flexible in that arbitrary data types
- * can be passed without the wasted space that would be caused by a struct-based
- * approach that would need to reserve more space than required for a given message
- *
- * This example uses a byte for each data point to determine its type. This seems
- * wasteful to use up a full extra byte for each data type, however, as seen with
- * Node 5 in the example below, the end goal is to have abstract types associated
- * with sensor data. Thus we have a type-space of 255 possible sensor types which
- * will carry semantic weight as well as deeper indication of how to parse out the
- * subsequent bytes
- *
- * The general messaging format will look like:
- *
- * NODE_ID MSG_ID MSG_COUNT DATA_TYPE DATA DATA_TYPE DATA ... etc
- *
- * e.g. Air quality sample data point #100 from node 3 might look like:
- *
- * 3 100 1 AIR_QUALITY 20 1234567
- *
- * where AIR_QAULITY is a constant in the type space, 20 is some meaningful value
- * for the specified type and 1234567 is a bogus timestamp. The protocol would
- * know to parse out the IDs, and the number of records, and then parse the
- * remainder of the message according to the type and data of each record
- *
- * Or another example which does not require a timestamp:
- *
- * 3 101 BATTERY_LEVEL 39
- *
- * Where the BATTERY_LEVEL data type is protocol-determined to be divided by 10
- *
- * In reality, there will be multiple nodes each with multiple data points. So,
- * for example:
- *
- * 2 1 3 BAT 39 GPS 3 42.04507 -87.68770 DUST 20 12345 3 1 1 BAT 42
- *
- * Is a messages containing Node 2 data message #1, with battery, GPS, and
- * air quality records (with the latter having a timestamp) and Node 3 having
- * only a battery value to deliver
- *
- * The following example does some sanity checking on standard numerica data
- * types, then includes a sensor node data set for Node 5
- *
- **/
- #include <stdio.h>
- #include <stdlib.h>
- #define CHAR 1
- #define INT8 2
- #define UINT8 3
- #define INT16 4
- #define UINT16 5
- #define BATTERY 6
- #define GPS 7
- #define AIR_PARTICULATE 8
- /** Utilities for traversing the byte message */
- uint8_t next_8_bit(uint8_t* data, int len, int* index, uint8_t* val)
- {
- *val = data[*index];
- *index += 1;
- if (*index > len) {
- printf("\nBAD BYTE SEQUENCE\n");
- return 0;
- }
- return 1;
- }
- uint8_t next_16_bit(uint8_t* data, int len, int* index, uint16_t* val)
- {
- if (*index > len-2) {
- printf("\nBAD BYTE SEQUENCE: Not enough data for 16-bit value\n");
- return 0;
- }
- *val = (data[*index] << 8) | (data[*index+1] & 0xff);
- *index += 2;
- return 1;
- }
- uint8_t next_32_bit(uint8_t* data, int len, int* index, uint32_t* val)
- {
- if (*index > len-4) {
- printf("\nBAD BYTE SEQUENCE: Not enough data for 32-bit value\n");
- return 0;
- }
- *val = (data[*index] << 24)
- | (data[*index+1] << 16)
- | (data[*index+2] << 8)
- | (data[*index+3] & 0xff);
- *index += 4;
- return 1;
- }
- void printval8(uint8_t val, uint8_t data_type)
- {
- if (data_type == CHAR) {
- printf("%c ", (char)val);
- } else if (data_type == INT8) {
- printf("%d ", (int8_t)val);
- } else if (data_type == UINT8) {
- printf("%d ", val);
- }
- }
- void printval16(uint16_t val, uint8_t data_type)
- {
- if (data_type == INT16) {
- printf("%d ", (int16_t)val);
- } else if (data_type == UINT16) {
- printf("%d ", val);
- }
- }
- /**
- * Floating points are not supported. Instead, types will be protocol defined
- * to divide by a power of 10 according to required precision for that specific
- * data type
- */
- /**
- * This example byte sequence will result in human-readable print of:
- *
- * NODE ID: 3; MSG ID: 1; MSG COUNT: 8; MESSAGES:
- * ! ~ A Z a z 0 255
- *
- * NODE ID: 4; MSG ID: 1; MSG COUNT: 7; MESSAGES:
- * -128 127 65535 0 32767 -32768 0
- *
- * NODE ID: 5; MSG ID: 1; MSG COUNT: 3; MESSAGES:
- * BAT: 3.9; SATS: 3; LAT: 42.04507; LON: -87.68770; DUST: 20; TIMESTAMP: 12345;
- *
- **/
- int main(int argc, char** argv)
- {
- int32_t latitude = 4204507;
- int32_t longitude = -8768770;
- uint8_t example[] = {
- // Node 3, some 8-bit testing
- 3, 1, 8,
- CHAR, '!',
- CHAR, '~',
- CHAR, 'A',
- CHAR, 'Z',
- CHAR, 'a',
- CHAR, 'z',
- UINT8, 0,
- UINT8, 255,
- // Node 4, 8 and 16-bit testing
- 4, 1, 7,
- INT8, -128,
- INT8, 127,
- UINT16, 65535 >> 8, 65535 & 0xff,
- UINT16, 0 >> 8, 0 & 0xff,
- INT16, 32767 >> 8, 32767 & 0xff,
- INT16, -32768 >> 8, -32768 & 0xff,
- INT16, 0 >> 8, 0 & 0xff,
- // Node 5 starts to look like real sensor data
- 5, 1, 3,
- BATTERY, 39,
- GPS, 3,
- latitude >> 24, latitude >> 16,
- latitude >> 8, latitude & 0xff,
- longitude >> 24, longitude >> 16,
- longitude >> 8, longitude & 0xff,
- AIR_PARTICULATE, 20, 12345 >> 8, 12345 & 0xff
- };
- int len = sizeof(example);
- uint8_t node_id;
- uint8_t msg_id;
- uint8_t record_count;
- uint8_t data_type;
- uint8_t val8;
- uint16_t val16;
- uint32_t val32;
- for (int i=0; i+4<sizeof(example);) { // min 5 bytes for a node message
- node_id = example[i++];
- msg_id = example[i++];
- record_count = example[i++];
- printf("NODE ID: %d; MSG ID: %d; MSG COUNT: %d; MESSAGES:\n",
- node_id, msg_id, record_count);
- for (int j=0; j<record_count; j++) {
- data_type = example[i++];
- switch(data_type) {
- /* 8-bit type testing */
- case CHAR :
- case INT8 :
- case UINT8 :
- if (!next_8_bit(example, len, &i, &val8)) break;
- printval8(val8, data_type);
- break;
- /* 16-bit type testing */
- case INT16 :
- case UINT16 :
- if (!next_16_bit(example, len, &i, &val16)) break;
- printval16(val16, data_type);
- break;
- /* abstract types */
- case BATTERY :
- if (!next_8_bit(example, len, &i, &val8)) break;
- printf("BAT: %2.1f; ", val8 / 10.0);
- break;
- case GPS :
- if (!next_8_bit(example, len, &i, &val8)) break;
- printf("SATS: %d; ", val8);
- if (!next_32_bit(example, len, &i, &val32)) break;
- printf("LAT: %8.5f; ", (int32_t)val32 / 100000.0);
- if (!next_32_bit(example, len, &i, &val32)) break;
- printf("LON: %8.5f; ", (int32_t)val32 / 100000.0);
- break;
- case AIR_PARTICULATE :
- if (!next_8_bit(example, len, &i, &val8)) break;
- printf("DUST: %d; ", val8);
- if (!next_16_bit(example, len, &i, &val16)) break;
- printf("TIMESTAMP: %d; ", val16);
- break;
- }
- }
- printf("\n\n");
- }
- }
Add Comment
Please, Sign In to add comment