3333ENDPOINT_URL_PRODUCTION_POWER = "https://{}/ivp/mod/603980032/mode/power"
3434ENDPOINT_URL_INFO_XML = "https://{}/info.xml"
3535ENDPOINT_URL_STREAM = "https://{}/stream/meter"
36+ ENDPOINT_URL_PRODUCTION_REPORT = "https://{}/ivp/meters/reports/production"
3637ENDPOINT_URL_PDM_ENERGY = "https://{}/ivp/pdm/energy"
3738
3839ENVOY_MODEL_M = "Metered"
@@ -548,23 +549,44 @@ def __new__(cls, *a, **kw):
548549class EnvoyMeteredWithCT (EnvoyMetered ):
549550 """Adds CT based sensors, like current usage per phase"""
550551
551- def __new__ (cls , * a , ** kw ):
552+ def __new__ (cls , reader , ** kw ):
552553 # Add phase CT production value attributes, as this class is
553554 # chosen when one production CT is enabled.
554555 for attr , path in {
555- "production" : ".wNow" ,
556- "daily_production" : ".whToday" ,
557- "lifetime_production" : ".whLifetime" ,
556+ "production" : ".currW" ,
557+ "lifetime_production" : ".whDlvdCum" ,
558558 "voltage" : ".rmsVoltage" ,
559+ "ampere" : ".rmsCurrent" ,
560+ "apparent_power" : ".apprntPwr" ,
561+ "power_factor" : ".pwrFactor" ,
562+ "reactive_power" : ".reactPwr" ,
563+ "frequency" : ".freqHz" ,
559564 }.items ():
560- ct_path = cls . _production_ct
561- setattr (cls , f"{ attr } _value" , ct_path + path )
565+ ct_path = "endpoint_production_report"
566+ setattr (cls , f"{ attr } _value" , f" { ct_path } .cumulative { path } " )
562567
563568 # Also create paths for all phases.
564569 for i , phase in enumerate (["l1" , "l2" , "l3" ]):
565570 full_path = f"{ ct_path } .lines[{ i } ]{ path } "
566571 setattr (cls , f"{ attr } _{ phase } _value" , full_path )
567572
573+ setattr (
574+ cls ,
575+ "daily_production_value" ,
576+ "endpoint_production_json_results.production[?(@.type=='eim')].whToday" ,
577+ )
578+ for i , phase in enumerate (["l1" , "l2" , "l3" ]):
579+ setattr (
580+ cls ,
581+ f"daily_production_{ phase } _value"
582+ "endpoint_production_json_results.production[?(@.type=='eim')].lines[{i}].whToday" ,
583+ )
584+
585+ # When we're using the endpoint_production_report primarily, then the following
586+ # endpoint can be used way less frequently
587+ reader .uri_registry ["endpoint_production_json_results" ]["cache_time" ] = 50
588+ reader .uri_registry ["endpoint_production_inverters" ]["cache_time" ] = 290
589+
568590 return EnvoyMetered .__new__ (cls )
569591
570592
@@ -640,6 +662,7 @@ def url(endpoint, *a, **kw):
640662 iurl ("production_power" , ENDPOINT_URL_PRODUCTION_POWER , cache = 3600 )
641663 url ("info_results" , ENDPOINT_URL_INFO_XML , cache = 86400 )
642664 url ("inventory_results" , ENDPOINT_URL_INVENTORY , cache = 300 )
665+ url ("production_report" , ENDPOINT_URL_PRODUCTION_REPORT , cache = 0 )
643666 iurl ("pdm_energy" , ENDPOINT_URL_PDM_ENERGY )
644667
645668 # If IPv6 address then enclose host in brackets
@@ -1279,6 +1302,11 @@ async def _async_getattr(self, key):
12791302 lifetime_production_phase = _async_getattr
12801303 lifetime_consumption_phase = _async_getattr
12811304 voltage_phase = _async_getattr
1305+ frequency_phase = _async_getattr
1306+ ampere_phase = _async_getattr
1307+ apparent_power_phase = _async_getattr
1308+ power_factor_phase = _async_getattr
1309+ reactive_power_phase = _async_getattr
12821310
12831311 async def set_production_power (self , power_on ):
12841312 if self .endpoint_production_power is not None :
@@ -1369,6 +1397,9 @@ def run_in_console(
13691397 self .production_phase ("production_l1" ),
13701398 self .production_phase ("production_l2" ),
13711399 self .production_phase ("production_l3" ),
1400+ self .frequency_phase ("frequency_l1" ),
1401+ self .frequency_phase ("frequency_l2" ),
1402+ self .frequency_phase ("frequency_l3" ),
13721403 return_exceptions = False ,
13731404 )
13741405 )
@@ -1392,6 +1423,9 @@ def run_in_console(
13921423 "production_phase(l1)" ,
13931424 "production_phase(l2)" ,
13941425 "production_phase(l3)" ,
1426+ "frequency(l1)" ,
1427+ "frequency(l2)" ,
1428+ "frequency(l3)" ,
13951429 ]
13961430 pprint .pprint (dict (zip (fields , results )))
13971431
0 commit comments