Esempio n. 1
0
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;
	}
}
Esempio n. 2
0
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;
}