foxesscloud 2.7.9__py3-none-any.whl → 2.8.1__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.
@@ -1,7 +1,7 @@
1
1
  ##################################################################################################
2
2
  """
3
3
  Module: Fox ESS Cloud
4
- Updated: 28 January 2025
4
+ Updated: 12 March 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.0"
13
+ version = "1.9.3"
14
14
  print(f"FoxESS-Cloud version {version}")
15
15
 
16
16
  debug_setting = 1
@@ -590,6 +590,7 @@ battery_settings = None
590
590
 
591
591
  # 1 = Residual Energy, 2 = Residual Capacity (HV), 3 = Residual Capacity per battery (Mira)
592
592
  residual_handling = 1
593
+ residual_scale = 0.01
593
594
 
594
595
  # charge rates based on residual_handling. Index is bms temperature
595
596
  battery_params = {
@@ -619,7 +620,7 @@ battery_params = {
619
620
  }
620
621
 
621
622
  def get_battery(info=1, rated=None, count=None):
622
- global device_id, battery, debug_setting, messages, residual_handling, battery_params
623
+ global device_id, battery, debug_setting, messages, residual_handling, battery_params, residual_scale
623
624
  if get_device() is None:
624
625
  return None
625
626
  output(f"getting battery", 2)
@@ -655,11 +656,14 @@ def get_battery(info=1, rated=None, count=None):
655
656
  battery['residual_handling'] = residual_handling
656
657
  battery['soh'] = None
657
658
  battery['soh_supported'] = False
659
+ if battery.get('status') is None:
660
+ battery['status'] = 0 if battery.get('volt') is None or battery['volt'] <= 0 else 1
658
661
  if battery.get('status') is None or battery['status'] != 1:
659
662
  output(f"** get_battery(): battery status not available")
660
663
  return None
664
+ battery['status'] = 1
661
665
  if battery.get('residual') is not None:
662
- battery['residual'] /= 1000
666
+ battery['residual'] *= residual_scale / 10
663
667
  if battery['residual_handling'] == 2:
664
668
  capacity = battery.get('residual')
665
669
  soc = battery.get('soc')
@@ -1826,7 +1830,7 @@ def rescale_history(data, steps):
1826
1830
  # station = 0: use device_id, 1 = use station_id
1827
1831
  ##################################################################################################
1828
1832
 
1829
- report_vars = ['yield', 'input','generation', 'feedin', 'loads', 'gridConsumption', 'chargeEnergyToTal', 'dischargeEnergyToTal']
1833
+ report_vars = ['PVEnergyTotal', 'input','generation', 'feedin', 'loads', 'gridConsumption', 'chargeEnergyToTal', 'dischargeEnergyToTal']
1830
1834
  report_names = ['PV Yield', 'Input', 'Generation', 'Grid Export', 'Consumption', 'Grid Import', 'Battery Charge', 'Battery Discharge']
1831
1835
 
1832
1836
  # fix power values after fox corrupts high word of 32-bit energy total
@@ -3093,7 +3097,10 @@ def charge_needed(forecast=None, consumption=None, update_settings=0, timed_mode
3093
3097
  bat_current = battery['current']
3094
3098
  temperature = battery['temperature']
3095
3099
  residual = battery['residual']
3096
- capacity = charge_config['capacity'] if charge_config.get('capacity') is not None else battery.get('capacity')
3100
+ capacity = battery.get('capacity')
3101
+ if charge_config.get('capacity') is not None:
3102
+ capacity = charge_config['capacity']
3103
+ residual = (capacity * current_soc / 100) if capacity is not None and current_soc is not None else None
3097
3104
  if capacity is None:
3098
3105
  output(f"Battery capacity could not be estimated. Please add the parameter 'capacity=xx' in kWh")
3099
3106
  return None
foxesscloud/openapi.py CHANGED
@@ -1,7 +1,7 @@
1
1
  ##################################################################################################
2
2
  """
3
3
  Module: Fox ESS Cloud using Open API
4
- Updated: 27 January 2025
4
+ Updated: 12 March 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.9"
13
+ version = "2.8.1"
14
14
  print(f"FoxESS-Cloud Open API version {version}")
15
15
 
16
16
  debug_setting = 1
@@ -1010,7 +1010,7 @@ def get_flag():
1010
1010
  return None
1011
1011
  output(f"getting flag", 2)
1012
1012
  body = {'deviceSN': device_sn}
1013
- response = signed_post(path="/op/v0/device/scheduler/get/flag", body=body)
1013
+ response = signed_post(path="/op/v1/device/scheduler/get/flag", body=body)
1014
1014
  if response.status_code != 200:
1015
1015
  output(f"** get_flag() got response code {response.status_code}: {response.reason}")
1016
1016
  return None
@@ -1040,7 +1040,7 @@ def get_schedule():
1040
1040
  return None
1041
1041
  output(f"getting schedule", 2)
1042
1042
  body = {'deviceSN': device_sn}
1043
- response = signed_post(path="/op/v0/device/scheduler/get", body=body)
1043
+ response = signed_post(path="/op/v1/device/scheduler/get", body=body)
1044
1044
  if response.status_code != 200:
1045
1045
  output(f"** get_schedule() got response code {response.status_code}: {response.reason}")
1046
1046
  return None
@@ -1133,7 +1133,7 @@ def set_period(start=None, end=None, mode=None, min_soc=None, max_soc=None, fdso
1133
1133
  period = {'enable': enable, 'startHour': start_hour, 'startMinute': start_minute, 'endHour': end_hour, 'endMinute': end_minute, 'workMode': mode,
1134
1134
  'minSocOnGrid': int(min_soc), 'fdSoc': int(fdsoc), 'fdPwr': int(fdpwr)}
1135
1135
  if max_soc is not None:
1136
- period['maxsoc'] = int(max_soc)
1136
+ period['maxSoc'] = int(max_soc)
1137
1137
  return period
1138
1138
 
1139
1139
  # set a schedule from a period or list of time segment periods
@@ -1160,7 +1160,7 @@ def set_schedule(periods=None, enable=True):
1160
1160
  output(f"** set_schedule(): maximum of 8 periods allowed, {len(periods)} provided")
1161
1161
  body = {'deviceSN': device_sn, 'groups': periods[-8:]}
1162
1162
  setting_delay()
1163
- response = signed_post(path="/op/v0/device/scheduler/enable", body=body)
1163
+ response = signed_post(path="/op/v1/device/scheduler/enable", body=body)
1164
1164
  if response.status_code != 200:
1165
1165
  output(f"** set_schedule() periods response code {response.status_code}: {response.reason}")
1166
1166
  return None
@@ -1171,7 +1171,7 @@ def set_schedule(periods=None, enable=True):
1171
1171
  schedule['periods'] = periods
1172
1172
  body = {'deviceSN': device_sn, 'enable': 1 if enable else 0}
1173
1173
  setting_delay()
1174
- response = signed_post(path="/op/v0/device/scheduler/set/flag", body=body)
1174
+ response = signed_post(path="/op/v1/device/scheduler/set/flag", body=body)
1175
1175
  if response.status_code != 200:
1176
1176
  output(f"** set_schedule() flag response code {response.status_code}: {response.reason}")
1177
1177
  return None
@@ -1530,8 +1530,8 @@ def rescale_history(data, steps):
1530
1530
  # plot = 0: no plot, 1 = plot variables separately, 2 = combine variables
1531
1531
  ##################################################################################################
1532
1532
 
1533
- report_vars = ['generation', 'feedin', 'loads', 'gridConsumption', 'chargeEnergyToTal', 'dischargeEnergyToTal']
1534
- report_names = ['Generation', 'Grid Export', 'Consumption', 'Grid Import', 'Battery Charge', 'Battery Discharge']
1533
+ report_vars = ['generation', 'feedin', 'loads', 'gridConsumption', 'chargeEnergyToTal', 'dischargeEnergyToTal', 'PVEnergyTotal']
1534
+ report_names = ['Generation', 'Grid Export', 'Consumption', 'Grid Import', 'Battery Charge', 'Battery Discharge', 'PV Yield']
1535
1535
 
1536
1536
  # fix power values after corruption of high word of 32-bit energy total
1537
1537
  fix_values = 1
@@ -2764,7 +2764,10 @@ def charge_needed(forecast=None, consumption=None, update_settings=0, timed_mode
2764
2764
  bat_current = battery['current']
2765
2765
  temperature = battery['temperature']
2766
2766
  residual = battery['residual']
2767
- capacity = charge_config['capacity'] if charge_config.get('capacity') is not None else battery.get('capacity')
2767
+ capacity = battery.get('capacity')
2768
+ if charge_config.get('capacity') is not None:
2769
+ capacity = charge_config['capacity']
2770
+ residual = (capacity * current_soc / 100) if capacity is not None and current_soc is not None else None
2768
2771
  if capacity is None:
2769
2772
  output(f"Battery capacity could not be estimated. Please add the parameter 'capacity=xx' in kWh")
2770
2773
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foxesscloud
3
- Version: 2.7.9
3
+ Version: 2.8.1
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
@@ -809,6 +809,11 @@ This setting can be:
809
809
 
810
810
  # Version Info
811
811
 
812
+ 2.8.1<br>
813
+ Update from v0 to v1 for scheduler API.
814
+ PVEnergyTotal added to report variables.
815
+ Fix residual if capacity is specified for charge_needed().
816
+
812
817
  2.7.9<br>
813
818
  Add 'consumption' input for charge_needed().
814
819
  Avoid throwing exception in battery_info() if there is no capacity info.
@@ -0,0 +1,7 @@
1
+ foxesscloud/foxesscloud.py,sha256=keJUa9j7OhAJF1lnbNAbTaFTnJm3T-XyiyuWOwF8KdM,224235
2
+ foxesscloud/openapi.py,sha256=HTYc-ueI_gZRelOduaABzWBzaGsJTZlpo_1fWqkEhSc,208461
3
+ foxesscloud-2.8.1.dist-info/LICENCE,sha256=8JF-24QkE8UfdII-g6RaIEvM-PZ9zwaEcxlwYUDMt-4,1079
4
+ foxesscloud-2.8.1.dist-info/METADATA,sha256=ptLAC2vtyV5pYu-HE8p8Ot_JoMPgnTCYNChXA0dCmv0,63522
5
+ foxesscloud-2.8.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
6
+ foxesscloud-2.8.1.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
7
+ foxesscloud-2.8.1.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- foxesscloud/foxesscloud.py,sha256=6subMmEgHYVGQWFvf7LZ5dOwfygUxNM4jRct74OfwkY,223877
2
- foxesscloud/openapi.py,sha256=FQVHqSsm5sEZ3rDq_MRutag1eGmTwPZTn1Qr-I3n8Ho,208291
3
- foxesscloud-2.7.9.dist-info/LICENCE,sha256=8JF-24QkE8UfdII-g6RaIEvM-PZ9zwaEcxlwYUDMt-4,1079
4
- foxesscloud-2.7.9.dist-info/METADATA,sha256=RdNw-jLKWmu-wko-wDa6215WoalBlsu_qzsRlIL5JVc,63366
5
- foxesscloud-2.7.9.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
6
- foxesscloud-2.7.9.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
7
- foxesscloud-2.7.9.dist-info/RECORD,,