foxesscloud 2.7.5__tar.gz → 2.7.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/LICENCE +1 -1
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/PKG-INFO +12 -3
- foxesscloud-2.7.5/src/foxesscloud.egg-info/PKG-INFO → foxesscloud-2.7.7/README.md +11 -16
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/pyproject.toml +1 -1
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/src/foxesscloud/foxesscloud.py +29 -22
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/src/foxesscloud/openapi.py +39 -27
- foxesscloud-2.7.5/README.md → foxesscloud-2.7.7/src/foxesscloud.egg-info/PKG-INFO +25 -2
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/setup.cfg +0 -0
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/src/foxesscloud.egg-info/SOURCES.txt +0 -0
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/src/foxesscloud.egg-info/dependency_links.txt +0 -0
- {foxesscloud-2.7.5 → foxesscloud-2.7.7}/src/foxesscloud.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foxesscloud
|
3
|
-
Version: 2.7.
|
3
|
+
Version: 2.7.7
|
4
4
|
Summary: library for accessing Fox ESS cloud data using Open API
|
5
5
|
Author-email: Tony Matthews <tony@quasair.co.uk>
|
6
6
|
Project-URL: Homepage, https://github.com/TonyM1958/FoxESS-Cloud
|
@@ -629,7 +629,7 @@ f.get_pvoutput(d, tou)
|
|
629
629
|
```
|
630
630
|
|
631
631
|
+ d is the date or a list of dates, to get data for. The default is yesterday.
|
632
|
-
+ tou:
|
632
|
+
+ tou: the default, tou=0, does not split data and is more accurate. Setting tou=1 uploads data with time of use. Setting tou=2 integrates all values and allows set_pvoutput() to work with pv inverters that do not provide energy stats.
|
633
633
|
+ setting integrate_load_power to 1 will calculate load energy by integrating the load power instead of using data from Fox. This tries to overcome the limitation where the inverter does not track load power / energy correctly when there is secondary generation. When set to 0 (default), the Fox load energy is used.
|
634
634
|
|
635
635
|
You can copy and paste the output data to the pvoutput data CSV Loader, using the following settings:
|
@@ -652,7 +652,7 @@ f.set_pvoutput(d, system_id, tou, push, run_after)
|
|
652
652
|
|
653
653
|
+ d is optional and is the date, or a list of dates, to upload
|
654
654
|
+ system_id is optional and allow you to select where data is uploaded to (where you have more than 1 registered system)
|
655
|
-
+ tou:
|
655
|
+
+ tou: the default, tou=0, does not split data and is more accurate. Setting tou=1 uploads data with time of use. Setting tou=2 integrates all values and allows set_pvoutput() to work with pv inverters that do not provide energy stats.
|
656
656
|
+ push: optional. 0 = do not sent to pushover, 1 = send summary to pushover, 2 = send first day summary only
|
657
657
|
+ run_after: optional. Only generate data on or after this hour. Default 0.
|
658
658
|
|
@@ -807,6 +807,15 @@ This setting can be:
|
|
807
807
|
|
808
808
|
# Version Info
|
809
809
|
|
810
|
+
2.7.7<br>
|
811
|
+
Updates to get_pvoutput() to support solar inverters that don't provide grid energy by setting tou=2.
|
812
|
+
Default tariff changed to None.
|
813
|
+
|
814
|
+
2.7.6<br>
|
815
|
+
Updates to support F, G, R and S series inverters.
|
816
|
+
Updates to set_named_settings() to load metadata if not already done and save new value.
|
817
|
+
Fix divide by zero error when using pvoutput with solar only inverters.
|
818
|
+
|
810
819
|
2.7.5<br>
|
811
820
|
Update to support T series inverters.
|
812
821
|
|
@@ -1,17 +1,3 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: foxesscloud
|
3
|
-
Version: 2.7.5
|
4
|
-
Summary: library for accessing Fox ESS cloud data using Open API
|
5
|
-
Author-email: Tony Matthews <tony@quasair.co.uk>
|
6
|
-
Project-URL: Homepage, https://github.com/TonyM1958/FoxESS-Cloud
|
7
|
-
Project-URL: Bug Tracker, https://github.com/TonyM1958/FoxESS-Cloud/issues
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
10
|
-
Classifier: Operating System :: OS Independent
|
11
|
-
Requires-Python: >=3.7
|
12
|
-
Description-Content-Type: text/markdown
|
13
|
-
License-File: LICENCE
|
14
|
-
|
15
1
|
# FoxESS-Cloud
|
16
2
|
|
17
3
|
<a href="https://www.buymeacoffee.com/tonym1958" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174" align="right"></a>
|
@@ -629,7 +615,7 @@ f.get_pvoutput(d, tou)
|
|
629
615
|
```
|
630
616
|
|
631
617
|
+ d is the date or a list of dates, to get data for. The default is yesterday.
|
632
|
-
+ tou:
|
618
|
+
+ tou: the default, tou=0, does not split data and is more accurate. Setting tou=1 uploads data with time of use. Setting tou=2 integrates all values and allows set_pvoutput() to work with pv inverters that do not provide energy stats.
|
633
619
|
+ setting integrate_load_power to 1 will calculate load energy by integrating the load power instead of using data from Fox. This tries to overcome the limitation where the inverter does not track load power / energy correctly when there is secondary generation. When set to 0 (default), the Fox load energy is used.
|
634
620
|
|
635
621
|
You can copy and paste the output data to the pvoutput data CSV Loader, using the following settings:
|
@@ -652,7 +638,7 @@ f.set_pvoutput(d, system_id, tou, push, run_after)
|
|
652
638
|
|
653
639
|
+ d is optional and is the date, or a list of dates, to upload
|
654
640
|
+ system_id is optional and allow you to select where data is uploaded to (where you have more than 1 registered system)
|
655
|
-
+ tou:
|
641
|
+
+ tou: the default, tou=0, does not split data and is more accurate. Setting tou=1 uploads data with time of use. Setting tou=2 integrates all values and allows set_pvoutput() to work with pv inverters that do not provide energy stats.
|
656
642
|
+ push: optional. 0 = do not sent to pushover, 1 = send summary to pushover, 2 = send first day summary only
|
657
643
|
+ run_after: optional. Only generate data on or after this hour. Default 0.
|
658
644
|
|
@@ -807,6 +793,15 @@ This setting can be:
|
|
807
793
|
|
808
794
|
# Version Info
|
809
795
|
|
796
|
+
2.7.7<br>
|
797
|
+
Updates to get_pvoutput() to support solar inverters that don't provide grid energy by setting tou=2.
|
798
|
+
Default tariff changed to None.
|
799
|
+
|
800
|
+
2.7.6<br>
|
801
|
+
Updates to support F, G, R and S series inverters.
|
802
|
+
Updates to set_named_settings() to load metadata if not already done and save new value.
|
803
|
+
Fix divide by zero error when using pvoutput with solar only inverters.
|
804
|
+
|
810
805
|
2.7.5<br>
|
811
806
|
Update to support T series inverters.
|
812
807
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
##################################################################################################
|
2
2
|
"""
|
3
3
|
Module: Fox ESS Cloud
|
4
|
-
Updated:
|
4
|
+
Updated: 11 January 2025
|
5
5
|
By: Tony Matthews
|
6
6
|
"""
|
7
7
|
##################################################################################################
|
@@ -10,7 +10,7 @@ By: Tony Matthews
|
|
10
10
|
# ALL RIGHTS ARE RESERVED © Tony Matthews 2023
|
11
11
|
##################################################################################################
|
12
12
|
|
13
|
-
version = "1.8.
|
13
|
+
version = "1.8.8"
|
14
14
|
print(f"FoxESS-Cloud version {version}")
|
15
15
|
|
16
16
|
debug_setting = 1
|
@@ -435,7 +435,7 @@ device_sn = None
|
|
435
435
|
var_list = None
|
436
436
|
raw_vars = var_list
|
437
437
|
|
438
|
-
def get_device(sn=None):
|
438
|
+
def get_device(sn=None, device_type=None):
|
439
439
|
global device_list, device, device_id, device_sn, firmware, battery, var_list, debug_setting, messages, flag, schedule, templates, remote_settings
|
440
440
|
if get_token() is None:
|
441
441
|
return None
|
@@ -490,31 +490,32 @@ def get_device(sn=None):
|
|
490
490
|
firmware = get_firmware()
|
491
491
|
remote_settings = get_ui()
|
492
492
|
# parse the model code to work out attributes
|
493
|
-
model_code = device['deviceType'].upper()
|
494
|
-
if model_code[
|
495
|
-
|
493
|
+
model_code = device['deviceType'].upper() if device_type is None else device_type
|
494
|
+
if model_code[0] in 'FGRST':
|
495
|
+
phase = '1' if model_code[0] in 'FGS' else '3'
|
496
|
+
model_code = model_code[0] + phase + '-' + model_code[1:]
|
496
497
|
elif model_code[:2] == 'KH':
|
497
498
|
model_code = 'KH-' + model_code[2:]
|
498
499
|
elif model_code[:4] == 'AIO-':
|
499
500
|
model_code = 'AIO' + model_code[4:]
|
500
|
-
device['eps'] = 'E' in model_code
|
501
|
+
device['eps'] = 'E' in model_code[2:]
|
501
502
|
parts = model_code.split('-')
|
502
503
|
model = parts[0]
|
503
|
-
if model not in ['T3', 'KH', 'H1', 'AC1', 'H3', 'AC3', 'AIOH1', 'AIOH3']:
|
504
|
+
if model not in ['F1', 'G1', 'R3', 'S1', 'T3', 'KH', 'H1', 'AC1', 'H3', 'AC3', 'AIOH1', 'AIOH3']:
|
504
505
|
output(f"** device model not recognised for deviceType: {device['deviceType']}")
|
505
506
|
return device
|
506
507
|
device['model'] = model
|
507
508
|
device['phase'] = 3 if model[-1:] == '3' else 1
|
508
509
|
for p in parts[1:]:
|
509
510
|
if p.replace('.','').isnumeric():
|
510
|
-
power = float(p)
|
511
|
-
if power >=
|
512
|
-
device['power'] =
|
511
|
+
power = float(p) / (1000 if model in ['F1', 'S1'] else 1.0)
|
512
|
+
if power >= 0.5 and power < 100.0:
|
513
|
+
device['power'] = power
|
513
514
|
break
|
514
515
|
if device.get('power') is None:
|
515
516
|
output(f"** device power not found for deviceType: {device['deviceType']}")
|
516
517
|
# set max charge current
|
517
|
-
if model in ['T3']:
|
518
|
+
if model in ['F1', 'G1', 'R3', 'S1', 'T3']:
|
518
519
|
device['max_charge_current'] = None
|
519
520
|
elif model in ['KH']:
|
520
521
|
device['max_charge_current'] = 50
|
@@ -2379,7 +2380,7 @@ custom_periods = {'name': 'Custom',
|
|
2379
2380
|
}
|
2380
2381
|
|
2381
2382
|
tariff_list = [octopus_flux, intelligent_octopus, octopus_cosy, octopus_go, agile_octopus, bg_driver, eon_drive, economy_7, custom_periods]
|
2382
|
-
tariff =
|
2383
|
+
tariff = None
|
2383
2384
|
|
2384
2385
|
##################################################################################################
|
2385
2386
|
# Strategy - schedule templates
|
@@ -3064,7 +3065,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
3064
3065
|
output(f"full_charge = {full_charge}")
|
3065
3066
|
if test_soc is not None:
|
3066
3067
|
current_soc = test_soc
|
3067
|
-
capacity = 14.
|
3068
|
+
capacity = 14.36
|
3068
3069
|
residual = test_soc * capacity / 100
|
3069
3070
|
bat_volt = 317.4
|
3070
3071
|
bat_power = 0.0
|
@@ -3856,18 +3857,19 @@ integrate_load_power = 0
|
|
3856
3857
|
##################################################################################################
|
3857
3858
|
|
3858
3859
|
# get pvoutput data for upload to pvoutput api or via Bulk Loader
|
3859
|
-
# tou: 0 = no time of use, 1 = use time of use periods if available
|
3860
|
+
# tou: 0 = no time of use, 1 = use time of use periods if available, 2 = integrate all values
|
3860
3861
|
|
3861
3862
|
def get_pvoutput(d = None, tou = 0):
|
3862
3863
|
global tariff, pv_calibration, ct2_calibration, integrate_load_power
|
3863
3864
|
if d is None:
|
3864
3865
|
d = date_list()[0]
|
3865
|
-
tou = 0 if tariff is None else 1 if tou == 1 or tou == True else 0
|
3866
3866
|
if type(d) is list:
|
3867
3867
|
print(f"---------------- get_pvoutput ------------------")
|
3868
3868
|
print(f"Date range {d[0]} to {d[-1]} has {len(d)} days")
|
3869
3869
|
if tou == 1:
|
3870
3870
|
print(f"Time of use: {tariff['name']}")
|
3871
|
+
elif tou == 2:
|
3872
|
+
print(f"All values integrated from power")
|
3871
3873
|
if integrate_load_power == 1:
|
3872
3874
|
print(f"Consumption integrated from Load Power")
|
3873
3875
|
print(f"------------------------------------------------")
|
@@ -3881,12 +3883,15 @@ def get_pvoutput(d = None, tou = 0):
|
|
3881
3883
|
v = ['feedin', 'gridConsumption']
|
3882
3884
|
if integrate_load_power == 0:
|
3883
3885
|
v.append('loads')
|
3884
|
-
|
3885
|
-
|
3886
|
-
|
3886
|
+
if tou == 2:
|
3887
|
+
report_data = []
|
3888
|
+
else:
|
3889
|
+
report_data = get_report('day', d=d, v=v, summary=2)
|
3890
|
+
if report_data is None:
|
3891
|
+
return None
|
3887
3892
|
# get raw power data for the day
|
3888
|
-
v = ['pvPower', 'meterPower2', 'feedinPower', 'gridConsumptionPower'] if tou
|
3889
|
-
if integrate_load_power == 1:
|
3893
|
+
v = ['pvPower', 'meterPower2', 'feedinPower', 'gridConsumptionPower'] if tou > 0 else ['pvPower', 'meterPower2']
|
3894
|
+
if integrate_load_power == 1 or tou == 2:
|
3890
3895
|
v.append('loadsPower')
|
3891
3896
|
raw_data = get_raw('day', d=d + ' 00:00:00', v=v , summary=1)
|
3892
3897
|
if raw_data is None or len(raw_data) == 0 or raw_data[0].get('kwh') is None or raw_data[0].get('max') is None:
|
@@ -3916,7 +3921,7 @@ def get_pvoutput(d = None, tou = 0):
|
|
3916
3921
|
export_tou = ',,,'
|
3917
3922
|
# process list of report_data values (no TOU)
|
3918
3923
|
for var in report_data:
|
3919
|
-
wh = int(var['total'] * 1000)
|
3924
|
+
wh = int(var['total'] * 1000) if var['total'] is not None else 0
|
3920
3925
|
if var['variable'] == 'feedin':
|
3921
3926
|
export_wh = wh
|
3922
3927
|
export = f"{wh},"
|
@@ -3936,10 +3941,12 @@ def get_pvoutput(d = None, tou = 0):
|
|
3936
3941
|
generate = f"{wh},"
|
3937
3942
|
power = f"{int(var['max'] * 1000)},{var['max_time']},"
|
3938
3943
|
elif var['variable'] == 'feedinPower':
|
3944
|
+
export_wh = wh if tou == 2 else export_wh
|
3939
3945
|
calibrate = export_wh / wh if wh > 0.0 else 1.0
|
3940
3946
|
export = f","
|
3941
3947
|
export_tou = f"{int(peak * calibrate)},{int(off_peak * calibrate)},{int((wh - peak - off_peak) * calibrate)},0"
|
3942
3948
|
elif var['variable'] == 'gridConsumptionPower':
|
3949
|
+
grid_wh = wh if tou == 2 else grid_wh
|
3943
3950
|
calibrate = grid_wh / wh if wh > 0.0 else 1.0
|
3944
3951
|
grid = f"{int(peak * calibrate)},{int(off_peak * calibrate)},{int((wh - peak - off_peak) * calibrate)},0,"
|
3945
3952
|
elif var['variable'] == 'loadsPower':
|
@@ -1,7 +1,7 @@
|
|
1
1
|
##################################################################################################
|
2
2
|
"""
|
3
3
|
Module: Fox ESS Cloud using Open API
|
4
|
-
Updated:
|
4
|
+
Updated: 11 January 2025
|
5
5
|
By: Tony Matthews
|
6
6
|
"""
|
7
7
|
##################################################################################################
|
@@ -10,7 +10,7 @@ By: Tony Matthews
|
|
10
10
|
# ALL RIGHTS ARE RESERVED © Tony Matthews 2024
|
11
11
|
##################################################################################################
|
12
12
|
|
13
|
-
version = "2.7.
|
13
|
+
version = "2.7.7"
|
14
14
|
print(f"FoxESS-Cloud Open API version {version}")
|
15
15
|
|
16
16
|
debug_setting = 1
|
@@ -419,7 +419,7 @@ device_list = None
|
|
419
419
|
device = None
|
420
420
|
device_sn = None
|
421
421
|
|
422
|
-
def get_device(sn=None):
|
422
|
+
def get_device(sn=None, device_type=None):
|
423
423
|
global device_list, device, device_sn, battery, debug_setting, schedule, remote_settings
|
424
424
|
if get_vars() is None:
|
425
425
|
return None
|
@@ -480,31 +480,32 @@ def get_device(sn=None):
|
|
480
480
|
get_generation()
|
481
481
|
# remote_settings = get_ui()
|
482
482
|
# parse the model code to work out attributes
|
483
|
-
model_code = device['deviceType'].upper()
|
484
|
-
if model_code[
|
485
|
-
|
486
|
-
|
483
|
+
model_code = device['deviceType'].upper() if device_type is None else device_type
|
484
|
+
if model_code[0] in 'FGRST':
|
485
|
+
phase = '1' if model_code[0] in 'FGS' else '3'
|
486
|
+
model_code = model_code[0] + phase + '-' + model_code[1:]
|
487
|
+
elif model_code[:2] == 'KH':
|
487
488
|
model_code = 'KH-' + model_code[2:]
|
488
489
|
elif model_code[:4] == 'AIO-':
|
489
490
|
model_code = 'AIO' + model_code[4:]
|
490
|
-
device['eps'] = 'E' in model_code
|
491
|
+
device['eps'] = 'E' in model_code[2:]
|
491
492
|
parts = model_code.split('-')
|
492
493
|
model = parts[0]
|
493
|
-
if model not in ['T3', 'KH', 'H1', 'AC1', 'H3', 'AC3', 'AIOH1', 'AIOH3']:
|
494
|
+
if model not in ['F1', 'G1', 'R3', 'S1', 'T3', 'KH', 'H1', 'AC1', 'H3', 'AC3', 'AIOH1', 'AIOH3']:
|
494
495
|
output(f"** device model not recognised for deviceType: {device['deviceType']}")
|
495
496
|
return device
|
496
497
|
device['model'] = model
|
497
498
|
device['phase'] = 3 if model[-1:] == '3' else 1
|
498
499
|
for p in parts[1:]:
|
499
500
|
if p.replace('.','').isnumeric():
|
500
|
-
power = float(p)
|
501
|
-
if power >=
|
502
|
-
device['power'] =
|
501
|
+
power = float(p) / (1000 if model in ['F1', 'S1'] else 1.0)
|
502
|
+
if power >= 0.5 and power < 100.0:
|
503
|
+
device['power'] = power
|
503
504
|
break
|
504
505
|
if device.get('power') is None:
|
505
506
|
output(f"** device power not found for deviceType: {device['deviceType']}")
|
506
507
|
# set max charge current
|
507
|
-
if model in ['T3']:
|
508
|
+
if model in ['F1', 'G1', 'R3', 'S1', 'T3']:
|
508
509
|
device['max_charge_current'] = None
|
509
510
|
elif model in ['KH']:
|
510
511
|
device['max_charge_current'] = 50
|
@@ -842,7 +843,7 @@ def get_settings():
|
|
842
843
|
named_settings = {}
|
843
844
|
|
844
845
|
def get_remote_settings(name):
|
845
|
-
global device_sn, debug_setting, messages, name_data
|
846
|
+
global device_sn, debug_setting, messages, name_data, named_settings
|
846
847
|
if get_device() is None:
|
847
848
|
return None
|
848
849
|
output(f"getting remote settings", 2)
|
@@ -878,7 +879,7 @@ def get_named_settings(name):
|
|
878
879
|
return get_remote_settings(name)
|
879
880
|
|
880
881
|
def set_named_settings(name, value, force=0):
|
881
|
-
global device_sn, debug_setting
|
882
|
+
global device_sn, debug_setting, named_settings
|
882
883
|
if get_device() is None:
|
883
884
|
return None
|
884
885
|
if force == 1 and get_schedule().get('enable'):
|
@@ -888,6 +889,10 @@ def set_named_settings(name, value, force=0):
|
|
888
889
|
for (n, v) in name:
|
889
890
|
result.append(set_named_settings(name=n, value=v))
|
890
891
|
return result
|
892
|
+
if named_settings.get(name) is None:
|
893
|
+
result = get_named_settings(name)
|
894
|
+
if result is None:
|
895
|
+
return None
|
891
896
|
output(f"\nSetting {name} to {value}", 1)
|
892
897
|
body = {'sn': device_sn, 'key': name, 'value': f"{value}"}
|
893
898
|
setting_delay()
|
@@ -901,8 +906,9 @@ def set_named_settings(name, value, force=0):
|
|
901
906
|
output(f"** cannot update {name} when schedule is active")
|
902
907
|
else:
|
903
908
|
output(f"** set_named_settings(): ({name}, {value}) {errno_message(response)}")
|
904
|
-
return
|
905
|
-
|
909
|
+
return None
|
910
|
+
named_settings[name]['value'] = f"{value}"
|
911
|
+
return value
|
906
912
|
|
907
913
|
##################################################################################################
|
908
914
|
# wrappers for named settings
|
@@ -2046,7 +2052,7 @@ custom_periods = {'name': 'Custom',
|
|
2046
2052
|
}
|
2047
2053
|
|
2048
2054
|
tariff_list = [octopus_flux, intelligent_octopus, octopus_cosy, octopus_go, agile_octopus, bg_driver, eon_drive, economy_7, custom_periods]
|
2049
|
-
tariff =
|
2055
|
+
tariff = None
|
2050
2056
|
|
2051
2057
|
##################################################################################################
|
2052
2058
|
# Strategy - schedule templates
|
@@ -2730,7 +2736,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
2730
2736
|
output(f"full_charge = {full_charge}")
|
2731
2737
|
if test_soc is not None:
|
2732
2738
|
current_soc = test_soc
|
2733
|
-
capacity = 14.
|
2739
|
+
capacity = 14.36
|
2734
2740
|
residual = test_soc * capacity / 100
|
2735
2741
|
bat_volt = 317.4
|
2736
2742
|
bat_power = 0.0
|
@@ -3523,18 +3529,19 @@ integrate_load_power = 0
|
|
3523
3529
|
##################################################################################################
|
3524
3530
|
|
3525
3531
|
# get pvoutput data for upload to pvoutput api or via Bulk Loader
|
3526
|
-
# tou: 0 = no time of use, 1 = use time of use periods if available
|
3532
|
+
# tou: 0 = no time of use, 1 = use time of use periods if available, 2 = integrate all values
|
3527
3533
|
|
3528
3534
|
def get_pvoutput(d = None, tou = 0):
|
3529
3535
|
global tariff, pv_calibration, ct2_calibration, integrate_load_power
|
3530
3536
|
if d is None:
|
3531
3537
|
d = date_list()[0]
|
3532
|
-
tou = 0 if tariff is None else 1 if tou == 1 or tou == True else 0
|
3533
3538
|
if type(d) is list:
|
3534
3539
|
print(f"---------------- get_pvoutput ------------------")
|
3535
3540
|
print(f"Date range {d[0]} to {d[-1]} has {len(d)} days")
|
3536
3541
|
if tou == 1:
|
3537
3542
|
print(f"Time of use: {tariff['name']}")
|
3543
|
+
elif tou == 2:
|
3544
|
+
print(f"All values integrated from power")
|
3538
3545
|
if integrate_load_power == 1:
|
3539
3546
|
print(f"Consumption integrated from Load Power")
|
3540
3547
|
print(f"------------------------------------------------")
|
@@ -3548,12 +3555,15 @@ def get_pvoutput(d = None, tou = 0):
|
|
3548
3555
|
v = ['feedin', 'gridConsumption']
|
3549
3556
|
if integrate_load_power == 0:
|
3550
3557
|
v.append('loads')
|
3551
|
-
|
3552
|
-
|
3553
|
-
|
3558
|
+
if tou == 2:
|
3559
|
+
report_data = []
|
3560
|
+
else:
|
3561
|
+
report_data = get_report('day', d=d, v=v, summary=2)
|
3562
|
+
if report_data is None:
|
3563
|
+
return None
|
3554
3564
|
# get raw power data for the day
|
3555
|
-
v = ['pvPower', 'meterPower2', 'feedinPower', 'gridConsumptionPower'] if tou
|
3556
|
-
if integrate_load_power == 1:
|
3565
|
+
v = ['pvPower', 'meterPower2', 'feedinPower', 'gridConsumptionPower'] if tou > 0 else ['pvPower', 'meterPower2']
|
3566
|
+
if integrate_load_power == 1 or tou == 2:
|
3557
3567
|
v.append('loadsPower')
|
3558
3568
|
raw_data = get_raw('day', d=d + ' 00:00:00', v=v , summary=1)
|
3559
3569
|
if raw_data is None or len(raw_data) == 0 or raw_data[0].get('kwh') is None or raw_data[0].get('max') is None:
|
@@ -3583,7 +3593,7 @@ def get_pvoutput(d = None, tou = 0):
|
|
3583
3593
|
export_tou = ',,,'
|
3584
3594
|
# process list of report_data values (no TOU)
|
3585
3595
|
for var in report_data:
|
3586
|
-
wh = int(var['total'] * 1000)
|
3596
|
+
wh = int(var['total'] * 1000) if var['total'] is not None else 0
|
3587
3597
|
if var['variable'] == 'feedin':
|
3588
3598
|
export_wh = wh
|
3589
3599
|
export = f"{wh},"
|
@@ -3603,10 +3613,12 @@ def get_pvoutput(d = None, tou = 0):
|
|
3603
3613
|
generate = f"{wh},"
|
3604
3614
|
power = f"{int(var['max'] * 1000)},{var['max_time']},"
|
3605
3615
|
elif var['variable'] == 'feedinPower':
|
3616
|
+
export_wh = wh if tou == 2 else export_wh
|
3606
3617
|
calibrate = export_wh / wh if wh > 0.0 else 1.0
|
3607
3618
|
export = f","
|
3608
3619
|
export_tou = f"{int(peak * calibrate)},{int(off_peak * calibrate)},{int((wh - peak - off_peak) * calibrate)},0"
|
3609
3620
|
elif var['variable'] == 'gridConsumptionPower':
|
3621
|
+
grid_wh = wh if tou == 2 else grid_wh
|
3610
3622
|
calibrate = grid_wh / wh if wh > 0.0 else 1.0
|
3611
3623
|
grid = f"{int(peak * calibrate)},{int(off_peak * calibrate)},{int((wh - peak - off_peak) * calibrate)},0,"
|
3612
3624
|
elif var['variable'] == 'loadsPower':
|
@@ -1,3 +1,17 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: foxesscloud
|
3
|
+
Version: 2.7.7
|
4
|
+
Summary: library for accessing Fox ESS cloud data using Open API
|
5
|
+
Author-email: Tony Matthews <tony@quasair.co.uk>
|
6
|
+
Project-URL: Homepage, https://github.com/TonyM1958/FoxESS-Cloud
|
7
|
+
Project-URL: Bug Tracker, https://github.com/TonyM1958/FoxESS-Cloud/issues
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Requires-Python: >=3.7
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
License-File: LICENCE
|
14
|
+
|
1
15
|
# FoxESS-Cloud
|
2
16
|
|
3
17
|
<a href="https://www.buymeacoffee.com/tonym1958" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174" align="right"></a>
|
@@ -615,7 +629,7 @@ f.get_pvoutput(d, tou)
|
|
615
629
|
```
|
616
630
|
|
617
631
|
+ d is the date or a list of dates, to get data for. The default is yesterday.
|
618
|
-
+ tou:
|
632
|
+
+ tou: the default, tou=0, does not split data and is more accurate. Setting tou=1 uploads data with time of use. Setting tou=2 integrates all values and allows set_pvoutput() to work with pv inverters that do not provide energy stats.
|
619
633
|
+ setting integrate_load_power to 1 will calculate load energy by integrating the load power instead of using data from Fox. This tries to overcome the limitation where the inverter does not track load power / energy correctly when there is secondary generation. When set to 0 (default), the Fox load energy is used.
|
620
634
|
|
621
635
|
You can copy and paste the output data to the pvoutput data CSV Loader, using the following settings:
|
@@ -638,7 +652,7 @@ f.set_pvoutput(d, system_id, tou, push, run_after)
|
|
638
652
|
|
639
653
|
+ d is optional and is the date, or a list of dates, to upload
|
640
654
|
+ system_id is optional and allow you to select where data is uploaded to (where you have more than 1 registered system)
|
641
|
-
+ tou:
|
655
|
+
+ tou: the default, tou=0, does not split data and is more accurate. Setting tou=1 uploads data with time of use. Setting tou=2 integrates all values and allows set_pvoutput() to work with pv inverters that do not provide energy stats.
|
642
656
|
+ push: optional. 0 = do not sent to pushover, 1 = send summary to pushover, 2 = send first day summary only
|
643
657
|
+ run_after: optional. Only generate data on or after this hour. Default 0.
|
644
658
|
|
@@ -793,6 +807,15 @@ This setting can be:
|
|
793
807
|
|
794
808
|
# Version Info
|
795
809
|
|
810
|
+
2.7.7<br>
|
811
|
+
Updates to get_pvoutput() to support solar inverters that don't provide grid energy by setting tou=2.
|
812
|
+
Default tariff changed to None.
|
813
|
+
|
814
|
+
2.7.6<br>
|
815
|
+
Updates to support F, G, R and S series inverters.
|
816
|
+
Updates to set_named_settings() to load metadata if not already done and save new value.
|
817
|
+
Fix divide by zero error when using pvoutput with solar only inverters.
|
818
|
+
|
796
819
|
2.7.5<br>
|
797
820
|
Update to support T series inverters.
|
798
821
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|