foxesscloud 2.8.6__py3-none-any.whl → 2.8.8__py3-none-any.whl
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/foxesscloud.py +28 -14
- foxesscloud/openapi.py +48 -15
- {foxesscloud-2.8.6.dist-info → foxesscloud-2.8.8.dist-info}/METADATA +24 -18
- foxesscloud-2.8.8.dist-info/RECORD +7 -0
- foxesscloud-2.8.6.dist-info/RECORD +0 -7
- {foxesscloud-2.8.6.dist-info → foxesscloud-2.8.8.dist-info}/LICENCE +0 -0
- {foxesscloud-2.8.6.dist-info → foxesscloud-2.8.8.dist-info}/WHEEL +0 -0
- {foxesscloud-2.8.6.dist-info → foxesscloud-2.8.8.dist-info}/top_level.txt +0 -0
foxesscloud/foxesscloud.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
##################################################################################################
|
2
2
|
"""
|
3
3
|
Module: Fox ESS Cloud
|
4
|
-
Updated:
|
4
|
+
Updated: 2 October 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.9.
|
13
|
+
version = "1.9.8"
|
14
14
|
print(f"FoxESS-Cloud version {version}")
|
15
15
|
|
16
16
|
debug_setting = 1
|
@@ -653,6 +653,8 @@ def get_battery(info=1, rated=None, count=None):
|
|
653
653
|
residual_handling = 2
|
654
654
|
elif battery['info']['masterSN'][:7] == '60MBB01' and battery['info']['masterVersion'] >= '1.014':
|
655
655
|
residual_handling = 3
|
656
|
+
if debug_setting > 1:
|
657
|
+
print(f"raw battery = {battery}")
|
656
658
|
battery['residual_handling'] = residual_handling
|
657
659
|
battery['soh'] = None
|
658
660
|
battery['soh_supported'] = False
|
@@ -910,14 +912,14 @@ def get_min():
|
|
910
912
|
output(f"** get_min(), no result data, {errno_message(errno)}")
|
911
913
|
return None
|
912
914
|
battery_settings['minSoc'] = result.get('minSoc')
|
913
|
-
battery_settings['
|
915
|
+
battery_settings['minSocOnGrid'] = result.get('minGridSoc')
|
914
916
|
return battery_settings
|
915
917
|
|
916
918
|
##################################################################################################
|
917
919
|
# set min soc from battery_settings or parameters
|
918
920
|
##################################################################################################
|
919
921
|
|
920
|
-
def set_min(
|
922
|
+
def set_min(minSocOnGrid = None, minSoc = None, force = 0):
|
921
923
|
global device_sn, battery_settings, debug_setting, messages
|
922
924
|
if get_device() is None:
|
923
925
|
return None
|
@@ -926,16 +928,24 @@ def set_min(minGridSoc = None, minSoc = None, force = 0):
|
|
926
928
|
output(f"** set_min(): cannot set min SoC mode when a schedule is enabled")
|
927
929
|
return None
|
928
930
|
set_schedule(enable=0)
|
929
|
-
data = {'sn': device_sn}
|
930
931
|
if battery_settings is None:
|
931
932
|
battery_settings = {}
|
932
|
-
if
|
933
|
-
|
934
|
-
|
933
|
+
if minSocOnGrid is not None:
|
934
|
+
if minSocOnGrid < 0 or minSocOnGrid > 100:
|
935
|
+
output(f"** set_min(): invalid minSocOnGrid = {minSocOnGrid}. Must be between 0 and 100")
|
936
|
+
return None
|
937
|
+
battery_settings['minSocOnGrid'] = minSocOnGrid
|
935
938
|
if minSoc is not None:
|
936
|
-
|
939
|
+
if minSoc < 0 or minSoc > 100:
|
940
|
+
output(f"** set_min(): invalid minSoc = {minSoc}. Must be between 0 and 100")
|
941
|
+
return None
|
937
942
|
battery_settings['minSoc'] = minSoc
|
938
|
-
|
943
|
+
data = {'sn': device_sn}
|
944
|
+
if battery_settings.get('minSocOnGrid') is not None:
|
945
|
+
data['minGridSoc'] = battery_settings['minSocOnGrid']
|
946
|
+
if battery_settings.get('minSoc') is not None:
|
947
|
+
data['minSoc'] = battery_settings['minSoc']
|
948
|
+
output(f"\nSetting minSocOnGrid = {battery_settings.get('minSocOnGrid')}, minSoc = {battery_settings.get('minSoc')}", 1)
|
939
949
|
setting_delay()
|
940
950
|
response = signed_post(path="/c/v0/device/battery/soc/set", data=data)
|
941
951
|
if response.status_code != 200:
|
@@ -1417,7 +1427,7 @@ def find_template(name):
|
|
1417
1427
|
|
1418
1428
|
# create a period structure. Note: end time is exclusive.
|
1419
1429
|
def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdsoc=None, fdpwr=None, price=None, segment=None, quiet=1):
|
1420
|
-
global schedule
|
1430
|
+
global schedule, device
|
1421
1431
|
if schedule is None and get_flag() is None:
|
1422
1432
|
return None
|
1423
1433
|
if segment is not None and type(segment) is dict:
|
@@ -1442,7 +1452,11 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
|
|
1442
1452
|
return None
|
1443
1453
|
min_soc = 10 if min_soc is None else min_soc
|
1444
1454
|
max_soc = None if schedule.get('maxsoc') is None or schedule['maxsoc'] == False else 100 if max_soc is None else max_soc
|
1455
|
+
if mode == 'ForceCharge' and fdsoc is None:
|
1456
|
+
fdsoc = max_soc if max_soc is not None else 100
|
1445
1457
|
fdsoc = min_soc if fdsoc is None else fdsoc
|
1458
|
+
power = (device['power'] * 1000) if device.get('power') is not None else None
|
1459
|
+
fdpwr = power if fdpwr is None and power is not None and mode in ['ForceCharge', 'ForceDischarge'] else fdpwr
|
1446
1460
|
fdpwr = 0 if fdpwr is None else fdpwr
|
1447
1461
|
if min_soc < 10 or min_soc > 100:
|
1448
1462
|
output(f"set_period(): ** min_soc must be between 10 and 100")
|
@@ -1450,8 +1464,8 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
|
|
1450
1464
|
if max_soc is not None and (max_soc < 10 or max_soc > 100):
|
1451
1465
|
output(f"set_period(): ** max_soc must be between 10 and 100")
|
1452
1466
|
return None
|
1453
|
-
if fdpwr < 0 or fdpwr >
|
1454
|
-
output(f"set_period(): ** fdpwr must be between 0 and
|
1467
|
+
if fdpwr < 0 or fdpwr > 30000:
|
1468
|
+
output(f"set_period(): ** fdpwr must be between 0 and 30000")
|
1455
1469
|
return None
|
1456
1470
|
if fdsoc < min_soc or fdsoc > 100:
|
1457
1471
|
output(f"set_period(): ** fdsoc must between {min_soc} and 100")
|
@@ -1459,7 +1473,7 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
|
|
1459
1473
|
if quiet == 0:
|
1460
1474
|
s = f" {hours_time(start)}-{hours_time(end)} {mode}, minsoc {min_soc}%"
|
1461
1475
|
s += f", maxsoc {max_soc}%" if max_soc is not None and mode == 'ForceCharge' else ""
|
1462
|
-
s += f", fdPwr {fdpwr}W, fdSoC {fdsoc}%" if mode
|
1476
|
+
s += f", fdPwr {fdpwr}W, fdSoC {fdsoc}%" if mode in ['ForceCharge', 'ForceDischarge'] else ""
|
1463
1477
|
s += f", {price:.2f}p/kWh" if price is not None else ""
|
1464
1478
|
output(s, 1)
|
1465
1479
|
start_h, start_m = split_hours(start)
|
foxesscloud/openapi.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
##################################################################################################
|
2
2
|
"""
|
3
3
|
Module: Fox ESS Cloud using Open API
|
4
|
-
Updated:
|
4
|
+
Updated: 2 October 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.8.
|
13
|
+
version = "2.8.8"
|
14
14
|
print(f"FoxESS-Cloud Open API version {version}")
|
15
15
|
|
16
16
|
debug_setting = 1
|
@@ -371,9 +371,10 @@ def get_site(name=None):
|
|
371
371
|
|
372
372
|
logger_list = None
|
373
373
|
logger = None
|
374
|
+
logger_sn = None
|
374
375
|
|
375
376
|
def get_logger(sn=None):
|
376
|
-
global logger_list, logger, debug_setting
|
377
|
+
global logger_list, logger, logger_sn, debug_setting
|
377
378
|
if get_vars() is None:
|
378
379
|
return None
|
379
380
|
if logger is not None and sn is None:
|
@@ -408,8 +409,30 @@ def get_logger(sn=None):
|
|
408
409
|
else:
|
409
410
|
n = 0
|
410
411
|
logger = logger_list[n]
|
412
|
+
logger_sn = logger.get('moduleSN')
|
411
413
|
return logger
|
412
414
|
|
415
|
+
def get_signal(sn=None):
|
416
|
+
global logger_list, logger, logger_sn, debug_setting
|
417
|
+
if get_vars() is None:
|
418
|
+
return None
|
419
|
+
if sn is None:
|
420
|
+
if logger_sn is None:
|
421
|
+
get_logger()
|
422
|
+
sn = logger_sn
|
423
|
+
if sn is None:
|
424
|
+
return None
|
425
|
+
output(f"getting signal", 2)
|
426
|
+
body = {'sn': sn}
|
427
|
+
response = signed_post(path="/op/v0/module/getSignal", body=body)
|
428
|
+
if response.status_code != 200:
|
429
|
+
output(f"** get_signal() got response code {response.status_code}: {response.reason}")
|
430
|
+
return None
|
431
|
+
result = response.json().get('result')
|
432
|
+
if result is None:
|
433
|
+
output(f"** get_signal(), no result data, {errno_message(response)}")
|
434
|
+
return None
|
435
|
+
return result
|
413
436
|
|
414
437
|
##################################################################################################
|
415
438
|
# get list of devices and select one, using the serial number if there is more than 1
|
@@ -593,6 +616,8 @@ def get_battery(info=0, v=None, rated=None, count=None):
|
|
593
616
|
battery = {}
|
594
617
|
for i in range(0, len(battery_vars)):
|
595
618
|
battery[battery_data[i]] = result[i].get('value')
|
619
|
+
if debug_setting > 1:
|
620
|
+
print(f"raw battery = {battery}")
|
596
621
|
battery['residual_handling'] = residual_handling
|
597
622
|
battery['soh'] = None
|
598
623
|
battery['soh_supported'] = False
|
@@ -798,13 +823,13 @@ def set_min(minSocOnGrid = None, minSoc = None, force = 0):
|
|
798
823
|
if battery_settings is None:
|
799
824
|
battery_settings = {}
|
800
825
|
if minSocOnGrid is not None:
|
801
|
-
if minSocOnGrid <
|
802
|
-
output(f"** set_min(): invalid minSocOnGrid = {minSocOnGrid}. Must be between
|
826
|
+
if minSocOnGrid < 0 or minSocOnGrid > 100:
|
827
|
+
output(f"** set_min(): invalid minSocOnGrid = {minSocOnGrid}. Must be between 0 and 100")
|
803
828
|
return None
|
804
829
|
battery_settings['minSocOnGrid'] = minSocOnGrid
|
805
830
|
if minSoc is not None:
|
806
|
-
if minSoc <
|
807
|
-
output(f"** set_min(): invalid minSoc = {minSoc}. Must be between
|
831
|
+
if minSoc < 0 or minSoc > 100:
|
832
|
+
output(f"** set_min(): invalid minSoc = {minSoc}. Must be between 0 and 100")
|
808
833
|
return None
|
809
834
|
battery_settings['minSoc'] = minSoc
|
810
835
|
body = {'sn': device_sn}
|
@@ -812,7 +837,7 @@ def set_min(minSocOnGrid = None, minSoc = None, force = 0):
|
|
812
837
|
body['minSocOnGrid'] = battery_settings['minSocOnGrid']
|
813
838
|
if battery_settings.get('minSoc') is not None:
|
814
839
|
body['minSoc'] = battery_settings['minSoc']
|
815
|
-
output(f"\nSetting
|
840
|
+
output(f"\nSetting minSocOnGrid = {battery_settings.get('minSocOnGrid')}, minSoc = {battery_settings.get('minSoc')}", 1)
|
816
841
|
setting_delay()
|
817
842
|
response = signed_post(path="/op/v0/device/battery/soc/set", body=body)
|
818
843
|
if response.status_code != 200:
|
@@ -1108,9 +1133,9 @@ def build_strategy_from_schedule():
|
|
1108
1133
|
|
1109
1134
|
# create time segment structure. Note: end time is exclusive.
|
1110
1135
|
def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdsoc=None, fdpwr=None, price=None, segment=None, enable=1, quiet=1):
|
1111
|
-
global schedule
|
1112
|
-
if schedule is None
|
1113
|
-
|
1136
|
+
global schedule, device
|
1137
|
+
if schedule is None:
|
1138
|
+
get_schedule()
|
1114
1139
|
if segment is not None and type(segment) is dict:
|
1115
1140
|
start = segment.get('start')
|
1116
1141
|
end = segment.get('end')
|
@@ -1132,8 +1157,12 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
|
|
1132
1157
|
output(f"** mode must be one of {work_modes}")
|
1133
1158
|
return None
|
1134
1159
|
min_soc = 10 if min_soc is None else min_soc
|
1135
|
-
max_soc = None if schedule.get('maxsoc') is None or schedule['maxsoc'] == False else 100 if max_soc is None else max_soc
|
1160
|
+
max_soc = None if schedule is None or schedule.get('maxsoc') is None or schedule['maxsoc'] == False else 100 if max_soc is None else max_soc
|
1161
|
+
if mode == 'ForceCharge' and fdsoc is None:
|
1162
|
+
fdsoc = max_soc if max_soc is not None else 100
|
1136
1163
|
fdsoc = min_soc if fdsoc is None else fdsoc
|
1164
|
+
power = (device['power'] * 1000) if device.get('power') is not None else None
|
1165
|
+
fdpwr = power if fdpwr is None and device.get('power') is not None and mode in ['ForceCharge', 'ForceDischarge'] else fdpwr
|
1137
1166
|
fdpwr = 0 if fdpwr is None else fdpwr
|
1138
1167
|
if min_soc < 10 or min_soc > 100:
|
1139
1168
|
output(f"set_period(): ** min_soc must be between 10 and 100")
|
@@ -1141,8 +1170,8 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
|
|
1141
1170
|
if max_soc is not None and (max_soc < 10 or max_soc > 100):
|
1142
1171
|
output(f"set_period(): ** max_soc must be between 10 and 100")
|
1143
1172
|
return None
|
1144
|
-
if fdpwr < 0 or fdpwr >
|
1145
|
-
output(f"set_period(): ** fdpwr must be between 0 and
|
1173
|
+
if fdpwr < 0 or fdpwr > 30000:
|
1174
|
+
output(f"set_period(): ** fdpwr must be between 0 and 30000")
|
1146
1175
|
return None
|
1147
1176
|
if fdsoc < min_soc or fdsoc > 100:
|
1148
1177
|
output(f"set_period(): ** fdsoc must between {min_soc} and 100")
|
@@ -1150,7 +1179,7 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
|
|
1150
1179
|
if quiet == 0:
|
1151
1180
|
s = f" {hours_time(start)}-{hours_time(end)} {mode}, minsoc {min_soc}%"
|
1152
1181
|
s += f", maxsoc {max_soc}%" if max_soc is not None and mode == 'ForceCharge' else ""
|
1153
|
-
s += f", fdPwr {fdpwr}W, fdSoC {fdsoc}%" if mode
|
1182
|
+
s += f", fdPwr {fdpwr}W, fdSoC {fdsoc}%" if mode in ['ForceCharge', 'ForceDischarge'] else ""
|
1154
1183
|
s += f", {price:.2f}p/kWh" if price is not None else ""
|
1155
1184
|
output(s, 1)
|
1156
1185
|
start_hour, start_minute = split_hours(start)
|
@@ -1636,6 +1665,10 @@ def get_report(dimension='day', d=None, v=None, summary=1, save=None, load=None,
|
|
1636
1665
|
if errno > 0 or result is None or len(result) == 0:
|
1637
1666
|
output(f"** get_report(), no report data available, {errno_message(response)}")
|
1638
1667
|
return None
|
1668
|
+
# correct variables in year report (AP 19/09/2025):
|
1669
|
+
if dimension == 'year':
|
1670
|
+
for i, var in enumerate(result):
|
1671
|
+
var['variable'] = v[i]
|
1639
1672
|
# correct errors in report values:
|
1640
1673
|
if fix_values == 1:
|
1641
1674
|
for var in result:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foxesscloud
|
3
|
-
Version: 2.8.
|
3
|
+
Version: 2.8.8
|
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
|
@@ -63,13 +63,14 @@ For example, replace _my.fox_api_key_ with the API key. Add you inverter serial
|
|
63
63
|
Residual handling configures how battery residual energy reported by Fox is handled:
|
64
64
|
+ 1: Fox returns the current battery residual energy and battery capacity is calculated using soc
|
65
65
|
+ 2: Fox returns the current battery capacity and battery residual is calculated using soc
|
66
|
+
+ 3: Fox returns the residual capacity per battery (Mira)
|
66
67
|
|
67
68
|
If a value is set for f.plot_file, any charts created will also be saved to an image file:
|
68
69
|
+ f.plot_file: the file name to use. The file extension determines the format - .png, .pdf or .svg. If you provide just a filename, each chart will over-write the file. The default is None and disables saving.
|
69
70
|
+ f.plot_no: if the file name contains ###, this will be replaced by 3 digit plot number that increases for each chart created. The default is 0.
|
70
71
|
+ f.plot_dpi: sets the image resolution. The default is 150. Reducing this value produces smaller, lower resolution images. Increasing this value produces larger, highe resolution images
|
71
72
|
|
72
|
-
If you set f.pushover_user_key to your user_key for pushover.net, a summary from set_tariff(), charge_needed(), set_pvoutput() and battery_info() will be sent to your pushover app.
|
73
|
+
If you set f.pushover_user_key to your user_key for [pushover.net](https://pushover.net), a summary from set_tariff(), charge_needed(), set_pvoutput() and battery_info() will be sent to your pushover app.
|
73
74
|
|
74
75
|
You can set 'f.storage' to a path to save files to a different location such as cloud storage. The default is to use the current working directory.
|
75
76
|
|
@@ -90,6 +91,7 @@ Load information about a site, data logger or inverter (device):
|
|
90
91
|
```
|
91
92
|
f.get_site()
|
92
93
|
f.get_logger()
|
94
|
+
f.get_signal()
|
93
95
|
f.get_device()
|
94
96
|
```
|
95
97
|
|
@@ -98,7 +100,9 @@ By default, this will load the first item in the list provided by the cloud. If
|
|
98
100
|
+ Logger: full or partial serial number
|
99
101
|
+ Inverter: full or partial serial number
|
100
102
|
|
101
|
-
When an item is selected, the functions returns a dictionary containing item details and saves these to a global variable (f.site, f.logger, f.device respectively)
|
103
|
+
When an item is selected, the functions returns a dictionary containing item details and saves these to a global variable (f.site, f.logger, f.device respectively).
|
104
|
+
|
105
|
+
get_signal() is ancillary to get_logger() and returns the current data logger signal strength and time stamp.
|
102
106
|
|
103
107
|
Once an inverter is selected, you can make other calls to get information:
|
104
108
|
|
@@ -142,7 +146,7 @@ get_schedule() returns the current work mode / soc schedule settings. The result
|
|
142
146
|
|
143
147
|
get_named_settings() returns the value of a named setting. If 'name' is a list, it returns a list of values.
|
144
148
|
+ f.named_settings is updated. This is dictionary of information and current value, indexed by 'name'.
|
145
|
-
+ named_settings
|
149
|
+
+ named_settings currently supported include: ExportLimit, MinSoc, MinSocOnGrid, MaxSoc, GridCode, WorkMode
|
146
150
|
|
147
151
|
|
148
152
|
## Inverter Settings
|
@@ -152,7 +156,6 @@ You can change inverter settings using:
|
|
152
156
|
f.set_min(minSocOnGrid, minSoc)
|
153
157
|
f.set_charge(ch1, st1, en1, ch2, st2, en2, enable)
|
154
158
|
f.set_period(start, end, mode, min_soc, max_soc, fdsoc, fdpwr, price, segment)
|
155
|
-
f.charge_periods(st0, en0, st1, en1, st2, en2, min_soc, target_soc, start_soc)
|
156
159
|
f.set_schedule(periods, enable)
|
157
160
|
f.set_named_settings(name, value, force)
|
158
161
|
```
|
@@ -160,6 +163,7 @@ f.set_named_settings(name, value, force)
|
|
160
163
|
set_min() applies new SoC settings to the inverter. The parameters update battery_settings:
|
161
164
|
+ minSocOnGrid: min Soc on Grid setting e.g. 15 = 15%
|
162
165
|
+ minSoc: min Soc setting e.g. 10 = 10%
|
166
|
+
+ force: setting to 1 will disable Mode Scheduler, if enabled. Default is 0.
|
163
167
|
|
164
168
|
set_charge() takes the charge times from the battery_settings and applies these to the inverter. The parameters are optional and will update battery_settings. You should specify all 3 parameter for a time period:
|
165
169
|
+ ch1: enable charge from grid for period 1 (default True)
|
@@ -180,16 +184,7 @@ set_period() returns a period structure that can be used to build a list for set
|
|
180
184
|
+ enable: sets whether this time segment is enable (1) or disabled (0). The default is enabled.
|
181
185
|
+ segment: optional, allows the parameters for the period to be passed as a dictionary instead of individual values.
|
182
186
|
|
183
|
-
|
184
|
-
+ st0: the start time for period 0 when you don't want the battery to discharge before charging
|
185
|
-
+ en0: the end time for period 0
|
186
|
-
+ st1: the start time for the period when the battery charges from the grid
|
187
|
-
+ en1: the end time for period 1
|
188
|
-
+ st2: the start time for period 2 when you don't want the batteru to discharge after charging
|
189
|
-
+ en2: the end time for period 2
|
190
|
-
+ min_soc: the min_soc to use when building the strategy
|
191
|
-
+ start_soc: the min_soc to use for period 0
|
192
|
-
+ target_soc: the max_soc to set during period 1 and min_soc to use for period 2
|
187
|
+
Before calling set_period(), do at least one call to get_schedule(). This will inspect the schedule result to check if max_soc is supported and set the flag f.schedule['maxsoc'] to enable or disable this field as appropriate.
|
193
188
|
|
194
189
|
set_schedule() configures a list of scheduled work mode / soc changes with enable=1. If called with enable=0, any existing schedules are disabled. To enable a schedule, you must provide a list of time segments
|
195
190
|
+ periods: a time segment or list of time segments created using f.set_period().
|
@@ -197,9 +192,9 @@ set_schedule() configures a list of scheduled work mode / soc changes with enabl
|
|
197
192
|
|
198
193
|
set_named_settings() sets the 'name' setting to 'value'.
|
199
194
|
+ 'name' may also be a list of (name, value) pairs.
|
200
|
-
+
|
195
|
+
+ force: setting to 1 will disable Mode Scheduler, if enabled. Default is 0.
|
201
196
|
+ a return value of 1 is success. 0 means setting failed. None is another error e.g. device not found, invalid name or value.
|
202
|
-
+ named_settings
|
197
|
+
+ named_settings currently supported include: ExportLimit, MinSoc, MinSocOnGrid, MaxSoc, GridCode, WorkMode
|
203
198
|
|
204
199
|
|
205
200
|
## Real Time Data
|
@@ -826,7 +821,18 @@ This setting can be:
|
|
826
821
|
|
827
822
|
# Version Info
|
828
823
|
|
829
|
-
2.8.
|
824
|
+
2.8.8<br>
|
825
|
+
Fix problem where Open API returns conflicting variable names when reporting stats by year.
|
826
|
+
Update daily template for Saturn Cloud to new YAML format.
|
827
|
+
Update set_min() to accept 0 instead of 10.
|
828
|
+
|
829
|
+
2.8.7<br>
|
830
|
+
Added f.get_signal().
|
831
|
+
Updated set_period so you don't have to call get_schedule before.
|
832
|
+
Update set_period() to pass fdpwr and fdsoc for ForceCharge and display value.
|
833
|
+
Increase max value of fdpwr from 6000 to 30000.
|
834
|
+
|
835
|
+
2.8.6<br>
|
830
836
|
Update to charge_needed() to get current work mode.
|
831
837
|
|
832
838
|
2.8.5<br>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
foxesscloud/foxesscloud.py,sha256=vd3nBwhrqxkRmKMRa6iOXOiFq8Eg4czmv9_NNghiSq0,225903
|
2
|
+
foxesscloud/openapi.py,sha256=pgn4e_bVjTr_IWjHoeNFWM1GI3vlpD9dOOCkmpy4Yqg,211084
|
3
|
+
foxesscloud-2.8.8.dist-info/LICENCE,sha256=8JF-24QkE8UfdII-g6RaIEvM-PZ9zwaEcxlwYUDMt-4,1079
|
4
|
+
foxesscloud-2.8.8.dist-info/METADATA,sha256=zPZSZtAiAyBJPfe93ZsOVTWSFVrIYOYlvkw4Icxil4Y,66133
|
5
|
+
foxesscloud-2.8.8.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
6
|
+
foxesscloud-2.8.8.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
|
7
|
+
foxesscloud-2.8.8.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
foxesscloud/foxesscloud.py,sha256=_Su3Dcs0CSM2TlbAmCtouM4LkhYfYZ2Bk70eVgZqBJg,225011
|
2
|
-
foxesscloud/openapi.py,sha256=ftS5WZ838P3kSbjoHB0Ypcb6MYV-ePGX6nDbhpEpf0I,209702
|
3
|
-
foxesscloud-2.8.6.dist-info/LICENCE,sha256=8JF-24QkE8UfdII-g6RaIEvM-PZ9zwaEcxlwYUDMt-4,1079
|
4
|
-
foxesscloud-2.8.6.dist-info/METADATA,sha256=YceASwn6QpmzkI1IXtC33PQ-lBW0XWZU6YbmxYj3eMo,65928
|
5
|
-
foxesscloud-2.8.6.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
6
|
-
foxesscloud-2.8.6.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
|
7
|
-
foxesscloud-2.8.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|