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; } }
bool CToonThermostat::ParsePowerUsage(const Json::Value &root) { if (root["powerUsage"].empty()) return false; time_t atime = mytime(NULL); unsigned long powerusage1 = (unsigned long)(root["powerUsage"]["meterReadingLow"].asFloat()); unsigned long powerusage2 = (unsigned long)(root["powerUsage"]["meterReading"].asFloat()); if ((powerusage1 == 0) && (powerusage2 == 0)) { //New firmware does not provide meter readings anymore if (root["powerUsage"]["dayUsage"].empty() == false) { unsigned long usage1 = (unsigned long)(root["powerUsage"]["dayUsage"].asFloat()); unsigned long usage2 = (unsigned long)(root["powerUsage"]["dayLowUsage"].asFloat()); if (usage1 < m_LastUsage1) { m_OffsetUsage1 += m_LastUsage1; } if (usage2 < m_LastUsage2) { m_OffsetUsage2 += m_LastUsage2; } m_p1power.powerusage1 = m_OffsetUsage1 + usage1; m_p1power.powerusage2 = m_OffsetUsage2 + usage2; m_LastUsage1 = usage1; m_LastUsage2 = usage2; } } else { m_p1power.powerusage1 = powerusage1; m_p1power.powerusage2 = powerusage2; } if (root["powerUsage"]["meterReadingProdu"].empty() == false) { unsigned long powerdeliv1 = (unsigned long)(root["powerUsage"]["meterReadingLowProdu"].asFloat()); unsigned long powerdeliv2 = (unsigned long)(root["powerUsage"]["meterReadingProdu"].asFloat()); if ((powerdeliv1 != 0) || (powerdeliv2 != 0)) { m_p1power.powerdeliv1 = powerdeliv1; m_p1power.powerdeliv2 = powerdeliv2; } else { //Have not received an example from a user that has produced with the new firmware //for now ignoring } } m_p1power.usagecurrent = (unsigned long)(root["powerUsage"]["value"].asFloat()); //Watt m_p1power.delivcurrent = (unsigned long)(root["powerUsage"]["valueProduced"].asFloat()); //Watt if (root["powerUsage"]["valueSolar"].empty() == false) { float valueSolar = (float)(root["powerUsage"]["valueSolar"].asFloat()); if (valueSolar != 0) { SendWattMeter(1, 1, 255, valueSolar, "Solar"); } } //Send Electra if value changed, or at least every 5 minutes if ( (m_p1power.usagecurrent != m_lastelectrausage) || (m_p1power.delivcurrent != m_lastelectradeliv) || (atime - m_lastSharedSendElectra >= 300) ) { if ((m_p1power.powerusage1 != 0) || (m_p1power.powerusage2 != 0) || (m_p1power.powerdeliv1 != 0) || (m_p1power.powerdeliv2 != 0)) { m_lastSharedSendElectra = atime; m_lastelectrausage = m_p1power.usagecurrent; m_lastelectradeliv = m_p1power.delivcurrent; sDecodeRXMessage(this, (const unsigned char *)&m_p1power, NULL, 255); } } return true; }