Newer
Older
weather_station / hidwh1080rptparser.cpp
#include "hidwh1080rptparser.h"

WH1080ReportParser::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();
}

void WH1080ReportParser::SetReadingBlock(uint8_t high, uint8_t low) {
  report[1] = high;
  report[2] = low;
  report[5] = high;
  report[6] = low;
  readingBlockZero = false;
  chunkStart = 0;
}

void WH1080ReportParser::SetReadingZero() {
  report[1] = 0;
  report[2] = 0;
  report[5] = 0;
  report[6] = 0;
  readingBlockZero = true;
  chunkStart = 0;
}

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) {
      SetReadingBlock(chunk[WH1080_CURRENT_POS + 1], chunk[WH1080_CURRENT_POS]);
      startDelay = millis() + 250;
    } else {
      if (memcmp(chunk, lastChunk, WH1080_BUFFER_CHUNK) != 0) {
        memcpy(lastChunk, chunk, WH1080_BUFFER_CHUNK);
        // wake up XBee
/*        digitalWrite(2, LOW);
        delay(1000); */
        Serial.print("{\"period\":");
        Serial.print(millis() - lastMillis);
        lastMillis = millis();
        Serial.print(",\"delay\":");
        Serial.print(chunk[WH1080_DELAY]);
        if (chunk[WH1080_HUMIDITY_IN] != 0xFF) {
          Serial.print(",\"in_humidity\":");
          Serial.print(chunk[WH1080_HUMIDITY_IN]);
        }
        if (!((chunk[WH1080_TEMPERATURE_IN] == 0xFF) && (chunk[WH1080_TEMPERATURE_IN + 1] == 0xFF))) {
          Serial.print(",\"in_temp\":");
          Serial.print((((chunk[WH1080_TEMPERATURE_IN+1] & 0x7f) << 8) + chunk[WH1080_TEMPERATURE_IN]) * ((chunk[WH1080_TEMPERATURE_IN+1] & 0x80) ? -0.1 : 0.1));
        }
        if (chunk[WH1080_HUMIDITY_OUT] != 0xFF) {
          Serial.print(",\"out_humidity\":");
          Serial.print(chunk[WH1080_HUMIDITY_OUT]);
        }
        if (!((chunk[WH1080_TEMPERATURE_OUT] == 0xFF) && (chunk[WH1080_TEMPERATURE_OUT + 1] == 0xFF))) {
          Serial.print(",\"out_temp\":");
          Serial.print((((chunk[WH1080_TEMPERATURE_OUT+1] & 0x7f) << 8) + chunk[WH1080_TEMPERATURE_OUT]) * ((chunk[WH1080_TEMPERATURE_OUT+1] & 0x80) ? -0.1 : 0.1));
        }
        if (!((chunk[WH1080_ABS_PRESSURE] == 0xFF) && (chunk[WH1080_ABS_PRESSURE + 1] == 0xFF))) {
          Serial.print(",\"pressure\":");
          Serial.print(((chunk[WH1080_ABS_PRESSURE+1] << 8) + chunk[WH1080_ABS_PRESSURE]) * 0.1);
        }
        if (!((chunk[WH1080_WIND_AVE] == 0xFF) && ((chunk[WH1080_WIND_GUST + 1] & 0x0F) == 0x0F))) {
          Serial.print(",\"wind_speed\":");
          Serial.print((chunk[WH1080_WIND_AVE] + ((chunk[WH1080_WIND_GUST+1] & 0x0f) << 8)) * 0.1);
        }
        if (!((chunk[WH1080_WIND_GUST] == 0xFF) && ((chunk[WH1080_WIND_GUST + 1] & 0xF0) == 0xF0))) {
          Serial.print(",\"wind_gust\":");
          Serial.print((chunk[WH1080_WIND_GUST] + ((chunk[WH1080_WIND_GUST+1] & 0xf0) << 4)) * 0.1);
        }
        if (chunk[WH1080_WIND_DIR] != 0xFF) {
          Serial.print(",\"wind_dir\":");
          Serial.print(chunk[WH1080_WIND_DIR] * 22.5);
        }
        if (!((chunk[WH1080_RAIN] == 0xFF) && (chunk[WH1080_RAIN + 1] == 0xFF))) {
          Serial.print(",\"rain\":");
          Serial.print(((chunk[WH1080_RAIN+1] << 8) + chunk[WH1080_RAIN]) * 0.3); // TODO: check overflow bit
        }
        Serial.print(",\"status\":");
        Serial.print(chunk[WH1080_STATUS]);
        Serial.println("}");
/*        delay(5000);
        digitalWrite(2, HIGH); // put XBee to sleep */
      }
      SetReadingZero();
      startDelay = millis() + 5000;
    }
  } else {
    memcpy(chunk + chunkStart, buf, len);
    chunkStart += len;
  }
}