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"); }
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()); //} } } } }
bool CRFLinkBase::ParseLine(const std::string &sLine) { m_LastReceivedTime = mytime(NULL); std::vector<std::string> results; StringSplit(sLine, ";", results); if (results.size() < 2) return false; //not needed bool bHideDebugLog = ( (sLine.find("PONG") != std::string::npos)|| (sLine.find("PING") != std::string::npos) ); int RFLink_ID = atoi(results[0].c_str()); if (RFLink_ID != 20) { return false; //only accept RFLink->Master messages } #ifdef ENABLE_LOGGING if (!bHideDebugLog) _log.Log(LOG_NORM, "RFLink: %s", sLine.c_str()); #endif //std::string Sensor_ID = results[1]; if (results.size() >2) { //Status reply std::string Name_ID = results[2]; if ((Name_ID.find("Nodo RadioFrequencyLink") != std::string::npos) || (Name_ID.find("RFLink Gateway") != std::string::npos)) { _log.Log(LOG_STATUS, "RFLink: Controller Initialized!..."); WriteInt("10;VERSION;\n"); // 20;3C;VER=1.1;REV=37;BUILD=01; //Enable DEBUG //write("10;RFDEBUG=ON;\n"); //Enable Undecoded DEBUG //write("10;RFUDEBUG=ON;\n"); return true; } if (Name_ID.find("VER") != std::string::npos) { //_log.Log(LOG_STATUS, "RFLink: %s", sLine.c_str()); int versionlo = 0; int versionhi = 0; int revision = 0; int build = 0; if (results[2].find("VER") != std::string::npos) { versionhi = RFLinkGetIntStringValue(results[2]); versionlo = RFLinkGetIntDecStringValue(results[2]); } if (results[3].find("REV") != std::string::npos){ revision = RFLinkGetIntStringValue(results[3]); } if (results[4].find("BUILD") != std::string::npos) { build = RFLinkGetIntStringValue(results[4]); } _log.Log(LOG_STATUS, "RFLink Detected, Version: %d.%d Revision: %d Build: %d", versionhi, versionlo, revision, build); std::stringstream sstr; sstr << revision << "." << build; m_Version = sstr.str(); mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy m_LastReceivedTime = m_LastHeartbeat; m_bTXokay = true; // variable to indicate an OK was received return true; } if (Name_ID.find("PONG") != std::string::npos) { //_log.Log(LOG_STATUS, "RFLink: PONG received!..."); mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy m_LastReceivedTime = m_LastHeartbeat; m_bTXokay = true; // variable to indicate an OK was received return true; } if (Name_ID.find("OK") != std::string::npos) { //_log.Log(LOG_STATUS, "RFLink: OK received!..."); mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy m_LastReceivedTime = m_LastHeartbeat; m_bTXokay = true; // variable to indicate an OK was received return true; } else if (Name_ID.find("CMD UNKNOWN") != std::string::npos) { _log.Log(LOG_ERROR, "RFLink: Error/Unknown command received!..."); m_bTXokay = true; // variable to indicate an ERROR was received return true; } } if (results.size() < 4) return true; if (results[3].find("ID=") == std::string::npos) return false; //?? mytime(&m_LastHeartbeatReceive); // keep heartbeat happy mytime(&m_LastHeartbeat); // keep heartbeat happy //_log.Log(LOG_STATUS, "RFLink: t1=%d t2=%d", m_LastHeartbeat, m_LastHeartbeatReceive); m_LastReceivedTime = m_LastHeartbeat; std::stringstream ss; unsigned int ID; ss << std::hex << results[3].substr(3); ss >> ID; int Node_ID = (ID & 0xFF00) >> 8; int Child_ID = ID & 0xFF; bool bHaveTemp = false; float temp = 0; bool bHaveHum = false; int humidity = 0; bool bHaveHumStatus = false; int humstatus = 0; bool bHaveBaro = false; float baro = 0; int baroforecast = 0; bool bHaveRain = false; float raincounter = 0; bool bHaveLux = false; float lux = 0; bool bHaveUV = false; float uv = 0; bool bHaveWindDir = false; int windir = 0; bool bHaveWindSpeed = false; float windspeed = 0; bool bHaveWindGust = false; float windgust = 0; bool bHaveWindTemp = false; float windtemp = 0; bool bHaveWindChill = false; float windchill = 0; bool bHaveRGB = false; int rgb = 0; bool bHaveRGBW = false; int rgbw = 0; bool bHaveSound = false; int sound = 0; bool bHaveCO2 = false; int co2 = 0; bool bHaveBlind = false; int blind = 0; bool bHaveKWatt = false; float kwatt = 0; bool bHaveWatt = false; float watt = 0; bool bHaveDistance = false; float distance = 0; bool bHaveMeter = false; float meter = 0; bool bHaveVoltage = false; float voltage = 0; bool bHaveCurrent = false; float current = 0; bool bHaveCurrent2 = false; float current2 = 0; bool bHaveCurrent3 = false; float current3 = 0; bool bHaveImpedance = false; float impedance = 0; bool bHaveSwitch = false; int switchunit = 0; bool bHaveSwitchCmd = false; std::string switchcmd = ""; int switchlevel = 0; int BatteryLevel = 255; std::string tmpstr; int iTemp; for (size_t ii = 4; ii < results.size(); ii++) { if (results[ii].find("TEMP") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveTemp = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } temp = float(iTemp) / 10.0f; } else if (results[ii].find("HUM") != std::string::npos) { bHaveHum = true; humidity = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("HSTATUS") != std::string::npos) { bHaveHumStatus = true; humstatus = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("BARO") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveBaro = true; baro = float(iTemp); } else if (results[ii].find("BFORECAST") != std::string::npos) { baroforecast = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RAIN") != std::string::npos) { bHaveRain = true; iTemp = RFLinkGetHexStringValue(results[ii]); raincounter = float(iTemp) / 10.0f; } else if (results[ii].find("LUX") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveLux = true; lux = float(iTemp); } else if (results[ii].find("UV") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveUV = true; uv = float(iTemp) /10.0f; } else if (results[ii].find("BAT") != std::string::npos) { tmpstr = RFLinkGetStringValue(results[ii]); BatteryLevel = (tmpstr == "OK") ? 100 : 0; } else if (results[ii].find("WINDIR") != std::string::npos) { bHaveWindDir = true; windir = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("WINSP") != std::string::npos) { bHaveWindSpeed = true; iTemp = RFLinkGetHexStringValue(results[ii]); // received value is km/u windspeed = (float(iTemp) * 0.0277778f); //convert to m/s } else if (results[ii].find("WINGS") != std::string::npos) { bHaveWindGust = true; iTemp = RFLinkGetHexStringValue(results[ii]); // received value is km/u windgust = (float(iTemp) * 0.0277778f); //convert to m/s } else if (results[ii].find("WINTMP") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWindTemp = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } windtemp = float(iTemp) / 10.0f; } else if (results[ii].find("WINCHL") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWindChill = true; if ((iTemp & 0x8000) == 0x8000) { //negative temp iTemp = -(iTemp & 0xFFF); } windchill = float(iTemp) / 10.0f; } else if (results[ii].find("SOUND") != std::string::npos) { bHaveSound = true; sound = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("CO2") != std::string::npos) { bHaveCO2 = true; co2 = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RGBW") != std::string::npos) { bHaveRGBW = true; rgbw = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("RGB") != std::string::npos) { bHaveRGB = true; rgb = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("BLIND") != std::string::npos) { bHaveBlind = true; blind = RFLinkGetIntStringValue(results[ii]); } else if (results[ii].find("KWATT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveKWatt = true; kwatt = float(iTemp) / 1000.0f; } else if (results[ii].find("WATT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveWatt = true; watt = float(iTemp) / 10.0f; } else if (results[ii].find("DIST") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveDistance = true; distance = float(iTemp) / 10.0f; } else if (results[ii].find("METER") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveMeter = true; meter = float(iTemp) / 10.0f; } else if (results[ii].find("VOLT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveVoltage = true; voltage = float(iTemp) / 10.0f; } else if (results[ii].find("CURRENT") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent = true; current = float(iTemp) / 10.0f; } else if (results[ii].find("CURRENT2") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent2 = true; current2 = float(iTemp) / 10.0f; } else if (results[ii].find("CURRENT3") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent3 = true; current3 = float(iTemp) / 10.0f; } else if (results[ii].find("IMPEDANCE") != std::string::npos) { iTemp = RFLinkGetHexStringValue(results[ii]); bHaveCurrent = true; current = float(iTemp) / 10.0f; } else if (results[ii].find("SWITCH") != std::string::npos) { bHaveSwitch = true; switchunit = RFLinkGetHexStringValue(results[ii]); } else if (results[ii].find("CMD") != std::string::npos) { bHaveSwitchCmd = true; switchcmd = RFLinkGetStringValue(results[ii]); } else if (results[ii].find("SMOKEALERT") != std::string::npos) { bHaveSwitch = true; switchunit = 1; bHaveSwitchCmd = true; switchcmd = RFLinkGetStringValue(results[ii]); } else if (results[ii].find("CHIME") != std::string::npos) { bHaveSwitch = true; switchunit = 2; bHaveSwitchCmd = true; switchcmd = "ON"; } } std::string tmp_Name = results[2]; if (bHaveTemp&&bHaveHum&&bHaveBaro) { SendTempHumBaroSensor(ID, BatteryLevel, temp, humidity, baro, baroforecast, tmp_Name); } else if (bHaveTemp&&bHaveHum) { SendTempHumSensor(ID, BatteryLevel, temp, humidity, tmp_Name); } else if (bHaveTemp) { SendTempSensor(ID, BatteryLevel, temp, tmp_Name); } else if (bHaveHum) { SendHumiditySensor(ID, BatteryLevel, humidity, tmp_Name); } else if (bHaveBaro) { SendBaroSensor(Node_ID, Child_ID, BatteryLevel, baro, baroforecast, tmp_Name); } if (bHaveLux) { SendLuxSensor(Node_ID, Child_ID, BatteryLevel, lux, tmp_Name); } if (bHaveUV) { SendUVSensor(Node_ID, Child_ID, BatteryLevel, uv, tmp_Name); } if (bHaveRain) { SendRainSensor(ID, BatteryLevel, float(raincounter), tmp_Name); } if (bHaveWindDir && bHaveWindSpeed && bHaveWindGust && bHaveWindChill) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, tmp_Name); } else if (bHaveWindDir && bHaveWindGust) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, tmp_Name); } else if (bHaveWindSpeed) { SendWind(ID, BatteryLevel, float(windir), windspeed, windgust, windtemp, windchill, bHaveWindTemp, tmp_Name); } if (bHaveCO2) { SendAirQualitySensor((ID & 0xFF00) >> 8, ID & 0xFF, BatteryLevel, co2, tmp_Name); } if (bHaveSound) { SendSoundSensor(ID, BatteryLevel, sound, tmp_Name); } if (bHaveRGB) { //RRGGBB SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgb, false, tmp_Name); } if (bHaveRGBW) { //RRGGBBWW SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgbw, true, tmp_Name); } if (bHaveBlind) { SendBlindSensor(Node_ID, Child_ID, BatteryLevel, blind, tmp_Name); } if (bHaveKWatt&bHaveWatt) { SendKwhMeterOldWay(Node_ID, Child_ID, BatteryLevel, watt / 100.0f, kwatt, tmp_Name); } else if (bHaveKWatt) { SendKwhMeterOldWay(Node_ID, Child_ID, BatteryLevel, watt / 100.0f, kwatt, tmp_Name); } else if (bHaveWatt) { SendKwhMeterOldWay(Node_ID, Child_ID, BatteryLevel, watt / 100.0f, kwatt, tmp_Name); } if (bHaveDistance) { SendDistanceSensor(Node_ID, Child_ID, BatteryLevel, distance, tmp_Name); } if (bHaveMeter) { SendMeterSensor(Node_ID, Child_ID, BatteryLevel, meter, tmp_Name); } if (bHaveVoltage) { SendVoltageSensor(Node_ID, Child_ID, BatteryLevel, voltage, tmp_Name); } if (bHaveCurrent && bHaveCurrent2 && bHaveCurrent3) { SendCurrentSensor(ID, BatteryLevel, current, current2, current3, tmp_Name); } else if (bHaveCurrent) { SendCurrentSensor(ID, BatteryLevel, current, 0, 0, tmp_Name); } if (bHaveImpedance) { SendPercentageSensor(Node_ID, Child_ID, BatteryLevel, impedance, tmp_Name); } if (bHaveSwitch && bHaveSwitchCmd) { std::string switchType = results[2]; SendSwitchInt(ID, switchunit, BatteryLevel, switchType, switchcmd, switchlevel); } return true; }
void 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, <ime); 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"); } }
void MySensorsBase::SendSensor2Domoticz(_tMySensorNode *pNode, _tMySensorChild *pChild, const _eSetType vType) { m_iLastSendNodeBatteryValue = 255; if (pChild->hasBattery) { m_iLastSendNodeBatteryValue = pChild->batValue; } int cNode = (pChild->nodeID << 8) | pChild->childID; int intValue; float floatValue; std::string stringValue; switch (vType) { case V_TEMP: { float Temp = 0; pChild->GetValue(V_TEMP, Temp); _tMySensorChild *pChildHum = FindChildWithValueType(pChild->nodeID, V_HUM); _tMySensorChild *pChildBaro = FindChildWithValueType(pChild->nodeID, V_PRESSURE); if (pChildHum && pChildBaro) { int Humidity; float Baro; bool bHaveHumidity = pChildHum->GetValue(V_HUM, Humidity); bool bHaveBaro = pChildBaro->GetValue(V_PRESSURE, Baro); if (bHaveHumidity && bHaveBaro) { int forecast = bmpbaroforecast_unknown; _tMySensorChild *pSensorForecast = FindChildWithValueType(pChild->nodeID, V_FORECAST); if (pSensorForecast) { pSensorForecast->GetValue(V_FORECAST, forecast); } if (forecast == bmpbaroforecast_cloudy) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } //We are using the TempHumBaro Float type now, convert the forecast int nforecast = wsbaroforcast_some_clouds; if (Baro <= 980) nforecast = wsbaroforcast_heavy_rain; else if (Baro <= 995) { if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } else if (Baro >= 1029) nforecast = wsbaroforcast_sunny; switch (forecast) { case bmpbaroforecast_sunny: nforecast = wsbaroforcast_sunny; break; case bmpbaroforecast_cloudy: nforecast = wsbaroforcast_cloudy; break; case bmpbaroforecast_thunderstorm: nforecast = wsbaroforcast_heavy_rain; break; case bmpbaroforecast_rain: if (Temp>1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } SendTempHumBaroSensorFloat(cNode, pChild->batValue, Temp, Humidity, Baro, nforecast, (!pChild->childName.empty()) ? pChild->childName : "TempHumBaro"); } } else if (pChildHum) { int Humidity; bool bHaveHumidity = pChildHum->GetValue(V_HUM, Humidity); if (bHaveHumidity) { SendTempHumSensor(cNode, pChild->batValue, Temp, Humidity, (!pChild->childName.empty()) ? pChild->childName : "TempHum"); } } else { SendTempSensor(cNode, pChild->batValue, Temp, (!pChild->childName.empty()) ? pChild->childName : "Temp"); } } break; case V_HUM: { _tMySensorChild *pChildTemp = FindChildWithValueType(pChild->nodeID, V_TEMP); _tMySensorChild *pChildBaro = FindChildWithValueType(pChild->nodeID, V_PRESSURE); int forecast = bmpbaroforecast_unknown; _tMySensorChild *pSensorForecast = FindChildWithValueType(pChild->nodeID, V_FORECAST); if (pSensorForecast) { pSensorForecast->GetValue(V_FORECAST, forecast); } if (forecast == bmpbaroforecast_cloudy) { if (pChildBaro) { float Baro; if (pChildBaro->GetValue(V_PRESSURE, Baro)) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } } } float Temp; float Baro; int Humidity; pChild->GetValue(V_HUM, Humidity); if (pChildTemp && pChildBaro) { bool bHaveTemp = pChildTemp->GetValue(V_TEMP, Temp); bool bHaveBaro = pChildBaro->GetValue(V_PRESSURE, Baro); if (bHaveTemp && bHaveBaro) { cNode = (pChildTemp->nodeID << 8) | pChildTemp->childID; //We are using the TempHumBaro Float type now, convert the forecast int nforecast = wsbaroforcast_some_clouds; if (Baro <= 980) nforecast = wsbaroforcast_heavy_rain; else if (Baro <= 995) { if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } else if (Baro >= 1029) nforecast = wsbaroforcast_sunny; switch (forecast) { case bmpbaroforecast_sunny: nforecast = wsbaroforcast_sunny; break; case bmpbaroforecast_cloudy: nforecast = wsbaroforcast_cloudy; break; case bmpbaroforecast_thunderstorm: nforecast = wsbaroforcast_heavy_rain; break; case bmpbaroforecast_rain: if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } SendTempHumBaroSensorFloat(cNode, pChildTemp->batValue, Temp, Humidity, Baro, nforecast, (!pChild->childName.empty()) ? pChild->childName : "TempHumBaro"); } } else if (pChildTemp) { bool bHaveTemp = pChildTemp->GetValue(V_TEMP, Temp); if (bHaveTemp) { cNode = (pChildTemp->nodeID << 8) | pChildTemp->childID; SendTempHumSensor(cNode, pChildTemp->batValue, Temp, Humidity, (!pChild->childName.empty()) ? pChild->childName : "TempHum"); } } else { SendHumiditySensor(cNode, pChild->batValue, Humidity); } } break; case V_PRESSURE: { float Baro; pChild->GetValue(V_PRESSURE, Baro); _tMySensorChild *pSensorTemp = FindChildWithValueType(pChild->nodeID, V_TEMP); _tMySensorChild *pSensorHum = FindChildWithValueType(pChild->nodeID, V_HUM); int forecast = bmpbaroforecast_unknown; _tMySensorChild *pSensorForecast = FindChildWithValueType(pChild->nodeID, V_FORECAST); if (pSensorForecast) { pSensorForecast->GetValue(V_FORECAST, forecast); } if (forecast == bmpbaroforecast_cloudy) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } if (pSensorTemp && pSensorHum) { float Temp; int Humidity; bool bHaveTemp = pSensorTemp->GetValue(V_TEMP, Temp); bool bHaveHumidity = pSensorHum->GetValue(V_HUM, Humidity); if (bHaveTemp && bHaveHumidity) { cNode = (pSensorTemp->nodeID << 8) | pSensorTemp->childID; //We are using the TempHumBaro Float type now, convert the forecast int nforecast = wsbaroforcast_some_clouds; if (Baro <= 980) nforecast = wsbaroforcast_heavy_rain; else if (Baro <= 995) { if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } else if (Baro >= 1029) nforecast = wsbaroforcast_sunny; switch (forecast) { case bmpbaroforecast_sunny: nforecast = wsbaroforcast_sunny; break; case bmpbaroforecast_cloudy: nforecast = wsbaroforcast_cloudy; break; case bmpbaroforecast_thunderstorm: nforecast = wsbaroforcast_heavy_rain; break; case bmpbaroforecast_rain: if (Temp > 1) nforecast = wsbaroforcast_rain; else nforecast = wsbaroforcast_snow; break; } SendTempHumBaroSensorFloat(cNode, pSensorTemp->batValue, Temp, Humidity, Baro, nforecast, (!pChild->childName.empty()) ? pChild->childName : "TempHumBaro"); } } else SendBaroSensor(pChild->nodeID, pChild->childID, pChild->batValue, Baro, forecast); } break; case V_TRIPPED: // Tripped status of a security sensor. 1 = Tripped, 0 = Untripped if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue == 1), 100, "Security Sensor"); break; case V_ARMED: //Armed status of a security sensor. 1 = Armed, 0 = Bypassed if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue == 1), 100, "Security Sensor"); break; case V_LOCK_STATUS: //Lock status. 1 = Locked, 0 = Unlocked if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue == 1), 100, "Lock Sensor"); break; case V_STATUS: // Light status. 0 = off 1 = on if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID, (intValue != 0), 100, "Light"); break; case V_SCENE_ON: if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID + intValue, true, 100, "Scene"); break; case V_SCENE_OFF: if (pChild->GetValue(vType, intValue)) UpdateSwitch(pChild->nodeID, pChild->childID + intValue, false, 100, "Scene"); break; case V_PERCENTAGE: // Dimmer value. 0 - 100 % if (pChild->GetValue(vType, intValue)) { int level = intValue; UpdateSwitch(pChild->nodeID, pChild->childID, (level != 0), level, "Light"); } break; case V_RGB: //RRGGBB if (pChild->GetValue(vType, intValue)) SendRGBWSwitch(pChild->nodeID, pChild->childID, pChild->batValue, intValue, false, (!pChild->childName.empty()) ? pChild->childName : "RGB Light"); break; case V_RGBW: //RRGGBBWW if (pChild->GetValue(vType, intValue)) SendRGBWSwitch(pChild->nodeID, pChild->childID, pChild->batValue, intValue, true, (!pChild->childName.empty()) ? pChild->childName : "RGBW Light"); break; case V_UP: case V_DOWN: case V_STOP: if (pChild->GetValue(vType, intValue)) SendBlindSensor(pChild->nodeID, pChild->childID, pChild->batValue, intValue, (!pChild->childName.empty()) ? pChild->childName : "Blinds/Window"); break; case V_LIGHT_LEVEL: if (pChild->GetValue(vType, floatValue)) { _tLightMeter lmeter; lmeter.id1 = 0; lmeter.id2 = 0; lmeter.id3 = 0; lmeter.id4 = pChild->nodeID; lmeter.dunit = pChild->childID; lmeter.fLux = floatValue; lmeter.battery_level = pChild->batValue; if (pChild->hasBattery) lmeter.battery_level = pChild->batValue; sDecodeRXMessage(this, (const unsigned char *)&lmeter); } break; case V_LEVEL: if ((pChild->presType == S_DUST)|| (pChild->presType == S_AIR_QUALITY)) { if (pChild->GetValue(vType, intValue)) { _tAirQualityMeter meter; meter.len = sizeof(_tAirQualityMeter) - 1; meter.type = pTypeAirQuality; meter.subtype = sTypeVoltcraft; meter.airquality = intValue; meter.id1 = pChild->nodeID; meter.id2 = pChild->childID; sDecodeRXMessage(this, (const unsigned char *)&meter); } } else if (pChild->presType == S_LIGHT_LEVEL) { if (pChild->GetValue(vType, intValue)) { _tLightMeter lmeter; lmeter.id1 = 0; lmeter.id2 = 0; lmeter.id3 = 0; lmeter.id4 = pChild->nodeID; lmeter.dunit = pChild->childID; lmeter.fLux = (float)intValue; lmeter.battery_level = pChild->batValue; if (pChild->hasBattery) lmeter.battery_level = pChild->batValue; sDecodeRXMessage(this, (const unsigned char *)&lmeter); } } else if (pChild->presType == S_SOUND) { if (pChild->GetValue(vType, intValue)) SendSoundSensor(cNode, pChild->batValue, intValue, (!pChild->childName.empty()) ? pChild->childName : "Sound Level"); } else if (pChild->presType == S_MOISTURE) { if (pChild->GetValue(vType, intValue)) { _tGeneralDevice gdevice; gdevice.subtype = sTypeSoilMoisture; gdevice.intval1 = intValue; gdevice.id = pChild->nodeID; sDecodeRXMessage(this, (const unsigned char *)&gdevice); } } break; case V_RAIN: if (pChild->GetValue(vType, floatValue)) SendRainSensor(cNode, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Rain"); break; case V_WATT: { if (pChild->GetValue(vType, floatValue)) { _tMySensorChild *pSensorKwh = pNode->FindChildWithValueType(pChild->childID, V_KWH);// FindChildWithValueType(pChild->nodeID, V_KWH); if (pSensorKwh) { float Kwh; if (pSensorKwh->GetValue(V_KWH, Kwh)) SendKwhMeter(pSensorKwh->nodeID, pSensorKwh->childID, pSensorKwh->batValue, floatValue / 1000.0f, Kwh, (!pChild->childName.empty()) ? pChild->childName : "Meter"); } else { SendWattMeter(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Usage"); } } } break; case V_KWH: if (pChild->GetValue(vType, floatValue)) { _tMySensorChild *pSensorWatt = pNode->FindChildWithValueType(pChild->childID, V_WATT);// FindChildWithValueType(pChild->nodeID, V_WATT); if (pSensorWatt) { float Watt; if (pSensorWatt->GetValue(V_WATT, Watt)) SendKwhMeter(pChild->nodeID, pChild->childID, pChild->batValue, Watt / 1000.0f, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Meter"); } else { SendKwhMeter(pChild->nodeID, pChild->childID, pChild->batValue, 0, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Meter"); } } break; case V_DISTANCE: if (pChild->GetValue(vType, floatValue)) SendDistanceSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue); break; case V_FLOW: //Flow of water in meter (for now send as a percentage sensor) if (pChild->GetValue(vType, floatValue)) SendPercentageSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Water Flow"); break; case V_VOLUME: //Water Volume if (pChild->GetValue(vType, floatValue)) SendMeterSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Water"); break; case V_VOLTAGE: if (pChild->GetValue(vType, floatValue)) SendVoltageSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Voltage"); break; case V_UV: if (pChild->GetValue(vType, floatValue)) SendUVSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue); break; case V_IMPEDANCE: if (pChild->GetValue(vType, floatValue)) SendPercentageSensor(pChild->nodeID, pChild->childID, pChild->batValue, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Impedance"); break; case V_WEIGHT: if (pChild->GetValue(vType, floatValue)) { while (1 == 0); } break; case V_CURRENT: if (pChild->GetValue(vType, floatValue)) SendCurrentSensor(cNode, pChild->batValue, floatValue, 0, 0, (!pChild->childName.empty()) ? pChild->childName : "Current"); break; case V_FORECAST: if (pChild->GetValue(vType, intValue)) { _tMySensorChild *pSensorBaro = FindChildWithValueType(pChild->nodeID, V_PRESSURE); if (pSensorBaro) { float Baro; if (pSensorBaro->GetValue(V_PRESSURE, Baro)) { int forecast = intValue; if (forecast == bmpbaroforecast_cloudy) { if (Baro < 1010) forecast = bmpbaroforecast_rain; } SendBaroSensor(pSensorBaro->nodeID, pSensorBaro->childID, pSensorBaro->batValue, Baro, forecast); } } else { if (pChild->GetValue(V_FORECAST, stringValue)) { std::stringstream sstr; sstr << pChild->nodeID; std::string devname = (!pChild->childName.empty()) ? pChild->childName : "Forecast"; m_sql.UpdateValue(m_HwdID, sstr.str().c_str(), pChild->childID, pTypeGeneral, sTypeTextStatus, 12, pChild->batValue, 0, stringValue.c_str(), devname); } } } break; case V_WIND: case V_GUST: case V_DIRECTION: MakeAndSendWindSensor(pChild->nodeID, (!pChild->childName.empty()) ? pChild->childName : "Wind"); break; case V_HVAC_SETPOINT_HEAT: if (pChild->GetValue(vType, floatValue)) { SendSetPointSensor(pNode->nodeID, pChild->childID, floatValue, (!pChild->childName.empty()) ? pChild->childName : "Heater Setpoint"); } break; } }
void 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"); } }
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); }
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; }
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, <ime); 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; }