void C1Wire::ReportTemperatureHumidity(const std::string& deviceId, const float temperature, const float humidity) { if ((temperature == -1000.0) || (humidity == -1000.0)) return; unsigned char deviceIdByteArray[DEVICE_ID_SIZE]={0}; DeviceIdToByteArray(deviceId,deviceIdByteArray); uint16_t NodeID = (deviceIdByteArray[0] << 8) | deviceIdByteArray[1]; SendTempHumSensor(NodeID, 255, temperature, round(humidity), "TempHum"); }
bool CDavisLoggerSerial::HandleLoopData(const unsigned char *data, size_t len) { const uint8_t *pData=data+1; #ifndef DEBUG_DAVIS if (len!=100) return false; if ( (data[1]!='L')|| (data[2]!='O')|| (data[3]!='O')|| (data[96]!=0x0a)|| (data[97]!=0x0d) ) return false; //bool bIsRevA = (data[4]=='P'); #else // FILE *fOut=fopen("davisrob.bin","wb+"); // fwrite(data,1,len,fOut); // fclose(fOut); unsigned char szBuffer[200]; FILE *fIn=fopen("E:\\davis2.bin","rb+"); //FILE *fIn=fopen("davisrob.bin","rb+"); fread(&szBuffer,1,100,fIn); fclose(fIn); pData=szBuffer+1; bool bIsRevA(szBuffer[4]=='P'); #endif RBUF tsen; memset(&tsen,0,sizeof(RBUF)); unsigned char tempIdx=1; bool bBaroValid=false; float BaroMeter=0; bool bInsideTemperatureValid=false; float InsideTemperature=0; bool bInsideHumidityValid=false; int InsideHumidity=0; bool bOutsideTemperatureValid=false; float OutsideTemperature=0; bool bOutsideHumidityValid=false; int OutsideHumidity=0; bool bWindDirectionValid=false; int WindDirection=0; bool bWindSpeedValid=false; float WindSpeed=0; bool bWindSpeedAVR10Valid=false; float WindSpeedAVR10=0; bool bUVValid=false; float UV=0; //Barometer if ((pData[7]!=0xFF)&&(pData[8]!=0xFF)) { bBaroValid=true; BaroMeter=((unsigned int)((pData[8] << 8) | pData[7])) / 29.53f; //in hPa } //Inside Temperature if ((pData[9]!=0xFF)||(pData[10]!=0x7F)) { bInsideTemperatureValid=true; InsideTemperature=((unsigned int)((pData[10] << 8) | pData[9])) / 10.f; InsideTemperature = (InsideTemperature - 32.0f) * 5.0f / 9.0f; } //Inside Humidity if (pData[11]!=0xFF) { InsideHumidity=pData[11]; if (InsideHumidity<101) bInsideHumidityValid=true; } if (bBaroValid&&bInsideTemperatureValid&&bInsideHumidityValid) { uint8_t forecastitem = pData[89]; int forecast = 0; if ((forecastitem & 0x01) == 0x01) forecast = wsbaroforcast_rain; else if ((forecastitem & 0x02) == 0x02) forecast = wsbaroforcast_cloudy; else if ((forecastitem & 0x04) == 0x04) forecast = wsbaroforcast_some_clouds; else if ((forecastitem & 0x08) == 0x08) forecast = wsbaroforcast_sunny; else if ((forecastitem & 0x10) == 0x10) forecast = wsbaroforcast_snow; SendTempHumBaroSensorFloat(tempIdx++, 255, InsideTemperature, InsideHumidity, BaroMeter, forecast, "THB"); } //Outside Temperature if ((pData[12]!=0xFF)||(pData[13]!=0x7F)) { bOutsideTemperatureValid=true; OutsideTemperature=((unsigned int)((pData[13] << 8) | pData[12])) / 10.f; OutsideTemperature = (OutsideTemperature - 32.0f) * 5.0f / 9.0f; } //Outside Humidity if (pData[33]!=0xFF) { OutsideHumidity=pData[33]; if (OutsideHumidity<101) bOutsideHumidityValid=true; } if (bOutsideTemperatureValid||bOutsideHumidityValid) { if ((bOutsideTemperatureValid)&&(bOutsideHumidityValid)) { //Temp+hum SendTempHumSensor(tempIdx++, 255, OutsideTemperature, OutsideHumidity,"Outside TempHum"); } else if (bOutsideTemperatureValid) { //Temp SendTempSensor(tempIdx++, 255, OutsideTemperature, "Outside Temp"); } else if (bOutsideHumidityValid) { //hum SendHumiditySensor(tempIdx++, 255, OutsideHumidity, "Outside Humidity"); } } tempIdx=10; //Add Extra Temp/Hum Sensors int iTmp; for (int iTmp=0; iTmp<7; iTmp++) { bool bTempValid=false; bool bHumValid=false; float temp=0; uint8_t hum=0; if (pData[18+iTmp]!=0xFF) { bTempValid=true; temp=pData[18+iTmp]-90.0f; temp = (temp - 32.0f) * 5.0f / 9.0f; } if (pData[34+iTmp]!=0xFF) { bHumValid=true; hum=pData[34+iTmp]; } if ((bTempValid)&&(bHumValid)) { //Temp+hum SendTempHumSensor(tempIdx++, 255, temp, hum, "Extra TempHum"); } else if (bTempValid) { //Temp SendTempSensor(tempIdx++, 255, temp, "Extra Temp"); } else if (bHumValid) { //hum SendHumiditySensor(tempIdx++, 255, hum, "Extra Humidity"); } } tempIdx=20; //Add Extra Soil Temp Sensors for (iTmp=0; iTmp<4; iTmp++) { bool bTempValid=false; float temp=0; if (pData[25+iTmp]!=0xFF) { bTempValid=true; temp=pData[25+iTmp]-90.0f; temp = (temp - 32.0f) * 5.0f / 9.0f; } if (bTempValid) { SendTempSensor(tempIdx++, 255, temp, "Soil Temp"); } } tempIdx=30; //Add Extra Leaf Temp Sensors for (iTmp=0; iTmp<4; iTmp++) { bool bTempValid=false; float temp=0; if (pData[29+iTmp]!=0xFF) { bTempValid=true; temp=pData[29+iTmp]-90.0f; temp = (temp - 32.0f) * 5.0f / 9.0f; } if (bTempValid) { SendTempSensor(tempIdx++, 255, temp, "Leaf Temp"); } } //Wind Speed if (pData[14]!=0xFF) { bWindSpeedValid=true; WindSpeed=(pData[14])*(4.0f/9.0f); } //Wind Speed AVR 10 minutes if (pData[15]!=0xFF) { bWindSpeedAVR10Valid=true; WindSpeedAVR10=(pData[15])*(4.0f/9.0f); } //Wind Direction if ((pData[16]!=0xFF)&&(pData[17]!=0x7F)) { bWindDirectionValid=true; WindDirection=((unsigned int)((pData[17] << 8) | pData[16])); } if ((bWindSpeedValid)&&(bWindDirectionValid)) { memset(&tsen,0,sizeof(RBUF)); tsen.WIND.packetlength=sizeof(tsen.WIND)-1; tsen.WIND.packettype=pTypeWIND; tsen.WIND.subtype=sTypeWINDNoTemp; tsen.WIND.battery_level=9; tsen.WIND.rssi=12; tsen.WIND.id1=0; tsen.WIND.id2=1; int aw=round(WindDirection); tsen.WIND.directionh=(BYTE)(aw/256); aw-=(tsen.WIND.directionh*256); tsen.WIND.directionl=(BYTE)(aw); tsen.WIND.av_speedh=0; tsen.WIND.av_speedl=0; int sw=round(WindSpeed*10.0f); tsen.WIND.av_speedh=(BYTE)(sw/256); sw-=(tsen.WIND.av_speedh*256); tsen.WIND.av_speedl=(BYTE)(sw); tsen.WIND.gusth=0; tsen.WIND.gustl=0; //this is not correct, why no wind temperature? and only chill? tsen.WIND.chillh=0; tsen.WIND.chilll=0; tsen.WIND.temperatureh=0; tsen.WIND.temperaturel=0; if (bOutsideTemperatureValid) { tsen.WIND.tempsign=(OutsideTemperature>=0)?0:1; tsen.WIND.chillsign=(OutsideTemperature>=0)?0:1; int at10=round(abs(OutsideTemperature*10.0f)); tsen.WIND.temperatureh=(BYTE)(at10/256); tsen.WIND.chillh=(BYTE)(at10/256); at10-=(tsen.WIND.chillh*256); tsen.WIND.temperaturel=(BYTE)(at10); tsen.WIND.chilll=(BYTE)(at10); } sDecodeRXMessage(this, (const unsigned char *)&tsen.WIND, NULL, 255); } //UV if (pData[43]!=0xFF) { UV=(pData[43])/10.0f; if (UV<100) bUVValid=true; } if (bUVValid) { RBUF tsen; memset(&tsen,0,sizeof(RBUF)); tsen.UV.packetlength=sizeof(tsen.UV)-1; tsen.UV.packettype=pTypeUV; tsen.UV.subtype=sTypeUV1; tsen.UV.battery_level=9; tsen.UV.rssi=12; tsen.UV.id1=0; tsen.UV.id2=1; tsen.UV.uv=(BYTE)round(UV*10); sDecodeRXMessage(this, (const unsigned char *)&tsen.UV, NULL, 255); } //Rain Rate if ((pData[41]!=0xFF)&&(pData[42]!=0xFF)) { float rainRate=((unsigned int)((pData[42] << 8) | pData[41])) / 100.0f; //inches rainRate*=25.4f; //mm } //Rain Day if ((pData[50]!=0xFF)&&(pData[51]!=0xFF)) { float rainDay=((unsigned int)((pData[51] << 8) | pData[50])) / 100.0f; //inches rainDay*=25.4f; //mm } //Rain Year if ((pData[54]!=0xFF)&&(pData[55]!=0xFF)) { float rainYear=((unsigned int)((pData[55] << 8) | pData[54])) / 100.0f; //inches rainYear*=25.4f; //mm SendRainSensor(1, 255, rainYear, "Rain"); } //Solar Radiation if ((pData[44]!=0xFF)&&(pData[45]!=0x7F)) { unsigned int solarRadiation=((unsigned int)((pData[45] << 8) | pData[44]));//Watt/M2 _tGeneralDevice gdevice; gdevice.subtype=sTypeSolarRadiation; gdevice.floatval1=float(solarRadiation); sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255); } //Soil Moistures for (int iMoister=0; iMoister<4; iMoister++) { if (pData[62+iMoister]!=0xFF) { int moister=pData[62+iMoister]; SendMoistureSensor(1 + iMoister, 255, moister, "Moisture"); } } //Leaf Wetness for (int iLeaf=0; iLeaf<4; iLeaf++) { if (pData[66+iLeaf]!=0xFF) { int leaf_wetness=pData[66+iLeaf]; _tGeneralDevice gdevice; gdevice.subtype=sTypeLeafWetness; gdevice.intval1=leaf_wetness; gdevice.id=1+iLeaf; sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255); } } return true; }
bool CRFLinkBase::ParseLine(const std::string &sLine) { m_LastReceivedTime = mytime(NULL); std::vector<std::string> results; StringSplit(sLine, ";", results); if (results.size() < 2) return false; //not needed bool bHideDebugLog = ( (sLine.find("PONG") != std::string::npos)|| (sLine.find("PING") != std::string::npos) ); int RFLink_ID = atoi(results[0].c_str()); if (RFLink_ID != 20) { return false; //only accept RFLink->Master messages } #ifdef ENABLE_LOGGING if (!bHideDebugLog) _log.Log(LOG_NORM, "RFLink: %s", sLine.c_str()); #endif //std::string Sensor_ID = results[1]; if (results.size() >2) { //Status reply std::string Name_ID = results[2]; if ((Name_ID.find("Nodo RadioFrequencyLink") != std::string::npos) || (Name_ID.find("RFLink Gateway") != std::string::npos)) { _log.Log(LOG_STATUS, "RFLink: Controller Initialized!..."); WriteInt("10;VERSION;\n"); // 20;3C;VER=1.1;REV=37;BUILD=01; //Enable DEBUG //write("10;RFDEBUG=ON;\n"); //Enable Undecoded DEBUG //write("10;RFUDEBUG=ON;\n"); return true; } if (Name_ID.find("VER") != std::string::npos) { //_log.Log(LOG_STATUS, "RFLink: %s", sLine.c_str()); int versionlo = 0; int versionhi = 0; int revision = 0; int build = 0; if (results[2].find("VER") != std::string::npos) { versionhi = RFLinkGetIntStringValue(results[2]); versionlo = RFLinkGetIntDecStringValue(results[2]); } if (results[3].find("REV") != std::string::npos){ revision = RFLinkGetIntStringValue(results[3]); } if (results[4].find("BUILD") != std::string::npos) { build = RFLinkGetIntStringValue(results[4]); } _log.Log(LOG_STATUS, "RFLink Detected, Version: %d.%d Revision: %d Build: %d", versionhi, versionlo, revision, build); std::stringstream sstr; sstr << revision << "." << build; m_Version = sstr.str(); mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy m_LastReceivedTime = m_LastHeartbeat; m_bTXokay = true; // variable to indicate an OK was received return true; } if (Name_ID.find("PONG") != std::string::npos) { //_log.Log(LOG_STATUS, "RFLink: PONG received!..."); mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy m_LastReceivedTime = m_LastHeartbeat; m_bTXokay = true; // variable to indicate an OK was received return true; } if (Name_ID.find("OK") != std::string::npos) { //_log.Log(LOG_STATUS, "RFLink: OK received!..."); mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy m_LastReceivedTime = m_LastHeartbeat; m_bTXokay = true; // variable to indicate an OK was received return true; } else if (Name_ID.find("CMD UNKNOWN") != std::string::npos) { _log.Log(LOG_ERROR, "RFLink: Error/Unknown command received!..."); m_bTXokay = true; // variable to indicate an ERROR was received return true; } } if (results.size() < 4) return true; if (results[3].find("ID=") == std::string::npos) return false; //?? mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy //_log.Log(LOG_STATUS, "RFLink: t1=%d t2=%d", m_LastHeartbeat, m_LastHeartbeatReceive); m_LastReceivedTime = m_LastHeartbeat; std::stringstream ss; unsigned int ID; ss << std::hex << results[3].substr(3); ss >> ID; int Node_ID = (ID & 0xFF00) >> 8; int Child_ID = ID & 0xFF; bool bHaveTemp = false; float temp = 0; bool bHaveHum = false; int humidity = 0; bool bHaveHumStatus = false; int humstatus = 0; bool bHaveBaro = false; float baro = 0; int baroforecast = 0; bool bHaveRain = false; float raincounter = 0; bool bHaveLux = false; float lux = 0; bool bHaveUV = false; float uv = 0; bool bHaveWindDir = false; int windir = 0; bool bHaveWindSpeed = false; float windspeed = 0; bool bHaveWindGust = false; float windgust = 0; bool bHaveWindTemp = false; float windtemp = 0; bool bHaveWindChill = false; float windchill = 0; bool bHaveRGB = false; int rgb = 0; bool bHaveRGBW = false; int rgbw = 0; bool bHaveSound = false; int sound = 0; bool bHaveCO2 = false; int co2 = 0; bool bHaveBlind = false; int blind = 0; bool bHaveKWatt = false; float kwatt = 0; bool bHaveWatt = false; float watt = 0; bool bHaveDistance = false; float distance = 0; bool bHaveMeter = false; float meter = 0; bool bHaveVoltage = false; float voltage = 0; bool bHaveCurrent = false; float current = 0; bool bHaveCurrent2 = false; float current2 = 0; bool bHaveCurrent3 = false; float current3 = 0; bool bHaveImpedance = false; float impedance = 0; bool bHaveSwitch = false; int switchunit = 0; bool bHaveSwitchCmd = false; std::string switchcmd = ""; int switchlevel = 0; int BatteryLevel = 255; std::string tmpstr; int iTemp; for (size_t ii = 4; ii < results.size(); ii++) { if (results[ii].find("TEMP") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveTemp = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } temp = float(iTemp) / 10.0f; } else if (results[ii].find("HUM") != std::string::npos) { bHaveHum = true; humidity = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("HSTATUS") != std::string::npos) { bHaveHumStatus = true; humstatus = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("BARO") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveBaro = true; baro = float(iTemp); } else if (results[ii].find("BFORECAST") != std::string::npos) { baroforecast = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RAIN") != std::string::npos) { bHaveRain = true; iTemp = RFLinkGetHexStringValue(results[ii]); raincounter = float(iTemp) / 10.0f; } else if (results[ii].find("LUX") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveLux = true; lux = float(iTemp); } else if (results[ii].find("UV") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveUV = true; uv = float(iTemp) /10.0f; } else if (results[ii].find("BAT") != std::string::npos) { tmpstr = RFLinkGetStringValue(results[ii]); BatteryLevel = (tmpstr == "OK") ? 100 : 0; } else if (results[ii].find("WINDIR") != std::string::npos) { bHaveWindDir = true; windir = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("WINSP") != std::string::npos) { bHaveWindSpeed = true; iTemp = RFLinkGetHexStringValue(results[ii]); // received value is km/u windspeed = (float(iTemp) * 0.0277778f); //convert to m/s } else if (results[ii].find("WINGS") != std::string::npos) { bHaveWindGust = true; iTemp = RFLinkGetHexStringValue(results[ii]); // received value is km/u windgust = (float(iTemp) * 0.0277778f); //convert to m/s } else if (results[ii].find("WINTMP") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWindTemp = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } windtemp = float(iTemp) / 10.0f; } else if (results[ii].find("WINCHL") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWindChill = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } windchill = float(iTemp) / 10.0f; } else if (results[ii].find("SOUND") != std::string::npos) { bHaveSound = true; sound = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("CO2") != std::string::npos) { bHaveCO2 = true; co2 = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RGBW") != std::string::npos) { bHaveRGBW = true; rgbw = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RGB") != std::string::npos) { bHaveRGB = true; rgb = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("BLIND") != std::string::npos) { bHaveBlind = true; blind = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("KWATT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveKWatt = true; kwatt = float(iTemp) / 1000.0f; } else if (results[ii].find("WATT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWatt = true; watt = float(iTemp) / 10.0f; } else if (results[ii].find("DIST") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveDistance = true; distance = float(iTemp) / 10.0f; } else if (results[ii].find("METER") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveMeter = true; meter = float(iTemp) / 10.0f; } else if (results[ii].find("VOLT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveVoltage = true; voltage = float(iTemp) / 10.0f; } else if (results[ii].find("CURRENT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent = true; current = float(iTemp) / 10.0f; } else if (results[ii].find("CURRENT2") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent2 = true; current2 = float(iTemp) / 10.0f; } else if (results[ii].find("CURRENT3") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent3 = true; current3 = float(iTemp) / 10.0f; } else if (results[ii].find("IMPEDANCE") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent = true; current = float(iTemp) / 10.0f; } else if (results[ii].find("SWITCH") != std::string::npos) { bHaveSwitch = true; switchunit = RFLinkGetHexStringValue(results[ii]); } else if (results[ii].find("CMD") != std::string::npos) { bHaveSwitchCmd = true; switchcmd = RFLinkGetStringValue(results[ii]); } else if (results[ii].find("SMOKEALERT") != std::string::npos) { bHaveSwitch = true; switchunit = 1; bHaveSwitchCmd = true; switchcmd = RFLinkGetStringValue(results[ii]); } else if (results[ii].find("CHIME") != std::string::npos) { bHaveSwitch = true; switchunit = 2; bHaveSwitchCmd = true; switchcmd = "ON"; } } std::string tmp_Name = results[2]; if (bHaveTemp&&bHaveHum&&bHaveBaro) { SendTempHumBaroSensor(ID, BatteryLevel, temp, humidity, baro, baroforecast, tmp_Name); } else if (bHaveTemp&&bHaveHum) { SendTempHumSensor(ID, BatteryLevel, temp, humidity, tmp_Name); } else if (bHaveTemp) { SendTempSensor(ID, BatteryLevel, temp, tmp_Name); } else if (bHaveHum) { SendHumiditySensor(ID, BatteryLevel, humidity, tmp_Name); } else if (bHaveBaro) { SendBaroSensor(Node_ID, Child_ID, BatteryLevel, baro, baroforecast, tmp_Name); } if (bHaveLux) { SendLuxSensor(Node_ID, Child_ID, BatteryLevel, lux, tmp_Name); } if (bHaveUV) { SendUVSensor(Node_ID, Child_ID, BatteryLevel, uv, tmp_Name); } if (bHaveRain) { SendRainSensor(ID, BatteryLevel, float(raincounter), tmp_Name); } if (bHaveWindDir && bHaveWindSpeed && bHaveWindGust && bHaveWindChill) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, tmp_Name); } else if (bHaveWindDir && bHaveWindGust) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, tmp_Name); } else if (bHaveWindSpeed) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, tmp_Name); } if (bHaveCO2) { SendAirQualitySensor((ID & 0xFF00) >> 8, ID & 0xFF, BatteryLevel, co2, tmp_Name); } if (bHaveSound) { SendSoundSensor(ID, BatteryLevel, sound, tmp_Name); } if (bHaveRGB) { //RRGGBB SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgb, false, tmp_Name); } if (bHaveRGBW) { //RRGGBBWW SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgbw, true, tmp_Name); } if (bHaveBlind) { SendBlindSensor(Node_ID, Child_ID, BatteryLevel, blind, tmp_Name); } if (bHaveKWatt&bHaveWatt) { SendKwhMeterOldWay(Node_ID, Child_ID, BatteryLevel, watt / 100.0f, kwatt, tmp_Name); } else if (bHaveKWatt) { SendKwhMeterOldWay(Node_ID, Child_ID, BatteryLevel, watt / 100.0f, kwatt, tmp_Name); } else if (bHaveWatt) { SendKwhMeterOldWay(Node_ID, Child_ID, BatteryLevel, watt / 100.0f, kwatt, tmp_Name); } if (bHaveDistance) { SendDistanceSensor(Node_ID, Child_ID, BatteryLevel, distance, tmp_Name); } if (bHaveMeter) { SendMeterSensor(Node_ID, Child_ID, BatteryLevel, meter, tmp_Name); } if (bHaveVoltage) { SendVoltageSensor(Node_ID, Child_ID, BatteryLevel, voltage, tmp_Name); } if (bHaveCurrent && bHaveCurrent2 && bHaveCurrent3) { SendCurrentSensor(ID, BatteryLevel, current, current2, current3, tmp_Name); } else if (bHaveCurrent) { SendCurrentSensor(ID, BatteryLevel, current, 0, 0, tmp_Name); } if (bHaveImpedance) { SendPercentageSensor(Node_ID, Child_ID, BatteryLevel, impedance, tmp_Name); } if (bHaveSwitch && bHaveSwitchCmd) { std::string switchType = results[2]; SendSwitchInt(ID, switchunit, BatteryLevel, switchType, switchcmd, switchlevel); } return true; }
void Meteostick::ParseLine() { if (m_bufferpos < 1) return; std::string sLine((char*)&m_buffer); std::vector<std::string> results; StringSplit(sLine, " ", results); if (results.size() < 1) return; //invalid data switch (m_state) { case MSTATE_INIT: if (sLine.find("# MeteoStick Version") == 0) { _log.Log(LOG_STATUS, sLine.c_str()); return; } if (results[0] == "?") { //Turn off filters write("f0\n"); m_state = MSTATE_FILTERS; } return; case MSTATE_FILTERS: //Set output to 'computer values' write("o1\n"); m_state = MSTATE_VALUES; return; case MSTATE_VALUES: #ifdef USE_868_Mhz //Set listen frequency to 868Mhz write("m1\n"); #else //Set listen frequency to 915Mhz write("m0\n"); #endif m_state = MSTATE_DATA; return; } if (m_state != MSTATE_DATA) return; if (results.size() < 3) return; unsigned char rCode = results[0][0]; if (rCode == '#') return; //#ifdef _DEBUG _log.Log(LOG_NORM, sLine.c_str()); //#endif switch (rCode) { case 'B': //temperature in Celsius, pressure in hPa if (results.size() >= 3) { float temp = static_cast<float>(atof(results[1].c_str())); float baro = static_cast<float>(atof(results[2].c_str())); SendTempBaroSensor(0, temp, baro, "Meteostick Temp+Baro"); } break; case 'W': //current wind speed in m / s, wind direction in degrees if (results.size() >= 5) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); if (m_LastOutsideTemp[ID%MAX_IDS] != 12345) { float speed = static_cast<float>(atof(results[2].c_str())); int direction = static_cast<int>(atoi(results[3].c_str())); SendWindSensor(ID, m_LastOutsideTemp[ID%MAX_IDS], speed, direction, "Wind"); } } break; case 'T': //temperature in degree Celsius, humidity in percent if (results.size() >= 5) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); float temp = static_cast<float>(atof(results[2].c_str())); int hum = static_cast<int>(atoi(results[3].c_str())); SendTempHumSensor(ID, temp, hum, "Outside Temp+Hum"); m_LastOutsideTemp[ID%MAX_IDS] = temp; m_LastOutsideHum[ID%MAX_IDS] = hum; } break; case 'R': //Rain //counter value (value 0 - 255), ticks, 1 tick = 0.2mm or 0.01in //it only has a small counter, so we should make the total counter ourselfses if (results.size() >= 4) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); int raincntr = atoi(results[2].c_str()); float Rainmm = 0; if (m_LastRainValue[ID%MAX_IDS] != -1) { int cntr_diff = (raincntr - m_LastRainValue[ID%MAX_IDS])&255; Rainmm = float(cntr_diff); #ifdef RAIN_IN_MM //one tick is one mm Rainmm*=0.2f; //convert to mm; #else //one tick is 0.01 inch, we need to convert this also to mm //Rainmm *= 0.01f; //convert to inch //Rainmm *= 25.4f; //convert to mm //or directly Rainmm *= 0.254; #endif } m_LastRainValue[ID%MAX_IDS] = raincntr; if (m_ActRainCounter[ID%MAX_IDS] == -1) { //Get Last stored Rain counter float rcounter=GetRainSensorCounter(ID); m_ActRainCounter[ID%MAX_IDS] = rcounter; } m_ActRainCounter[ID%MAX_IDS] += Rainmm; SendRainSensor(ID, m_ActRainCounter[ID%MAX_IDS], "Rain"); } break; case 'S': //solar radiation, solar radiation in W / qm if (results.size() >= 4) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); float Radiation = static_cast<float>(atof(results[2].c_str())); SendSolarRadiationSensor(ID, Radiation, "Solar Radiation"); } break; case 'U': //UV index if (results.size() >= 4) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); float UV = static_cast<float>(atof(results[2].c_str())); SendUVSensor(ID, UV, "UV"); } break; case 'L': //wetness data of a leaf station //channel number (1 - 4), leaf wetness (0-15) if (results.size() >= 5) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); unsigned char Channel = (unsigned char)atoi(results[2].c_str()); unsigned char Wetness = (unsigned char)atoi(results[3].c_str()); SendLeafWetnessRainSensor(ID, Channel, Wetness, "Leaf Wetness"); } break; case 'M': //soil moisture of a soil station //channel number (1 - 4), Soil moisture in cbar(0 - 200) if (results.size() >= 5) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); unsigned char Channel = (unsigned char)atoi(results[2].c_str()); unsigned char Moisture = (unsigned char)atoi(results[3].c_str()); SendSoilMoistureSensor(ID, Channel, Moisture, "Soil Moisture"); } break; case 'O': //soil / leaf temperature of a soil / leaf station //channel number (1 - 4), soil / leaf temperature in degrees Celsius if (results.size() >= 5) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); unsigned char Channel = (unsigned char)atoi(results[2].c_str()); float temp = static_cast<float>(atof(results[3].c_str())); unsigned char finalID = (ID * 10) + Channel; SendTempSensor(finalID, temp, "Soil/Leaf Temp"); } break; case 'P': //solar panel power in(0 - 100) if (results.size() >= 4) { unsigned char ID = (unsigned char)atoi(results[1].c_str()); float Percentage = static_cast<float>(atof(results[2].c_str())); SendPercentage(ID, Percentage, "power of solar panel"); } break; default: _log.Log(LOG_STATUS, "Unknown Type: %c", rCode); break; } }
void CAccuWeather::GetMeterDetails() { std::string sResult; #ifdef DEBUG_AccuWeatherR sResult=ReadFile("E:\\AccuWeather.json"); #else std::stringstream sURL; std::string szLoc = CURLEncode::URLEncode(m_LocationKey); sURL << "https://dataservice.accuweather.com/currentconditions/v1/" << szLoc << "?apikey=" << m_APIKey << "&details=true"; try { bool bret; std::string szURL = sURL.str(); bret = HTTPClient::GET(szURL, sResult); if (!bret) { _log.Log(LOG_ERROR, "AccuWeather: Error getting http data!"); return; } } catch (...) { _log.Log(LOG_ERROR, "AccuWeather: Error getting http data!"); return; } #endif #ifdef DEBUG_AccuWeatherW SaveString2Disk(sResult, "E:\\AccuWeather.json"); #endif try { Json::Value root; Json::Reader jReader; bool ret = jReader.parse(sResult, root); if (!ret) { _log.Log(LOG_ERROR, "AccuWeather: Invalid data received!"); return; } if (root.size() < 1) { _log.Log(LOG_ERROR, "AccuWeather: Invalid data received!"); return; } root = root[0]; if (root["LocalObservationDateTime"].empty()) { _log.Log(LOG_ERROR, "AccuWeather: Invalid data received, or unknown location!"); return; } float temp = 0; int humidity = 0; int barometric = 0; int barometric_forcast = baroForecastNoInfo; if (!root["Temperature"].empty()) { temp = root["Temperature"]["Metric"]["Value"].asFloat(); } if (!root["RelativeHumidity"].empty()) { humidity = root["RelativeHumidity"].asInt(); } if (!root["Pressure"].empty()) { barometric = atoi(root["Pressure"]["Metric"]["Value"].asString().c_str()); if (barometric < 1000) barometric_forcast = baroForecastRain; else if (barometric < 1020) barometric_forcast = baroForecastCloudy; else if (barometric < 1030) barometric_forcast = baroForecastPartlyCloudy; else barometric_forcast = baroForecastSunny; if (!root["WeatherIcon"].empty()) { int forcasticon = atoi(root["WeatherIcon"].asString().c_str()); switch (forcasticon) { case 1: case 2: case 3: barometric_forcast = baroForecastSunny; break; case 4: case 5: case 6: barometric_forcast = baroForecastCloudy; break; case 7: case 8: case 9: case 10: case 11: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 39: case 40: case 41: case 42: case 43: case 44: barometric_forcast = baroForecastRain; break; case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: barometric_forcast = baroForecastCloudy; break; } } } if (barometric != 0) { //Add temp+hum+baro device SendTempHumBaroSensor(1, 255, temp, humidity, static_cast<float>(barometric), barometric_forcast, "THB"); } else if (humidity != 0) { //add temp+hum device SendTempHumSensor(1, 255, temp, humidity, "TempHum"); } else { //add temp device SendTempSensor(1, 255, temp, "Temperature"); } //Wind if (!root["Wind"].empty()) { int wind_degrees = -1; float windspeed_ms = 0; float windgust_ms = 0; float wind_temp = temp; float wind_chill = temp; if (!root["Wind"]["Direction"].empty()) { wind_degrees = root["Wind"]["Direction"]["Degrees"].asInt(); } if (!root["Wind"]["Speed"].empty()) { windspeed_ms = root["Wind"]["Speed"]["Metric"]["Value"].asFloat() / 3.6f; //km/h to m/s } if (!root["WindGust"].empty()) { if (!root["WindGust"]["Speed"].empty()) { windgust_ms = root["WindGust"]["Speed"]["Metric"]["Value"].asFloat() / 3.6f; //km/h to m/s } } if (!root["RealFeelTemperature"].empty()) { wind_chill = root["RealFeelTemperature"]["Metric"]["Value"].asFloat(); } if (wind_degrees != -1) { SendWind(1, 255, wind_degrees, windspeed_ms, windgust_ms, temp, wind_chill, true, "Wind"); } } //UV if (!root["UVIndex"].empty()) { float UV = static_cast<float>(atof(root["UVIndex"].asString().c_str())); if ((UV < 16) && (UV >= 0)) { SendUVSensor(0, 1, 255, UV, "UV"); } } //Rain if (!root["PrecipitationSummary"].empty()) { if (!root["PrecipitationSummary"]["Precipitation"].empty()) { float RainCount = static_cast<float>(atof(root["PrecipitationSummary"]["Precipitation"]["Metric"]["Value"].asString().c_str())); if ((RainCount != -9999.00f) && (RainCount >= 0.00f)) { RBUF tsen; memset(&tsen, 0, sizeof(RBUF)); tsen.RAIN.packetlength = sizeof(tsen.RAIN) - 1; tsen.RAIN.packettype = pTypeRAIN; tsen.RAIN.subtype = sTypeRAINWU; tsen.RAIN.battery_level = 9; tsen.RAIN.rssi = 12; tsen.RAIN.id1 = 0; tsen.RAIN.id2 = 1; tsen.RAIN.rainrateh = 0; tsen.RAIN.rainratel = 0; if (!root["PrecipitationSummary"]["PastHour"].empty()) { float rainrateph = static_cast<float>(atof(root["PrecipitationSummary"]["PastHour"]["Metric"]["Value"].asString().c_str())); if (rainrateph != -9999.00f) { int at10 = round(std::abs(rainrateph*10.0f)); tsen.RAIN.rainrateh = (BYTE)(at10 / 256); at10 -= (tsen.RAIN.rainrateh * 256); tsen.RAIN.rainratel = (BYTE)(at10); } } int tr10 = int((float(RainCount)*10.0f)); tsen.RAIN.raintotal1 = 0; tsen.RAIN.raintotal2 = (BYTE)(tr10 / 256); tr10 -= (tsen.RAIN.raintotal2 * 256); tsen.RAIN.raintotal3 = (BYTE)(tr10); sDecodeRXMessage(this, (const unsigned char *)&tsen.RAIN, NULL, 255); } } } //Visibility if (!root["Visibility"].empty()) { if (!root["Visibility"]["Metric"].empty()) { float visibility = root["Visibility"]["Metric"]["Value"].asFloat(); if (visibility >= 0) { _tGeneralDevice gdevice; gdevice.subtype = sTypeVisibility; gdevice.floatval1 = visibility; sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255); } } } //Forecast URL if (!root["Link"].empty()) { m_ForecastURL = root["Link"].asString(); } } catch (...) { _log.Log(LOG_ERROR, "AccuWeather: Error parsing JSon data!"); } }
void CNest::GetMeterDetails() { std::string sResult; #ifdef DEBUG_NextThermostatR sResult = ReadFile("E:\\nest.json"); #else if (m_UserName.size()==0) return; if (m_Password.size()==0) return; if (m_bDoLogin) { if (!Login()) return; } std::vector<std::string> ExtraHeaders; ExtraHeaders.push_back("user-agent:Nest/1.1.0.10 CFNetwork/548.0.4"); ExtraHeaders.push_back("Authorization:Basic " + m_AccessToken); ExtraHeaders.push_back("X-nl-user-id:" + m_UserID); ExtraHeaders.push_back("X-nl-protocol-version:1"); //Get Data std::string sURL = m_TransportURL + NEST_GET_STATUS + m_UserID; if (!HTTPClient::GET(sURL, ExtraHeaders, sResult)) { _log.Log(LOG_ERROR, "Nest: Error getting current state!"); m_bDoLogin = true; return; } #endif #ifdef DEBUG_NextThermostatW SaveString2Disk(sResult, "E:\\nest.json"); #endif Json::Value root; Json::Reader jReader; if (!jReader.parse(sResult, root)) { _log.Log(LOG_ERROR, "Nest: Invalid data received!"); m_bDoLogin = true; return; } bool bHaveShared = !root["shared"].empty(); bool bHaveTopaz = !root["topaz"].empty(); if ((!bHaveShared) && (!bHaveTopaz)) { _log.Log(LOG_ERROR, "Nest: request not successful, restarting..!"); m_bDoLogin = true; return; } //Protect if (bHaveTopaz) { if (root["topaz"].size() < 1) { _log.Log(LOG_ERROR, "Nest: request not successful, restarting..!"); m_bDoLogin = true; return; } Json::Value::Members members = root["topaz"].getMemberNames(); if (members.size() < 1) { _log.Log(LOG_ERROR, "Nest: request not successful, restarting..!"); m_bDoLogin = true; return; } int SwitchIndex = 1; for (Json::Value::iterator itDevice = root["topaz"].begin(); itDevice != root["topaz"].end(); ++itDevice) { Json::Value device = *itDevice; std::string devstring = itDevice.key().asString(); if (device["where_id"].empty()) continue; std::string whereid = device["where_id"].asString(); //lookup name std::string devName = devstring; if (!root["where"].empty()) { for (Json::Value::iterator itWhere = root["where"].begin(); itWhere != root["where"].end(); ++itWhere) { Json::Value iwhere = *itWhere; if (!iwhere["wheres"].empty()) { for (Json::Value::iterator itWhereNest = iwhere["wheres"].begin(); itWhereNest != iwhere["wheres"].end(); ++itWhereNest) { Json::Value iwhereItt = *itWhereNest; if (!iwhereItt["where_id"].empty()) { std::string tmpWhereid = iwhereItt["where_id"].asString(); if (tmpWhereid == whereid) { devName = iwhereItt["name"].asString(); break; } } } } } } bool bIAlarm = false; bool bBool; if (!device["component_speaker_test_passed"].empty()) { bBool = device["component_speaker_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_smoke_test_passed"].empty()) { bBool = device["component_smoke_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_heat_test_passed"].empty()) { bBool = device["component_heat_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_buzzer_test_passed"].empty()) { bBool = device["component_buzzer_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_us_test_passed"].empty()) { bBool = device["component_us_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_temp_test_passed"].empty()) { bBool = device["component_temp_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_wifi_test_passed"].empty()) { bBool = device["component_wifi_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_als_test_passed"].empty()) { bBool = device["component_als_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_co_test_passed"].empty()) { bBool = device["component_co_test_passed"].asBool(); if (!bBool) bIAlarm = true; } if (!device["component_hum_test_passed"].empty()) { bBool = device["component_hum_test_passed"].asBool(); if (!bBool) bIAlarm = true; } UpdateSmokeSensor(SwitchIndex, bIAlarm, devName); SwitchIndex++; } } //Thermostat if (!bHaveShared) return; if (root["shared"].size()<1) { if (bHaveTopaz) return; _log.Log(LOG_ERROR, "Nest: request not successful, restarting..!"); m_bDoLogin = true; return; } size_t iThermostat = 0; for (Json::Value::iterator ittStructure = root["structure"].begin(); ittStructure != root["structure"].end(); ++ittStructure) { Json::Value nstructure = *ittStructure; if (!nstructure.isObject()) continue; std::string StructureID = ittStructure.key().asString(); std::string StructureName = nstructure["name"].asString(); for (Json::Value::iterator ittDevice = nstructure["devices"].begin(); ittDevice != nstructure["devices"].end(); ++ittDevice) { std::string devID = (*ittDevice).asString(); if (devID.find("device.")==std::string::npos) continue; std::string Serial = devID.substr(7); if (root["device"].empty()) continue; if (root["device"][Serial].empty()) continue; //not found !? if (root["shared"][Serial].empty()) continue; //Nothing shared? Json::Value ndevice = root["device"][Serial]; if (!ndevice.isObject()) continue; std::string Name = "Thermostat"; if (!ndevice["where_id"].empty()) { //Lookup our 'where' (for the Name of the thermostat) std::string where_id = ndevice["where_id"].asString(); if (!root["where"].empty()) { if (!root["where"][StructureID].empty()) { for (Json::Value::iterator ittWheres = root["where"][StructureID]["wheres"].begin(); ittWheres != root["where"][StructureID]["wheres"].end(); ++ittWheres) { Json::Value nwheres = *ittWheres; if (nwheres["where_id"] == where_id) { Name = StructureName + " " + nwheres["name"].asString(); break; } } } } } _tNestThemostat ntherm; ntherm.Serial = Serial; ntherm.StructureID = StructureID; ntherm.Name = Name; m_thermostats[iThermostat] = ntherm; Json::Value nshared = root["shared"][Serial]; //Setpoint if (!nshared["target_temperature"].empty()) { float currentSetpoint = nshared["target_temperature"].asFloat(); SendSetPointSensor((const unsigned char)(iThermostat * 3) + 1, currentSetpoint, Name + " Setpoint"); } //Room Temperature/Humidity if (!nshared["current_temperature"].empty()) { float currentTemp = nshared["current_temperature"].asFloat(); int Humidity = root["device"][Serial]["current_humidity"].asInt(); SendTempHumSensor((iThermostat * 3) + 2, 255, currentTemp, Humidity, Name + " TempHum"); } // Check if thermostat is currently Heating if (nshared["can_heat"].asBool() && !nshared["hvac_heater_state"].empty()) { bool bIsHeating = nshared["hvac_heater_state"].asBool(); UpdateSwitch((unsigned char)(113 + (iThermostat * 3)), bIsHeating, Name + " HeatingOn"); } // Check if thermostat is currently Cooling if (nshared["can_cool"].asBool() && !nshared["hvac_ac_state"].empty()) { bool bIsCooling = nshared["hvac_ac_state"].asBool(); UpdateSwitch((unsigned char)(114 + (iThermostat * 3)), bIsCooling, Name + " CoolingOn"); } //Away if (!nstructure["away"].empty()) { bool bIsAway = nstructure["away"].asBool(); SendSwitch((iThermostat * 3) + 3, 1, 255, bIsAway, 0, Name + " Away"); } iThermostat++; } } }
void MySensorsBase::SendSensor2Domoticz(_tMySensorNode *pNode, _tMySensorChild *pChild, const _eSetType vType) { m_iLastSendNodeBatteryValue = 255; if (pChild->hasBattery) { m_iLastSendNodeBatteryValue = pChild->batValue; } int cNode = (pChild->nodeID << 8) | pChild->childID; int intValue; float floatValue; std::string stringValue; switch (vType) { case V_TEMP: { float Temp = 0; pChild->GetValue(V_TEMP, Temp); _tMySensorChild *pChildHum = FindChildWithValueType(pChild->nodeID, V_HUM); _tMySensorChild *pChildBaro = FindChildWithValueType(pChild->nodeID, V_PRESSURE); if (pChildHum && pChildBaro) { int Humidity; float Baro; bool bHaveHumidity = pChildHum->GetValue(V_HUM, Humidity); bool bHaveBaro = pChildBaro->GetValue(V_PRESSURE, Baro); if (bHaveHumidity && bHaveBaro) { int forecast = bmpbaroforecast_unknown; _tMySensorChild *pSensorForecast = FindChildWithValueType(pChild->nodeID, V_FORECAST); if (pSensorForecast) { pSensorForecast->GetValue(V_FORECAST, forecast); } if (forecast == bmpbaroforecast_cloudy) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } //We are using the TempHumBaro Float type now, convert the forecast int nforecast = wsbaroforcast_some_clouds; if (Baro <= 980) nforecast = wsbaroforcast_heavy_rain; else if (Baro <= 995) { if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } else if (Baro >= 1029) nforecast = wsbaroforcast_sunny; switch (forecast) { case bmpbaroforecast_sunny: nforecast = wsbaroforcast_sunny; break; case bmpbaroforecast_cloudy: nforecast = wsbaroforcast_cloudy; break; case bmpbaroforecast_thunderstorm: nforecast = wsbaroforcast_heavy_rain; break; case bmpbaroforecast_rain: if (Temp>1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } SendTempHumBaroSensorFloat(cNode, pChild->batValue, Temp, Humidity, Baro, nforecast, (!pChild->childName.empty()) ? pChild->childName : "TempHumBaro"); } } else if (pChildHum) { int Humidity; bool bHaveHumidity = pChildHum->GetValue(V_HUM, Humidity); if (bHaveHumidity) { SendTempHumSensor(cNode, pChild->batValue, Temp, Humidity, (!pChild->childName.empty()) ? pChild->childName : "TempHum"); } } else { SendTempSensor(cNode, pChild->batValue, Temp, (!pChild->childName.empty()) ? pChild->childName : "Temp"); } } break; case V_HUM: { _tMySensorChild *pChildTemp = FindChildWithValueType(pChild->nodeID, V_TEMP); _tMySensorChild *pChildBaro = FindChildWithValueType(pChild->nodeID, V_PRESSURE); int forecast = bmpbaroforecast_unknown; _tMySensorChild *pSensorForecast = FindChildWithValueType(pChild->nodeID, V_FORECAST); if (pSensorForecast) { pSensorForecast->GetValue(V_FORECAST, forecast); } if (forecast == bmpbaroforecast_cloudy) { if (pChildBaro) { float Baro; if (pChildBaro->GetValue(V_PRESSURE, Baro)) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } } } float Temp; float Baro; int Humidity; pChild->GetValue(V_HUM, Humidity); if (pChildTemp && pChildBaro) { bool bHaveTemp = pChildTemp->GetValue(V_TEMP, Temp); bool bHaveBaro = pChildBaro->GetValue(V_PRESSURE, Baro); if (bHaveTemp && bHaveBaro) { cNode = (pChildTemp->nodeID << 8) | pChildTemp->childID; //We are using the TempHumBaro Float type now, convert the forecast int nforecast = wsbaroforcast_some_clouds; if (Baro <= 980) nforecast = wsbaroforcast_heavy_rain; else if (Baro <= 995) { if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } else if (Baro >= 1029) nforecast = wsbaroforcast_sunny; switch (forecast) { case bmpbaroforecast_sunny: nforecast = wsbaroforcast_sunny; break; case bmpbaroforecast_cloudy: nforecast = wsbaroforcast_cloudy; break; case bmpbaroforecast_thunderstorm: nforecast = wsbaroforcast_heavy_rain; break; case bmpbaroforecast_rain: if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } SendTempHumBaroSensorFloat(cNode, pChildTemp->batValue, Temp, Humidity, Baro, nforecast, (!pChild->childName.empty()) ? pChild->childName : "TempHumBaro"); } } else if (pChildTemp) { bool bHaveTemp = pChildTemp->GetValue(V_TEMP, Temp); if (bHaveTemp) { cNode = (pChildTemp->nodeID << 8) | pChildTemp->childID; SendTempHumSensor(cNode, pChildTemp->batValue, Temp, Humidity, (!pChild->childName.empty()) ? pChild->childName : "TempHum"); } } else { SendHumiditySensor(cNode, pChild->batValue, Humidity); } } break; case V_PRESSURE: { float Baro; pChild->GetValue(V_PRESSURE, Baro); _tMySensorChild *pSensorTemp = FindChildWithValueType(pChild->nodeID, V_TEMP); _tMySensorChild *pSensorHum = FindChildWithValueType(pChild->nodeID, V_HUM); int forecast = bmpbaroforecast_unknown; _tMySensorChild *pSensorForecast = FindChildWithValueType(pChild->nodeID, V_FORECAST); if (pSensorForecast) { pSensorForecast->GetValue(V_FORECAST, forecast); } if (forecast == bmpbaroforecast_cloudy) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } if (pSensorTemp && pSensorHum) { float Temp; int Humidity; bool bHaveTemp = pSensorTemp->GetValue(V_TEMP, Temp); bool bHaveHumidity = pSensorHum->GetValue(V_HUM, Humidity); if (bHaveTemp && bHaveHumidity) { cNode = (pSensorTemp->nodeID << 8) | pSensorTemp->childID; //We are using the TempHumBaro Float type now, convert the forecast int nforecast = wsbaroforcast_some_clouds; if (Baro <= 980) nforecast = wsbaroforcast_heavy_rain; else if (Baro <= 995) { if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } else if (Baro >= 1029) nforecast = wsbaroforcast_sunny; switch (forecast) { case bmpbaroforecast_sunny: nforecast = wsbaroforcast_sunny; break; case bmpbaroforecast_cloudy: nforecast = wsbaroforcast_cloudy; break; case bmpbaroforecast_thunderstorm: nforecast = wsbaroforcast_heavy_rain; break; case bmpbaroforecast_rain: if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } SendTempHumBaroSensorFloat(cNode, pSensorTemp->batValue, Temp, Humidity, Baro, nforecast, (!pChild->childName.empty()) ? pChild->childName : "TempHumBaro"); } } else SendBaroSensor(pChild->nodeID, pChild->childID, pChild->batValue, Baro, forecast); } break; case V_TRIPPED: // Tripped status of a security sensor. 1 = Tripped, 0 = Untripped if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue == 1), 100, "Security Sensor"); break; case V_ARMED: //Armed status of a security sensor. 1 = Armed, 0 = Bypassed if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue == 1), 100, "Security Sensor"); break; case V_LOCK_STATUS: //Lock status. 1 = Locked, 0 = Unlocked if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue == 1), 100, "Lock Sensor"); break; case V_STATUS: // Light status. 0 = off 1 = on if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue != 0), 100, "Light"); break; case V_SCENE_ON: if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID + intValue, true, 100, "Scene"); break; case V_SCENE_OFF: if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID + intValue, false, 100, "Scene"); break; case V_PERCENTAGE: // Dimmer value. 0 - 100 % if (pChild->GetValue(vType, intValue)) { int level = intValue; UpdateSwitch(pChild->nodeID, pChild->childID, (level != 0), level, "Light"); } break; case V_RGB: //RRGGBB if (pChild->GetValue(vType, intValue)) SendRGBWSwitch(pChild->nodeID, pChild->childID, pChild->batValue, intValue, false, (!pChild->childName.empty()) ? pChild->childName : "RGB Light"); break; case V_RGBW: //RRGGBBWW if (pChild->GetValue(vType, intValue)) SendRGBWSwitch(pChild->nodeID, pChild->childID, pChild->batValue, intValue, true, (!pChild->childName.empty()) ? pChild->childName : "RGBW Light"); break; case V_UP: case V_DOWN: case V_STOP: if (pChild->GetValue(vType, intValue)) SendBlindSensor(pChild->nodeID, pChild->childID, pChild->batValue, intValue, (!pChild->childName.empty()) ? pChild->childName : "Blinds/Window"); break; case V_LIGHT_LEVEL: if (pChild->GetValue(vType, floatValue)) { _tLightMeter lmeter; lmeter.id1 = 0; lmeter.id2 = 0; lmeter.id3 = 0; lmeter.id4 = pChild->nodeID; lmeter.dunit = pChild->childID; lmeter.fLux = floatValue; lmeter.battery_level = pChild->batValue; if (pChild->hasBattery) lmeter.battery_level = pChild->batValue; sDecodeRXMessage(this, (const unsigned char *)&lmeter); } break; case V_LEVEL: if ((pChild->presType == S_DUST)|| (pChild->presType == S_AIR_QUALITY)) { if (pChild->GetValue(vType, intValue)) { _tAirQualityMeter meter; meter.len = sizeof(_tAirQualityMeter) - 1; meter.type = pTypeAirQuality; meter.subtype = sTypeVoltcraft; meter.airquality = intValue; meter.id1 = pChild->nodeID; meter.id2 = pChild->childID; sDecodeRXMessage(this, (const unsigned char *)&meter); } } else if (pChild->presType == S_LIGHT_LEVEL) { if (pChild->GetValue(vType, intValue)) { _tLightMeter lmeter; lmeter.id1 = 0; lmeter.id2 = 0; lmeter.id3 = 0; lmeter.id4 = pChild->nodeID; lmeter.dunit = pChild->childID; lmeter.fLux = (float)intValue; lmeter.battery_level = pChild->batValue; if (pChild->hasBattery) lmeter.battery_level = pChild->batValue; sDecodeRXMessage(this, (const unsigned char *)&lmeter); } } else if (pChild->presType == S_SOUND) { if (pChild->GetValue(vType, intValue)) SendSoundSensor(cNode, pChild->batValue, intValue, (!pChild->childName.empty()) ? pChild->childName : "Sound Level"); } else if (pChild->presType == S_MOISTURE) { if (pChild->GetValue(vType, intValue)) { _tGeneralDevice gdevice; gdevice.subtype = sTypeSoilMoisture; gdevice.intval1 = intValue; gdevice.id = pChild->nodeID; sDecodeRXMessage(this, (const unsigned char *)&gdevice); } } break; case V_RAIN: if (pChild->GetValue(vType, floatValue)) SendRainSensor(cNode, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Rain"); break; case V_WATT: { if (pChild->GetValue(vType, floatValue)) { _tMySensorChild *pSensorKwh = pNode->FindChildWithValueType(pChild->childID, V_KWH);// FindChildWithValueType(pChild->nodeID, V_KWH); if (pSensorKwh) { float Kwh; if (pSensorKwh->GetValue(V_KWH, Kwh)) SendKwhMeter(pSensorKwh->nodeID, pSensorKwh->childID, pSensorKwh->batValue, floatValue / 1000.0f, Kwh, (!pChild->childName.empty()) ? pChild->childName : "Meter"); } else { SendWattMeter(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Usage"); } } } break; case V_KWH: if (pChild->GetValue(vType, floatValue)) { _tMySensorChild *pSensorWatt = pNode->FindChildWithValueType(pChild->childID, V_WATT);// FindChildWithValueType(pChild->nodeID, V_WATT); if (pSensorWatt) { float Watt; if (pSensorWatt->GetValue(V_WATT, Watt)) SendKwhMeter(pChild->nodeID, pChild->childID, pChild->batValue, Watt / 1000.0f, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Meter"); } else { SendKwhMeter(pChild->nodeID, pChild->childID, pChild->batValue, 0, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Meter"); } } break; case V_DISTANCE: if (pChild->GetValue(vType, floatValue)) SendDistanceSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue); break; case V_FLOW: //Flow of water in meter (for now send as a percentage sensor) if (pChild->GetValue(vType, floatValue)) SendPercentageSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Water Flow"); break; case V_VOLUME: //Water Volume if (pChild->GetValue(vType, floatValue)) SendMeterSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Water"); break; case V_VOLTAGE: if (pChild->GetValue(vType, floatValue)) SendVoltageSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Voltage"); break; case V_UV: if (pChild->GetValue(vType, floatValue)) SendUVSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue); break; case V_IMPEDANCE: if (pChild->GetValue(vType, floatValue)) SendPercentageSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Impedance"); break; case V_WEIGHT: if (pChild->GetValue(vType, floatValue)) { while (1 == 0); } break; case V_CURRENT: if (pChild->GetValue(vType, floatValue)) SendCurrentSensor(cNode, pChild->batValue, floatValue, 0, 0, (!pChild->childName.empty()) ? pChild->childName : "Current"); break; case V_FORECAST: if (pChild->GetValue(vType, intValue)) { _tMySensorChild *pSensorBaro = FindChildWithValueType(pChild->nodeID, V_PRESSURE); if (pSensorBaro) { float Baro; if (pSensorBaro->GetValue(V_PRESSURE, Baro)) { int forecast = intValue; if (forecast == bmpbaroforecast_cloudy) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } SendBaroSensor(pSensorBaro->nodeID, pSensorBaro->childID, pSensorBaro->batValue, Baro, forecast); } } else { if (pChild->GetValue(V_FORECAST, stringValue)) { std::stringstream sstr; sstr << pChild->nodeID; std::string devname = (!pChild->childName.empty()) ? pChild->childName : "Forecast"; m_sql.UpdateValue(m_HwdID, sstr.str().c_str(), pChild->childID, pTypeGeneral, sTypeTextStatus, 12, pChild->batValue, 0, stringValue.c_str(), devname); } } } break; case V_WIND: case V_GUST: case V_DIRECTION: MakeAndSendWindSensor(pChild->nodeID, (!pChild->childName.empty()) ? pChild->childName : "Wind"); break; case V_HVAC_SETPOINT_HEAT: if (pChild->GetValue(vType, floatValue)) { SendSetPointSensor(pNode->nodeID, pChild->childID, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Heater Setpoint"); } break; } }
void CWunderground::GetMeterDetails() { std::string sResult; #ifdef DEBUG_WUNDERGROUND sResult= ReadFile("E:\\wu.json"); #else std::stringstream sURL; std::string szLoc = CURLEncode::URLEncode(m_Location); sURL << "http://api.wunderground.com/api/" << m_APIKey << "/conditions/q/" << szLoc << ".json"; bool bret; std::string szURL=sURL.str(); bret=HTTPClient::GET(szURL,sResult); if (!bret) { _log.Log(LOG_ERROR,"Wunderground: Error getting http data!"); return; } #ifdef DEBUG_WUNDERGROUND2 SaveString2Disk(sResult, "E:\\wu.json"); #endif #endif Json::Value root; Json::Reader jReader; bool ret=jReader.parse(sResult,root); if (!ret) { _log.Log(LOG_ERROR,"WUnderground: Invalid data received!"); return; } bool bValid = true; if (root["response"].empty() == true) { bValid = false; } else if (!root["response"]["error"].empty()) { bValid = false; if (!root["response"]["error"]["description"].empty()) { _log.Log(LOG_ERROR, "WUnderground: Error: %s", root["response"]["error"]["description"].asString().c_str()); return; } } else if (root["current_observation"].empty()==true) { bValid = false; return; } else if (root["current_observation"]["temp_c"].empty() == true) { bValid = false; } if (!bValid) { _log.Log(LOG_ERROR, "WUnderground: Invalid data received, or no data returned!"); return; } /* std::string tmpstr2 = root.toStyledString(); FILE *fOut = fopen("E:\\underground.json", "wb+"); fwrite(tmpstr2.c_str(), 1, tmpstr2.size(), fOut); fclose(fOut); */ std::string tmpstr; float temp; int humidity=0; int barometric=0; int barometric_forcast=baroForecastNoInfo; temp=root["current_observation"]["temp_c"].asFloat(); if (root["current_observation"]["relative_humidity"].empty()==false) { tmpstr=root["current_observation"]["relative_humidity"].asString(); size_t pos=tmpstr.find("%"); if (pos==std::string::npos) { _log.Log(LOG_ERROR,"WUnderground: Invalid data received!"); return; } humidity=atoi(tmpstr.substr(0,pos).c_str()); } if (root["current_observation"]["pressure_mb"].empty()==false) { barometric=atoi(root["current_observation"]["pressure_mb"].asString().c_str()); if (barometric<1000) barometric_forcast=baroForecastRain; else if (barometric<1020) barometric_forcast=baroForecastCloudy; else if (barometric<1030) barometric_forcast=baroForecastPartlyCloudy; else barometric_forcast=baroForecastSunny; if (root["current_observation"]["icon"].empty()==false) { std::string forcasticon=root["current_observation"]["icon"].asString(); if (forcasticon=="partlycloudy") { barometric_forcast=baroForecastPartlyCloudy; } else if (forcasticon=="cloudy") { barometric_forcast=baroForecastCloudy; } else if (forcasticon=="sunny") { barometric_forcast=baroForecastSunny; } else if (forcasticon=="rain") { barometric_forcast=baroForecastRain; } } } if (barometric!=0) { //Add temp+hum+baro device SendTempHumBaroSensor(1, 255, temp, humidity, static_cast<float>(barometric), barometric_forcast, "THB"); } else if (humidity!=0) { //add temp+hum device SendTempHumSensor(1, 255, temp, humidity, "TempHum"); } else { //add temp device SendTempSensor(1, 255, temp, "Temperature"); } //Wind int wind_degrees=-1; float wind_mph=-1; float wind_gust_mph=-1; float windspeed_ms=0; float windgust_ms=0; float wind_temp=temp; float wind_chill=temp; int windgust=1; float windchill=-1; if (root["current_observation"]["wind_degrees"].empty()==false) { wind_degrees=atoi(root["current_observation"]["wind_degrees"].asString().c_str()); } if (root["current_observation"]["wind_mph"].empty()==false) { if ((root["current_observation"]["wind_mph"] != "N/A") && (root["current_observation"]["wind_mph"] != "--")) { float temp_wind_mph = static_cast<float>(atof(root["current_observation"]["wind_mph"].asString().c_str())); if (temp_wind_mph!=-9999.00f) { wind_mph=temp_wind_mph; //convert to m/s windspeed_ms=wind_mph*0.44704f; } } } if (root["current_observation"]["wind_gust_mph"].empty()==false) { if ((root["current_observation"]["wind_gust_mph"] != "N/A") && (root["current_observation"]["wind_gust_mph"] != "--")) { float temp_wind_gust_mph = static_cast<float>(atof(root["current_observation"]["wind_gust_mph"].asString().c_str())); if (temp_wind_gust_mph!=-9999.00f) { wind_gust_mph=temp_wind_gust_mph; //convert to m/s windgust_ms=wind_gust_mph*0.44704f; } } } if (root["current_observation"]["feelslike_c"].empty()==false) { if ((root["current_observation"]["feelslike_c"] != "N/A") && (root["current_observation"]["feelslike_c"] != "--")) { wind_chill = static_cast<float>(atof(root["current_observation"]["feelslike_c"].asString().c_str())); } } if (wind_degrees!=-1) { RBUF tsen; memset(&tsen,0,sizeof(RBUF)); tsen.WIND.packetlength=sizeof(tsen.WIND)-1; tsen.WIND.packettype=pTypeWIND; tsen.WIND.subtype=sTypeWIND4; tsen.WIND.battery_level=9; tsen.WIND.rssi=12; tsen.WIND.id1=0; tsen.WIND.id2=1; float winddir=float(wind_degrees); int aw=round(winddir); tsen.WIND.directionh=(BYTE)(aw/256); aw-=(tsen.WIND.directionh*256); tsen.WIND.directionl=(BYTE)(aw); tsen.WIND.av_speedh=0; tsen.WIND.av_speedl=0; int sw=round(windspeed_ms*10.0f); tsen.WIND.av_speedh=(BYTE)(sw/256); sw-=(tsen.WIND.av_speedh*256); tsen.WIND.av_speedl=(BYTE)(sw); tsen.WIND.gusth=0; tsen.WIND.gustl=0; int gw=round(windgust_ms*10.0f); tsen.WIND.gusth=(BYTE)(gw/256); gw-=(tsen.WIND.gusth*256); tsen.WIND.gustl=(BYTE)(gw); //this is not correct, why no wind temperature? and only chill? tsen.WIND.chillh=0; tsen.WIND.chilll=0; tsen.WIND.temperatureh=0; tsen.WIND.temperaturel=0; tsen.WIND.tempsign=(wind_temp>=0)?0:1; int at10=round(std::abs(wind_temp*10.0f)); tsen.WIND.temperatureh=(BYTE)(at10/256); at10-=(tsen.WIND.temperatureh*256); tsen.WIND.temperaturel=(BYTE)(at10); tsen.WIND.chillsign=(wind_temp>=0)?0:1; at10=round(std::abs(wind_chill*10.0f)); tsen.WIND.chillh=(BYTE)(at10/256); at10-=(tsen.WIND.chillh*256); tsen.WIND.chilll=(BYTE)(at10); sDecodeRXMessage(this, (const unsigned char *)&tsen.WIND, NULL, 255); } //UV if (root["current_observation"].empty() == false) { if (root["current_observation"]["UV"].empty() == false) { if ((root["current_observation"]["UV"] != "N/A") && (root["current_observation"]["UV"] != "--")) { float UV = static_cast<float>(atof(root["current_observation"]["UV"].asString().c_str())); if ((UV < 16) && (UV >= 0)) { SendUVSensor(0, 1, 255, UV, "UV"); } } } } //Rain if (root["current_observation"]["precip_today_metric"].empty() == false) { if ((root["current_observation"]["precip_today_metric"] != "N/A") && (root["current_observation"]["precip_today_metric"] != "--")) { float RainCount = static_cast<float>(atof(root["current_observation"]["precip_today_metric"].asString().c_str())); if ((RainCount != -9999.00f) && (RainCount >= 0.00f)) { RBUF tsen; memset(&tsen, 0, sizeof(RBUF)); tsen.RAIN.packetlength = sizeof(tsen.RAIN) - 1; tsen.RAIN.packettype = pTypeRAIN; tsen.RAIN.subtype = sTypeRAINWU; tsen.RAIN.battery_level = 9; tsen.RAIN.rssi = 12; tsen.RAIN.id1 = 0; tsen.RAIN.id2 = 1; tsen.RAIN.rainrateh = 0; tsen.RAIN.rainratel = 0; if (root["current_observation"]["precip_1hr_metric"].empty() == false) { if ((root["current_observation"]["precip_1hr_metric"] != "N/A") && (root["current_observation"]["precip_1hr_metric"] != "--")) { float rainrateph = static_cast<float>(atof(root["current_observation"]["precip_1hr_metric"].asString().c_str())); if (rainrateph != -9999.00f) { int at10 = round(std::abs(rainrateph*10.0f)); tsen.RAIN.rainrateh = (BYTE)(at10 / 256); at10 -= (tsen.RAIN.rainrateh * 256); tsen.RAIN.rainratel = (BYTE)(at10); } } } int tr10 = int((float(RainCount)*10.0f)); tsen.RAIN.raintotal1 = 0; tsen.RAIN.raintotal2 = (BYTE)(tr10 / 256); tr10 -= (tsen.RAIN.raintotal2 * 256); tsen.RAIN.raintotal3 = (BYTE)(tr10); sDecodeRXMessage(this, (const unsigned char *)&tsen.RAIN, NULL, 255); } } } //Visibility if (root["current_observation"]["visibility_km"].empty() == false) { if ((root["current_observation"]["visibility_km"] != "N/A") && (root["current_observation"]["visibility_km"] != "--")) { float visibility = static_cast<float>(atof(root["current_observation"]["visibility_km"].asString().c_str())); if (visibility >= 0) { _tGeneralDevice gdevice; gdevice.subtype = sTypeVisibility; gdevice.floatval1 = visibility; sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255); } } } //Solar Radiation if (root["current_observation"]["solarradiation"].empty() == false) { if ((root["current_observation"]["solarradiation"] != "N/A") && (root["current_observation"]["solarradiation"] != "--")) { float radiation = static_cast<float>(atof(root["current_observation"]["solarradiation"].asString().c_str())); if (radiation >= 0.0f) { _tGeneralDevice gdevice; gdevice.subtype = sTypeSolarRadiation; gdevice.floatval1 = radiation; sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255); } } } }
void CNestThermostat::GetMeterDetails() { if (m_UserName.size()==0) return; if (m_Password.size()==0) return; std::string sResult; if (m_bDoLogin) { if (!Login()) return; } std::vector<std::string> ExtraHeaders; ExtraHeaders.push_back("user-agent:Nest/1.1.0.10 CFNetwork/548.0.4"); ExtraHeaders.push_back("Authorization:Basic " + m_AccessToken); ExtraHeaders.push_back("X-nl-user-id:" + m_UserID); ExtraHeaders.push_back("X-nl-protocol-version:1"); //Get Data std::string sURL = m_TransportURL + NEST_GET_STATUS + m_UserID; if (!HTTPClient::GET(sURL, ExtraHeaders, sResult)) { _log.Log(LOG_ERROR, "NestThermostat: Error getting current state!"); m_bDoLogin = true; return; } Json::Value root; Json::Reader jReader; if (!jReader.parse(sResult, root)) { _log.Log(LOG_ERROR, "NestThermostat: Invalid data received!"); m_bDoLogin = true; return; } if (root["shared"].empty() == true) { _log.Log(LOG_ERROR, "NestThermostat: request not successful, restarting..!"); m_bDoLogin = true; return; } if (root["shared"].size()<1) { _log.Log(LOG_ERROR, "NestThermostat: request not successful, restarting..!"); m_bDoLogin = true; return; } Json::Value::Members members = root["shared"].getMemberNames(); if (members.size() < 1) { _log.Log(LOG_ERROR, "NestThermostat: request not successful, restarting..!"); m_bDoLogin = true; return; } //Get Serial m_Serial = *members.begin(); //Get Structure members = root["structure"].getMemberNames(); if (members.size() < 1) { _log.Log(LOG_ERROR, "NestThermostat: request not successful, restarting..!"); m_bDoLogin = true; return; } m_StructureID = *members.begin(); Json::Value vShared = *root["shared"].begin(); //Setpoint if (!vShared["target_temperature"].empty()) { float currentSetpoint = vShared["target_temperature"].asFloat(); SendSetPointSensor(1, currentSetpoint, "Room Setpoint"); } //Room Temperature/Humidity if (!vShared["current_temperature"].empty()) { float currentTemp = vShared["current_temperature"].asFloat(); int Humidity = root["device"][m_Serial]["current_humidity"].asInt(); SendTempHumSensor(2, 255, currentTemp, Humidity, "Room TempHum"); } //Away Json::Value vStructure = *root["structure"].begin(); if (!vStructure["away"].empty()) { bool bIsAway = vStructure["away"].asBool(); SendSwitch(3, 1, 255, bIsAway, 0, "Away"); } }
bool CRFLink::ParseLine(const std::string &sLine) { m_LastReceivedTime = mytime(NULL); std::vector<std::string> results; StringSplit(sLine, ";", results); if (results.size() < 2) return false; //not needed bool bHideDebugLog = ( (sLine.find("PONG") != std::string::npos)|| (sLine.find("PING") != std::string::npos) ); int RFLink_ID = atoi(results[0].c_str()); if (RFLink_ID != 20) { return false; //only accept RFLink->Master messages } #ifdef ENABLE_LOGGING if (!bHideDebugLog) _log.Log(LOG_NORM, "RFLink: %s", sLine.c_str()); #endif //std::string Sensor_ID = results[1]; if (results.size() >2) { //Status reply std::string Name_ID = results[2]; if (Name_ID.find("Nodo RadioFrequencyLink") != std::string::npos) { _log.Log(LOG_STATUS, "RFLink: Controller Initialized!..."); //Enable DEBUG //write("10;RFDEBUG=ON;\n"); //Enable Undecoded DEBUG //write("10;RFUDEBUG=ON;\n"); return true; } if (Name_ID.find("OK") != std::string::npos) { //_log.Log(LOG_STATUS, "RFLink: OK received!..."); m_bTXokay = true; // variable to indicate an OK was received return true; } } if (results.size() < 4) return true; if (results[3].find("ID=") == std::string::npos) return false; //?? std::stringstream ss; unsigned int ID; ss << std::hex << results[3].substr(3); ss >> ID; int Node_ID = (ID & 0xFF00) >> 8; int Child_ID = ID & 0xFF; bool bHaveTemp = false; float temp = 0; bool bHaveHum = false; int humidity = 0; bool bHaveHumStatus = false; int humstatus = 0; bool bHaveBaro = false; float baro = 0; int baroforecast = 0; bool bHaveRain = false; int raincounter = 0; bool bHaveLux = false; float lux = 0; bool bHaveUV = false; float uv = 0; bool bHaveWindDir = false; int windir = 0; bool bHaveWindSpeed = false; float windspeed = 0; bool bHaveWindGust = false; float windgust = 0; bool bHaveWindTemp = false; float windtemp = 0; bool bHaveWindChill = false; float windchill = 0; bool bHaveRGB = false; int rgb = 0; bool bHaveRGBW = false; int rgbw = 0; bool bHaveSound = false; int sound = 0; bool bHaveCO2 = false; int co2 = 0; bool bHaveBlind = false; int blind = 0; bool bHaveKWatt = false; float kwatt = 0; bool bHaveWatt = false; float watt = 0; bool bHaveDistance = false; float distance = 0; bool bHaveMeter = false; float meter = 0; bool bHaveVoltage = false; float voltage = 0; bool bHaveCurrent = false; float current = 0; bool bHaveSwitch = false; int switchunit = 0; bool bHaveSwitchCmd = false; std::string switchcmd = ""; int switchlevel = 0; int BatteryLevel = 255; std::string tmpstr; int iTemp; for (size_t ii = 4; ii < results.size(); ii++) { if (results[ii].find("TEMP") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveTemp = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } temp = float(iTemp) / 10.0f; } else if (results[ii].find("HUM") != std::string::npos) { bHaveHum = true; humidity = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("HSTATUS") != std::string::npos) { bHaveHumStatus = true; humstatus = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("BARO") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveBaro = true; baro = float(iTemp); } else if (results[ii].find("BFORECAST") != std::string::npos) { baroforecast = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RAIN") != std::string::npos) { bHaveRain = true; raincounter = RFLinkGetHexStringValue(results[ii]); } else if (results[ii].find("LUX") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveLux = true; lux = float(iTemp); } else if (results[ii].find("UV") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveUV = true; uv = float(iTemp); } else if (results[ii].find("BAT") != std::string::npos) { tmpstr = RFLinkGetStringValue(results[ii]); BatteryLevel = (tmpstr == "OK") ? 100 : 0; } else if (results[ii].find("WINDIR") != std::string::npos) { bHaveWindDir = true; windir = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("WINSP") != std::string::npos) { bHaveWindSpeed = true; iTemp = RFLinkGetHexStringValue(results[ii]); windspeed = float(iTemp) * 0.0277778f; //convert to m/s } else if (results[ii].find("WINGS") != std::string::npos) { bHaveWindGust = true; iTemp = RFLinkGetHexStringValue(results[ii]); windgust = float(iTemp) * 0.0277778f; //convert to m/s } else if (results[ii].find("WINTMP") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWindTemp = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } windtemp = float(iTemp) / 10.0f; } else if (results[ii].find("WINCHL") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWindChill = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } windchill = float(iTemp) / 10.0f; } else if (results[ii].find("SOUND") != std::string::npos) { bHaveSound = true; sound = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("CO2") != std::string::npos) { bHaveCO2 = true; co2 = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RGBW") != std::string::npos) { bHaveRGBW = true; rgbw = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RGB") != std::string::npos) { bHaveRGB = true; rgb = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("BLIND") != std::string::npos) { bHaveBlind = true; blind = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("KWATT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveKWatt = true; kwatt = float(iTemp) / 10.0f; } else if (results[ii].find("WATT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWatt = true; watt = float(iTemp) / 10.0f; } else if (results[ii].find("DIST") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveDistance = true; distance = float(iTemp) / 10.0f; } else if (results[ii].find("METER") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveMeter = true; meter = float(iTemp) / 10.0f; } else if (results[ii].find("VOLT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveVoltage = true; voltage = float(iTemp) / 10.0f; } else if (results[ii].find("CURRENT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent = true; current = float(iTemp) / 10.0f; } else if (results[ii].find("SWITCH") != std::string::npos) { bHaveSwitch = true; switchunit = RFLinkGetHexStringValue(results[ii]); } else if (results[ii].find("CMD") != std::string::npos) { bHaveSwitchCmd = true; switchcmd = RFLinkGetStringValue(results[ii]); } else if (results[ii].find("SMOKEALERT") != std::string::npos) { bHaveSwitch = true; switchunit = 1; bHaveSwitchCmd = true; switchcmd = RFLinkGetStringValue(results[ii]); } } if (bHaveTemp&&bHaveHum&&bHaveBaro) { SendTempHumBaroSensor(ID, BatteryLevel, temp, humidity, baro, baroforecast); } else if (bHaveTemp&&bHaveHum) { SendTempHumSensor(ID, BatteryLevel, temp, humidity, "TempHum"); } else if (bHaveTemp) { SendTempSensor(ID, BatteryLevel, temp,"Temp"); } else if (bHaveHum) { SendHumiditySensor(ID, BatteryLevel, humidity); } else if (bHaveBaro) { SendBaroSensor(Node_ID, Child_ID, BatteryLevel, baro, baroforecast); } if (bHaveLux) { SendLuxSensor(Node_ID, Child_ID, BatteryLevel, lux, "Lux"); } if (bHaveUV) { SendUVSensor(Node_ID, Child_ID, BatteryLevel, uv); } if (bHaveRain) { SendRainSensor(ID, BatteryLevel, float(raincounter), "Rain"); } if (bHaveWindDir && bHaveWindSpeed && bHaveWindGust && bHaveWindChill) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, "Wind"); } else if (bHaveWindDir && bHaveWindGust) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, "Wind"); } else if (bHaveWindSpeed) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, "Wind"); } if (bHaveCO2) { SendAirQualitySensor((ID & 0xFF00) >> 8, ID & 0xFF, BatteryLevel, co2, "CO2"); } if (bHaveSound) { SendSoundSensor(ID, BatteryLevel, sound, "Sound"); } if (bHaveRGB) { //RRGGBB SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgb, false, "RGB Light"); } if (bHaveRGBW) { //RRGGBBWW SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgbw, true, "RGBW Light"); } if (bHaveBlind) { SendBlindSensor(Node_ID, Child_ID, BatteryLevel, blind, "Blinds/Window"); } if (bHaveKWatt) { SendKwhMeter(Node_ID, Child_ID, BatteryLevel, kwatt / 1000.0f, kwatt, "Meter"); } if (bHaveWatt) { SendKwhMeter(Node_ID, Child_ID, BatteryLevel, 0, watt, "Meter"); } if (bHaveDistance) { SendDistanceSensor(Node_ID, Child_ID, BatteryLevel, distance); } if (bHaveMeter) { SendMeterSensor(Node_ID, Child_ID, BatteryLevel, meter); } if (bHaveVoltage) { SendVoltageSensor(Node_ID, Child_ID, BatteryLevel, voltage, "Voltage"); } if (bHaveCurrent) { SendCurrentSensor(ID, BatteryLevel, current, 0, 0, "Current"); } if (bHaveSwitch && bHaveSwitchCmd) { std::string switchType = results[2]; SendSwitchInt(ID, switchunit, BatteryLevel, switchType, switchcmd, switchlevel); } return true; }
void CDarkSky::GetMeterDetails() { std::string sResult; #ifdef DEBUG_DarkSkyR sResult=ReadFile("E:\\DarkSky.json"); #else std::stringstream sURL; std::string szLoc = m_Location; std::string szExclude = "minutely,hourly,daily,alerts,flags"; sURL << "https://api.darksky.net/forecast/" << m_APIKey << "/" << szLoc << "?exclude=" << szExclude; try { bool bret; std::string szURL = sURL.str(); bret = HTTPClient::GET(szURL, sResult); if (!bret) { _log.Log(LOG_ERROR, "DarkSky: Error getting http data!."); return; } } catch (...) { _log.Log(LOG_ERROR, "DarkSky: Error getting http data!"); return; } #ifdef DEBUG_DarkSkyW SaveString2Disk(sResult, "E:\\DarkSky.json"); #endif #endif Json::Value root; Json::Reader jReader; bool ret=jReader.parse(sResult,root); if ((!ret) || (!root.isObject())) { _log.Log(LOG_ERROR,"DarkSky: Invalid data received! Check Location, use a City or GPS Coordinates (xx.yyyy,xx.yyyyy)"); return; } if (root["currently"].empty()==true) { _log.Log(LOG_ERROR,"DarkSky: Invalid data received, or unknown location!"); return; } /* std::string tmpstr2 = root.toStyledString(); FILE *fOut = fopen("E:\\DarkSky.json", "wb+"); fwrite(tmpstr2.c_str(), 1, tmpstr2.size(), fOut); fclose(fOut); */ float temp; int humidity=0; int barometric=0; int barometric_forcast=baroForecastNoInfo; temp=root["currently"]["temperature"].asFloat(); //Convert to celcius temp=float((temp-32)*(5.0/9.0)); if (root["currently"]["humidity"].empty()==false) { humidity=round(root["currently"]["humidity"].asFloat()*100.0f); } if (root["currently"]["pressure"].empty()==false) { barometric=atoi(root["currently"]["pressure"].asString().c_str()); if (barometric<1000) barometric_forcast=baroForecastRain; else if (barometric<1020) barometric_forcast=baroForecastCloudy; else if (barometric<1030) barometric_forcast=baroForecastPartlyCloudy; else barometric_forcast=baroForecastSunny; if (root["currently"]["icon"].empty()==false) { std::string forcasticon=root["currently"]["icon"].asString(); if ((forcasticon=="partly-cloudy-day")||(forcasticon=="partly-cloudy-night")) { barometric_forcast=baroForecastPartlyCloudy; } else if (forcasticon=="cloudy") { barometric_forcast=baroForecastCloudy; } else if ((forcasticon=="clear-day")||(forcasticon=="clear-night")) { barometric_forcast=baroForecastSunny; } else if ((forcasticon=="rain")||(forcasticon=="snow")) { barometric_forcast=baroForecastRain; } } } if (barometric!=0) { //Add temp+hum+baro device SendTempHumBaroSensor(1, 255, temp, humidity, static_cast<float>(barometric), barometric_forcast, "THB"); } else if (humidity!=0) { //add temp+hum device SendTempHumSensor(1, 255, temp, humidity, "TempHum"); } else { //add temp device SendTempSensor(1, 255, temp, "Temperature"); } //Wind int wind_degrees=-1; float windspeed_ms=0; float windgust_ms=0; float wind_temp=temp; float wind_chill=temp; int windgust=1; float windchill=-1; if (root["currently"]["windBearing"].empty()==false) { wind_degrees=atoi(root["currently"]["windBearing"].asString().c_str()); } if (root["currently"]["windSpeed"].empty()==false) { if ((root["currently"]["windSpeed"] != "N/A") && (root["currently"]["windSpeed"] != "--")) { float temp_wind_mph = static_cast<float>(atof(root["currently"]["windSpeed"].asString().c_str())); if (temp_wind_mph!=-9999.00f) { //convert to m/s windspeed_ms=temp_wind_mph*0.44704f; } } } if (root["currently"]["windGust"].empty()==false) { if ((root["currently"]["windGust"] != "N/A") && (root["currently"]["windGust"] != "--")) { float temp_wind_gust_mph = static_cast<float>(atof(root["currently"]["windGust"].asString().c_str())); if (temp_wind_gust_mph!=-9999.00f) { //convert to m/s windgust_ms=temp_wind_gust_mph*0.44704f; } } } if (root["currently"]["apparentTemperature"].empty()==false) { if ((root["currently"]["apparentTemperature"] != "N/A") && (root["currently"]["apparentTemperature"] != "--")) { wind_chill = static_cast<float>(atof(root["currently"]["apparentTemperature"].asString().c_str())); //Convert to celcius wind_chill=float((wind_chill-32)*(5.0/9.0)); } } if (wind_degrees!=-1) { RBUF tsen; memset(&tsen,0,sizeof(RBUF)); tsen.WIND.packetlength=sizeof(tsen.WIND)-1; tsen.WIND.packettype=pTypeWIND; tsen.WIND.subtype=sTypeWIND4; tsen.WIND.battery_level=9; tsen.WIND.rssi=12; tsen.WIND.id1=0; tsen.WIND.id2=1; float winddir=float(wind_degrees); int aw=round(winddir); tsen.WIND.directionh=(BYTE)(aw/256); aw-=(tsen.WIND.directionh*256); tsen.WIND.directionl=(BYTE)(aw); tsen.WIND.av_speedh=0; tsen.WIND.av_speedl=0; int sw=round(windspeed_ms*10.0f); tsen.WIND.av_speedh=(BYTE)(sw/256); sw-=(tsen.WIND.av_speedh*256); tsen.WIND.av_speedl=(BYTE)(sw); tsen.WIND.gusth=0; tsen.WIND.gustl=0; int gw=round(windgust_ms*10.0f); tsen.WIND.gusth=(BYTE)(gw/256); gw-=(tsen.WIND.gusth*256); tsen.WIND.gustl=(BYTE)(gw); //this is not correct, why no wind temperature? and only chill? tsen.WIND.chillh=0; tsen.WIND.chilll=0; tsen.WIND.temperatureh=0; tsen.WIND.temperaturel=0; tsen.WIND.tempsign=(wind_temp>=0)?0:1; int at10=round(std::abs(wind_temp*10.0f)); tsen.WIND.temperatureh=(BYTE)(at10/256); at10-=(tsen.WIND.temperatureh*256); tsen.WIND.temperaturel=(BYTE)(at10); tsen.WIND.chillsign=(wind_temp>=0)?0:1; at10=round(std::abs(wind_chill*10.0f)); tsen.WIND.chillh=(BYTE)(at10/256); at10-=(tsen.WIND.chillh*256); tsen.WIND.chilll=(BYTE)(at10); sDecodeRXMessage(this, (const unsigned char *)&tsen.WIND, NULL, 255); } //UV if (root["currently"]["uvIndex"].empty() == false) { if ((root["currently"]["uvIndex"] != "N/A") && (root["currently"]["uvIndex"] != "--")) { float UV = root["currently"]["uvIndex"].asFloat(); if ((UV < 16) && (UV >= 0)) { SendUVSensor(0, 1, 255, UV, "UV Index"); } } } //Rain if (root["currently"]["precipIntensity"].empty()==false) { if ((root["currently"]["precipIntensity"] != "N/A") && (root["currently"]["precipIntensity"] != "--")) { float RainCount = static_cast<float>(atof(root["currently"]["precipIntensity"].asString().c_str()))*25.4f; //inches to mm if ((RainCount!=-9999.00f)&&(RainCount>=0.00f)) { RBUF tsen; memset(&tsen,0,sizeof(RBUF)); tsen.RAIN.packetlength=sizeof(tsen.RAIN)-1; tsen.RAIN.packettype=pTypeRAIN; tsen.RAIN.subtype=sTypeRAINWU; tsen.RAIN.battery_level=9; tsen.RAIN.rssi=12; tsen.RAIN.id1=0; tsen.RAIN.id2=1; tsen.RAIN.rainrateh=0; tsen.RAIN.rainratel=0; int tr10=int((float(RainCount)*10.0f)); tsen.RAIN.raintotal1=0; tsen.RAIN.raintotal2=(BYTE)(tr10/256); tr10-=(tsen.RAIN.raintotal2*256); tsen.RAIN.raintotal3=(BYTE)(tr10); sDecodeRXMessage(this, (const unsigned char *)&tsen.RAIN, NULL, 255); } } } //Visibility if (root["currently"]["visibility"].empty()==false) { if ((root["currently"]["visibility"] != "N/A") && (root["currently"]["visibility"] != "--")) { float visibility = static_cast<float>(atof(root["currently"]["visibility"].asString().c_str()))*1.60934f; //miles to km if (visibility>=0) { _tGeneralDevice gdevice; gdevice.subtype=sTypeVisibility; gdevice.floatval1=visibility; sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255); } } } //Solar Radiation if (root["currently"]["ozone"].empty()==false) { if ((root["currently"]["ozone"] != "N/A") && (root["currently"]["ozone"] != "--")) { float radiation = static_cast<float>(atof(root["currently"]["ozone"].asString().c_str())); if (radiation>=0.0f) { SendCustomSensor(1, 0, 255, radiation, "Ozone Sensor", "DU"); //(dobson units) } } } }
void CDaikin::GetSensorInfo() { std::string sResult; #ifdef DEBUG_DaikinR sResult = ReadFile("E:\\Daikin_get_sensor_info.txt"); #else std::stringstream szURL; if (m_Password.empty()) { szURL << "http://" << m_szIPAddress << ":" << m_usIPPort; } else { szURL << "http://" << m_Username << ":" << m_Password << "@" << m_szIPAddress << ":" << m_usIPPort; } szURL << "/aircon/get_sensor_info"; if (!HTTPClient::GET(szURL.str(), sResult)) { _log.Log(LOG_ERROR, "Daikin: Error connecting to: %s", m_szIPAddress.c_str()); return; } #ifdef DEBUG_DaikinW SaveString2Disk(sResult, "E:\\Daikin_get_sensor_info.txt"); #endif #endif if (sResult.find("ret=OK") == std::string::npos) { _log.Log(LOG_ERROR, "Daikin: Error getting data (check IP/Port)"); return; } std::vector<std::string> results; StringSplit(sResult, ",", results); if (results.size() < 6) { _log.Log(LOG_ERROR, "Daikin: Invalid data received"); return; } float htemp = -1; int hhum = -1; std::vector<std::string>::const_iterator itt; for (itt = results.begin(); itt != results.end(); ++itt) { std::string sVar = *itt; std::vector<std::string> results2; StringSplit(sVar, "=", results2); if (results2.size() != 2) continue; if (results2[0] == "htemp") { htemp = static_cast<float>(atof(results2[1].c_str())); } else if (results2[0] == "hhum") { if (results2[1]!="-") hhum = static_cast<int>(atoi(results2[1].c_str())); } else if (results2[0] == "otemp") { SendTempSensor(11, -1, static_cast<float>(atof(results2[1].c_str())), "Outside Temperature"); } if (htemp != -1) { if (hhum != -1) SendTempHumSensor(10, -1, htemp, hhum, "Home Temp+Hum"); else SendTempSensor(10, -1, htemp, "Home Temperature"); } } }