/***********************************************************************
 *
 * Copyrigth: Karl Hammar, Aspö Data, LGPL
 *
 */

#ifndef __DAVIS_VANTAGE_H__
#define __DAVIS_VANTAGE_H__

#include <aspoutil.h>
#include <stdint.h>

/*
  the protocol used by Davis inc. in their procducts like the weather
  stations Vantag Pro, as defined in:

  http://www.davisnet.com/support/weather/download/VantageSerialProtocolDocs_v230.pdf
  page references are to that document
 */

/******************************
 * I Introdution, p. 4
 */

#define DAVIS_DEF_BAUDRATE 19200
uint16_t davis_value_u16(uint8_t *buf);

/******************************
 * VI. Command formats, p. 6

 1, ACK response: '\006' + data, alt. '\030' + data
WRD LOOP HILOWS PUTRAIN PUTET GETEE EEBRD EEBWR CALED CALFIX BAR
CLRLOG CLRVAR CLRHIGHS CLRLOWS CLRBITS CLRDATA SETTIME GETTIME SETPER
NEWSETUP

 2, OK response: "\n\rOK\n\r" + data, (thoose marked with (?) have examples with only "OK\n\r"-response)
RXCHECK STRMON STRMOFF VER RECEIVERS NVER EERD (?) EEWR BARDATA
BAUD GAIN LAMPS

 3, DONE response: OK resp. followed after some time by "DONE\n\r", p. 16-17
CLRALM CLRCAL (?) CLRGRA 

 4, Not specified, p. 19
STOP START 

 5. as specified in X. Download Protocol, p. 52
DMP DMPAFT
*/

#define DAVIS_OK_RESPONSE(buf) (!memcmp("\n\rOK\n\r",buf,6))
#define DAVIS_OK_DATA 6 /* where data in response packet starts */

/* check that it is a OK-respone, remove the OK, trailing [\r\n], */
/* and add an '\0' so buf behaves like a c-string */
/* returns new length or -1 for error */
int davis_ok_cleanup(uint8_t *buf, size_t len);

/******************************
 * VIII. Command Details, p8-20

  WRD response data, p. 9
 */

extern const struct intstr * const davis_station_type;
extern const size_t davis_station_type_sz;

/******************************
 * IX. Data Formats

 1. LOOP data format, p. 20-23
    name, offset // element_size_in_bytes x how_many_of_thoose
    my offset is with initial ACK, i.e. +1 compared to the one in the table
*/

#define DAVIS_MAGIC                 0 /* 1 x 4 */
#define DAVIS_BAR_TREND             4 /* 1 */
#define DAVIS_PACKET_TYPE           5 /* 1 */
#define DAVIS_NEXT_RECORD           6 /* 2 */
#define DAVIS_BAROMETER             8 /* 2 */
#define DAVIS_INSIDE_TEMPERATURE   10 /* 2 */
#define DAVIS_INSIDE_HUMIDITY      12 /* 1 */
#define DAVIS_OUTSIDE_TEMPERATURE  13 /* 2 */
#define DAVIS_WIND_SPEED           15 /* 1 */
#define DAVIS_AVG_WIND_SPEED       16 /* 1 */
#define DAVIS_WIND_DIRECTION       17 /* 2 */
#define DAVIS_EXTRA_TEMPERATURE    19 /* 1 x 7 */
#define DAVIS_SOIL_TEMPERATURE     26 /* 1 x 4 */
#define DAVIS_LEAF_TEMPERATURE     30 /* 1 x 4 */
#define DAVIS_OUTSIDE_HUMIDITY     34 /* 1 */
#define DAVIS_EXTRA_HUMIDITY       35 /* 1 x 7 */
#define DAVIS_RAIN_RATE            42 /* 2 */
#define DAVIS_UV                   44 /* 1 */
#define DAVIS_SOLAR_RADIATION      45 /* 2 */
#define DAVIS_STORM_RAIN           47 /* 2 */
#define DAVIS_START_DATE_STORM     49 /* 2 */
#define DAVIS_DAY_RAIN             51 /* 2 */
#define DAVIS_MONTH_RAIN           53 /* 2 */
#define DAVIS_YEAR_RAIN            55 /* 2 */
#define DAVIS_DAY_ET               57 /* 2 */
#define DAVIS_MONTH_ET             59 /* 2 */
#define DAVIS_YEAR_ET              61 /* 2 */
#define DAVIS_SOIL_MOISTURE        63 /* 1 x 4 */
#define DAVIS_LEAF_WETNESS         67 /* 1 x 4 */
#define DAVIS_INSIDE_ALARM         71 /* 1 */
#define DAVIS_RAIN_ALARM           72 /* 1 */
#define DAVIS_OUTSIDE_ALARM        73 /* 2 */
#define DAVIS_EXTRA_TEMP_HUM_ALARM 75 /* 1 x 8 */
#define DAVIS_SOIL_LEAF_ALARM      83 /* 1 x 4 */
#define DAVIS_TRANSMITTER_BATTERY_STATUS 87 /* 1 */
#define DAVIS_CONSOLE_BATTERY_VOLTAGE 88 /* 2 */
#define DAVIS_FORECAST_ICON        90 /* 1 */
#define DAVIS_FORECAST_RULE_NUMBER 91 /* 1 */
#define DAVIS_TIME_SUNRISE         92 /* 2 */
#define DAVIS_TIME_SUNSET          94 /* 2 */
#define DAVIS_LFCR                 96 /* 1 x 2 */
#define DAVIS_CRC                  98 /* 2 */

/* arr of chars ended with NULL, long and short names */
extern const char *davis_loop_headers[];
extern const char *davis_loop_hdr[];

struct davis_loop_decoded {
  /* I've sorted theese to get uint16_t's first */
  uint16_t barometer;
  uint16_t inside_temperature;
  uint16_t outside_temperature;
  uint16_t wind_direction;
  uint16_t rain_rate;
  uint16_t solar_radiation;
  uint16_t storm_rain;
  /*
  uint16_t start_date_storm;
  uint16_t day_rain;
  uint16_t month_rain;
  uint16_t year_rain;
  uint16_t day_et;
  uint16_t month_et;
  uint16_t year_et;
  uint16_t outside_alarm;
  */
  uint16_t console_battery_voltage;
  /*
  uint16_t time_sunrise;
  uint16_t time_sunset;
  */

  uint8_t inside_humidity;
  uint8_t wind_speed;
  uint8_t extra_temperature[7];
  uint8_t soil_temperature[4];
  uint8_t leaf_temperature[4];
  uint8_t outside_humidity;
  uint8_t extra_humidity[7];
  uint8_t uv;
  uint8_t soil_moisture[4];
  uint8_t leaf_wetness[4];
  /*
  uint8_t inside_alarm;
  uint8_t rain_alarm;
  uint8_t extra_temp_hum_alarm[8];
  uint8_t soil_leaf_alarm[4];
  */
  uint8_t transmitter_battery_status;
  /*
  uint8_t forecast_icon;
  uint8_t forecast_rule_number;
  */
};

int davis_loop_cnv(uint8_t *buf, struct davis_loop_decoded *pkt);
int davis_loop_pr_hdr(void);
int davis_loop_pr_cnv(struct davis_loop_decoded *pkt);

/******************************
 * XI. CRC calculation, p. 32-34
 */

extern const uint16_t * const davis_crc_table;
extern const int davis_crc_table_sz;
uint16_t davis_crc(uint8_t data, uint16_t crc);
int davis_crc_buf(uint8_t *buf, size_t len);

#endif
