/*
 LangloPackets.h - Langlo LoRa network packet structures
 Version 1.0.0	06/11/2019
 Version 1.0.1	23/11/2019	Reduce max packet size to 64 (payload <= 51 per LoRaWAN)
 Version 1.0.2	04/02/2020	Add Voltage packet type
 Version 1.1.0  28/03/2020  Replace all float types with int/uint
 Version 1.2.0  02/03/2021	Expand packet header structure (MACs, Sequence #, unused)
 							Add GPS packet type (using float...)
							Add VOX & Light packet types
 
 Created by Peter Harrison, November 2019
*/
 
#ifndef LangloPackets_h
#define LangloPackets_h

// Langlo LoRa packet structure

const int LGO_PacketSize = 64;
const int LGO_HeaderSize = 16;
const int LGO_PayloadSize = 48;  // LGO_PacketSize - LGO_HeaderSize

union dataPacket {
  uint8_t packetByte[LGO_PacketSize];
  struct packetContent {
    uint32_t destinationMAC;           // 4 bytes
    uint32_t sourceMAC;                // 4 bytes
    uint32_t checksum;                 // 4 bytes
    uint16_t sequenceNumber;           // 2 bytes
    uint8_t type;                      // 1 byte
    uint8_t byteCount;                 // 1 byte
    uint8_t payload[LGO_PayloadSize];  // max 48 bytes
  } content;
};

const int powerTypePacket         = 0x00;
const int voltageTypePacket		  = 0x01;
const int tankTypePacket          = 0x11;
const int pumpTypePacket          = 0x12;
const int weatherTypePacket       = 0x20;
const int atmosphereTypePacket    = 0x21;
const int temperatureTypePacket   = 0x27;
const int rainfallTypePacket      = 0x22;
const int windTypePacket          = 0x23;
const int voxTypePacket           = 0x24;
const int lightTypePacket         = 0x25;
const int uvTypePacket       	  = 0x26;
const int sprinklerTypePacket     = 0x30;
const int gpsTypePacket           = 0x40;
const int awtsTypePacket		  = 0x50;

const int powerPayloadBytes       = 0x0C;
const int voltagePayloadBytes	  = 0x02;
const int tankPayloadBytes        = 0x02;
const int pumpPayloadBytes        = 0x01;
const int weatherPayloadBytes     = 0x0B;
const int atmospherePayloadBytes  = 0x06;
const int temperaturePayloadBytes = 0x02;
const int rainfallPayloadBytes    = 0x02;
const int windPayloadBytes        = 0x04;
const int voxPayloadBytes         = 0x02;
const int lightPayloadBytes       = 0x02;
const int uvPayloadBytes          = 0x06;
const int sprinklerPayloadBytes   = 0x30;
const int gpsPayloadBytes         = 0x10;
const int awtsPayloadBytes        = 0x04;
const int defaultPayloadBytes     = 0x30;

// Power Type

union powerPayload {
  uint8_t payloadByte[12];
  struct payloadContent {
  	uint16_t voltage;
  	uint16_t current;
  } battery, panel, load;
};

// Voltage Type

union voltagePayload {
  uint8_t payloadByte[2];
  struct payloadContent {
  	uint16_t voltage;
  } source;
};

// Tank Type

union tankPayload {
  uint8_t payloadByte[2];
  struct payloadContent {
    uint16_t level;				// struct will allow flexibility to add more parameters
  } tank;
};

// Pump Type

union pumpPayload {
  uint8_t payloadByte[1];
  struct payloadContent {
    uint8_t on;					// struct will allow flexibility to add more parameters
  } power;
};

// Weather Type

union weatherPayload {
  uint8_t payloadByte[11];
  struct payloadContent {
    int16_t temperature;
    uint16_t pressure;
    uint16_t humidity;
    uint16_t rainfall;
    uint16_t windBearing;
    uint8_t windSpeed;
  } recorded;
};

// Atmosphere Type

union atmospherePayload {
  uint8_t payloadByte[6];
  struct payloadContent {
    int16_t temperature;
    uint16_t pressure;
    uint16_t humidity;
  } recorded;
};

// Temperature Type

union temperaturePayload {
  uint8_t payloadByte[2];
  struct payloadContent {
    int16_t temperature;
  } recorded;
};

// Rainfall Type

union rainfallPayload {
  uint8_t payloadByte[2];
  struct payloadContent {
    uint16_t rainfall;
  } recorded;
};

// Wind Type

union windPayload {
  uint8_t payloadByte[4];
  struct payloadContent {
    uint16_t windBearing;
    uint16_t windSpeed;
  } recorded;
};

// VOX Type

union voxPayload {
  uint8_t payloadByte[2];
  struct payloadContent {
    uint16_t voxLevel;
  } recorded;
};

// Light Type

union lightPayload {
  uint8_t payloadByte[2];
  struct payloadContent {
    uint16_t ambientLight;
  } recorded;
};

// UV Type

union uvPayload {
  uint8_t payloadByte[6];
  struct payloadContent {
    uint16_t uvA;
    uint16_t uvB;
    uint16_t uvIndex;
  } recorded;
};

// Controller Type

union controllerPayload {
	uint8_t payloadByte[LGO_PayloadSize];			// No structure defined at this time
};

// GPS Type

union gpsPayload {
  uint8_t payloadByte[16];
  struct payloadContent {
    float latitude;
    float longitude;
    float altitude;
    float hdop;
  } position;
};

// AWTS Type

union awtsPayload {
  uint8_t payloadByte[4];
  struct payloadContent {
    int16_t blowerPressure;
    uint16_t itLevel;
  } recorded;
};

// Generic Type

union genericPayload {
  uint8_t payload[LGO_PayloadSize];
  powerPayload power;
  voltagePayload voltage;
  tankPayload tank;
  pumpPayload pump;
  weatherPayload weather;
  atmospherePayload atmosphere;
  temperaturePayload temperature;
  rainfallPayload rainfall;
  windPayload wind;
  voxPayload vox;
  lightPayload light;
  uvPayload uv;
  controllerPayload controller;
  gpsPayload gps;
  awtsPayload awts;
};

#endif
