foxesscloud 2.9.1__tar.gz → 2.9.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foxesscloud
3
- Version: 2.9.1
3
+ Version: 2.9.2
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
@@ -180,12 +180,16 @@ set_period() returns a period structure that can be used to build a list for set
180
180
  + max_soc: optional, default is 100
181
181
  + fdsoc: optional, default is 10. Used when setting a period with ForceDischarge mode
182
182
  + fdpwr: optional, default is 0. Used when setting a period with ForceDischarge mode
183
+ + import_limit: optional, default is None (not set). Used when setting a period with ForceCharge mode
184
+ + export_limit: optional, default is None (not set). Used when setting a period with ForceDischarge mode
183
185
  + price: optional, default None. Used to display plunge pricing for time period.
184
186
  + enable: sets whether this time segment is enable (1) or disabled (0). The default is enabled.
185
187
  + segment: optional, allows the parameters for the period to be passed as a dictionary instead of individual values.
186
188
 
187
189
  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.
188
190
 
191
+ The variable f.max_periods is used to check the number of time periods allowed. The default is 8.
192
+
189
193
  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
190
194
  + periods: a time segment or list of time segments created using f.set_period().
191
195
  + enable: 1 to enable schedules, 0 to disable schedules. The default is 1.
@@ -821,6 +825,10 @@ This setting can be:
821
825
 
822
826
  # Version Info
823
827
 
828
+ 2.9.2 - 2025/11/30<br>
829
+ Update get_schedule(), set_period() and set_schedule() to use v2 interface and add setting import_limit and export_limit.
830
+ Added f.max_periods to allow for more time periods in schedules (default is 8).
831
+
824
832
  2.9.1 - 2025/10/25<br>
825
833
  Change default contingency for charge_needed() to [25,15,10,20] and special contingency to 35.
826
834
  Update info shown around contingency.
@@ -166,12 +166,16 @@ set_period() returns a period structure that can be used to build a list for set
166
166
  + max_soc: optional, default is 100
167
167
  + fdsoc: optional, default is 10. Used when setting a period with ForceDischarge mode
168
168
  + fdpwr: optional, default is 0. Used when setting a period with ForceDischarge mode
169
+ + import_limit: optional, default is None (not set). Used when setting a period with ForceCharge mode
170
+ + export_limit: optional, default is None (not set). Used when setting a period with ForceDischarge mode
169
171
  + price: optional, default None. Used to display plunge pricing for time period.
170
172
  + enable: sets whether this time segment is enable (1) or disabled (0). The default is enabled.
171
173
  + segment: optional, allows the parameters for the period to be passed as a dictionary instead of individual values.
172
174
 
173
175
  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.
174
176
 
177
+ The variable f.max_periods is used to check the number of time periods allowed. The default is 8.
178
+
175
179
  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
176
180
  + periods: a time segment or list of time segments created using f.set_period().
177
181
  + enable: 1 to enable schedules, 0 to disable schedules. The default is 1.
@@ -807,6 +811,10 @@ This setting can be:
807
811
 
808
812
  # Version Info
809
813
 
814
+ 2.9.2 - 2025/11/30<br>
815
+ Update get_schedule(), set_period() and set_schedule() to use v2 interface and add setting import_limit and export_limit.
816
+ Added f.max_periods to allow for more time periods in schedules (default is 8).
817
+
810
818
  2.9.1 - 2025/10/25<br>
811
819
  Change default contingency for charge_needed() to [25,15,10,20] and special contingency to 35.
812
820
  Update info shown around contingency.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "foxesscloud"
7
- version = "2.9.1"
7
+ version = "2.9.2"
8
8
  authors = [
9
9
  {name="Tony Matthews", email="tony@quasair.co.uk"},
10
10
  ]
@@ -1,7 +1,7 @@
1
1
  ##################################################################################################
2
2
  """
3
3
  Module: Fox ESS Cloud using Open API
4
- Updated: 25 October 2025
4
+ Updated: 30 November 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.9.1"
13
+ version = "2.9.2"
14
14
  print(f"FoxESS-Cloud Open API version {version}")
15
15
 
16
16
  debug_setting = 1
@@ -1053,6 +1053,7 @@ def set_work_mode(mode, force = 0):
1053
1053
  ##################################################################################################
1054
1054
 
1055
1055
  schedule = None
1056
+ max_periods = 8
1056
1057
 
1057
1058
  # get the current switch status
1058
1059
  def get_flag():
@@ -1090,7 +1091,7 @@ def get_schedule():
1090
1091
  return None
1091
1092
  output(f"getting schedule", 2)
1092
1093
  body = {'deviceSN': device_sn}
1093
- response = signed_post(path="/op/v1/device/scheduler/get", body=body)
1094
+ response = signed_post(path="/op/v2/device/scheduler/get", body=body)
1094
1095
  if response.status_code != 200:
1095
1096
  output(f"** get_schedule() got response code {response.status_code}: {response.reason}")
1096
1097
  return None
@@ -1107,7 +1108,7 @@ def get_schedule():
1107
1108
  for g in result['groups']:
1108
1109
  if g['enable'] == 1 and g['workMode'] in work_modes:
1109
1110
  schedule['periods'].append(g)
1110
- if g.get('maxSoc') is not None:
1111
+ if g.get('extraParam') is not None and g['extraParam'].get('maxSoc') is not None:
1111
1112
  schedule['maxsoc'] = True
1112
1113
  return schedule
1113
1114
 
@@ -1126,6 +1127,8 @@ def build_strategy_from_schedule():
1126
1127
  period['max_soc'] = p.get('maxSoc')
1127
1128
  period['fdsoc'] = p.get('fdsoc')
1128
1129
  period['fdpwr'] = p.get('fdpwr')
1130
+ period['import_limit'] = p.get('importLimit')
1131
+ period['export_limit'] = p.get('exportLimit')
1129
1132
  strategy.append(period)
1130
1133
  return strategy
1131
1134
 
@@ -1134,7 +1137,7 @@ def build_strategy_from_schedule():
1134
1137
  ##################################################################################################
1135
1138
 
1136
1139
  # create time segment structure. Note: end time is exclusive.
1137
- 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):
1140
+ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdsoc=None, fdpwr=None, import_limit=None, export_limit=None, price=None, segment=None, enable=1, quiet=1):
1138
1141
  global schedule, device
1139
1142
  if schedule is None:
1140
1143
  get_schedule()
@@ -1146,6 +1149,8 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
1146
1149
  max_soc = segment.get('max_soc')
1147
1150
  fdsoc = segment.get('fdSoc')
1148
1151
  fdpwr = segment.get('fdPwr')
1152
+ import_limit = segment.get('import_limit')
1153
+ export_limit = segment.get('export_limit')
1149
1154
  price = segment.get('price')
1150
1155
  start = time_hours(start)
1151
1156
  # adjust exclusive time to inclusive
@@ -1166,8 +1171,8 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
1166
1171
  power = (device['power'] * 1000) if device.get('power') is not None else None
1167
1172
  fdpwr = power if fdpwr is None and device.get('power') is not None and ('ForceCharge' in mode or 'ForceDischarge' in mode) else fdpwr
1168
1173
  fdpwr = 0 if fdpwr is None else fdpwr
1169
- if min_soc < 10 or min_soc > 100:
1170
- output(f"set_period(): ** min_soc must be between 10 and 100")
1174
+ if min_soc < 0 or min_soc > 100:
1175
+ output(f"set_period(): ** min_soc must be between 0 and 100")
1171
1176
  return None
1172
1177
  if max_soc is not None and (max_soc < 10 or max_soc > 100):
1173
1178
  output(f"set_period(): ** max_soc must be between 10 and 100")
@@ -1187,14 +1192,13 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
1187
1192
  start_hour, start_minute = split_hours(start)
1188
1193
  end_hour, end_minute = split_hours(end)
1189
1194
  period = {'enable': enable, 'startHour': start_hour, 'startMinute': start_minute, 'endHour': end_hour, 'endMinute': end_minute, 'workMode': mode,
1190
- 'minSocOnGrid': int(min_soc), 'fdSoc': int(fdsoc), 'fdPwr': int(fdpwr)}
1191
- if max_soc is not None:
1192
- period['maxSoc'] = int(max_soc)
1195
+ 'extraParam': {'minSocOnGrid': int(min_soc), 'fdSoc': int(fdsoc), 'fdPwr': int(fdpwr), 'maxSoc': max_soc, 'importLimit': import_limit,
1196
+ 'exportLimit': export_limit }}
1193
1197
  return period
1194
1198
 
1195
1199
  # set a schedule from a period or list of time segment periods
1196
1200
  def set_schedule(periods=None, enable=True):
1197
- global device_sn, debug_setting, schedule
1201
+ global device_sn, debug_setting, schedule, max_periods
1198
1202
  if get_flag() is None:
1199
1203
  return None
1200
1204
  if schedule.get('support') == False:
@@ -1202,6 +1206,7 @@ def set_schedule(periods=None, enable=True):
1202
1206
  return None
1203
1207
  output(f"set_schedule(): enable = {enable}, periods = {periods}", 2)
1204
1208
  if debug_setting > 2:
1209
+ print(f"** schedule not set (debug_setting={debug_setting})")
1205
1210
  return None
1206
1211
  if type(enable) is int:
1207
1212
  enable = True if enable == 1 else False
@@ -1212,11 +1217,11 @@ def set_schedule(periods=None, enable=True):
1212
1217
  if periods is not None:
1213
1218
  if type(periods) is not list:
1214
1219
  periods = [periods]
1215
- if len(periods) > 8:
1216
- output(f"** set_schedule(): maximum of 8 periods allowed, {len(periods)} provided")
1217
- body = {'deviceSN': device_sn, 'groups': periods[-8:]}
1220
+ if len(periods) > max_periods:
1221
+ output(f"** set_schedule(): maximum of {max_periods} periods allowed, {len(periods)} provided")
1222
+ body = {'deviceSN': device_sn, 'groups': periods[-max_periods:]}
1218
1223
  setting_delay()
1219
- response = signed_post(path="/op/v1/device/scheduler/enable", body=body)
1224
+ response = signed_post(path="/op/v2/device/scheduler/enable", body=body)
1220
1225
  if response.status_code != 200:
1221
1226
  output(f"** set_schedule() periods response code {response.status_code}: {response.reason}")
1222
1227
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foxesscloud
3
- Version: 2.9.1
3
+ Version: 2.9.2
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
@@ -180,12 +180,16 @@ set_period() returns a period structure that can be used to build a list for set
180
180
  + max_soc: optional, default is 100
181
181
  + fdsoc: optional, default is 10. Used when setting a period with ForceDischarge mode
182
182
  + fdpwr: optional, default is 0. Used when setting a period with ForceDischarge mode
183
+ + import_limit: optional, default is None (not set). Used when setting a period with ForceCharge mode
184
+ + export_limit: optional, default is None (not set). Used when setting a period with ForceDischarge mode
183
185
  + price: optional, default None. Used to display plunge pricing for time period.
184
186
  + enable: sets whether this time segment is enable (1) or disabled (0). The default is enabled.
185
187
  + segment: optional, allows the parameters for the period to be passed as a dictionary instead of individual values.
186
188
 
187
189
  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.
188
190
 
191
+ The variable f.max_periods is used to check the number of time periods allowed. The default is 8.
192
+
189
193
  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
190
194
  + periods: a time segment or list of time segments created using f.set_period().
191
195
  + enable: 1 to enable schedules, 0 to disable schedules. The default is 1.
@@ -821,6 +825,10 @@ This setting can be:
821
825
 
822
826
  # Version Info
823
827
 
828
+ 2.9.2 - 2025/11/30<br>
829
+ Update get_schedule(), set_period() and set_schedule() to use v2 interface and add setting import_limit and export_limit.
830
+ Added f.max_periods to allow for more time periods in schedules (default is 8).
831
+
824
832
  2.9.1 - 2025/10/25<br>
825
833
  Change default contingency for charge_needed() to [25,15,10,20] and special contingency to 35.
826
834
  Update info shown around contingency.
File without changes
File without changes