Found a way to fix it, but it involves some steps:
Steps performed to fix the jump (A huge jump up that is!!!, very rare occasion!!):
- press 'Edit' on the Enphase kWh delivery sensor and notice the IDX
- shutdown Domoticz, cleanly
- copy the database domoticz.db (if there are domoticz.db-wal and domoticz.db-shm files, also copy these!)
- make also a backup/zip, so you can always go back!!!
- open the database with an editor like (for example) SQLite Expert Personal edition
- go a sql query editor and execute
DELETE FROM Meter WHERE DeviceRowID = (above found IDX), for example
DELETE FROM Meter WHERE DeviceRowID = 8023
- open the Meter_Calendar table, filter all records where DeviceRowID = (above found IDX)
- find the moment where the big jump is, you will see the 'value' column have a HUGE value, copy/note this value, this is your 'offset' that you need to subtract from the 'counter' column from that point
For example my view:
Code: Select all
rowid DeviceRowID Value Date Counter Price
107941 8023 26919 2024-08-06 00:00:00.000 3780803 5.2376
108002 8023 17667 2024-08-07 00:00:00.000 3798470 3.3184
108064 8023 7182913 2024-08-08 00:00:00.000 10981383 1454.4884
108126 8023 14854 2024-08-09 00:00:00.000 10996237 2.3638
108187 8023 24588 2024-08-10 00:00:00.000 11020825 3.1892
108248 8023 28569 2024-08-11 00:00:00.000 11049394 3.8624
108309 8023 29174 2024-08-12 00:00:00.000 11078568 5.591
108370 8023 26394 2024-08-13 00:00:00.000 11104962 6.3272
...
...
7182913 is my 'offset' to subtract from that day onwards in the counter field, till today/yesterday, so all records from that day!
(I let excel help me with this)
The moment where this is happening and you have a huge 'value', set this value to 0, and also set the 'price' column to zero, when you have done this, it will look like:
Code: Select all
rowid DeviceRowID Value Date Counter Price
107941 8023 26919 2024-08-06 00:00:00.000 3780803 5.2376
108002 8023 17667 2024-08-07 00:00:00.000 3798470 3.3184
108064 8023 0 2024-08-08 00:00:00.000 3798470 0
108126 8023 14854 2024-08-09 00:00:00.000 3813324 2.3638
108187 8023 24588 2024-08-10 00:00:00.000 3837912 3.1892
108248 8023 28569 2024-08-11 00:00:00.000 3866481 3.8624
108309 8023 29174 2024-08-12 00:00:00.000 3895655 5.591
108370 8023 26394 2024-08-13 00:00:00.000 3922049 6.3272
108431 8023 9123 2024-08-14 00:00:00.000 3931172 2.4712
...
...
109285 8023 27285 2024-08-28 00:00:00.000 4204920 6.0352
(If you are unable to do this, or it is too complicate, too much work, you can also 'delete' all records from the moment where you have that 'huge' value), but do this at least for the last value, you will need this corrected counter value in the next step
- take a notice of the last corrected counter value, in my case '4204920'
- next, open the 'DeviceStatus' table, and make a filter/find your device (ID = (above id)
- change the 'sValue' so after the semicolon ( ; ) you change that value with the above value (4204920.000)
- next, open the 'UserVariables' table, and find your enphase offset (name should be something like 'EnphaseOffset_Production_xxxxxx')
- If your offset value above was 7182913, divide this by 1000, so you will get 7182.913
- subtract the uservariable with this, 3578.851000 - 7182.913 = -3604.062
- set the uservariable to this value (-3604.062)
- now close the editor, and copy the database back to your Domoticz folder (in the correct folder if you use a docker instance)
- start Domoticz again
I think we should be able to make a python script for this that detects the spike, and performs the above steps
But my python skills are limited
And I also should be able to detect the jump in the c++ code in the CounterHelper class.
Probably this addition will work, but maybe someone could test this offline
Code: Select all
void CounterHelper::SendKwhMeter(const int NodeID, const int ChildID, const int BatteryLevel, const double musage, double mtotal, const std::string& defaultname, int RssiLevel)
{
if (mtotal != 0)
{
double rTotal = m_CounterOffset + mtotal;
bool bHaveCounterIssue = false;
if (
(rTotal < m_nLastCounterValue)
&& (m_nLastCounterValue != 0)
)
{
//Possible counter reset (newly received counter value is less then previous recieved!)
m_CounterOffset = m_nLastCounterValue;
bHaveCounterIssue = true;
}
else if (m_nLastCounterValue > 10 && rTotal > 10)
{
constexpr double m_allowed_cntr_jump_perc = 500; //We consider a 500% jump 'not' normal... what's a good value?
if (abs((100.0 / m_nLastCounterValue) * rTotal) > m_allowed_cntr_jump_perc)
{
//Possible counter jump up!?
m_CounterOffset = (m_nLastCounterValue - mtotal);
bHaveCounterIssue = true;
}
}
if (bHaveCounterIssue)
{
m_sql.safe_query("UPDATE UserVariables SET Value='%q', LastUpdate='%s' WHERE (Name=='%q')", std::to_string(m_CounterOffset).c_str(), TimeToString(nullptr, TF_DateTime).c_str(), m_szUservariableName.c_str());
rTotal = m_CounterOffset + mtotal;
}
m_pHardwareBase->SendKwhMeter(NodeID, ChildID, BatteryLevel, musage, static_cast<double>(rTotal), defaultname, RssiLevel);
m_nLastCounterValue = rTotal;
}
}