void CSBFSpot::ImportOldMonthData() { _log.Log(LOG_STATUS, "SBFSpot Import Old Month Data: Start"); //check if this device exists in the database, if not exit bool bDeviceExits = true; std::vector<std::vector<std::string> > result; result = m_sql.safe_query("SELECT ID FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Type==%d) AND (Subtype==%d)", m_HwdID, "00000001", int(pTypeGeneral), int(sTypeKwh)); if (result.size() < 1) { //Lets create the sensor, and try again SendMeter(0, 1, 0, 0, "SolarMain"); result = m_sql.safe_query("SELECT ID FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Type==%d) AND (Subtype==%d)", m_HwdID, "00000001", int(pTypeGeneral), int(sTypeKwh)); if (result.size() < 1) { _log.Log(LOG_ERROR, "SBFSpot Import Old Month Data: FAILED - Cannot find sensor in database"); return; } } unsigned long long ulID; std::stringstream s_str(result[0][0]); s_str >> ulID; //Try actual year, and previous year time_t atime = time(NULL); struct tm ltime; localtime_r(&atime, <ime); int totyearsback = 2; int startYear = ltime.tm_year + 1900 - totyearsback; for (int iYear = startYear; iYear != startYear + 1 + totyearsback; iYear++) { for (int iMonth = 1; iMonth != 12+1; iMonth++) { ImportOldMonthData(ulID,iYear, iMonth); } } _log.Log(LOG_STATUS, "SBFSpot Import Old Month Data: Complete"); }
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,temp,"SolarMain"); SendPercentage(SE_FREQ,freq,"Hz"); SendVoltage(SE_VOLT_AC,voltageAC,"AC"); SendVoltage(SE_VOLT_DC,voltageDC,"DC"); } b+=restbytes; dlen-=restbytes; continue; } return (b-pData); }
void CPVOutputInput::GetMeterDetails() { if (m_SID.size()==0) return; if (m_KEY.size()==0) return; std::string sResult; std::stringstream sstr; sstr << "http://pvoutput.org/service/r2/getstatus.jsp?sid=" << m_SID << "&key=" << m_KEY; if (!HTTPClient::GET(sstr.str(),sResult)) { _log.Log(LOG_ERROR,"PVOutput (Input): Error login!"); return; } std::vector<std::string> splitresult; StringSplit(sResult,",",splitresult); if (splitresult.size()<9) { _log.Log(LOG_ERROR,"PVOutput (Input): Invalid Data received!"); return; } double Usage=atof(splitresult[3].c_str()); if (Usage < 0) Usage = 0; bool bHaveConsumption=false; double Consumption=0; if (splitresult[5]!="NaN") { Consumption=atof(splitresult[5].c_str()); if (Consumption < 0) Consumption = 0; bHaveConsumption=true; } if (splitresult[6]!="NaN") { double Efficiency=atof(splitresult[6].c_str())*100.0; if (Efficiency>100.0) Efficiency=100.0; SendPercentage(1,float(Efficiency),"Efficiency"); } if (splitresult[7]!="NaN") { double Temperature=atof(splitresult[7].c_str()); SendTempSensor(1,float(Temperature),"Temperature"); } if (splitresult[8]!="NaN") { double Voltage=atof(splitresult[8].c_str()); if (Voltage>=0) SendVoltage(1,float(Voltage),"Voltage"); } sstr.clear(); sstr.str(""); sstr << "http://pvoutput.org/service/r2/getstatistic.jsp?sid=" << m_SID << "&key=" << m_KEY << "&c=1"; if (!HTTPClient::GET(sstr.str(),sResult)) { _log.Log(LOG_ERROR,"PVOutput (Input): Error login!"); return; } StringSplit(sResult,",",splitresult); if (splitresult.size()<11) { _log.Log(LOG_ERROR,"PVOutput (Input): Invalid Data received!"); return; } double kWhCounterUsage=atof(splitresult[0].c_str()); SendMeter(0, 1, Usage / 1000.0, kWhCounterUsage / 1000.0, "SolarMain"); if (bHaveConsumption) { if (splitresult.size() > 11) { double kWhCounterConsumed = atof(splitresult[11].c_str()); if (kWhCounterConsumed != 0) { SendMeter(0, 2, Consumption / 1000.0, kWhCounterConsumed / 1000.0, "SolarConsumed"); } } } }
void S0MeterBase::ParseLine() { if (m_bufferpos<2) return; std::string sLine((char*)&m_buffer); std::vector<std::string> results; StringSplit(sLine,":",results); if (results.size()<1) return; //invalid data if (results[0][0]=='/') { //Meter restart //m_bMeterRestart=true; //Software Version std::string MeterID=results[0].substr(1); std::string SoftwareVersion=results[1]; _log.Log(LOG_STATUS,"S0 Meter: ID: %s, Version: %s",MeterID.c_str(),SoftwareVersion.c_str()); return; } if (results.size()<4) { _log.Log(LOG_ERROR,"S0 Meter: Invalid Data received! %s",sLine.c_str()); return; } int totmeters=(results.size()-4)/3; if (totmeters>max_s0_meters) totmeters=max_s0_meters; //ID:0001:I:99:M1:123:456:M2:234:567 = ID(1)/Pulse Interval(3)/M1Actual(5)/M1Total(7)/M2Actual(8)/M2Total(9) //std::string MeterID=results[1]; double s0_pulse_interval=atof(results[3].c_str()); int roffset = 4; if (results[0] == "ID") { for (int ii = 0; ii < totmeters; ii++) { m_meters[ii].m_PacketsSinceLastPulseChange++; double s0_pulse = atof(results[roffset + 1].c_str()); unsigned long LastTotalPulses = m_meters[ii].total_pulses; m_meters[ii].total_pulses = (unsigned long)atol(results[roffset + 2].c_str()); if (m_meters[ii].total_pulses < LastTotalPulses) { //counter has looped m_meters[ii].m_counter_start += (LastTotalPulses + m_meters[ii].total_pulses); m_meters[ii].first_total_pulses_received = m_meters[ii].total_pulses; } if (s0_pulse != 0) { double pph = ((double)m_meters[ii].m_pulse_per_unit) / 1000; // Pulses per (watt) hour double ActualUsage = ((3600.0 / double(m_meters[ii].m_PacketsSinceLastPulseChange*s0_pulse_interval) / pph) * s0_pulse); m_meters[ii].m_PacketsSinceLastPulseChange = 0; m_meters[ii].m_last_values[m_meters[ii].m_value_buffer_write_pos] = ActualUsage; m_meters[ii].m_value_buffer_write_pos = (m_meters[ii].m_value_buffer_write_pos + 1) % 5; if (m_meters[ii].m_value_buffer_total < 5) m_meters[ii].m_value_buffer_total++; //Calculate Average double vTotal = 0; for (int iBuf = 0; iBuf < m_meters[ii].m_value_buffer_total; iBuf++) vTotal += m_meters[ii].m_last_values[iBuf]; m_meters[ii].m_CurrentUsage = vTotal / double(m_meters[ii].m_value_buffer_total); #ifdef _DEBUG _log.Log(LOG_STATUS, "S0 Meter: M%d, Watt: %.3f", ii + 1, m_meters[ii].m_CurrentUsage); #endif } else { if (m_meters[ii].m_PacketsSinceLastPulseChange > 5 * 6) { //No pulses received for a long time, consider no usage m_meters[ii].m_PacketsSinceLastPulseChange = 0; m_meters[ii].m_last_values[0] = 0; m_meters[ii].m_value_buffer_total = 0; m_meters[ii].m_value_buffer_write_pos = 0; m_meters[ii].m_CurrentUsage = 0; } } if ((m_meters[ii].total_pulses != 0) || (m_meters[ii].m_firstTime)) { m_meters[ii].m_firstTime = false; if (m_meters[ii].first_total_pulses_received == 0) m_meters[ii].first_total_pulses_received = m_meters[ii].total_pulses; double counter_value = m_meters[ii].m_counter_start + (((double)(m_meters[ii].total_pulses - m_meters[ii].first_total_pulses_received) / ((double)m_meters[ii].m_pulse_per_unit))); m_meters[ii].m_current_counter = counter_value; SendMeter(ii + 1, m_meters[ii].m_CurrentUsage / 1000.0f, counter_value); } roffset += 3; } } else if(results[0] == "EID") { roffset = 2; for (int ii = 0; ii < totmeters; ii++) { double s0_counter = atof(results[roffset + 1].c_str()); if (s0_counter != 0) { if (m_meters[ii].m_firstTime) { m_meters[ii].m_current_counter = s0_counter; m_meters[ii].m_firstTime = false; } if (s0_counter < m_meters[ii].m_current_counter) { //counter has looped m_meters[ii].m_counter_start += m_meters[ii].m_current_counter; } m_meters[ii].m_current_counter = s0_counter; m_meters[ii].m_CurrentUsage = atof(results[roffset + 2].c_str()); double counter_value = m_meters[ii].m_counter_start + s0_counter; SendMeter(ii + 1, m_meters[ii].m_CurrentUsage / 1000.0f, m_meters[ii].m_current_counter); } roffset += 3; } } }
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"); } }