foxesscloud 2.5.3__py3-none-any.whl → 2.5.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: 23 September 2024
4
+ Updated: 25 September 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.6.5"
13
+ version = "1.6.6"
14
14
  print(f"FoxESS-Cloud version {version}")
15
15
 
16
16
  debug_setting = 1
@@ -2264,11 +2264,6 @@ regions = {'A':'Eastern England', 'B':'East Midlands', 'C':'London', 'D':'Mersey
2264
2264
  'J':'South Eastern England', 'K':'Southern Wales', 'L':'South Western England', 'M':'Yorkshire', 'N':'Southern Scotland', 'P':'Northern Scotland'}
2265
2265
 
2266
2266
 
2267
- # preset weightings for average 30 minute pricing over charging duration:
2268
- front_loaded = [1.0, 0.9, 0.8, 0.7, 0.6, 0.5] # 3 hour average, front loaded
2269
- first_hour = [1.0, 1.0] # lowest average price for first hour
2270
-
2271
-
2272
2267
  tariff_config = {
2273
2268
  'product': "AGILE-24-04-03", # product code to use for Octopus API
2274
2269
  'region': "H", # region code to use for Octopus API
@@ -2277,7 +2272,7 @@ tariff_config = {
2277
2272
  'plunge_price': [1, 10], # plunge price in p/kWh inc VAT over 24 hours from 7am, 7pm
2278
2273
  'plunge_slots': 6, # number of 30 minute slots to use
2279
2274
  'data_wrap': 6, # prices to show per line
2280
- 'show_data': 0, # show pricing data
2275
+ 'show_data': 1, # show pricing data
2281
2276
  'show_plot': 1 # plot pricing data
2282
2277
  }
2283
2278
 
@@ -2361,13 +2356,13 @@ def get_agile_times(tariff=agile_octopus, d=None):
2361
2356
  # show the results
2362
2357
  if tariff_config['show_data'] > 0:
2363
2358
  data_wrap = tariff_config['data_wrap'] if tariff_config.get('data_wrap') is not None else 6
2364
- t = (now.hour * 2) % data_wrap
2365
- s = f"\nPricing on {today} p/kWh inc VAT:\n" + " " * t * 13
2359
+ col = (now.hour * 2) % data_wrap
2360
+ s = f"\nPrice p/kWh inc VAT on {today}:"
2366
2361
  for i in range(0, len(prices)):
2367
- s += "\n" if i > 0 and t % data_wrap == 0 else ""
2368
- s += f" {prices[i]['time']} {prices[i]['price']:4.1f},"
2369
- t += 1
2370
- output(s[:-1])
2362
+ s += (f"\n {prices[i]['time']} " + " " * col * 6) if i == 0 or col == 0 else ""
2363
+ s += f" {prices[i]['price']:4.1f}"
2364
+ col = (col + 1) % data_wrap
2365
+ output(s)
2371
2366
  if tariff_config['show_plot'] > 0:
2372
2367
  plt.figure(figsize=(figure_width, figure_width/2))
2373
2368
  x_timed = [i for i in range(0, len(prices))]
@@ -2394,7 +2389,8 @@ def get_best_charge_period(start, duration):
2394
2389
  key = [k for k in ['off_peak1', 'off_peak2', 'off_peak3', 'off_peak4'] if hour_in(start, tariff.get(k))]
2395
2390
  key = key[0] if len(key) > 0 else None
2396
2391
  end = tariff[key]['end'] if key is not None else round_time(start + duration)
2397
- span = int(duration * 2 + 0.99)
2392
+ span = int(duration * 2 + 0.99) # number of slots needed for charging
2393
+ last = (duration * 2) % 1 # amount of last slot used for charging
2398
2394
  coverage = max([round_time(end - start), duration])
2399
2395
  period = {'start': start, 'end': round_time(start + coverage)}
2400
2396
  prices = tariff['agile']['prices']
@@ -2403,13 +2399,14 @@ def get_best_charge_period(start, duration):
2403
2399
  return None
2404
2400
  elif len(slots) == 1:
2405
2401
  best = slots
2406
- price = prices[slots[0]]['price']
2407
2402
  best_start = start
2403
+ price = prices[best[0]]['price']
2408
2404
  else:
2409
2405
  # best charge time for duration
2410
2406
  weighting = tariff_config.get('weighting')
2411
2407
  times = []
2412
- weights = ([1.0] * span) if weighting is None else (weighting + [1.0] * span)[:span]
2408
+ weights = ([1.0] * (span)) if weighting is None else (weighting + [1.0] * span)[:span]
2409
+ weights[-1] *= last if last > 0.0 else 1.0
2413
2410
  best = None
2414
2411
  price = None
2415
2412
  for i in range(0, len(slots) - span + 1):
@@ -2964,7 +2961,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
2964
2961
  solcast_value = fsolcast.daily[forecast_day]['kwh']
2965
2962
  solcast_timed = forecast_value_timed(fsolcast, today, tomorrow, base_hour, run_time, time_offset)
2966
2963
  solcast_from = time_hours(fsolcast.daily[today]['from']) if fsolcast.daily[today].get('from') is not None else 0
2967
- output(f"\nSolcast forecast for {tomorrow}: {fsolcast.daily[tomorrow]['kwh']:.1f}") # get forecast.solar data and produce time line
2964
+ output(f"\nSolcast: {tomorrow} {fsolcast.daily[tomorrow]['kwh']:.1f}kWh") # get forecast.solar data and produce time line
2968
2965
  solar_value = None
2969
2966
  solar_profile = None
2970
2967
  if forecast is None and solar_arrays is not None and (system_time.hour in forecast_times or run_after == 0):
@@ -2972,7 +2969,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
2972
2969
  if fsolar is not None and hasattr(fsolar, 'daily') and fsolar.daily.get(forecast_day) is not None:
2973
2970
  solar_value = fsolar.daily[forecast_day]['kwh']
2974
2971
  solar_timed = forecast_value_timed(fsolar, today, tomorrow, base_hour, run_time, 0)
2975
- output(f"\nSolar forecast for {tomorrow}: {fsolar.daily[tomorrow]['kwh']:.1f}")
2972
+ output(f"\nSolar: {tomorrow} {fsolar.daily[tomorrow]['kwh']:.1f}kWh")
2976
2973
  if solcast_value is None and solar_value is None and debug_setting > 1:
2977
2974
  output(f"\nNo forecasts available at this time")
2978
2975
  # get generation data
@@ -3073,7 +3070,8 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
3073
3070
  charge_message = "** test charge **"
3074
3071
  # work out charge needed
3075
3072
  if kwh_min > (reserve + kwh_contingency) and kwh_needed < charge_config['min_kwh']:
3076
- output(f"\nNo charging needed ({today} {hours_time(hour_now)} {current_soc:.0f}%)")
3073
+ output(f"\nNo charging needed:")
3074
+ output(f" SoC now: {current_soc:.0f}% at {hours_time(hour_now)} on {today}")
3077
3075
  charge_message = "no charge needed"
3078
3076
  kwh_needed = 0.0
3079
3077
  hours = 0.0
@@ -3086,8 +3084,9 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
3086
3084
  work_mode_timed[t]['min_soc'] = start_soc
3087
3085
  else:
3088
3086
  if test_charge is None:
3089
- output(f"\nCharge needed {kwh_needed:.2f}kWh ({today} {hours_time(hour_now)} {current_soc:.0f}%)")
3087
+ output(f"\nCharge needed {kwh_needed:.2f}kWh:")
3090
3088
  charge_message = "with charge added"
3089
+ output(f" SoC now: {current_soc:.0f}% at {hours_time(hour_now)} on {today}")
3091
3090
  output(f" Start SoC: {start_residual / capacity * 100:.0f}% at {hours_time(adjusted_hour(time_to_start, time_line))} ({start_residual:.2f}kWh)")
3092
3091
  # work out time to add kwh_needed to battery
3093
3092
  taper_time = 10/60 if (start_residual + kwh_needed) >= (capacity * 0.95) else 0
@@ -3136,17 +3135,16 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
3136
3135
  output(f" PV cover: {expected / consumption * 100:.0f}% ({expected:.1f}/{consumption:.1f})")
3137
3136
  if show_data > 0:
3138
3137
  data_wrap = charge_config['data_wrap'] if charge_config.get('data_wrap') is not None else 6
3139
- s = f"\nBattery Energy kWh:\n" if show_data == 2 else f"\nBattery SoC:\n"
3138
+ s = f"\nBattery Energy kWh:" if show_data == 2 else f"\nBattery SoC:"
3140
3139
  h = base_hour + 1
3141
3140
  t = steps_per_hour
3142
- s += " " * (14 if show_data == 2 else 13) * (h % data_wrap)
3143
3141
  while t < len(time_line) and bat_timed[t] is not None:
3144
- s += "\n" if t > steps_per_hour and h % data_wrap == 0 else ""
3145
- s += f" {hours_time(time_line[t])}"
3146
- s += f" {bat_timed[t]:5.2f}" if show_data == 2 else f" {bat_timed[t] / capacity * 100:3.0f}%,"
3142
+ col = h % data_wrap
3143
+ s += (f"\n {hours_time(time_line[t])}" + " " * col * 6) if t == steps_per_hour or col == 0 else ""
3144
+ s += f" {bat_timed[t]:5.2f}" if show_data == 2 else f" {bat_timed[t] / capacity * 100:3.0f}%"
3147
3145
  h += 1
3148
3146
  t += steps_per_hour
3149
- output(s[:-1])
3147
+ output(s)
3150
3148
  if show_plot > 0:
3151
3149
  print()
3152
3150
  plt.figure(figsize=(figure_width, figure_width/2))
@@ -3274,17 +3272,16 @@ def charge_compare(save=None, v=None, show_data=1, show_plot=3):
3274
3272
  plots[v][i] = plots[v][i] / count[v][i] if count[v][i] > 0 else None
3275
3273
  if show_data > 0 and plots.get('SoC') is not None:
3276
3274
  data_wrap = charge_config['data_wrap'] if charge_config.get('data_wrap') is not None else 6
3277
- s = f"\nBattery Energy kWh:\n" if show_data == 2 else f"\nBattery SoC:\n"
3275
+ s = f"\nBattery Energy kWh:" if show_data == 2 else f"\nBattery SoC:"
3278
3276
  h = base_hour + 1
3279
3277
  t = steps_per_hour
3280
- s += " " * (14 if show_data == 2 else 13) * (h % data_wrap)
3281
- while t < len(time_line) and plots['SoC'][t] is not None:
3282
- s += "\n" if t > steps_per_hour and h % data_wrap == 0 else ""
3283
- s += f" {hours_time(time_line[t])}"
3284
- s += f" {plots['SoC'][t]:5.2f}" if show_data == 2 else f" {plots['SoC'][t] / capacity * 100:3.0f}%,"
3278
+ while t < len(time_line) and bat_timed[t] is not None:
3279
+ col = h % data_wrap
3280
+ s += (f"\n {hours_time(time_line[t])}" + " " * col * 6) if t == steps_per_hour or col == 0 else ""
3281
+ s += f" {plots['SoC'][t]:5.2f}" if show_data == 2 else f" {plots['SoC'][t] / capacity * 100:3.0f}%"
3285
3282
  h += 1
3286
3283
  t += steps_per_hour
3287
- print(s[:-1])
3284
+ print(s)
3288
3285
  if show_plot > 0:
3289
3286
  print()
3290
3287
  plt.figure(figsize=(figure_width, figure_width/2))
foxesscloud/openapi.py CHANGED
@@ -1,7 +1,7 @@
1
1
  ##################################################################################################
2
2
  """
3
3
  Module: Fox ESS Cloud using Open API
4
- Updated: 23 September 2024
4
+ Updated: 25 September 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.5.3"
13
+ version = "2.5.4"
14
14
  print(f"FoxESS-Cloud Open API version {version}")
15
15
 
16
16
  debug_setting = 1
@@ -2128,11 +2128,6 @@ regions = {'A':'Eastern England', 'B':'East Midlands', 'C':'London', 'D':'Mersey
2128
2128
  'J':'South Eastern England', 'K':'Southern Wales', 'L':'South Western England', 'M':'Yorkshire', 'N':'Southern Scotland', 'P':'Northern Scotland'}
2129
2129
 
2130
2130
 
2131
- # preset weightings for average 30 minute pricing over charging duration:
2132
- front_loaded = [1.0, 0.9, 0.8, 0.7, 0.6, 0.5] # 3 hour average, front loaded
2133
- first_hour = [1.0, 1.0] # lowest average price for first hour
2134
-
2135
-
2136
2131
  tariff_config = {
2137
2132
  'product': "AGILE-24-04-03", # product code to use for Octopus API
2138
2133
  'region': "H", # region code to use for Octopus API
@@ -2141,7 +2136,7 @@ tariff_config = {
2141
2136
  'plunge_price': [1, 10], # plunge price in p/kWh inc VAT over 24 hours from 7am, 7pm
2142
2137
  'plunge_slots': 6, # number of 30 minute slots to use
2143
2138
  'data_wrap': 6, # prices to show per line
2144
- 'show_data': 0, # show pricing data
2139
+ 'show_data': 1, # show pricing data
2145
2140
  'show_plot': 1 # plot pricing data
2146
2141
  }
2147
2142
 
@@ -2225,13 +2220,13 @@ def get_agile_times(tariff=agile_octopus, d=None):
2225
2220
  # show the results
2226
2221
  if tariff_config['show_data'] > 0:
2227
2222
  data_wrap = tariff_config['data_wrap'] if tariff_config.get('data_wrap') is not None else 6
2228
- t = (now.hour * 2) % data_wrap
2229
- s = f"\nPricing on {today} p/kWh inc VAT:\n" + " " * t * 13
2223
+ col = (now.hour * 2) % data_wrap
2224
+ s = f"\nPrice p/kWh inc VAT on {today}:"
2230
2225
  for i in range(0, len(prices)):
2231
- s += "\n" if i > 0 and t % data_wrap == 0 else ""
2232
- s += f" {prices[i]['time']} {prices[i]['price']:4.1f},"
2233
- t += 1
2234
- output(s[:-1])
2226
+ s += (f"\n {prices[i]['time']} " + " " * col * 6) if i == 0 or col == 0 else ""
2227
+ s += f" {prices[i]['price']:4.1f}"
2228
+ col = (col + 1) % data_wrap
2229
+ output(s)
2235
2230
  if tariff_config['show_plot'] > 0:
2236
2231
  plt.figure(figsize=(figure_width, figure_width/2))
2237
2232
  x_timed = [i for i in range(0, len(prices))]
@@ -2258,7 +2253,8 @@ def get_best_charge_period(start, duration):
2258
2253
  key = [k for k in ['off_peak1', 'off_peak2', 'off_peak3', 'off_peak4'] if hour_in(start, tariff.get(k))]
2259
2254
  key = key[0] if len(key) > 0 else None
2260
2255
  end = tariff[key]['end'] if key is not None else round_time(start + duration)
2261
- span = int(duration * 2 + 0.99)
2256
+ span = int(duration * 2 + 0.99) # number of slots needed for charging
2257
+ last = (duration * 2) % 1 # amount of last slot used for charging
2262
2258
  coverage = max([round_time(end - start), duration])
2263
2259
  period = {'start': start, 'end': round_time(start + coverage)}
2264
2260
  prices = tariff['agile']['prices']
@@ -2267,13 +2263,14 @@ def get_best_charge_period(start, duration):
2267
2263
  return None
2268
2264
  elif len(slots) == 1:
2269
2265
  best = slots
2270
- price = prices[slots[0]]['price']
2271
2266
  best_start = start
2267
+ price = prices[best[0]]['price']
2272
2268
  else:
2273
2269
  # best charge time for duration
2274
2270
  weighting = tariff_config.get('weighting')
2275
2271
  times = []
2276
- weights = ([1.0] * span) if weighting is None else (weighting + [1.0] * span)[:span]
2272
+ weights = ([1.0] * (span)) if weighting is None else (weighting + [1.0] * span)[:span]
2273
+ weights[-1] *= last if last > 0.0 else 1.0
2277
2274
  best = None
2278
2275
  price = None
2279
2276
  for i in range(0, len(slots) - span + 1):
@@ -2827,7 +2824,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
2827
2824
  if fsolcast is not None and hasattr(fsolcast, 'daily') and fsolcast.daily.get(forecast_day) is not None:
2828
2825
  solcast_value = fsolcast.daily[forecast_day]['kwh']
2829
2826
  solcast_timed = forecast_value_timed(fsolcast, today, tomorrow, base_hour, run_time, time_offset)
2830
- output(f"\nSolcast forecast for {tomorrow}: {fsolcast.daily[tomorrow]['kwh']:.1f}")
2827
+ output(f"\nSolcast: {tomorrow} {fsolcast.daily[tomorrow]['kwh']:.1f}kWh")
2831
2828
  # get forecast.solar data and produce time line
2832
2829
  solar_value = None
2833
2830
  solar_profile = None
@@ -2836,7 +2833,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
2836
2833
  if fsolar is not None and hasattr(fsolar, 'daily') and fsolar.daily.get(forecast_day) is not None:
2837
2834
  solar_value = fsolar.daily[forecast_day]['kwh']
2838
2835
  solar_timed = forecast_value_timed(fsolar, today, tomorrow, base_hour, run_time, 0)
2839
- output(f"\nSolar forecast for {tomorrow}: {fsolar.daily[tomorrow]['kwh']:.1f}")
2836
+ output(f"\nSolar: {tomorrow} {fsolar.daily[tomorrow]['kwh']:.1f}kWh")
2840
2837
  if solcast_value is None and solar_value is None and debug_setting > 1:
2841
2838
  output(f"\nNo forecasts available at this time")
2842
2839
  # get generation data
@@ -2937,7 +2934,8 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
2937
2934
  charge_message = "** test charge **"
2938
2935
  # work out charge needed
2939
2936
  if kwh_min > (reserve + kwh_contingency) and kwh_needed < charge_config['min_kwh'] and full_charge is None and test_charge is None and force_charge != 2:
2940
- output(f"\nNo charging needed ({today} {hours_time(hour_now)} {current_soc:.0f}%)")
2937
+ output(f"\nNo charging needed:")
2938
+ output(f" SoC now: {current_soc:.0f}% at {hours_time(hour_now)} on {today}")
2941
2939
  charge_message = "no charge needed"
2942
2940
  kwh_needed = 0.0
2943
2941
  hours = 0.0
@@ -2950,8 +2948,9 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
2950
2948
  work_mode_timed[t]['min_soc'] = start_soc
2951
2949
  else:
2952
2950
  if test_charge is None:
2953
- output(f"\nCharge needed {kwh_needed:.2f}kWh ({today} {hours_time(hour_now)} {current_soc:.0f}%)")
2951
+ output(f"\nCharge needed {kwh_needed:.2f}kWh:")
2954
2952
  charge_message = "with charge added"
2953
+ output(f" SoC now: {current_soc:.0f}% at {hours_time(hour_now)} on {today}")
2955
2954
  output(f" Start SoC: {start_residual / capacity * 100:.0f}% at {hours_time(adjusted_hour(time_to_start, time_line))} ({start_residual:.2f}kWh)")
2956
2955
  # work out time to add kwh_needed to battery
2957
2956
  taper_time = 10/60 if (start_residual + kwh_needed) >= (capacity * 0.95) else 0
@@ -3000,17 +2999,16 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
3000
2999
  output(f" PV cover: {expected / consumption * 100:.0f}% ({expected:.1f}/{consumption:.1f})")
3001
3000
  if show_data > 0:
3002
3001
  data_wrap = charge_config['data_wrap'] if charge_config.get('data_wrap') is not None else 6
3003
- s = f"\nBattery Energy kWh:\n" if show_data == 2 else f"\nBattery SoC:\n"
3002
+ s = f"\nBattery Energy kWh:" if show_data == 2 else f"\nBattery SoC:"
3004
3003
  h = base_hour + 1
3005
3004
  t = steps_per_hour
3006
- s += " " * (14 if show_data == 2 else 13) * (h % data_wrap)
3007
3005
  while t < len(time_line) and bat_timed[t] is not None:
3008
- s += "\n" if t > steps_per_hour and h % data_wrap == 0 else ""
3009
- s += f" {hours_time(time_line[t])}"
3010
- s += f" {bat_timed[t]:5.2f}" if show_data == 2 else f" {bat_timed[t] / capacity * 100:3.0f}%,"
3006
+ col = h % data_wrap
3007
+ s += (f"\n {hours_time(time_line[t])}" + " " * col * 6) if t == steps_per_hour or col == 0 else ""
3008
+ s += f" {bat_timed[t]:5.2f}" if show_data == 2 else f" {bat_timed[t] / capacity * 100:3.0f}%"
3011
3009
  h += 1
3012
3010
  t += steps_per_hour
3013
- output(s[:-1])
3011
+ output(s)
3014
3012
  if show_plot > 0:
3015
3013
  print()
3016
3014
  plt.figure(figsize=(figure_width, figure_width/2))
@@ -3137,17 +3135,16 @@ def charge_compare(save=None, v=None, show_data=1, show_plot=3):
3137
3135
  plots[v][i] = plots[v][i] / count[v][i] if count[v][i] > 0 else None
3138
3136
  if show_data > 0 and plots.get('SoC') is not None:
3139
3137
  data_wrap = charge_config['data_wrap'] if charge_config.get('data_wrap') is not None else 6
3140
- s = f"\nBattery Energy kWh:\n" if show_data == 2 else f"\nBattery SoC:\n"
3138
+ s = f"\nBattery Energy kWh:" if show_data == 2 else f"\nBattery SoC:"
3141
3139
  h = base_hour + 1
3142
3140
  t = steps_per_hour
3143
- s += " " * (14 if show_data == 2 else 13) * (h % data_wrap)
3144
- while t < len(time_line) and plots['SoC'][t] is not None:
3145
- s += "\n" if t > steps_per_hour and h % data_wrap == 0 else ""
3146
- s += f" {hours_time(time_line[t])}"
3147
- s += f" {plots['SoC'][t]:5.2f}" if show_data == 2 else f" {plots['SoC'][t] / capacity * 100:3.0f}%,"
3141
+ while t < len(time_line) and bat_timed[t] is not None:
3142
+ col = h % data_wrap
3143
+ s += (f"\n {hours_time(time_line[t])}" + " " * col * 6) if t == steps_per_hour or col == 0 else ""
3144
+ s += f" {plots['SoC'][t]:5.2f}" if show_data == 2 else f" {plots['SoC'][t] / capacity * 100:3.0f}%"
3148
3145
  h += 1
3149
3146
  t += steps_per_hour
3150
- print(s[:-1])
3147
+ print(s)
3151
3148
  if show_plot > 0:
3152
3149
  print()
3153
3150
  plt.figure(figsize=(figure_width, figure_width/2))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foxesscloud
3
- Version: 2.5.3
3
+ Version: 2.5.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
@@ -528,11 +528,11 @@ This gets the latest 30 minute pricing and uses this to work out the best off pe
528
528
  + forecast_times: a list of times when a forecast can be obtained from Solcast / forecast.solar, aligned with the host system time
529
529
  + strategy: an optional list of times and work modes (see below)
530
530
  + update: optional, 1 (the default) sets the current tariff to Agile Octopus. Setting to 0 does not change the current tariff
531
- + weighting: optional, default is None (see below)
531
+ + weighting: optional, default is None / flat (see below)
532
532
  + time_shift: optional system time shift in hours. The default is for system time to be UTC and to apply the current day light saving time (e.g. GMT/BST)
533
533
  + plunge_price: list of prices in p/kWh when plunge pricing is used (see below). The default is [0, 5].
534
534
  + plunge_slots: the number of 30 minute slots to use for plunge pricing. The default is 6, allowing up to 3 hours.
535
- + show_data: show 30 minute Agile pricing data. Default is 0.
535
+ + show_data: show 30 minute Agile pricing data. Default is 1.
536
536
  + show_plot: plot 30 minute Agile pricing data. Default is 1.
537
537
 
538
538
  Product codes include:
@@ -562,9 +562,7 @@ Region codes include:
562
562
  Pricing for tomorrow is updated around 5pm each day. If run before this time, prices from yesterday are used. By default, prices for tomorrow are fetched after 5pm. The setting for this is:
563
563
  + f.agile_update_time = 17
564
564
 
565
- The best charging period is determined based on the weighted average of the 30 minute prices over the duration. The default is flat (all prices are weighted equally). You can change the weighting by providing 'weighting'. The following preset weightings are provided:
566
- + f.front_loaded: [1.0, 0.9, 0.8, 0.7, 0.6, 0.5]
567
- + f.first_hour: [1.0, 1.0]
565
+ The best charging period is determined based on the weighted average of the 30 minute prices over the duration. The default is flat (all prices are weighted equally, except the last slot, which is pro rata to the charge duration used). You can over-ride the default weighting by providing a list of 30 minute values to apply.
568
566
 
569
567
  set_tariff() can configure multiple off-peak and peak periods for any tariff using the 'times' parameter. Times is a list of tuples:
570
568
  + containing values for key, 'start', 'end' and optional 'force'.
@@ -785,6 +783,12 @@ This setting can be:
785
783
 
786
784
  # Version Info
787
785
 
786
+ 2.5.4<br>
787
+ Remove preset 'weighting' that were not used.
788
+ Update weighting to apply the requested charge duration correctly.
789
+ Reformat price and SoC tables to reduce wrapping and make them easier to read on small screens.
790
+ Change default for set_tariff() to show Agile 30 minute prices.
791
+
788
792
  2.5.3<br>
789
793
  Reverted change to allow updates during a charge period to avoid removing charge in progress.
790
794
  Update contingency and show how this relates to battery SoC.
@@ -0,0 +1,7 @@
1
+ foxesscloud/foxesscloud.py,sha256=elLQc40Zt8QkjmiOhZ2gNe-Wqp5NE38LgnflHpUQMmc,210693
2
+ foxesscloud/openapi.py,sha256=aBVMx8eyh5WRbUQTiAFHh6SDNiKeksBplODIO1x3L-k,204407
3
+ foxesscloud-2.5.4.dist-info/LICENCE,sha256=-3xv8CElCJV8Bc8PbAsg3iyxMpAK8MoJneM3rXigxqI,1074
4
+ foxesscloud-2.5.4.dist-info/METADATA,sha256=KXfCjbfLt8t5jjQbLW_-7UJyoKBvskga5X0sxMkzxmk,55214
5
+ foxesscloud-2.5.4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
6
+ foxesscloud-2.5.4.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
7
+ foxesscloud-2.5.4.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- foxesscloud/foxesscloud.py,sha256=LkRglTcW4sAVPRgXxkhqyt7fcDcDk00ui_nnsdSU51Y,210817
2
- foxesscloud/openapi.py,sha256=2hyHrGpYNUQybmKCLRZmujW8CfnyS0bjKdxZwPpkjCU,204531
3
- foxesscloud-2.5.3.dist-info/LICENCE,sha256=-3xv8CElCJV8Bc8PbAsg3iyxMpAK8MoJneM3rXigxqI,1074
4
- foxesscloud-2.5.3.dist-info/METADATA,sha256=iXU6pABWNwPSUXW4-NrJWCiy3ZecYsiJPIKNAamHR-g,54937
5
- foxesscloud-2.5.3.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
6
- foxesscloud-2.5.3.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
7
- foxesscloud-2.5.3.dist-info/RECORD,,