diff --git a/WeatherStation.ino b/WeatherStation.ino new file mode 100644 index 0000000..3ae4ad3 --- /dev/null +++ b/WeatherStation.ino @@ -0,0 +1,54 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hidwh1080rptparser.h" + +USB Usb; +USBHub Hub(&Usb); +HIDUniversal Hid(&Usb); + +WH1080ReportParser parser; + +void setup() +{ + Serial.begin( 9600 ); + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + if (!Hid.SetReportParser(0, &parser)) + ErrorMessage(PSTR("SetReportParser"), 1 ); +} + +void loop() +{ + Usb.Task(); + if ((Usb.getUsbTaskState() == USB_STATE_RUNNING) && parser.startDelay && (parser.startDelay <= millis())) { + int rcode = Hid.SetReport(0, 0, 0x02, 0x01, sizeof(parser.report), parser.report); + if (rcode != 0) { + Serial.print("Rcode = "); + Serial.println(rcode, HEX); + } + parser.startDelay = 0; + } +} + diff --git a/hidwh1080rptparser.cpp b/hidwh1080rptparser.cpp new file mode 100644 index 0000000..d87ec50 --- /dev/null +++ b/hidwh1080rptparser.cpp @@ -0,0 +1,58 @@ +#include "hidwh1080rptparser.h" + +void WH1080ReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) +{ + // See http://www.jim-easterbrook.me.uk/weather/mm/ + if ((chunkStart + len) >= WH1080_BUFFER_CHUNK) { + memcpy(chunk + chunkStart, buf, WH1080_BUFFER_CHUNK - chunkStart); + chunkStart = 0; + if (readingBlockZero) { + unsigned short currentPos = chunk[WH1080_CURRENT_POS] + (chunk[WH1080_CURRENT_POS + 1] << 8); + report[1] = (uint8_t)(currentPos / 256); + report[2] = (uint8_t)(currentPos & 255); + report[5] = (uint8_t)(currentPos / 256); + report[6] = (uint8_t)(currentPos & 255); + readingBlockZero = false; + startDelay = millis() + 250; + } else { + if (memcmp(chunk, lastChunk, WH1080_BUFFER_CHUNK) != 0) { + memcpy(lastChunk, chunk, WH1080_BUFFER_CHUNK); + Serial.print("Time since last change: "); + Serial.println(millis() - lastMillis); + lastMillis = millis(); + Serial.print("Delay: "); + Serial.println(chunk[0]); + Serial.print("Indoor humidity: "); + Serial.println(chunk[1]); + Serial.print("Indoor temperature: "); + Serial.println((((chunk[3] & 0x7f) << 8) + chunk[2]) * ((chunk[3] & 0x80) ? -0.1 : 0.1)); + Serial.print("Outdoor humidity: "); + Serial.println(chunk[4]); + Serial.print("Outdoor temperature: "); + Serial.println((((chunk[6] & 0x7f) << 8) + chunk[5]) * ((chunk[6] & 0x80) ? -0.1 : 0.1)); + Serial.print("Absolute pressure: "); + Serial.println(((chunk[8] << 8) + chunk[7]) * 0.1); + Serial.print("Average wind speed: "); + Serial.println((chunk[9] + ((chunk[11] & 0x0f) << 8)) * 0.1); + Serial.print("Gust wind speed: "); + Serial.println((chunk[10] + ((chunk[11] & 0xf0) << 4)) * 0.1); + Serial.print("Wind direction: "); + Serial.println(chunk[12] * 22.5); + Serial.print("Total rain: "); + Serial.println(((chunk[14] << 8) + chunk[13]) * 0.3); + Serial.print("Status: "); + Serial.println(chunk[15], HEX); + } + readingBlockZero = true; + report[1] = 0; + report[2] = 0; + report[5] = 0; + report[6] = 0; + startDelay = millis() + 5000; + } + } else { + memcpy(chunk + chunkStart, buf, len); + chunkStart += len; + } +} + diff --git a/hidwh1080rptparser.h b/hidwh1080rptparser.h new file mode 100644 index 0000000..4732cba --- /dev/null +++ b/hidwh1080rptparser.h @@ -0,0 +1,83 @@ +#if !defined(__HIDWH1080RPTPARSER_H__) +#define __HIDWH1080RPTPARSER_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" +#include "confdescparser.h" +#include "hid.h" + +// Following taken from wview-5.20.2 +// +// Define the rain rate acuumulator period (minutes): +#define WH1080_RAIN_RATE_PERIOD 5 + +// Weather Station buffer parameters: +#define WH1080_RAIN_MAX 0x10000 // Wrap value for rain counter +#define WH1080_BUFFER_START 0x100 // Size of fixed block + // start of buffer records +#define WH1080_BUFFER_CHUNK 0x20 // Size of chunk received over USB +// Weather Station record memory positions: +#define WH1080_DELAY 0 // Position of delay parameter +#define WH1080_HUMIDITY_IN 1 // Position of inside humidity parameter +#define WH1080_TEMPERATURE_IN 2 // Position of inside temperature parameter +#define WH1080_HUMIDITY_OUT 4 // Position of outside humidity parameter +#define WH1080_TEMPERATURE_OUT 5 // Position of outside temperature parameter +#define WH1080_ABS_PRESSURE 7 // Position of absolute pressure parameter +#define WH1080_WIND_AVE 9 // Position of wind direction parameter +#define WH1080_WIND_GUST 10 // Position of wind direction parameter +#define WH1080_WIND_DIR 12 // Position of wind direction parameter +#define WH1080_RAIN 13 // Position of rain parameter +#define WH1080_STATUS 15 // Position of status parameter + +// Control block offsets: +#define WH1080_SAMPLING_INTERVAL 16 // Position of sampling interval +#define WH1080_DATA_COUNT 27 // Position of data_count parameter +#define WH1080_CURRENT_POS 30 // Position of current_pos parameter + +const prog_char WH1080_REPORT[] PROGMEM = { + 0xa1, 0x00, 0x00, 0x20, 0xa1, 0x00, 0x00, 0x20 +}; + +class WH1080ReportParser : public HIDReportParser +{ + uint8_t chunk[WH1080_BUFFER_CHUNK], lastChunk[WH1080_BUFFER_CHUNK]; + uint8_t chunkStart; + bool readingBlockZero; + unsigned short currentPos; + unsigned long lastMillis; + +public: + + unsigned long startDelay; + uint8_t report[8]; + + WH1080ReportParser() { + chunkStart = 0; + readingBlockZero = true; + for (uint8_t i = 0; i < sizeof(WH1080_REPORT); i++) { + report[i] = pgm_read_byte(&WH1080_REPORT[i]); + } + memset(lastChunk, 0, WH1080_BUFFER_CHUNK); + lastMillis = millis(); + startDelay = 1000 + millis(); + } + + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); +}; + +#endif // __HIDWH1080RPTPARSER_H__