foxesscloud 2.6.2__py3-none-any.whl → 2.6.4__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: 12 October 2024
4
+ Updated: 13 October 2024
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.7.4"
13
+ version = "1.7.6"
14
14
  print(f"FoxESS-Cloud version {version}")
15
15
 
16
16
  debug_setting = 1
@@ -632,7 +632,7 @@ def get_battery(info=1):
632
632
  output(f"** get_battery().info, no result data, {errno_message(errno)}")
633
633
  else:
634
634
  battery['info'] = result['batteries'][0]
635
- if battery['info']['masterVersion'] >= '1.014':
635
+ if battery['info']['masterVersion'] >= '1.014' and battery['info']['masterSN'][:7] == '60BBHV2':
636
636
  residual_handling = 2
637
637
  battery['residual_handling'] = residual_handling
638
638
  battery['rated_capacity'] = None
@@ -687,32 +687,35 @@ def get_batteries(info=1):
687
687
  for i in range(0, len(batteries)):
688
688
  batteries[i]['info'] = result['batteries'][i]
689
689
  for b in batteries:
690
- if b.get('info') is not None and b['info']['masterVersion'] >= '1.014':
690
+ b['residual_handling'] = residual_handling
691
+ if b.get('info') is not None and b['info']['masterVersion'] >= '1.014' and b['info']['masterSN'][:7] == '60BBHV2':
691
692
  b['residual_handling'] = 2
692
- if b.get('soh') is not None and b['soh'].isnumeric():
693
- b['soh_supported'] = True
694
- else:
695
- b['rated_capacity'] = None
696
- b['soh'] = None
697
- b['soh_supported'] = False
698
- for b in batteries:
699
- if b.get('soh_supported') is not None and b['soh_supported']:
700
- capacity = (b['ratedCapacity'] / 1000 * int(b['soh']) / 100)
693
+ rated_capacity = b.get('ratedCapacity')
694
+ b['ratedCapacity'] = rated_capacity if rated_capacity is not None and rated_capacity > 100 else None
695
+ soh = b.get('soh')
696
+ b['soh'] = int(soh) if soh.isnumeric() and int(soh) > 10 else None
697
+ b['soh_supported'] = b['soh'] is not None
698
+ for i, b in enumerate(batteries):
699
+ if i == 0:
700
+ residual_handling = b['residual_handling']
701
+ get_battery(info=0)
702
+ b['capacity'] = battery.get('capacity')
703
+ b['residual'] = battery.get('residual')
704
+ b['soc'] = battery.get('soc')
705
+ if b.get('capacity') is None and b.get('ratedCapacity') is not None and b.get('soh') is not None:
706
+ b['capacity'] = round(b['ratedCapacity'] / 1000 * b['soh'] / 100, 3)
707
+ if b.get('residual') is None and b.get('capacity') is not None and b.get('soc') is not None:
701
708
  soc = b.get('soc')
702
- residual = capacity * soc / 100 if capacity is not None and soc is not None else capacity
703
- b['capacity'] = round(capacity, 3)
709
+ residual = b['capacity'] * b['soc'] / 100
704
710
  b['residual'] = round(residual, 3)
705
- b['charge_rate'] = 50
706
- params = battery_params[residual_handling]
707
- b['charge_loss'] = params['charge_loss']
708
- b['discharge_loss'] = params['discharge_loss']
709
- if b.get('temperature') is not None:
710
- b['charge_rate'] = params['table'][int((b['temperature'] - params['offset']) / params['step'])]
711
- else:
712
- get_battery(info=info)
713
- batteries = [battery]
714
- break
715
- battery = batteries[0]
711
+ if b.get('capacity') is not None and b.get('ratedCapacity') is not None:
712
+ b['soh'] = round(b['capacity'] * 1000 / b['ratedCapacity'] * 100, 1)
713
+ b['charge_rate'] = 50
714
+ params = battery_params[b['residual_handling']]
715
+ b['charge_loss'] = params['charge_loss']
716
+ b['discharge_loss'] = params['discharge_loss']
717
+ if b.get('temperature') is not None:
718
+ b['charge_rate'] = params['table'][int((b['temperature'] - params['offset']) / params['step'])]
716
719
  return batteries
717
720
 
718
721
  ##################################################################################################
@@ -2351,7 +2354,7 @@ tariff_config = {
2351
2354
  'update_time': 16.5, # time in hours when tomrow's data can be fetched
2352
2355
  'weighting': None, # weights for weighted average
2353
2356
  'plunge_price': [3, 3], # plunge price in p/kWh inc VAT over 24 hours from 7am, 7pm
2354
- 'plunge_slots': 6, # number of 30 minute slots to use
2357
+ 'plunge_slots': 8, # number of 30 minute slots to use
2355
2358
  'data_wrap': 6, # prices to show per line
2356
2359
  'show_data': 1, # show pricing data
2357
2360
  'show_plot': 1 # plot pricing data
@@ -2412,9 +2415,9 @@ def get_agile_times(tariff=agile_octopus, d=None):
2412
2415
  plunge = []
2413
2416
  plunge_price = tariff_config['plunge_price'] if tariff_config.get('plunge_price') is not None else 2
2414
2417
  plunge_price = [plunge_price] if type(plunge_price) is not list else plunge_price
2415
- plunge_slots = tariff_config['plunge_slots'] if tariff_config.get('plunge_slots') is not None else 6
2418
+ plunge_slots = tariff_config['plunge_slots'] if tariff_config.get('plunge_slots') is not None else 8
2416
2419
  for i in range(0, len(prices)):
2417
- # hour relative index into list of plunge prices, starting at 7am
2420
+ # hour relative index into list of plunge prices and slots, starting at 7am
2418
2421
  x = int(((now.hour - 7 + i / 2) % 24) * len(plunge_price) / 24)
2419
2422
  if prices[i] is not None and prices[i]['price'] < plunge_price[x]:
2420
2423
  plunge.append(i)
@@ -3551,12 +3554,12 @@ def battery_info(log=0, plot=1, count=None, info=1, bat=None):
3551
3554
  for v in cell_temps:
3552
3555
  s +=f",{v:.0f}"
3553
3556
  return s
3554
- if rated_capacity is not None:
3555
- output(f"Rated Capacity: {rated_capacity / 1000:.2f}kWh")
3556
- output(f"SoH: {bat_soh}%")
3557
3557
  output(f"Current SoC: {current_soc}%")
3558
- output(f"Capacity: {capacity:.2f}kWh")
3559
- output(f"Residual: {residual:.2f}kWh" + (" (SoC x Capacity)" if bat['residual_handling'] == 2 else ""))
3558
+ output(f"Capacity: {capacity:.2f}kWh" + (" (Residual / SoC x 100)" if bat['residual_handling'] == 1 else ""))
3559
+ output(f"Residual: {residual:.2f}kWh" + (" (SoC x Capacity / 100)" if bat['residual_handling'] == 2 else ""))
3560
+ if rated_capacity is not None and bat_soh is not None:
3561
+ output(f"Rated Capacity: {rated_capacity / 1000:.2f}kWh")
3562
+ output(f"SoH: {bat_soh:.1f}%" + (" (Capacity / Rated Capacity x 100)" if not bat['soh_supported'] else ""))
3560
3563
  output(f"InvBatVolt: {bat_volt:.1f}V")
3561
3564
  output(f"InvBatCurrent: {bat_current:.1f}A")
3562
3565
  output(f"State: {'Charging' if bat_power < 0 else 'Discharging'} ({abs(bat_power):.3f}kW)")
foxesscloud/openapi.py CHANGED
@@ -1,7 +1,7 @@
1
1
  ##################################################################################################
2
2
  """
3
3
  Module: Fox ESS Cloud using Open API
4
- Updated: 12 October 2024
4
+ Updated: 13 October 2024
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.6.2"
13
+ version = "2.6.4"
14
14
  print(f"FoxESS-Cloud Open API version {version}")
15
15
 
16
16
  debug_setting = 1
@@ -605,6 +605,8 @@ def get_battery(info=0, v=None):
605
605
  def get_batteries(info=0):
606
606
  global battery, batteries
607
607
  get_battery(info=info)
608
+ if battery is None:
609
+ return None
608
610
  batteries = [battery]
609
611
  return batteries
610
612
 
@@ -2156,7 +2158,7 @@ tariff_config = {
2156
2158
  'update_time': 16.5, # time in hours when tomrow's data can be fetched
2157
2159
  'weighting': None, # weights for weighted average
2158
2160
  'plunge_price': [3, 3], # plunge price in p/kWh inc VAT over 24 hours from 7am, 7pm
2159
- 'plunge_slots': 6, # number of 30 minute slots to use
2161
+ 'plunge_slots': 8, # number of 30 minute slots to use
2160
2162
  'data_wrap': 6, # prices to show per line
2161
2163
  'show_data': 1, # show pricing data
2162
2164
  'show_plot': 1 # plot pricing data
@@ -2217,7 +2219,7 @@ def get_agile_times(tariff=agile_octopus, d=None):
2217
2219
  plunge = []
2218
2220
  plunge_price = tariff_config['plunge_price'] if tariff_config.get('plunge_price') is not None else 2
2219
2221
  plunge_price = [plunge_price] if type(plunge_price) is not list else plunge_price
2220
- plunge_slots = tariff_config['plunge_slots'] if tariff_config.get('plunge_slots') is not None else 6
2222
+ plunge_slots = tariff_config['plunge_slots'] if tariff_config.get('plunge_slots') is not None else 8
2221
2223
  for i in range(0, len(prices)):
2222
2224
  # hour relative index into list of plunge prices, starting at 7am
2223
2225
  x = int(((now.hour - 7 + i / 2) % 24) * len(plunge_price) / 24)
@@ -3351,12 +3353,12 @@ def battery_info(log=0, plot=1, count=None, info=1, bat=None):
3351
3353
  for v in cell_temps:
3352
3354
  s +=f",{v:.0f}"
3353
3355
  return s
3354
- if rated_capacity is not None:
3355
- output(f"Rated Capacity: {rated_capacity / 1000:.2f}kWh")
3356
- output(f"SoH: {bat_soh}%")
3357
3356
  output(f"Current SoC: {current_soc}%")
3358
- output(f"Capacity: {capacity:.2f}kWh")
3359
- output(f"Residual: {residual:.2f}kWh")
3357
+ output(f"Capacity: {capacity:.2f}kWh" + (" (Residual / SoC x 100)" if bat['residual_handling'] == 1 else ""))
3358
+ output(f"Residual: {residual:.2f}kWh" + (" (SoC x Capacity / 100)" if bat['residual_handling'] == 2 else ""))
3359
+ if rated_capacity is not None and bat_soh is not None:
3360
+ output(f"Rated Capacity: {rated_capacity / 1000:.2f}kWh")
3361
+ output(f"SoH: {bat_soh:.1f}%" + (" (Capacity / Rated Capacity x 100)" if not bat['soh_supported'] else ""))
3360
3362
  output(f"InvBatVolt: {bat_volt:.1f}V")
3361
3363
  output(f"InvBatCurrent: {bat_current:.1f}A")
3362
3364
  output(f"State: {'Charging' if bat_power < 0 else 'Discharging'} ({abs(bat_power):.3f}kW)")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foxesscloud
3
- Version: 2.6.2
3
+ Version: 2.6.4
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
@@ -787,6 +787,10 @@ This setting can be:
787
787
 
788
788
  # Version Info
789
789
 
790
+ 2.6.4<br>
791
+ Increase default plungs_slots from 6 to 8.
792
+ Correct battery capacity in get_batteries().
793
+
790
794
  2.6.2<br>
791
795
  Update battery calibration for charge_needed() when residual_handling is 2.
792
796
  Update get_battery() and get_batteries() to include states for ratedCapacity, soh, residual_handling and soh_supported.
@@ -0,0 +1,7 @@
1
+ foxesscloud/foxesscloud.py,sha256=kfb3Ard_s3LZ1hN53RfwcRUyEeMGd6TviHtoFmQyYDY,217547
2
+ foxesscloud/openapi.py,sha256=jFWMAlbhHAFqlKZlg8rALgU-jziUdrTjM0b4I0eTyAQ,207518
3
+ foxesscloud-2.6.4.dist-info/LICENCE,sha256=-3xv8CElCJV8Bc8PbAsg3iyxMpAK8MoJneM3rXigxqI,1074
4
+ foxesscloud-2.6.4.dist-info/METADATA,sha256=uNjXzpjeHGt65jOvDoLApHmb8-awuWtRg9BRfJKnzFU,57854
5
+ foxesscloud-2.6.4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
6
+ foxesscloud-2.6.4.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
7
+ foxesscloud-2.6.4.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- foxesscloud/foxesscloud.py,sha256=j1-EcJ3vudFCalHBbyBXUTl99s4-foWqq1831YLdHXg,216792
2
- foxesscloud/openapi.py,sha256=USny4eYMLxG2rg3FsijGp7w_cOT8eMMvy0pVN0DbVSU,207227
3
- foxesscloud-2.6.2.dist-info/LICENCE,sha256=-3xv8CElCJV8Bc8PbAsg3iyxMpAK8MoJneM3rXigxqI,1074
4
- foxesscloud-2.6.2.dist-info/METADATA,sha256=Y96zL2xTMWPk1yjNnO_QQgulzpPy82Q6IXiEVYHyxxE,57751
5
- foxesscloud-2.6.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
6
- foxesscloud-2.6.2.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
7
- foxesscloud-2.6.2.dist-info/RECORD,,