Files
aiData/Apps/TeLaiDian/Service.py
HuangHai 23dfa433b0 'commit'
2026-01-15 10:14:44 +08:00

156 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding=utf-8
import hashlib
import logging
import os
import sys
import uuid
from datetime import datetime
# Ensure sys path includes root for imports if not already
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if project_root not in sys.path:
sys.path.append(project_root)
from DbKit.Db import Db
from Config.Config import DB_URL
from Model.StationProfile import StationProfile
from Model.StationStatus import StationStatus
from Model.StationPriceSchedule import StationPriceSchedule
from Apps.TeLaiDian.Kit import setup_logger
# 初始化日志
logger = setup_logger("TeLaiDianService")
class TeLaiDianService:
def __init__(self):
self.db = Db(db_url=DB_URL)
self.station_profile_model = StationProfile()
self.station_status_model = StationStatus()
self.station_price_schedule_model = StationPriceSchedule()
self.operator = "特来电"
def generate_id(self):
return str(uuid.uuid4())
def get_hash(self, s: str) -> str:
return hashlib.md5(s.encode('utf-8')).hexdigest()
async def init_db(self):
await self.db.init_db()
async def close_db(self):
await self.db.close()
async def save_station_profile_only(self, station_name, address):
if not station_name or not address:
return False
station_hash = self.get_hash(station_name)
now = datetime.now()
async with await self.db.get_session() as session:
profile_id = self.generate_id()
await self.station_profile_model.save(
session=session,
id=profile_id,
station_hash=station_hash,
operator=self.operator,
station_name=station_name,
address=address,
valid_start_time=now
)
await session.commit()
logger.info(f"仅保存场站基础信息: {station_name}")
return True
async def save_station_data(self, station_name, address, prices, total_piles=None, free_piles=None, piles_detail=None, parking_info=None, distance=None):
"""
保存场站全量数据:名称、地址、24小时价格计划、当前状态
"""
now = datetime.now()
station_hash = hashlib.md5(f"{station_name}{address}".encode('utf-8')).hexdigest()
# 预处理价格:生成 24 小时的价格映射
hourly_schedule = [None] * 24
for p in prices:
try:
start_parts = p['start'].split(':')
end_parts = p['end'].split(':')
start_hour = int(start_parts[0])
end_hour = int(end_parts[0])
# 处理 00:00 作为结束时间的情况 (表示 24:00)
if end_hour == 0 and (int(end_parts[1]) == 0 if len(end_parts) > 1 else True):
if start_hour != 0:
end_hour = 24
# 提取各项价格
price_data = {
"price": float(p.get('price')) if p.get('price') is not None else 0.0,
"plus_price": float(p.get('plus_price')) if p.get('plus_price') is not None else None,
"market_price": float(p.get('market_price')) if p.get('market_price') is not None else None,
"elec_price": float(p.get('elec_price')) if p.get('elec_price') is not None else None,
"service_price": float(p.get('service_price')) if p.get('service_price') is not None else None
}
# 填充对应的小时槽位
curr = start_hour
# 如果是跨天的,比如 23:00 - 01:00
if end_hour < start_hour:
end_hour += 24
while curr < end_hour:
hourly_schedule[curr % 24] = price_data
curr += 1
except Exception as e:
logger.error(f"解析价格时段失败: {p}, error: {e}")
async with await self.db.get_session() as session:
# 1. 保存 Profile
profile_id = self.generate_id()
await self.station_profile_model.save(
session=session,
id=profile_id,
station_hash=station_hash,
operator=self.operator,
station_name=station_name,
address=address,
valid_start_time=now
)
# 2. 保存价格计划
schedule_id = self.generate_id()
await self.station_price_schedule_model.save(
session=session,
id=schedule_id,
station_hash=station_hash,
schedule_json=hourly_schedule,
valid_start_time=now
)
# 3. 保存当前状态快照 (包含当前小时的价格)
current_hour = now.hour
current_price_info = hourly_schedule[current_hour] or {}
status_id = self.generate_id()
await self.station_status_model.save(
session=session,
id=status_id,
station_hash=station_hash,
total_piles=total_piles,
free_piles=free_piles,
piles_detail_json=piles_detail,
parking_info=parking_info,
distance=distance,
current_price=current_price_info.get('price'),
pro_price=current_price_info.get('plus_price'),
market_price=current_price_info.get('market_price'),
valid_start_time=now
)
await session.commit()
logger.info(f"成功保存场站数据: {station_name} (桩数: {total_piles}, 空闲: {free_piles}, 停车费: {parking_info})")
return True