foxesscloud 2.7.1__py3-none-any.whl → 2.7.3__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 +24 -23
- foxesscloud/openapi.py +17 -17
- {foxesscloud-2.7.1.dist-info → foxesscloud-2.7.3.dist-info}/METADATA +11 -2
- foxesscloud-2.7.3.dist-info/RECORD +7 -0
- foxesscloud-2.7.1.dist-info/RECORD +0 -7
- {foxesscloud-2.7.1.dist-info → foxesscloud-2.7.3.dist-info}/LICENCE +0 -0
- {foxesscloud-2.7.1.dist-info → foxesscloud-2.7.3.dist-info}/WHEEL +0 -0
- {foxesscloud-2.7.1.dist-info → foxesscloud-2.7.3.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: 12 December 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.8.
|
13
|
+
version = "1.8.4"
|
14
14
|
print(f"FoxESS-Cloud version {version}")
|
15
15
|
|
16
16
|
debug_setting = 1
|
@@ -615,6 +615,7 @@ def get_battery(info=1, rated=None, count=None):
|
|
615
615
|
if get_device() is None:
|
616
616
|
return None
|
617
617
|
output(f"getting battery", 2)
|
618
|
+
battery = None
|
618
619
|
params = {'id': device_id}
|
619
620
|
response = signed_get(path="/c/v0/device/battery/info", params=params)
|
620
621
|
if response.status_code != 200:
|
@@ -625,11 +626,8 @@ def get_battery(info=1, rated=None, count=None):
|
|
625
626
|
errno = response.json().get('errno')
|
626
627
|
output(f"** get_battery(), no result data, {errno_message(errno)}")
|
627
628
|
return None
|
628
|
-
saved_info = battery['info'] if battery is not None and battery.get('info') is not None else None
|
629
629
|
battery = result
|
630
|
-
if
|
631
|
-
battery['info'] = saved_info
|
632
|
-
elif info == 1:
|
630
|
+
if info == 1:
|
633
631
|
response = signed_get(path="/generic/v0/device/battery/list", params=params)
|
634
632
|
if response.status_code != 200:
|
635
633
|
output(f"** get_battery().info got response code {response.status_code}: {response.reason}")
|
@@ -649,6 +647,9 @@ def get_battery(info=1, rated=None, count=None):
|
|
649
647
|
battery['residual_handling'] = residual_handling
|
650
648
|
battery['soh'] = None
|
651
649
|
battery['soh_supported'] = False
|
650
|
+
if battery.get('status') is None or battery['status'] != 1:
|
651
|
+
output(f"** get_battery(): battery status not available")
|
652
|
+
return None
|
652
653
|
if battery.get('residual') is not None:
|
653
654
|
battery['residual'] /= 1000
|
654
655
|
if battery['residual_handling'] == 2:
|
@@ -680,9 +681,9 @@ def get_battery(info=1, rated=None, count=None):
|
|
680
681
|
battery['charge_loss'] = params['charge_loss']
|
681
682
|
battery['discharge_loss'] = params['discharge_loss']
|
682
683
|
if battery.get('ratedCapacity') is not None and battery.get('capacity') is not None:
|
683
|
-
battery['soh'] = round(battery['capacity'] * 1000 / battery['ratedCapacity'] * 100, 1)
|
684
|
+
battery['soh'] = round(battery['capacity'] * 1000 / battery['ratedCapacity'] * 100, 1) if battery['ratedCapacity'] > 0.0 else None
|
684
685
|
if battery.get('temperature') is not None:
|
685
|
-
battery['charge_rate'] =
|
686
|
+
battery['charge_rate'] = interpolate((battery['temperature'] - params['offset']) / params['step'], params['table'])
|
686
687
|
return battery
|
687
688
|
|
688
689
|
def get_batteries(info=1, rated=None, count=None):
|
@@ -690,6 +691,7 @@ def get_batteries(info=1, rated=None, count=None):
|
|
690
691
|
if get_device() is None:
|
691
692
|
return None
|
692
693
|
output(f"getting batteries", 2)
|
694
|
+
batteries = None
|
693
695
|
params = {'id': device_id}
|
694
696
|
response = signed_get(path="/generic/v0/device/battery/info", params=params)
|
695
697
|
if response.status_code != 200:
|
@@ -722,6 +724,9 @@ def get_batteries(info=1, rated=None, count=None):
|
|
722
724
|
while len(count) < len(batteries):
|
723
725
|
count.append(None)
|
724
726
|
for i,b in enumerate(batteries):
|
727
|
+
if b.get('status') is None or b['status'] != 1:
|
728
|
+
output(f"** get_batteries(): battery {i+1} status not available")
|
729
|
+
continue
|
725
730
|
b['residual_handling'] = residual_handling
|
726
731
|
if b.get('info') is not None:
|
727
732
|
if b['info'].get('slaveBatteries') is not None:
|
@@ -738,6 +743,8 @@ def get_batteries(info=1, rated=None, count=None):
|
|
738
743
|
b['soh'] = int(soh) if soh.isnumeric() and int(soh) > 10 else None
|
739
744
|
b['soh_supported'] = b['soh'] is not None
|
740
745
|
for i, b in enumerate(batteries):
|
746
|
+
if b.get('status') is None or b['status'] != 1:
|
747
|
+
continue
|
741
748
|
if i == 0:
|
742
749
|
residual_handling = b['residual_handling']
|
743
750
|
get_battery(info=0)
|
@@ -751,13 +758,13 @@ def get_batteries(info=1, rated=None, count=None):
|
|
751
758
|
residual = b['capacity'] * b['soc'] / 100
|
752
759
|
b['residual'] = round(residual, 3)
|
753
760
|
if b.get('ratedCapacity') is not None and b.get('capacity') is not None:
|
754
|
-
b['soh'] = round(b['capacity'] * 1000 / b['ratedCapacity'] * 100, 1)
|
761
|
+
b['soh'] = round(b['capacity'] * 1000 / b['ratedCapacity'] * 100, 1) if b['ratedCapacity'] > 0.0 else None
|
755
762
|
b['charge_rate'] = None
|
756
763
|
params = battery_params[b['residual_handling']]
|
757
764
|
b['charge_loss'] = params['charge_loss']
|
758
765
|
b['discharge_loss'] = params['discharge_loss']
|
759
766
|
if b.get('temperature') is not None:
|
760
|
-
b['charge_rate'] =
|
767
|
+
b['charge_rate'] = interpolate((b['temperature'] - params['offset']) / params['step'], params['table'])
|
761
768
|
return batteries
|
762
769
|
|
763
770
|
##################################################################################################
|
@@ -801,7 +808,7 @@ def time_period(t):
|
|
801
808
|
result += f" Charge from grid" if t['enableGrid'] else f" Battery Hold"
|
802
809
|
return result
|
803
810
|
|
804
|
-
def set_charge(ch1=
|
811
|
+
def set_charge(ch1=True, st1=0, en1=0, ch2=True, st2=0, en2=0, force=0, enable=1):
|
805
812
|
global device_sn, battery_settings, debug_setting, messages, schedule
|
806
813
|
if get_device() is None:
|
807
814
|
return None
|
@@ -1774,7 +1781,7 @@ def report_value_profile(result):
|
|
1774
1781
|
current_total = sum(by_hour)
|
1775
1782
|
result = []
|
1776
1783
|
for t in range(0, 24):
|
1777
|
-
result.append(by_hour[t] * daily_average / current_total)
|
1784
|
+
result.append(by_hour[t] * daily_average / current_total if current_total != 0.0 else 0.0)
|
1778
1785
|
return (daily_average, result)
|
1779
1786
|
|
1780
1787
|
# forwards compatibility
|
@@ -1833,7 +1840,7 @@ def get_report(report_type='day', d=None, v=None, summary=1, save=None, load=Non
|
|
1833
1840
|
return None
|
1834
1841
|
id_name = 'deviceID' if station == 0 else 'stationID'
|
1835
1842
|
id_code = device_id if station == 0 else station_id
|
1836
|
-
query_path = '/
|
1843
|
+
query_path = '/generic/w/v0/device/history/report' if station == 0 else '/generic/w/v0/plant/history/report'
|
1837
1844
|
# process list of days
|
1838
1845
|
if d is not None and type(d) is list:
|
1839
1846
|
result_list = []
|
@@ -3060,7 +3067,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
3060
3067
|
output(f"full_charge = {full_charge}")
|
3061
3068
|
if test_soc is not None:
|
3062
3069
|
current_soc = test_soc
|
3063
|
-
capacity = 14.
|
3070
|
+
capacity = 14.40
|
3064
3071
|
residual = test_soc * capacity / 100
|
3065
3072
|
bat_volt = 317.4
|
3066
3073
|
bat_power = 0.0
|
@@ -3076,7 +3083,6 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
3076
3083
|
# get device and battery info from inverter
|
3077
3084
|
get_battery()
|
3078
3085
|
if battery is None or battery['status'] != 1:
|
3079
|
-
output(f"\nBattery status is not available")
|
3080
3086
|
return None
|
3081
3087
|
current_soc = battery['soc']
|
3082
3088
|
bat_volt = battery['volt']
|
@@ -3192,26 +3198,19 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
3192
3198
|
consumption_timed = timed_list([consumption * x / daily_sum for x in consumption_by_hour], base_hour, run_time)
|
3193
3199
|
# get Solcast data and produce time line
|
3194
3200
|
solcast_value = None
|
3195
|
-
solcast_profile = None
|
3196
3201
|
if forecast is None and solcast_api_key is not None and solcast_api_key != 'my.solcast_api_key' and (system_time.hour in forecast_times or run_after == 0):
|
3197
3202
|
fsolcast = Solcast(quiet=True, reload=reload, shading=charge_config.get('shading'), d=base_time)
|
3198
3203
|
if fsolcast is not None and hasattr(fsolcast, 'daily') and fsolcast.daily.get(forecast_day) is not None:
|
3199
3204
|
solcast_value = fsolcast.daily[forecast_day]['kwh']
|
3200
3205
|
solcast_timed = forecast_value_timed(fsolcast, today, tomorrow, base_hour, run_time, time_offset)
|
3201
|
-
solcast_from = time_hours(fsolcast.daily[today]['from']) if fsolcast.daily[today].get('from') is not None else 0
|
3202
|
-
output(f"\nSolcast: {tomorrow} {fsolcast.daily[tomorrow]['kwh']:.1f}kWh")
|
3203
3206
|
# get forecast.solar data and produce time line
|
3204
3207
|
solar_value = None
|
3205
|
-
solar_profile = None
|
3206
3208
|
if forecast is None and solar_arrays is not None and (system_time.hour in forecast_times or run_after == 0):
|
3207
3209
|
fsolar = Solar(quiet=True, shading=charge_config.get('shading'), d=base_time)
|
3208
3210
|
if fsolar is not None and hasattr(fsolar, 'daily') and fsolar.daily.get(forecast_day) is not None:
|
3209
3211
|
solar_value = fsolar.daily[forecast_day]['kwh']
|
3210
3212
|
solar_timed = forecast_value_timed(fsolar, today, tomorrow, base_hour, run_time, 0)
|
3211
|
-
|
3212
|
-
if solcast_value is None and solar_value is None and debug_setting > 1:
|
3213
|
-
output(f"\nNo forecasts available at this time")
|
3214
|
-
# choose expected value and produce generation time line
|
3213
|
+
# choose expected value
|
3215
3214
|
quarter = int(today[5:7] if charge_today else tomorrow[5:7]) // 3 % 4
|
3216
3215
|
sun_name = seasonal_sun[quarter]['name']
|
3217
3216
|
sun_profile = seasonal_sun[quarter]['sun']
|
@@ -3225,9 +3224,11 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
3225
3224
|
elif solcast_value is not None:
|
3226
3225
|
expected = solcast_value
|
3227
3226
|
generation_timed = solcast_timed
|
3227
|
+
output(f"\nSolcast: {tomorrow} {fsolcast.daily[tomorrow]['kwh']:.1f}kWh")
|
3228
3228
|
elif solar_value is not None:
|
3229
3229
|
expected = solar_value
|
3230
3230
|
generation_timed = solar_timed
|
3231
|
+
output(f"\nSolar: {tomorrow} {fsolar.daily[tomorrow]['kwh']:.1f}kWh")
|
3231
3232
|
else:
|
3232
3233
|
# no forecast, use generation history
|
3233
3234
|
generation = None
|
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: 12 December 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.7.
|
13
|
+
version = "2.7.3"
|
14
14
|
print(f"FoxESS-Cloud Open API version {version}")
|
15
15
|
|
16
16
|
debug_setting = 1
|
@@ -582,13 +582,18 @@ def get_battery(info=0, v=None, rated=None, count=None):
|
|
582
582
|
if v is None:
|
583
583
|
v = battery_vars
|
584
584
|
result = get_real(v)
|
585
|
-
|
586
|
-
battery = {}
|
585
|
+
battery = {}
|
587
586
|
for i in range(0, len(battery_vars)):
|
588
587
|
battery[battery_data[i]] = result[i].get('value')
|
589
588
|
battery['residual_handling'] = residual_handling
|
590
589
|
battery['soh'] = None
|
591
590
|
battery['soh_supported'] = False
|
591
|
+
if battery.get('status') is None:
|
592
|
+
battery['status'] = 0 if battery.get('volt') is None or battery['volt'] <= 0 else 1
|
593
|
+
if battery['status'] != 1:
|
594
|
+
output(f"** get_battery(): battery status not available")
|
595
|
+
return None
|
596
|
+
battery['status'] = 1
|
592
597
|
if battery['residual_handling'] == 2:
|
593
598
|
capacity = battery.get('residual')
|
594
599
|
soc = battery.get('soc')
|
@@ -621,9 +626,9 @@ def get_battery(info=0, v=None, rated=None, count=None):
|
|
621
626
|
battery['charge_loss'] = params['charge_loss']
|
622
627
|
battery['discharge_loss'] = params['discharge_loss']
|
623
628
|
if battery.get('ratedCapacity') is not None and battery.get('capacity') is not None:
|
624
|
-
battery['soh'] = round(battery['capacity'] * 1000 / battery['ratedCapacity'] * 100, 1)
|
629
|
+
battery['soh'] = round(battery['capacity'] * 1000 / battery['ratedCapacity'] * 100, 1) if battery['ratedCapacity'] > 0.0 else None
|
625
630
|
if battery.get('temperature') is not None:
|
626
|
-
battery['charge_rate'] =
|
631
|
+
battery['charge_rate'] = interpolate((battery['temperature'] - params['offset']) / params['step'], params['table'])
|
627
632
|
return battery
|
628
633
|
|
629
634
|
def get_batteries(info=0, rated=None, count=None):
|
@@ -674,7 +679,7 @@ def time_period(t, n):
|
|
674
679
|
result += f" Charge from grid" if enable else f" Battery Hold"
|
675
680
|
return result
|
676
681
|
|
677
|
-
def set_charge(ch1=
|
682
|
+
def set_charge(ch1=True, st1=0, en1=0, ch2=True, st2=0, en2=0, force = 0, enable=1):
|
678
683
|
global device_sn, battery_settings, debug_setting, time_period_vars
|
679
684
|
if get_device() is None:
|
680
685
|
return None
|
@@ -1472,7 +1477,7 @@ def report_value_profile(result):
|
|
1472
1477
|
current_total = sum(by_hour)
|
1473
1478
|
result = []
|
1474
1479
|
for t in range(0, 24):
|
1475
|
-
result.append(by_hour[t] * daily_average / current_total)
|
1480
|
+
result.append(by_hour[t] * daily_average / current_total if current_total != 0.0 else 0.0)
|
1476
1481
|
return (daily_average, result)
|
1477
1482
|
|
1478
1483
|
# rescale history data based on time and steps
|
@@ -2722,7 +2727,7 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
2722
2727
|
output(f"full_charge = {full_charge}")
|
2723
2728
|
if test_soc is not None:
|
2724
2729
|
current_soc = test_soc
|
2725
|
-
capacity = 14.
|
2730
|
+
capacity = 14.40
|
2726
2731
|
residual = test_soc * capacity / 100
|
2727
2732
|
bat_volt = 317.4
|
2728
2733
|
bat_power = 0.0
|
@@ -2738,7 +2743,6 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
2738
2743
|
# get device and battery info from inverter
|
2739
2744
|
get_battery()
|
2740
2745
|
if battery is None or battery['status'] != 1:
|
2741
|
-
output(f"\nBattery status is not available")
|
2742
2746
|
return None
|
2743
2747
|
current_soc = battery['soc']
|
2744
2748
|
bat_volt = battery['volt']
|
@@ -2858,25 +2862,19 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
2858
2862
|
consumption_timed = timed_list([consumption * x / daily_sum for x in consumption_by_hour], base_hour, run_time)
|
2859
2863
|
# get Solcast data and produce time line
|
2860
2864
|
solcast_value = None
|
2861
|
-
solcast_profile = None
|
2862
2865
|
if forecast is None and solcast_api_key is not None and solcast_api_key != 'my.solcast_api_key' and (system_time.hour in forecast_times or run_after == 0):
|
2863
2866
|
fsolcast = Solcast(quiet=True, reload=reload, shading=charge_config.get('shading'), d=base_time)
|
2864
2867
|
if fsolcast is not None and hasattr(fsolcast, 'daily') and fsolcast.daily.get(forecast_day) is not None:
|
2865
2868
|
solcast_value = fsolcast.daily[forecast_day]['kwh']
|
2866
2869
|
solcast_timed = forecast_value_timed(fsolcast, today, tomorrow, base_hour, run_time, time_offset)
|
2867
|
-
output(f"\nSolcast: {tomorrow} {fsolcast.daily[tomorrow]['kwh']:.1f}kWh")
|
2868
2870
|
# get forecast.solar data and produce time line
|
2869
2871
|
solar_value = None
|
2870
|
-
solar_profile = None
|
2871
2872
|
if forecast is None and solar_arrays is not None and (system_time.hour in forecast_times or run_after == 0):
|
2872
2873
|
fsolar = Solar(quiet=True, shading=charge_config.get('shading'), d=base_time)
|
2873
2874
|
if fsolar is not None and hasattr(fsolar, 'daily') and fsolar.daily.get(forecast_day) is not None:
|
2874
2875
|
solar_value = fsolar.daily[forecast_day]['kwh']
|
2875
2876
|
solar_timed = forecast_value_timed(fsolar, today, tomorrow, base_hour, run_time, 0)
|
2876
|
-
|
2877
|
-
if solcast_value is None and solar_value is None and debug_setting > 1:
|
2878
|
-
output(f"\nNo forecasts available at this time")
|
2879
|
-
# choose expected value and produce generation time line
|
2877
|
+
# choose expected value
|
2880
2878
|
quarter = int(today[5:7] if charge_today else tomorrow[5:7]) // 3 % 4
|
2881
2879
|
sun_name = seasonal_sun[quarter]['name']
|
2882
2880
|
sun_profile = seasonal_sun[quarter]['sun']
|
@@ -2890,9 +2888,11 @@ def charge_needed(forecast=None, update_settings=0, timed_mode=None, show_data=N
|
|
2890
2888
|
elif solcast_value is not None:
|
2891
2889
|
expected = solcast_value
|
2892
2890
|
generation_timed = solcast_timed
|
2891
|
+
output(f"\nSolcast: {tomorrow} {fsolcast.daily[tomorrow]['kwh']:.1f}kWh")
|
2893
2892
|
elif solar_value is not None:
|
2894
2893
|
expected = solar_value
|
2895
2894
|
generation_timed = solar_timed
|
2895
|
+
output(f"\nSolar: {tomorrow} {fsolar.daily[tomorrow]['kwh']:.1f}kWh")
|
2896
2896
|
else:
|
2897
2897
|
# no forecast, use generation data
|
2898
2898
|
generation = None
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foxesscloud
|
3
|
-
Version: 2.7.
|
3
|
+
Version: 2.7.3
|
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
|
@@ -807,6 +807,16 @@ This setting can be:
|
|
807
807
|
|
808
808
|
# Version Info
|
809
809
|
|
810
|
+
2.7.3<br>
|
811
|
+
Fix divide by zero error if get_report() returns no data.
|
812
|
+
|
813
|
+
2.7.2<br>
|
814
|
+
Fix to get_battery() to return error and flag status=0 in f.battery when the cloud is not returning valid data.
|
815
|
+
Fix exception calculating SoH if ratedCapacity is returned as 0 when cloud is not returning valid data.
|
816
|
+
Update charge_rate in charge_needed() to use a blended charge rate based on battery warming up during charging.
|
817
|
+
Fix exception in set_charge() caused by incorrect default parameter values.
|
818
|
+
Update charge_needed() to only show forecast that is in use.
|
819
|
+
|
810
820
|
2.7.1<br>
|
811
821
|
Update charge_needed() so it only gets generation history if there is no forecast to reduce API calls and save time.
|
812
822
|
Update default parameter values for set_charge() so the other time period is cleared if you only set 1 time.
|
@@ -816,7 +826,6 @@ Update battery predictions to more accurately reflect what happens when SoC gets
|
|
816
826
|
Correct model to use inverter operating losses instead of BMS losses when the battery is above min_soc.
|
817
827
|
Correct exception in Solcast and Solar when a forecast is not available.
|
818
828
|
|
819
|
-
|
820
829
|
2.7.0<br>
|
821
830
|
Allow charge_loss / discharge_loss to be configured for charge_needed().
|
822
831
|
Change 'Force Charge' to 'Battery Hold' in charge times to avoid confusion with Force Charge work mode.
|
@@ -0,0 +1,7 @@
|
|
1
|
+
foxesscloud/foxesscloud.py,sha256=VUtMRQwvQhbD8SHj51K1An83FEyfCtssLlxAK5wY5UU,222985
|
2
|
+
foxesscloud/openapi.py,sha256=eTJYn6pVc2urlOsJLMK-m6ZfuUgEer5yJnWkSz7LRTU,206970
|
3
|
+
foxesscloud-2.7.3.dist-info/LICENCE,sha256=-3xv8CElCJV8Bc8PbAsg3iyxMpAK8MoJneM3rXigxqI,1074
|
4
|
+
foxesscloud-2.7.3.dist-info/METADATA,sha256=U_uYp1fYEvxHKiltYxJFpBWwylar6vZGsTY-bObgOIA,62386
|
5
|
+
foxesscloud-2.7.3.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
6
|
+
foxesscloud-2.7.3.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
|
7
|
+
foxesscloud-2.7.3.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
foxesscloud/foxesscloud.py,sha256=rV8qX1sJyXEvmyie8kvJSFVd3sU-a-9Zcy-i-ag_gTQ,222996
|
2
|
-
foxesscloud/openapi.py,sha256=0oxiSNedH_9UnSDQmNaeXgPIaTvwqzg3fa1Dupdi7yQ,206923
|
3
|
-
foxesscloud-2.7.1.dist-info/LICENCE,sha256=-3xv8CElCJV8Bc8PbAsg3iyxMpAK8MoJneM3rXigxqI,1074
|
4
|
-
foxesscloud-2.7.1.dist-info/METADATA,sha256=Bl4xmInDDpLjnt1pp-Zn_N8dkBzxncEPlq-HPB2ZHts,61833
|
5
|
-
foxesscloud-2.7.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
6
|
-
foxesscloud-2.7.1.dist-info/top_level.txt,sha256=IWOrKSNZCLU6IDXSX_b4_bqCfbZoWAT4CC0w0Lg7PuU,12
|
7
|
-
foxesscloud-2.7.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|