void CHardwareMonitor::UpdateSystemSensor(const std::string& qType, const int dindex, const std::string& devName, const std::string& devValue)
{
	if (!m_HwdID) {
#ifdef _DEBUG
		_log.Log(LOG_NORM,"Hardware Monitor: Id not found!");
#endif		
		return;
	}
	int doffset = 0;
	if (qType == "Temperature")
	{
		doffset = 1000;
		float temp = static_cast<float>(atof(devValue.c_str()));
		SendTempSensor(doffset + dindex, 255, temp, devName);
	}
	else if (qType == "Load")
	{
		doffset = 1100;
		float perc = static_cast<float>(atof(devValue.c_str()));
		SendPercentageSensor(doffset + dindex, 0, 255, perc, devName);
	}
	else if (qType == "Fan")
	{
		doffset = 1200;
		int fanspeed = atoi(devValue.c_str());
		SendFanSensor(doffset + dindex, fanspeed, devName);
	}
	else if (qType == "Voltage")
	{
		doffset = 1300;
		float volt = static_cast<float>(atof(devValue.c_str()));
		SendVoltageSensor(0, doffset + dindex, 255, volt, devName);
	}
	else if (qType == "Current")
	{
		doffset = 1400;
		float curr = static_cast<float>(atof(devValue.c_str()));
		SendCurrent(doffset + dindex, curr, devName);
	}
	return;
}
void CHardwareMonitor::GetInternalVoltage()
{
	std::vector<std::string> ret = ExecuteCommandAndReturn(szInternalVoltageCommand);
	if (ret.empty())
		return;
	std::string tmpline = ret[0];
	if (tmpline.find("volt=") == std::string::npos)
		return;
	tmpline = tmpline.substr(5);
	size_t pos = tmpline.find("'");
	if (pos != std::string::npos)
	{
		tmpline = tmpline.substr(0, pos);
	}

	float voltage = static_cast<float>(atof(tmpline.c_str()));
	if (voltage == 0)
		return; //hardly possible for a on board temp sensor, if it is, it is probably not working

	SendVoltageSensor(0, 1, 255, voltage, "Internal Voltage");
}
Example #3
0
void CSterbox::GetMeterDetails()
{
	std::string sResult;
	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 << "/x.cgi"; 

	if (!HTTPClient::GET(szURL.str(),sResult))
	{
		_log.Log(LOG_ERROR,"Sterbox: Error connecting to: %s", m_szIPAddress.c_str());
		return;
	}
	std::vector<std::string> results;
	std::vector<std::string> outputs;
	std::vector<std::string> inputs;
	std::vector<std::string> analog;
	StringSplit(sResult, "<br>", results);
	if (results.size()<8)
	{
		_log.Log(LOG_ERROR,"Sterbox: Result 8 Error connecting to: %s", m_szIPAddress.c_str());
		return;
	}
	//if (results[0] != "<body>")
	std::string tmpstr;
	std::string tmpstr2;
	std::string tmpinp;
	tmpstr = results[0];
	if (tmpstr.find("<title>SterBox_State</title>") != std::string::npos)
	{
		_log.Log(LOG_ERROR, "Sterbox: Error getting status");
		return;
	}
	size_t ii;
	size_t jj;
	int pos1;
	int Idx = 0;

	if (m_Username.empty())
	{
		StringSplit("o,o,o,o,i,i,i,i", ",", inputs);
	}
	else
	{
		StringSplit(m_Username, ",", inputs);
		//_log.Log(LOG_ERROR,"Sterbox: Username : %s , IP: %s", m_Username.c_str(), m_szIPAddress.c_str());
	}

	for (ii = 1; ii < results.size(); ii++)
	{
		tmpstr = results[ii];
		if (tmpstr.find("OU") != std::string::npos)
		{
			tmpstr = tmpstr.substr(strlen("OU"));
			pos1 = tmpstr.find("=");
			if (pos1 != std::string::npos)
			{	
				tmpstr = tmpstr.substr(pos1+1);
				//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr.c_str());
				StringSplit(tmpstr, ",", outputs);
				for (jj = 0; jj < inputs.size(); jj++) 
				{	
					tmpinp = inputs[jj];
					//if (( jj < 4 || jj > 7  ))
					pos1 = tmpinp.find("o");
					if (pos1 != std::string::npos)
					{
					int lValue = 0;
					//tmpstr = tmpstr.substr(pos1+1);
					tmpstr2 = outputs[jj];
					//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr2.c_str());
					pos1 = tmpstr2.find("s");
					if (pos1 != std::string::npos)
					{
						lValue = 1;
					}
					else
					{
						lValue = 0;
					}
					std::stringstream sstr;
					sstr << "Relay " << jj;
					UpdateSwitch(1, jj, (lValue == 1) ? true : false, 100, sstr.str());
					}
				}
			}
		}
		else if (tmpstr.find("IN") != std::string::npos)
		{
			tmpstr = tmpstr.substr(strlen("IN"));
			pos1 = tmpstr.find("=");
			if (pos1 != std::string::npos)
			{	
				tmpstr = tmpstr.substr(pos1+1);
				//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr.c_str());
				StringSplit(tmpstr, ",", outputs);
				for (jj = 0; jj < inputs.size(); jj++) 
				{	
					tmpinp = inputs[jj];
					//if (( jj > 3 && jj < 8  ))
					pos1 = tmpinp.find("i");
					if (pos1 != std::string::npos)
					{
					int lValue = 0;
					//tmpstr = tmpstr.substr(pos1+1);
					tmpstr2 = outputs[jj];
					//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr2.c_str());
					pos1 = tmpstr2.find("S");
					if (pos1 != std::string::npos)
					{
						lValue = 1;
					}
					else
					{
						lValue = 0;
					}
					std::stringstream sstr;
					sstr << "Relay " << jj;
					UpdateSwitch(1, jj, (lValue == 1) ? true : false, 100, sstr.str());
					}
				}
			}
		}
		else if (tmpstr.find("AN") != std::string::npos)
		{
			tmpstr = tmpstr.substr(strlen("AN"));
			pos1 = tmpstr.find("=");
			if (pos1 != std::string::npos)
			{
				tmpstr = tmpstr.substr(pos1+1);
				StringSplit(tmpstr, ",", outputs);
				if (m_Password.empty())
				{
					StringSplit("t,t,t", ",", analog);
				}
				else
				{
					//StringSplit("t,t,t", ",", inputs);
					StringSplit(m_Password, ",", analog);
				//_log.Log(LOG_ERROR,"Sterbox: Pass : %s", m_Password.c_str());

				}
				for (jj = 0; jj < 3; jj++)
				{
					tmpstr2 = outputs[jj];
					tmpinp = analog[jj];
					tmpstr2 = tmpstr2.substr(1, 10);

					float lValue = (float)atof(tmpstr2.c_str());
					std::stringstream sstr;
					sstr << "Analog " << jj;
					pos1 = tmpinp.find("t");
					if (pos1 != std::string::npos)
					{
						SendTempSensor(jj,255,lValue, sstr.str());
					}
					pos1 = tmpinp.find("v");
					if (pos1 != std::string::npos)
					{
						SendVoltageSensor(0, jj, 255, lValue, sstr.str());
					}
					pos1 = tmpinp.find("l");
					if (pos1 != std::string::npos)
					{
						SendLuxSensor(0, jj, 255,lValue, sstr.str());
					}
					pos1 = tmpinp.find("h");
					if (pos1 != std::string::npos)
					{
						SendHumiditySensor(jj,255,int(lValue), sstr.str());
					}
	
					//SendTempSensor(jj,255,lValue, sstr.str());
					//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr2.c_str());

				}
				//Idx = atoi(tmpstr.substr(0, pos1).c_str());
				//tmpstr = tmpstr.substr(pos1 + 1);
				//pos1 = tmpstr.find("<");
				//if (pos1 != std::string::npos)
				//{
				//	int lValue = atoi(tmpstr.substr(0, pos1).c_str());
				//	float voltage = (float)(5.0f / 1023.0f)*lValue;
				//	if (voltage > 5.0f)
				//		voltage = 5.0f;
				//	std::stringstream sstr;
				//	sstr << "Voltage " << Idx;
				//	SendVoltageSensor(0, Idx, 255, voltage, sstr.str());
				//}
			}
		}
	}
}
Example #4
0
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;
}
Example #5
0
void CSBFSpot::GetMeterDetails()
{
	if (m_SBFDataPath.size() == 0)
	{
		_log.Log(LOG_ERROR, "SBFSpot: Data path empty!");
		return;
	}
	if (m_SBFPlantName.size() == 0)
	{
		_log.Log(LOG_ERROR, "SBFSpot: Plant name empty!");
		return;
	}

	time_t atime = time(NULL);
	struct tm ltime;
	localtime_r(&atime, &ltime);

	int ActHourMin = (ltime.tm_hour * 60) + ltime.tm_min;

	int sunRise = getSunRiseSunSetMinutes(true);
	int sunSet = getSunRiseSunSetMinutes(false);

	//We only poll one hour before sunrise till one hour after sunset
	if (ActHourMin + 120 < sunRise)
		return;
	if (ActHourMin - 120 > sunSet)
		return;

	char szLogFile[256];
	char szDateStr[50];
	strcpy(szDateStr, strftime_t("%Y%m%d", atime));
	sprintf(szLogFile, "%s%s-Spot-%s.csv", strftime_t(m_SBFDataPath.c_str(), atime), m_SBFPlantName.c_str(), szDateStr);

	std::string szSeperator = ";";
	bool bHaveVersion = false;
	std::string tmpString;
	std::ifstream infile;
	std::string szLastDate = "";
	std::vector<std::string> szLastLines;
	std::vector<std::string> results;
	std::string sLine;
	infile.open(szLogFile);
	if (!infile.is_open())
	{
		if ((ActHourMin > sunRise) && (ActHourMin < sunSet))
		{
			_log.Log(LOG_ERROR, "SBFSpot: Could not open spot file: %s", szLogFile);
		}
		return;
	}
	while (!infile.eof())
	{
		getline(infile, sLine);
		sLine.erase(std::remove(sLine.begin(), sLine.end(), '\r'), sLine.end());
		if (sLine.size() != 0)
		{
			if (sLine.find("sep=") == 0)
			{
				tmpString = sLine.substr(strlen("sep="));
				if (tmpString != "")
				{
					szSeperator = tmpString;
				}
			}
			else if (sLine.find("Version CSV1") == 0)
			{
				bHaveVersion = true;
			}
			else if (bHaveVersion)
			{
				if (
					(sLine.find(";DeviceName") == std::string::npos) &&
					(sLine.find(";Watt") == std::string::npos)
					)
				{
					StringSplit(sLine, szSeperator, results);
					if (results.size() >= 30)
					{
						if (m_SBFInverter.empty() || (m_SBFInverter == results[3]))
						{
							if (szLastDate.empty() || (szLastDate != results[0]))
							{
								szLastDate = results[0];
								szLastLines.clear();
							}
							if (szLastDate == results[0])
							{
								szLastLines.push_back(sLine);
							}
						}
					}
				}
			}
		}
	}
	infile.close();

	if (szLastLines.empty())
	{
		_log.Log(LOG_ERROR, "SBFSpot: No data record found in spot file!");
		return;
	}

	if (szLastDate == m_LastDateTime)
	{
		return;
	}
	m_LastDateTime = szLastDate;

	double kWhCounter = 0;
	double Pac = 0;
	int InvIdx = 0;

	std::vector<std::string>::const_iterator itt;
	for (itt = szLastLines.begin(); itt != szLastLines.end(); ++itt)
	{
		StringSplit(*itt, szSeperator, results);

		if (results[1].size() < 1)
		{
			_log.Log(LOG_ERROR, "SBFSpot: No data record found in spot file!");
			return;
		}
		if ((results[28] != "OK") && (results[28] != "Ok"))
		{
			_log.Log(LOG_ERROR, "SBFSpot: Invalid field [28] should be OK!");
			return;
		}

		std::string szKwhCounter = results[23];
		stdreplace(szKwhCounter, ",", ".");
		kWhCounter += atof(szKwhCounter.c_str());
		std::string szPacActual = results[20];
		stdreplace(szPacActual, ",", ".");
		Pac += atof(szPacActual.c_str());

		float voltage;
		tmpString = results[16];
		stdreplace(tmpString, ",", ".");
		voltage = static_cast<float>(atof(tmpString.c_str()));
		SendVoltageSensor(0, (InvIdx * 10) + 1, 255, voltage, "Volt uac1");
		tmpString = results[17];
		stdreplace(tmpString, ",", ".");
		voltage = static_cast<float>(atof(tmpString.c_str()));
		if (voltage != 0) {
			SendVoltageSensor(0, (InvIdx * 10) + 2, 255, voltage, "Volt uac2");
		}
		tmpString = results[18];
		stdreplace(tmpString, ",", ".");
		voltage = static_cast<float>(atof(tmpString.c_str()));
		if (voltage != 0) {
			SendVoltageSensor(0, (InvIdx * 10) + 3, 255, voltage, "Volt uac3");
		}

		float percentage;
		tmpString = results[21];
		stdreplace(tmpString, ",", ".");
		percentage = static_cast<float>(atof(tmpString.c_str()));
		SendPercentageSensor((InvIdx * 10) + 1, 0, 255, percentage, "Efficiency");
		tmpString = results[24];
		stdreplace(tmpString, ",", ".");
		percentage = static_cast<float>(atof(tmpString.c_str()));
		SendPercentageSensor((InvIdx * 10) + 2, 0, 255, percentage, "Hz");
		tmpString = results[27];
		stdreplace(tmpString, ",", ".");
		percentage = static_cast<float>(atof(tmpString.c_str()));
		SendPercentageSensor((InvIdx * 10) + 3, 0, 255, percentage, "BT_Signal");

		if (results.size() >= 31)
		{
			tmpString = results[30];
			stdreplace(tmpString, ",", ".");
			float temperature = static_cast<float>(atof(tmpString.c_str()));
			SendTempSensor((InvIdx * 10) + 1, 255, temperature, "Temperature");
		}
		InvIdx++;
	}
	//Send combined counter/pac
	if (kWhCounter != 0)
	{
		double LastUsage = 0;
		double LastTotal = 0;
		if (GetMeter(0, 1, LastUsage, LastTotal))
		{
			if (kWhCounter < (int)(LastTotal * 100) / 100)
			{
				_log.Log(LOG_ERROR, "SBFSpot: Actual KwH counter (%f) less then last Counter (%f)!", kWhCounter, LastTotal);
				return;
			}
		}
		SendMeter(0, 1, Pac / 1000.0, kWhCounter, "SolarMain");
	}
}
Example #6
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;
	}
}
Example #7
0
void SolarMaxTCP::ParseLine()
{
	std::string InputStr = std::string((const char*)&m_buffer);
	size_t npos = InputStr.find("|");
	if (npos == std::string::npos)
	{
		_log.Log(LOG_ERROR, "SolarMax: Invalid data received!");
		return;
	}
	InputStr = InputStr.substr(npos + 4);
	npos = InputStr.find("|");
	if (npos == std::string::npos)
	{
		_log.Log(LOG_ERROR, "SolarMax: Invalid data received!");
		return;
	}
	InputStr = InputStr.substr(0,npos);

	std::vector<std::string> results;
	StringSplit(InputStr, ";", results);
	if (results.size() < 2)
		return; //invalid data

	std::vector<std::string>::const_iterator itt;

	double kwhCounter = 0;
	double ActUsage = 0;

	for (itt = results.begin(); itt != results.end(); ++itt)
	{
		std::vector<std::string> varresults;
		StringSplit(*itt, "=", varresults);
		if (varresults.size() !=2)
			continue;

		std::string sLabel = varresults[0];
		std::string sVal = varresults[1];

		if (sLabel == "KT0")
		{
			//Energy total
			kwhCounter = SolarMaxGetHexStringValue(sVal);// / 10.0f;
		}
		else if (sLabel == "KDY")
		{
			//Energy Today
		}
		else if (sLabel == "PAC")
		{
			//AC power
			ActUsage = SolarMaxGetHexStringValue(sVal)/2.0f;
		}
		else if (sLabel == "UDC")
		{
			//DC voltage [mV]
			float voltage = float(SolarMaxGetHexStringValue(sVal)) / 10.0f;
			SendVoltageSensor(1, 2, 255, voltage, "DC voltage");
		}
		else if (sLabel == "UL1")
		{
			//AC voltage [mV]
			float voltage = float(SolarMaxGetHexStringValue(sVal)) / 10.0f;
			SendVoltageSensor(1, 3, 255, voltage, "AC voltage");
		}
		else if (sLabel == "IDC")
		{
			//DC current [mA]
			float amps = float(SolarMaxGetHexStringValue(sVal)) / 100.0f;
			SendCurrentSensor(4, 255, amps, 0, 0, "DC current");
		}
		else if (sLabel == "IL1")
		{
			//AC current [mA]
			float amps = float(SolarMaxGetHexStringValue(sVal)) / 100.0f;
			SendCurrentSensor(5, 255, amps, 0, 0, "AC current");
		}
		else if (sLabel == "PIN")
		{
			//Power installed [mW] (PIN)
			//float power_installed = (float)SolarMaxGetHexStringValue(sVal);
		}
		else if (sLabel == "PRL")
		{
			//AC power [%]
			float percentage = (float)SolarMaxGetHexStringValue(sVal);
			SendPercentageSensor(6, 6, 255, percentage, "AC power Percentage");
		}
		else if (sLabel == "TNF")
		{
			//AC Frequency (Hz)
			float freq = (float)SolarMaxGetHexStringValue(sVal)/100;
			SendPercentageSensor(7, 7, 255, freq, "Hz");
		}
		else if (sLabel == "TKK")
		{
			//Temperature Heat Sink
			float temp = (float)SolarMaxGetHexStringValue(sVal);// / 10.0f;
			SendTempSensor(8, 255, temp,"Temperature Heat Sink");
		}
	}
	if (kwhCounter != 0)
	{
		SendKwhMeterOldWay(1, 1, 255, ActUsage/1000.0f, kwhCounter, "kWh Meter");
	}

}
Example #8
0
int SolarEdgeBase::ParsePacket0x0500(const unsigned char *pData, int dlen)
{
	const unsigned char *b=pData;
	short *pShort;

	int orgdlen=dlen;
	//Meter and Panel report
	while (dlen>20)
	{
		bool bIsPanel=false;
		bool bIsMain=false;
		bool bIs0300=false;
		//0000 for Panel, 0010 for Main?
		pShort=(short*)b;
		int ReportType=*pShort;
		b+=2;
		dlen-=2;

		if (ReportType==0x000)
		{
			bIsPanel=true;
			bIsMain=false;
			bIs0300=false;
		}
		else if (ReportType==0x0010)
		{
			bIsPanel=false;
			bIsMain=true;
			bIs0300=false;
		}
		else if (ReportType==0x0300)
		{
			bIsPanel=false;
			bIsMain=false;
			bIs0300=true;
		}
		else
		{
			//don't know you!
			return orgdlen-2;
		}

		//PanelID/Main
		unsigned long ID2=*(unsigned long*)b;
		//sprintf_s(szTmp,"\"%08X\"",ID2);
		b+=4;
		dlen-=4;
		//rest bytes
		pShort=(short*)b;
		int restbytes=*pShort;
		//sprintf_s(szTmp,"\"%04d\"",restbytes);
		b+=2;
		dlen-=2;

		const unsigned char *b2=(const BYTE*)b;
		int len2=restbytes;
		//Something
		//sprintf_s(szTmp,"\"%02X%02X\"",b2[0],b2[1]);
		b2+=2;
		len2-=2;
		//F052 (F352 for 0300)
		b2+=2;
		len2-=2;
		//2 times ID
		b2+=4;
		len2-=4;
		//uL=*(unsigned long*)b2;
		b2+=4;
		len2-=4;

		if (bIsMain)
		{
			//Temp
			float temp=GetFloat(b2);
			b2+=4;
			//Watt P-Out
			float Watt=GetFloat(b2);
			b2+=4;
			float Pac=GetFloat(b2);
			b2+=4;
			//AC Voltage
			float voltageAC=GetFloat(b2);
			b2+=4;
			//Iets2
			float Iets2=GetFloat(b2);
			b2+=4;
			//Frequency
			float freq=GetFloat(b2);
			b2+=4;
			//Iets3
			float Iets3=GetFloat(b2);
			b2+=4;
			//Iets4
			float Iets4=GetFloat(b2);
			b2+=4;
			//DC Voltage
			float voltageDC=GetFloat(b2);
			b2+=4;
			//Iets5
			float Iets5=GetFloat(b2);
			b2+=4;
			//Counter
			float counter=GetFloat(b2);
			b2+=4;
			SendMeter(0,1, Pac/100.0f, counter/1000.0f, "SolarMain");
			SendTempSensor(1, 255, temp, "SolarMain");
			SendPercentageSensor(SE_FREQ, 0, 255, freq, "Hz");
			SendVoltageSensor(0, SE_VOLT_AC, 255, voltageAC, "AC");
			SendVoltageSensor(0, SE_VOLT_DC, 255, voltageDC, "DC");
		}
		b+=restbytes;
		dlen-=restbytes;
		continue;
	}
	return (b-pData);
}
Example #9
0
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;
}
Example #10
0
bool P1MeterBase::MatchLine()
{
	if ((strlen((const char*)&l_buffer)<1)||(l_buffer[0]==0x0a))
		return true; //null value (startup)
	uint8_t i;
	uint8_t found=0;
	Match *t;
	char value[20]="";
	std::string vString;

	for(i=0;(i<sizeof(matchlist)/sizeof(Match))&(!found);i++)
	{
		t = &matchlist[i];
		switch(t->matchtype)
		{
		case ID:
			// start of data
			if(strncmp(t->key, (const char*)&l_buffer, strlen(t->key)) == 0) {
				m_linecount=1;
				found=1;
			}
			continue; // we do not process anything else on this line
			break;
		case EXCLMARK:
			// end of data
			if(strncmp(t->key, (const char*)&l_buffer, strlen(t->key)) == 0) {
				l_exclmarkfound=1;
				found=1;
			}
			break;
		case STD:
			if(strncmp(t->key, (const char*)&l_buffer, strlen(t->key)) == 0)
				found=1;
			break;
		case DEVTYPE:
			if(m_gasmbuschannel==0){
				vString=(const char*)t->key+3;
				if (strncmp(vString.c_str(), (const char*)&l_buffer+3, strlen(t->key)-3) == 0)
					found=1;
				else
					i+=100; // skip matches with any other gas lines - we need to find the M0-Bus channel first
			}
			break;
		case GAS:
			if(strncmp((m_gasprefix+(t->key+3)).c_str(), (const char*)&l_buffer, strlen(t->key)) == 0){
				found=1;
			}
			if (m_p1version>=4)
				i+=100; // skip matches with any DSMR v2 gas lines
			break;
		case LINE17:
			if(strncmp((m_gasprefix+(t->key+3)).c_str(), (const char*)&l_buffer, strlen(t->key)) == 0){
				m_linecount = 17;
				found=1;
			}
			break;
		case LINE18:
			if((m_linecount == 18)&&(strncmp(t->key, (const char*)&l_buffer, strlen(t->key)) == 0))
				found=1;
			break;
		} //switch

		if(!found)
			continue;

		if (l_exclmarkfound) {
			if (m_p1version==0)
			{
				_log.Log(LOG_STATUS,"P1 Smart Meter: Meter is pre DSMR 4.0 - using DSMR 2.2 compatibility");
				m_p1version=2;
			}
			time_t atime=mytime(NULL);
			if (difftime(atime,m_lastUpdateTime)>=m_ratelimit) {
				m_lastUpdateTime=atime;
				sDecodeRXMessage(this, (const unsigned char *)&m_power, "Power", 255);
				if (m_voltagel1) {
					SendVoltageSensor(0, 1, 255, m_voltagel1, "Voltage L1");
					if (m_voltagel2)
						SendVoltageSensor(0, 2, 255, m_voltagel2, "Voltage L2");
					if (m_voltagel3)
						SendVoltageSensor(0, 3, 255, m_voltagel3, "Voltage L3");
				}
				if ( (m_gas.gasusage>0)&&( (m_gas.gasusage!=m_lastgasusage)||(difftime(atime,m_lastSharedSendGas)>=300) ) ){
					//only update gas when there is a new value, or 5 minutes are passed
					if (m_gasclockskew>=300){ // just accept it - we cannot sync to our clock
						m_lastSharedSendGas=atime;
						m_lastgasusage=m_gas.gasusage;
						sDecodeRXMessage(this, (const unsigned char *)&m_gas, "Gas", 255);
					}
					else if (atime>=m_gasoktime){
						struct tm ltime;
						localtime_r(&atime, &ltime);
						char myts[16];
						sprintf(myts,"%02d%02d%02d%02d%02d%02dW",ltime.tm_year%100,ltime.tm_mon+1,ltime.tm_mday,ltime.tm_hour,ltime.tm_min,ltime.tm_sec);
						if (ltime.tm_isdst)
						myts[12]='S';
						if ( (m_gastimestamp.length()>13) || (strncmp((const char*)&myts,m_gastimestamp.c_str(),m_gastimestamp.length())>=0) )
						{
							m_lastSharedSendGas=atime;
							m_lastgasusage=m_gas.gasusage;
							m_gasoktime+=300;
							sDecodeRXMessage(this, (const unsigned char *)&m_gas, "Gas", 255);
						}
						else // gas clock is ahead
						{
							struct tm gastm;
							gastm.tm_year = atoi(m_gastimestamp.substr(0, 2).c_str()) + 100;
							gastm.tm_mon = atoi(m_gastimestamp.substr(2, 2).c_str()) - 1;
							gastm.tm_mday = atoi(m_gastimestamp.substr(4, 2).c_str());
							gastm.tm_hour = atoi(m_gastimestamp.substr(6, 2).c_str());
							gastm.tm_min = atoi(m_gastimestamp.substr(8, 2).c_str());
							gastm.tm_sec = atoi(m_gastimestamp.substr(10, 2).c_str());
							if (m_gastimestamp.length()==12)
								gastm.tm_isdst = -1;
							else if (m_gastimestamp[12]=='W')
								gastm.tm_isdst = 0;
							else
								gastm.tm_isdst = 1;

							time_t gtime=mktime(&gastm);
							m_gasclockskew=difftime(gtime,atime);
							if (m_gasclockskew>=300){
								_log.Log(LOG_ERROR, "P1 Smart Meter: Unable to synchronize to the gas meter clock because it is more than 5 minutes ahead of my time");
							}
							else {
								m_gasoktime=gtime;
								_log.Log(LOG_STATUS, "P1 Smart Meter: Gas meter clock is %i seconds ahead - wait for my clock to catch up", (int)m_gasclockskew);
							}
						}
					}
				}
			}
			m_linecount=0;
			l_exclmarkfound=0;
		}
		else
		{
			vString=(const char*)&l_buffer+t->start;
			int ePos=t->width;
			ePos=vString.find_first_of("*)");

			if (ePos==std::string::npos)
			{
				// invalid message: value not delimited
				_log.Log(LOG_NORM,"P1 Smart Meter: Dismiss incoming - value is not delimited in line \"%s\"", l_buffer);
				return false;
			}

			if (ePos>19)
			{
				// invalid message: line too long
				_log.Log(LOG_NORM,"P1 Smart Meter: Dismiss incoming - value in line \"%s\" is oversized", l_buffer);
				return false;
			}

			if (ePos>0)
			{
				strcpy(value,vString.substr(0,ePos).c_str());
#ifdef _DEBUG
				_log.Log(LOG_NORM,"P1 Smart Meter: Key: %s, Value: %s", t->topic,value);
#endif
			}

			unsigned long temp_usage = 0;
			float temp_volt = 0;
			char *validate=value+ePos;

			switch (t->type)
			{
			case P1TYPE_VERSION:
				if (m_p1version==0)
					_log.Log(LOG_STATUS,"P1 Smart Meter: Meter reports as DSMR %c.%c", value[0], value[1]);
				m_p1version=value[0]-0x30;
				break;
			case P1TYPE_MBUSDEVICETYPE:
				temp_usage = (unsigned long)(strtod(value,&validate));
				if (temp_usage == 3) {
					m_gasmbuschannel = (char)l_buffer[2];
					m_gasprefix[2]=m_gasmbuschannel;
					_log.Log(LOG_STATUS,"P1 Smart Meter: Found gas meter on M-Bus channel %c", m_gasmbuschannel);
				}
				break;
			case P1TYPE_POWERUSAGE1:
				temp_usage = (unsigned long)(strtod(value,&validate)*1000.0f);
				if (!m_power.powerusage1 || m_p1version >= 4)
					m_power.powerusage1 = temp_usage;
				else if (temp_usage - m_power.powerusage1 < 10000)
					m_power.powerusage1 = temp_usage;
				break;
			case P1TYPE_POWERUSAGE2:
				temp_usage = (unsigned long)(strtod(value,&validate)*1000.0f);
				if (!m_power.powerusage2 || m_p1version >= 4)
					m_power.powerusage2 = temp_usage;
				else if (temp_usage - m_power.powerusage2 < 10000)
					m_power.powerusage2 = temp_usage;
				break;
			case P1TYPE_POWERDELIV1:
				temp_usage = (unsigned long)(strtod(value,&validate)*1000.0f);
				if (!m_power.powerdeliv1 || m_p1version >= 4)
					m_power.powerdeliv1 = temp_usage;
				else if (temp_usage - m_power.powerdeliv1 < 10000)
					m_power.powerdeliv1 = temp_usage;
				break;
			case P1TYPE_POWERDELIV2:
				temp_usage = (unsigned long)(strtod(value,&validate)*1000.0f);
				if (!m_power.powerdeliv2 || m_p1version >= 4)
					m_power.powerdeliv2 = temp_usage;
				else if (temp_usage - m_power.powerdeliv2 < 10000)
					m_power.powerdeliv2 = temp_usage;
				break;
			case P1TYPE_USAGECURRENT:
				temp_usage = (unsigned long)(strtod(value,&validate)*1000.0f);	//Watt
				if (temp_usage < 17250)
					m_power.usagecurrent = temp_usage;
				break;
			case P1TYPE_DELIVCURRENT:
				temp_usage = (unsigned long)(strtod(value,&validate)*1000.0f);	//Watt;
				if (temp_usage < 17250)
					m_power.delivcurrent = temp_usage;
				break;
			case P1TYPE_VOLTAGEL1:
				temp_volt = strtof(value,&validate);
				if (temp_volt < 300)
					m_voltagel1 = temp_volt; //Voltage L1;
				break;
			case P1TYPE_VOLTAGEL2:
				temp_volt = strtof(value,&validate);
				if (temp_volt < 300)
					m_voltagel2 = temp_volt; //Voltage L2;
				break;
			case P1TYPE_VOLTAGEL3:
				temp_volt = strtof(value,&validate);
				if (temp_volt < 300)
					m_voltagel3 = temp_volt; //Voltage L3;
				break;
			case P1TYPE_GASTIMESTAMP:
				m_gastimestamp = std::string(value);
				break;
			case P1TYPE_GASUSAGE:
			case P1TYPE_GASUSAGEDSMR4:
				temp_usage = (unsigned long)(strtod(value,&validate)*1000.0f);
				if (!m_gas.gasusage || m_p1version >= 4)
					m_gas.gasusage = temp_usage;
				else if (temp_usage - m_gas.gasusage < 20000)
					m_gas.gasusage = temp_usage;
				break;
			}

			if (ePos>0 && ((validate - value) != ePos)) {
				// invalid message: value is not a number
				_log.Log(LOG_NORM,"P1 Smart Meter: Dismiss incoming - value in line \"%s\" is not a number", l_buffer);
				return false;
			}

			if (t->type == P1TYPE_GASUSAGEDSMR4){ // need to get timestamp from this line as well
				vString=(const char*)&l_buffer+11;
				m_gastimestamp=vString.substr(0,13);
#ifdef _DEBUG
				_log.Log(LOG_NORM,"P1 Smart Meter: Key: gastimestamp, Value: %s", m_gastimestamp);
#endif
			}
		}
	}
	return true;
}