Commit d85b4ef3 authored by lcn's avatar lcn

修复Bug

parent b26c194c
...@@ -28,10 +28,10 @@ async def get_elec_price_dao(cid): ...@@ -28,10 +28,10 @@ async def get_elec_price_dao(cid):
async def get_max_demand_by_inlid(inlids): async def get_max_demand_by_inlid(inlids):
sql = """SELECT a.has_space,b.related_inlids FROM sql = """SELECT '[]' as has_space,b.inlid as related_inlids FROM
`algo_md_space_analysis_result` a `algo_md_space_analysis_result` a
LEFT JOIN algo_md_space_analysis_unit b on a.space_analysis_id=b.id LEFT JOIN algo_md_space_analysis_unit b on a.space_analysis_id=b.id
WHERE b.related_inlids in %s ORDER BY a.create_time DESC LIMIT %s""" WHERE b.inlid in %s ORDER BY a.month DESC LIMIT %s"""
async with MysqlUtil() as conn: async with MysqlUtil() as conn:
spaces = await conn.fetchall(sql, args=(inlids, len(inlids))) spaces = await conn.fetchall(sql, args=(inlids, len(inlids)))
return spaces return spaces
......
...@@ -888,7 +888,7 @@ async def elec_current_service_new15(point_id): ...@@ -888,7 +888,7 @@ async def elec_current_service_new15(point_id):
url = f"{SETTING.stb_url}db_electric?tz=Asia/Shanghai" url = f"{SETTING.stb_url}db_electric?tz=Asia/Shanghai"
sql = f"select last_row(*) from mt{mtid}_ele where pid={point_id}" sql = f"select last_row(*) from mt{mtid}_ele where pid={point_id}"
is_succ, results = await get_td_engine_data(url, sql) is_succ, results = await get_td_engine_data(url, sql)
if not is_succ or not results: if not is_succ or not results or results.get("code") > 0:
return '', {} return '', {}
head = parse_td_columns(results) head = parse_td_columns(results)
if not results["data"]: if not results["data"]:
......
...@@ -21,14 +21,14 @@ from unify_api.modules.energy_optimize.service.pv_optimation_tool import \ ...@@ -21,14 +21,14 @@ from unify_api.modules.energy_optimize.service.pv_optimation_tool import \
class PhotovoltaicOptimize(object): class PhotovoltaicOptimize(object):
def __init__(self, inlid): def __init__(self, inlid):
self._inlid = inlid self._inlid = inlid
async def calc_inline(self, pv_params): async def calc_inline(self, pv_params):
rlt = {'rlt_flag': True} rlt = {'rlt_flag': True}
inl_info = await self._get_inline_info() inl_info = await self._get_inline_info()
inline_vc = inl_info['inline_vc'] inline_vc = inl_info['inline_vc']
cid = inl_info['cid'] cid = inl_info['cid']
city = await self._get_company_city(cid) city = await self._get_company_city(cid)
df_pv = await self._construct_pv_curve(city) # construct df_pv df_pv = await self._construct_pv_curve(city) # construct df_pv
if len(df_pv) == 0: if len(df_pv) == 0:
rlt['rlt_flag'] = False rlt['rlt_flag'] = False
...@@ -39,12 +39,13 @@ class PhotovoltaicOptimize(object): ...@@ -39,12 +39,13 @@ class PhotovoltaicOptimize(object):
rlt['rlt_flag'] = False rlt['rlt_flag'] = False
rlt['message'] = '暂无' rlt['message'] = '暂无'
return rlt return rlt
pp = await self._get_company_price_policy(cid) pp = await self._get_company_price_policy(cid)
pp_info_d = PricePolicyHelper.map_price_policy(pp, inline_vc, pp_info_d = PricePolicyHelper.map_price_policy(pp, inline_vc,
max_dt.int_timestamp) max_dt.int_timestamp)
time_str_d = PricePolicyHelper.quarter_chars_2_time_str(pp_info_d['quarters']) time_str_d = PricePolicyHelper.quarter_chars_2_time_str(
pp_info_d['quarters'])
# construct pv_system # construct pv_system
price_type = pp_info_d['price_type'] price_type = pp_info_d['price_type']
pv_system = await self._construct_pv_system(pv_params, price_type) pv_system = await self._construct_pv_system(pv_params, price_type)
...@@ -57,25 +58,25 @@ class PhotovoltaicOptimize(object): ...@@ -57,25 +58,25 @@ class PhotovoltaicOptimize(object):
inline_var = await self._construct_inline_var(tc_runtime) inline_var = await self._construct_inline_var(tc_runtime)
# construct df_load # construct df_load
df_load = await self._construct_load_curve(max_dt) df_load = await self._construct_load_curve(max_dt)
# logger.info('pv_system: %s', pv_system) # logger.info('pv_system: %s', pv_system)
# logger.info('price: %s', price) # logger.info('price: %s', price)
# logger.info('env_benifit: %s', env_benifit) # logger.info('env_benifit: %s', env_benifit)
# logger.info('inline_var: %s', inline_var) # logger.info('inline_var: %s', inline_var)
# logger.info('df_load: %s', df_load) # logger.info('df_load: %s', df_load)
# logger.info('df_pv: %s', df_pv) # logger.info('df_pv: %s', df_pv)
pv_ot = PvOptimizationTool(pv_system, price, env_benifit, df_load, pv_ot = PvOptimizationTool(pv_system, price, env_benifit, df_load,
df_pv, inline_var) df_pv, inline_var)
pv_ot.output() pv_ot.output()
# assemble return value # assemble return value
rlt['install_cap'] = self._assemble_install_cap(pv_ot) rlt['install_cap'] = self._assemble_install_cap(pv_ot)
rlt['invest_evaluate'] = self._assemble_invest_evaluate(pv_ot) rlt['invest_evaluate'] = self._assemble_invest_evaluate(pv_ot)
rlt['opt_analysis'] = pv_ot.opt_analysis rlt['opt_analysis'] = pv_ot.opt_analysis
rlt['opt_curve'] = self._assemble_opt_curve(pv_ot) rlt['opt_curve'] = self._assemble_opt_curve(pv_ot)
return rlt return rlt
def _assemble_install_cap(self, pv_ot): def _assemble_install_cap(self, pv_ot):
install_cap = { install_cap = {
'capacity': pv_ot.invest_capacity["capacity"], 'capacity': pv_ot.invest_capacity["capacity"],
...@@ -84,7 +85,7 @@ class PhotovoltaicOptimize(object): ...@@ -84,7 +85,7 @@ class PhotovoltaicOptimize(object):
'first_year_ttl_kwh': pv_ot.invest_capacity["first_year_ttl_kwh"] 'first_year_ttl_kwh': pv_ot.invest_capacity["first_year_ttl_kwh"]
} }
return install_cap return install_cap
def _assemble_invest_evaluate(self, pv_ot): def _assemble_invest_evaluate(self, pv_ot):
cost_per_kwh = (pv_ot.price["rmb_per_wp"] - cost_per_kwh = (pv_ot.price["rmb_per_wp"] -
pv_ot.price["first_install_subsidy"]) pv_ot.price["first_install_subsidy"])
...@@ -94,7 +95,7 @@ class PhotovoltaicOptimize(object): ...@@ -94,7 +95,7 @@ class PhotovoltaicOptimize(object):
first_year_income = invest_income["first_year_income"] first_year_income = invest_income["first_year_income"]
first_year_income_rate = invest_income["first_year_income_rate"] first_year_income_rate = invest_income["first_year_income_rate"]
invest_income_year = invest_income["invest_income_year"] invest_income_year = invest_income["invest_income_year"]
i_and_r = { i_and_r = {
'user_type': pv_ot.pv_system["user_type"], 'user_type': pv_ot.pv_system["user_type"],
'ttl_invest': pv_ot.invest_capacity["ttl_invest"], 'ttl_invest': pv_ot.invest_capacity["ttl_invest"],
...@@ -114,7 +115,7 @@ class PhotovoltaicOptimize(object): ...@@ -114,7 +115,7 @@ class PhotovoltaicOptimize(object):
'first_year_income_rate': first_year_income_rate, 'first_year_income_rate': first_year_income_rate,
'invest_income_year': invest_income_year 'invest_income_year': invest_income_year
} }
env_benifit = pv_ot.invest_evaluate["env_benifit_per_year"] env_benifit = pv_ot.invest_evaluate["env_benifit_per_year"]
c_footprint = { c_footprint = {
'families': env_benifit['one_family_kwh'], 'families': env_benifit['one_family_kwh'],
...@@ -126,10 +127,10 @@ class PhotovoltaicOptimize(object): ...@@ -126,10 +127,10 @@ class PhotovoltaicOptimize(object):
'smoke': env_benifit['Smoke'], 'smoke': env_benifit['Smoke'],
'H2O': env_benifit['H2O'] 'H2O': env_benifit['H2O']
} }
invest_evaluate = {'i_and_r': i_and_r, 'carbon_footprint': c_footprint} invest_evaluate = {'i_and_r': i_and_r, 'carbon_footprint': c_footprint}
return invest_evaluate return invest_evaluate
def _assemble_opt_curve(self, pv_ot): def _assemble_opt_curve(self, pv_ot):
rlt = [] rlt = []
for idx, row in pv_ot.opt_curve.iterrows(): for idx, row in pv_ot.opt_curve.iterrows():
...@@ -140,7 +141,7 @@ class PhotovoltaicOptimize(object): ...@@ -140,7 +141,7 @@ class PhotovoltaicOptimize(object):
tmpd['pv_curve'] = row['pv_curve'] tmpd['pv_curve'] = row['pv_curve']
rlt.append(tmpd) rlt.append(tmpd)
return rlt return rlt
async def _construct_pv_system(self, pv_params, price_type): async def _construct_pv_system(self, pv_params, price_type):
area = pv_params['install_space'] area = pv_params['install_space']
# ratio fixed, convert to decimal, web backend just pass us a # ratio fixed, convert to decimal, web backend just pass us a
...@@ -151,10 +152,10 @@ class PhotovoltaicOptimize(object): ...@@ -151,10 +152,10 @@ class PhotovoltaicOptimize(object):
"where i.inlid=%s and i.cid=c.cid and " "where i.inlid=%s and i.cid=c.cid and "
"c.city=pv.city;") "c.city=pv.city;")
async with MysqlUtil() as conn: async with MysqlUtil() as conn:
hours = await conn.fetchone(sql, (self._inlid,)) hours = await conn.fetchone(sql, (self._inlid,)) or {}
hours = hours.get("peak_sunshine_hours") hours = hours.get("peak_sunshine_hours") or 0
annual_hours = hours * 365 annual_hours = hours * 365
# peak_sunshine_hours means annual_peak_sunshine_hours, the name # peak_sunshine_hours means annual_peak_sunshine_hours, the name
# in algorithm is misleading # in algorithm is misleading
pv_system = { pv_system = {
...@@ -169,7 +170,7 @@ class PhotovoltaicOptimize(object): ...@@ -169,7 +170,7 @@ class PhotovoltaicOptimize(object):
"peak_sunshine_hours": annual_hours # 年峰值日照小时数 "peak_sunshine_hours": annual_hours # 年峰值日照小时数
} }
return pv_system return pv_system
def _construct_price(self, pv_params, pp_info_d, time_str_d): def _construct_price(self, pv_params, pp_info_d, time_str_d):
cons_p = pv_params['rmb_per_wp'] cons_p = pv_params['rmb_per_wp']
user_p = pv_params['sel_use_per_kwh'] user_p = pv_params['sel_use_per_kwh']
...@@ -205,7 +206,7 @@ class PhotovoltaicOptimize(object): ...@@ -205,7 +206,7 @@ class PhotovoltaicOptimize(object):
sct = self._construct_section('v', pp_info_d, time_str_d) sct = self._construct_section('v', pp_info_d, time_str_d)
sfpv_price['section_v'] = sct sfpv_price['section_v'] = sct
return price_d return price_d
def _construct_env_benifit(self): def _construct_env_benifit(self):
env_benifit_param = { env_benifit_param = {
"one_family_kwh": 3600, # 一户家庭一年用3600度电 "one_family_kwh": 3600, # 一户家庭一年用3600度电
...@@ -218,147 +219,86 @@ class PhotovoltaicOptimize(object): ...@@ -218,147 +219,86 @@ class PhotovoltaicOptimize(object):
"tree": 18.3 # 1棵树1年可吸收18.3千克CO2 "tree": 18.3 # 1棵树1年可吸收18.3千克CO2
} }
return env_benifit_param return env_benifit_param
def _construct_section(self, p_char, pp_info_d, time_str_d): def _construct_section(self, p_char, pp_info_d, time_str_d):
""" contruct section_x for price_d.""" """ contruct section_x for price_d."""
section = {'price': pp_info_d['price_' + p_char]} section = {'price': pp_info_d['price_' + p_char]}
time_range_str = ';'.join(time_str_d[p_char]) time_range_str = ';'.join(time_str_d[p_char])
section['time_range'] = time_range_str section['time_range'] = time_range_str
return section return section
def _build_kwh_charge_sum_lastest_30(self, p_char): async def _build_kwh_charge_sum_lastest_30(self, p_char):
""" build es query sentance for get kwh sum and charge sum """ build es query sentance for get kwh sum and charge sum
within lastest 30 days for specified p_char. within lastest 30 days for specified p_char.
""" """
sql = f"""
select sum(kwh) kwh,sum(charge) charge from inline_15min_power
where inlid = %s and spfv = %s and create_time >= % s and create_time
< %s
"""
dt = pendulum.now() dt = pendulum.now()
dt_1_month_ago = dt.subtract(days=30) dt_1_month_ago = dt.subtract(days=30)
q = { start_time = dt_1_month_ago.format("YYYY-MM-DD HH:mm:ss")
"size": 0, end_time = dt.format("YYYY-MM-DD HH:mm:ss")
"query": { async with MysqlUtil() as conn:
"bool": { result = await conn.fetchone(sql, args=(self._inlid, p_char,
"must": [ start_time, end_time))
{"term": { return result or {}
"inlid": {
"value": self._inlid
}
}},
{"term": {
"spfv": {
"value": p_char
}
}},
{"range": {
"quarter_time": {
"gte": str(dt_1_month_ago),
"lt": str(dt)
}
}}
]
}
},
"aggs": {
"kwh": {
"sum": {
"field": "kwh"
}
},
"charge": {
"sum": {
"field": "charge"
}
}
}
}
return q
async def _construct_inline_var(self, inline_tc): async def _construct_inline_var(self, inline_tc):
inline_var = {'inline_capacity': inline_tc} inline_var = {'inline_capacity': inline_tc}
q = self._build_kwh_charge_sum_lastest_30("s") result = await self._build_kwh_charge_sum_lastest_30("s")
# search_rlt = self._es.search(inline_15min_power_esindex, q) # search_rlt = self._es.search(inline_15min_power_esindex, q)
async with EsUtil() as es: charge_s = result.get("charge") or 0
search_rlt = await es.search_origin(body=q, kwh_s = result.get("kwh") or 0
index=INLINE_15MIN_POWER_ESINDEX)
charge_s = search_rlt['aggregations']['charge']['value'] result = await self._build_kwh_charge_sum_lastest_30("p")
kwh_s = search_rlt['aggregations']['kwh']['value']
q = self._build_kwh_charge_sum_lastest_30("p")
# search_rlt = self._es.search(inline_15min_power_esindex, q) # search_rlt = self._es.search(inline_15min_power_esindex, q)
async with EsUtil() as es:
search_rlt = await es.search_origin(body=q, charge_p = result.get("charge") or 0
index=INLINE_15MIN_POWER_ESINDEX) kwh_p = result.get("kwh") or 0
charge_p = search_rlt['aggregations']['charge']['value']
kwh_p = search_rlt['aggregations']['kwh']['value']
# add 's' and 'p', because algorithm needs these # add 's' and 'p', because algorithm needs these
charge_sp = charge_s + charge_p charge_sp = charge_s + charge_p
kwh_sp = kwh_s + kwh_p kwh_sp = kwh_s + kwh_p
inline_var['peak_charge'] = charge_sp inline_var['peak_charge'] = charge_sp
inline_var['peak_kwh'] = kwh_sp inline_var['peak_kwh'] = kwh_sp
q = self._build_kwh_charge_sum_lastest_30("f") result = await self._build_kwh_charge_sum_lastest_30("f")
# search_rlt = self._es.search(inline_15min_power_esindex, q) # search_rlt = self._es.search(inline_15min_power_esindex, q)
async with EsUtil() as es: charge_f = result.get("charge") or 0
search_rlt = await es.search_origin(body=q, kwh_f = result.get("kwh") or 0
index=INLINE_15MIN_POWER_ESINDEX)
charge_f = search_rlt['aggregations']['charge']['value']
kwh_f = search_rlt['aggregations']['kwh']['value']
inline_var['flat_charge'] = charge_f inline_var['flat_charge'] = charge_f
inline_var['flat_kwh'] = kwh_f inline_var['flat_kwh'] = kwh_f
return inline_var return inline_var
def _build_load_curve(self, start_dt): async def _build_load_curve(self, start_dt):
end_dt = start_dt.add(days=1) end_dt = start_dt.add(days=1)
q = { start_time = start_dt.format("YYYY-MM-DD HH:mm:ss")
"size": 100, end_time = end_dt.format("YYYY-MM-DD HH:mm:ss")
"_source": ["quarter_time", "p"], sql = f"""
"query": { select create_time,p from inline_15min_power
"bool": { where inlid = %s and create_time >= %s and create_time < %s
"must": [ order by create_time asc limit 100
{"term": { """
"inlid": {
"value": self._inlid async with MysqlUtil() as conn:
} results = await conn.fetchall(sql, args=(self._inlid, start_time,
}}, end_time))
{"range": { return results or []
"quarter_time": {
"gte": str(start_dt),
"lt": str(end_dt)
}
}}
]
}
},
"sort": [
{
"quarter_time": {
"order": "asc"
}
}
]
}
return q
async def _construct_load_curve(self, start_dt): async def _construct_load_curve(self, start_dt):
q = self._build_load_curve(start_dt) hits_list = await self._build_load_curve(start_dt)
# search_rlt = self._es.search(inline_15min_power_esindex, q)
async with EsUtil() as es:
search_rlt = await es.search_origin(body=q,
index=INLINE_15MIN_POWER_ESINDEX)
# hits_list is already sorted by quarter_time asc # hits_list is already sorted by quarter_time asc
hits_list = search_rlt['hits']['hits']
kw_list = [] kw_list = []
for item in hits_list: for item in hits_list:
src_d = item['_source'] kw_list.append({
qrt_str = src_d['quarter_time'] 'quarter_time': item.get('create_time'),
dt = pendulum.from_format(qrt_str, 'YYYY-MM-DDTHH:mm:ssZ', 'load_curve': item.get('p')
tz='Asia/Shanghai') })
qrt_dt = datetime.datetime(year=dt.year, month=dt.month,
day=dt.day, hour=dt.hour,
minute=dt.minute, second=dt.second)
kw_list.append({'quarter_time': qrt_dt, 'load_curve': src_d['p']})
df = pd.DataFrame(kw_list) df = pd.DataFrame(kw_list)
return df return df
async def _construct_pv_curve(self, city): async def _construct_pv_curve(self, city):
sql = "select hour, p from algo_distributed_pv where city=%s " \ sql = "select hour, p from algo_distributed_pv where city=%s " \
"order by hour asc" "order by hour asc"
...@@ -374,7 +314,7 @@ class PhotovoltaicOptimize(object): ...@@ -374,7 +314,7 @@ class PhotovoltaicOptimize(object):
pv_list.append({'quarter_time': qrt_dt, 'pv_curve': item['p']}) pv_list.append({'quarter_time': qrt_dt, 'pv_curve': item['p']})
df = pd.DataFrame(pv_list) df = pd.DataFrame(pv_list)
return df return df
async def _get_inline_info(self): async def _get_inline_info(self):
""" get inline_vc, tc_runtime, cid from redis. """ get inline_vc, tc_runtime, cid from redis.
:return: a dict :return: a dict
...@@ -387,7 +327,7 @@ class PhotovoltaicOptimize(object): ...@@ -387,7 +327,7 @@ class PhotovoltaicOptimize(object):
'tc_runtime': info['tc_runtime'], 'tc_runtime': info['tc_runtime'],
'cid': info['cid']} 'cid': info['cid']}
return rlt return rlt
async def _get_company_price_policy(self, cid): async def _get_company_price_policy(self, cid):
result = AutoDic() result = AutoDic()
sql = 'SELECT * FROM price_policy where cid = %s' sql = 'SELECT * FROM price_policy where cid = %s'
...@@ -397,7 +337,7 @@ class PhotovoltaicOptimize(object): ...@@ -397,7 +337,7 @@ class PhotovoltaicOptimize(object):
result[str(policy['inline_vc'])][str(policy['start_month'])][ result[str(policy['inline_vc'])][str(policy['start_month'])][
policy['time_range']] = policy policy['time_range']] = policy
return result return result
async def _get_company_city(self, cid): async def _get_company_city(self, cid):
sql = "SELECT city from company where cid = %s" sql = "SELECT city from company where cid = %s"
async with MysqlUtil() as conn: async with MysqlUtil() as conn:
...@@ -405,60 +345,26 @@ class PhotovoltaicOptimize(object): ...@@ -405,60 +345,26 @@ class PhotovoltaicOptimize(object):
# company_j = self._r_cache.hget(company_hashname, str(cid)) # company_j = self._r_cache.hget(company_hashname, str(cid))
# c_info = json.loads(company_j) # c_info = json.loads(company_j)
return c_info['city'] return c_info['city']
def _build_max_kwh_day(self):
""" build es query sentance for find max kwh day."""
dt = pendulum.now()
dt_half_year_ago = dt.subtract(months=6)
q = {
"size": 1,
"query": {
"bool": {
"must": [
{"term": {
"inlid": {
"value": self._inlid
}
}},
{"range": {
"day": {
"gte": str(dt_half_year_ago),
"lt": str(dt)
}
}}
]
}
},
"sort": [
{
"kwh": {
"order": "desc"
}
}
]
}
return q
async def _find_kwh_max_day(self): async def _find_kwh_max_day(self):
""" find the max kwh day in latest 6 months. sql = f"""
:return: a dt object, or None if no doc select create_time from inline_1day_power
where inlid = %s and create_time >=%s and create_time < %s
order by kwh desc limit 1;
""" """
rlt = None
q = self._build_max_kwh_day()
# search_rlt = self._es.search(inline_1day_power_esindex, q) # search_rlt = self._es.search(inline_1day_power_esindex, q)
async with EsUtil() as es: dt = pendulum.now()
search_rlt = await es.search_origin(body=q, dt_half_year_ago = dt.subtract(months=6)
index=INLINE_1DAY_POWER_ESINDEX) start_time = dt_half_year_ago.format("YYYY-MM-DD HH:mm:ss")
hits_list = search_rlt['hits']['hits'] end_time = dt.format("YYYY-MM-DD HH:mm:ss")
try: async with MysqlUtil() as conn:
max_day_doc = hits_list[0]['_source'] result = await conn.fetchone(sql, args=(self._inlid,
except IndexError: start_time,
pass end_time))
else: if not result:
day_str = max_day_doc['day'] return None
rlt = pendulum.from_format(day_str, 'YYYY-MM-DDTHH:mm:ssZ', max_dt = result.get("create_time").strftime("%Y-%m-%d %H:%M:%S")
tz='Asia/Shanghai') return pendulum.parse(max_dt)
return rlt
async def pv_out_result(inlid, params): async def pv_out_result(inlid, params):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment