news 2026/6/26 9:13:14

地域文化适配穿搭推荐算法,根据用户所在城市气候,文化输出适配服饰风格。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
地域文化适配穿搭推荐算法,根据用户所在城市气候,文化输出适配服饰风格。

用 Python 构建地域文化适配穿搭推荐算法,根据用户输入的城市,结合当地气候特征与地域文化气质,输出适配的服饰风格方案,并以中立视角呈现分析过程。

一、实际应用场景描述

在《时尚产业与品牌创新》课程中,“在地化(Localization)”是品牌扩张的核心议题。同一品牌进入不同城市,往往面临水土不服:

- 哈尔滨 vs 三亚:冬季温差可达 50°C,羽绒服在哈尔滨是刚需,在三亚则是累赘。

- 成都 vs 上海:成都“巴适”“松弛”的地域文化偏好宽松、慵懒的穿搭;上海“摩登”“精致”的都市文化则更接受修身、干练的风格。

- 西安 vs 杭州:西安古城厚重,消费者更易接受“国风”“唐装”元素;杭州江南水乡,偏好“淡雅”“新中式”的柔美风格。

- 国际视野:纽约(快节奏/实用主义)vs 巴黎(浪漫/美学至上)vs 东京(克制/功能性)。

品牌与电商平台面临核心问题:

“如何根据用户的地理位置,自动推荐既符合当地气候,又契合当地文化气质的穿搭?”

二、引入痛点

- 气候与文化脱节:现有推荐系统多只考虑气温(如“今天降温,推荐羽绒服”),忽略了“穿这件羽绒服是否符合当地审美”。

- 数据孤岛:气象数据(温度/湿度)与文化数据(城市气质标签)割裂,缺乏统一的适配模型。

- 缺乏量化标准:什么是“成都风格”?什么是“上海风格”?缺乏可计算的特征向量。

- 静态推荐:季节变化、极端天气(寒潮/梅雨)缺乏动态调整机制。

⇒ 用 Python 构建城市画像数据库 + 气候-文化双因子权重模型 + 动态推荐引擎,实现“千人千城”的穿搭推荐。

三、核心逻辑讲解

1. 城市画像维度设计

我们将每个城市抽象为一个特征向量:

维度 子维度 说明 量化方式

气候特征 温度带 热带/亚热带/温带/寒带 年均温、1月均温、7月均温

降水特征 干燥/湿润/雨季 年降水量、湿度

特殊气候 季风/高原/沿海 布尔标记

文化气质 历史底蕴 古都/新城/移民城市 0-100 评分

审美倾向 厚重/轻盈/前卫/保守 0-100 评分

生活节奏 快/慢/慵懒/紧凑 0-100 评分

时尚开放度 国际/本土/保守 0-100 评分

2. 服饰风格特征库

定义几种典型风格的特征向量(与城市画像同构):

- 北方御寒风:保暖性↑↑,色彩厚重,版型宽松

- 江南淡雅风:透气性↑,色彩清新,面料柔软

- 都市摩登风:挺括度↑,色彩中性,剪裁利落

- 巴蜀慵懒风:舒适度↑,版型宽松,面料亲肤

- 海滨度假风:抗紫外线↑,色彩明快,面料轻薄

3. 适配算法核心公式

综合适配度 = w_climate × ClimateMatch + w_culture × CultureMatch

ClimateMatch = Σ(气候特征_i × 风格气候需求_i)

CultureMatch = Σ(文化气质_j × 风格文化需求_j)

最终推荐 = argmax(综合适配度)

4. 动态调节机制

- 季节系数:冬季提高保暖权重,夏季提高透气权重。

- 天气突变系数:寒潮预警时,临时提高保暖推荐优先级。

- 湿度修正:梅雨季节自动推荐防潮、速干材质。

四、代码模块化(regional_style_recommender.py)

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

"""

regional_style_recommender.py

地域文化适配穿搭推荐算法

根据城市气候与文化气质,输出最优服饰风格推荐

依赖: numpy, pandas, matplotlib

安装: pip install numpy pandas matplotlib

"""

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from matplotlib import rcParams

from dataclasses import dataclass, field

from typing import Dict, List, Tuple, Optional

from enum import Enum

# 中文字体设置

rcParams['font.sans-serif'] = ['Noto Sans CJK SC', 'SimHei', 'Microsoft YaHei']

rcParams['axes.unicode_minus'] = False

# ──────────────────────────────────────────────

# 1. 枚举与基础数据结构

# ──────────────────────────────────────────────

class ClimateZone(Enum):

"""气候带"""

FRIGID = "寒带"

TEMPERATE = "温带"

SUBTROPICAL = "亚热带"

TROPICAL = "热带"

PLATEAU = "高原"

class StyleTag(Enum):

"""风格标签"""

URBAN_CHIC = "都市摩登"

NORTHERN_WARM = "北方御寒"

JIANGNAN_ELEGANT = "江南淡雅"

BASHU_RELAXED = "巴蜀慵懒"

COASTAL_VACATION = "海滨度假"

ANCIENT_CAPITAL = "古都厚重"

AVANT_GARDE = "先锋前卫"

@dataclass

class CityProfile:

"""城市画像"""

city_name: str

region: str

# 气候特征 (0-100 评分)

temp_winter: float # 冬季温度(低=冷)

temp_summer: float # 夏季温度(高=热)

humidity: float # 湿度(高=潮湿)

wind_strength: float # 风力

sunshine: float # 日照时长

# 地理特征

climate_zone: ClimateZone

is_coastal: bool

is_plateau: bool

# 文化气质 (0-100 评分)

historical_depth: float # 历史底蕴

aesthetic_tendency: float # 审美倾向(0=厚重,100=轻盈)

life_pace: float # 生活节奏(0=慢,100=快)

fashion_openness: float # 时尚开放度

# 特殊标签

tags: List[str] = field(default_factory=list)

@dataclass

class StyleProfile:

"""服饰风格画像"""

style_tag: StyleTag

description: str

# 气候适应性 (0-100,越高越适应)

warmth_need: float # 保暖需求

breathability_need: float # 透气需求

moisture_resistance: float # 防潮需求

uv_protection_need: float # 防晒需求

# 文化适配性 (0-100)

elegance_match: float # 适配厚重/轻盈审美

pace_match: float # 适配快慢节奏

tradition_match: float # 适配传统/现代

boldness_match: float # 适配保守/前卫

# 推荐单品

recommended_items: List[str] = field(default_factory=list)

# ──────────────────────────────────────────────

# 2. 城市数据库模块

# ──────────────────────────────────────────────

class CityDatabase:

"""

中国主要城市画像数据库

数据基于气象局公开数据与城市文化研究综合评定

"""

@staticmethod

def get_city_profiles() -> Dict[str, CityProfile]:

return {

'北京': CityProfile(

city_name='北京', region='华北',

winter_temp=-5, summer_temp=30, humidity=45,

wind_strength=60, sunshine=70,

climate_zone=ClimateZone.TEMPERATE,

is_coastal=False, is_plateau=False,

historical_depth=95, aesthetic_tendency=40,

life_pace=80, fashion_openness=85,

tags=['首都', '古都', '政治中心', '干燥']

),

'上海': CityProfile(

city_name='上海', region='华东',

winter_temp=5, summer_temp=32, humidity=75,

wind_strength=40, sunshine=50,

climate_zone=ClimateZone.SUBTROPICAL,

is_coastal=True, is_plateau=False,

historical_depth=70, aesthetic_tendency=65,

life_pace=95, fashion_openness=98,

tags=['魔都', '金融中心', '国际化', '潮湿']

),

'成都': CityProfile(

city_name='成都', region='西南',

winter_temp=8, summer_temp=29, humidity=80,

wind_strength=20, wind_strength=20, sunshine=30,

climate_zone=ClimateZone.SUBTROPICAL,

is_coastal=False, is_plateau=False,

historical_depth=85, aesthetic_tendency=75,

life_pace=40, fashion_openness=80,

tags=['慢生活', '巴适', '休闲', '阴雨']

),

'哈尔滨': CityProfile(

city_name='哈尔滨', region='东北',

winter_temp=-20, summer_temp=25, humidity=65,

wind_strength=70, sunshine=60,

climate_zone=ClimateZone.TEMPERATE,

is_coastal=False, is_plateau=False,

historical_depth=75, aesthetic_tendency=30,

life_pace=60, fashion_openness=70,

tags=['冰城', '严寒', '冰雪文化']

),

'杭州': CityProfile(

city_name='杭州', region='华东',

winter_temp=6, summer_temp=31, humidity=78,

wind_strength=30, sunshine=45,

climate_zone=ClimateZone.SUBTROPICAL,

is_coastal=False, is_plateau=False,

historical_depth=90, aesthetic_tendency=85,

life_pace=65, fashion_openness=82,

tags=['江南', '西湖', '淡雅', '湿润']

),

'广州': CityProfile(

city_name='广州', region='华南',

winter_temp=15, summer_temp=33, humidity=82,

wind_strength=25, sunshine=55,

climate_zone=ClimateZone.SUBTROPICAL,

is_coastal=True, is_plateau=False,

historical_depth=80, aesthetic_tendency=90,

life_pace=85, fashion_openness=90,

tags=['花城', '湿热', '务实', '开放']

),

'西安': CityProfile(

city_name='西安', region='西北',

winter_temp=-2, summer_temp=32, humidity=55,

wind_strength=50, sunshine=65,

climate_zone=ClimateZone.TEMPERATE,

is_coastal=False, is_plateau=False,

historical_depth=98, aesthetic_tendency=35,

life_pace=60, fashion_openness=75,

tags=['十三朝古都', '厚重', '历史感']

),

'三亚': CityProfile(

city_name='三亚', region='海南',

winter_temp=25, summer_temp=32, humidity=85,

wind_strength=45, sunshine=80,

climate_zone=ClimateZone.TROPICAL,

is_coastal=True, is_plateau=False,

historical_depth=60, aesthetic_tendency=95,

life_pace=50, fashion_openness=85,

tags=['热带', '海滨', '度假', '紫外线强']

)

}

# ──────────────────────────────────────────────

# 3. 风格数据库模块

# ──────────────────────────────────────────────

class StyleDatabase:

"""服饰风格特征库"""

@staticmethod

def get_style_profiles() -> Dict[StyleTag, StyleProfile]:

return {

StyleTag.NORTHERN_WARM: StyleProfile(

style_tag=StyleTag.NORTHERN_WARM,

description="北方御寒风:注重保暖与层次感,色彩偏向厚重沉稳",

warmth_need=95, breathability_need=20,

moisture_resistance=60, uv_protection_need=30,

elegance_match=30, pace_match=60,

tradition_match=70, boldness_match=40,

recommended_items=['羽绒服', '羊毛大衣', '围巾', '雪地靴', '保暖内衣']

),

StyleTag.JIANGNAN_ELEGANT: StyleProfile(

style_tag=StyleTag.JIANGNAN_ELEGANT,

description="江南淡雅风:注重透气与水墨意境,色彩清新淡雅",

warmth_need=40, breathability_need=80,

moisture_resistance=85, uv_protection_need=50,

elegance_match=85, pace_match=50,

tradition_match=80, boldness_match=30,

recommended_items=['丝绸衬衫', '棉麻长裙', '针织开衫', '油纸伞', '软底鞋']

),

StyleTag.URBAN_CHIC: StyleProfile(

style_tag=StyleTag.URBAN_CHIC,

description="都市摩登风:注重剪裁与挺括感,色彩中性利落",

warmth_need=50, breathability_need=60,

moisture_resistance=50, uv_protection_need=40,

elegance_match=50, pace_match=95,

tradition_match=30, boldness_match=80,

recommended_items=['西装外套', '直筒裤', '衬衫', '高跟鞋', '手提包']

),

StyleTag.BASHU_RELAXED: StyleProfile(

style_tag=StyleTag.BASHU_RELAXED,

description="巴蜀慵懒风:注重舒适与松弛感,版型宽松随意",

warmth_need=45, breathability_need=75,

moisture_resistance=70, uv_protection_need=45,

elegance_match=70, pace_match=30,

tradition_match=60, boldness_match=50,

recommended_items=['宽松卫衣', '阔腿裤', '拖鞋', '渔夫帽', '帆布袋']

),

StyleTag.COASTAL_VACATION: StyleProfile(

style_tag=StyleTag.COASTAL_VACATION,

description="海滨度假风:注重防晒与轻盈感,色彩明快活泼",

warmth_need=20, breathability_need=95,

moisture_resistance=90, uv_protection_need=95,

elegance_match=90, pace_match=40,

tradition_match=20, boldness_match=90,

recommended_items=['防晒衣', '沙滩裙', '凉鞋', '太阳镜', '遮阳帽']

),

StyleTag.ANCIENT_CAPITAL: StyleProfile(

style_tag=StyleTag.ANCIENT_CAPITAL,

description="古都厚重风:注重历史感与文化符号,色彩浓郁深沉",

warmth_need=55, breathability_need=50,

moisture_resistance=55, uv_protection_need=40,

elegance_match=25, pace_match=55,

tradition_match=95, boldness_match=20,

recommended_items=['唐装', '汉服改良', '盘扣上衣', '布鞋', '折扇']

),

StyleTag.AVANT_GARDE: StyleProfile(

style_tag=StyleTag.AVANT_GARDE,

description="先锋前卫风:注重个性与实验性,打破常规",

warmth_need=50, breathability_need=65,

moisture_resistance=50, uv_protection_need=50,

elegance_match=50, pace_match=85,

tradition_match=10, boldness_match=100,

recommended_items=['解构外套', '不规则裙', '机能靴', '金属配饰', '透明包']

)

}

# ──────────────────────────────────────────────

# 4. 推荐算法核心模块

# ──────────────────────────────────────────────

class RecommendationEngine:

"""

地域文化适配穿搭推荐引擎

核心算法:双因子加权匹配

"""

def __init__(self, city_db: Dict[str, CityProfile], style_db: Dict[StyleTag, StyleProfile]):

self.city_db = city_db

self.style_db = style_db

# 权重配置

self.weights = {

'climate': 0.55, # 气候权重(生存需求优先)

'culture': 0.45 # 文化权重(精神需求)

}

# 气候特征权重

self.climate_feature_weights = {

'warmth': 0.35, # 保暖

'breathability': 0.25, # 透气

'moisture': 0.20, # 防潮

'uv_protection': 0.20 # 防晒

}

# 文化特征权重

self.culture_feature_weights = {

'elegance': 0.30, # 审美适配

'pace': 0.25, # 节奏适配

'tradition': 0.25, # 传统适配

'boldness': 0.20 # 前卫适配

}

def _normalize_city_climate(self, city: CityProfile) -> Dict[str, float]:

"""归一化城市气候特征"""

# 温度特征:冬季温度越低,保暖需求越高

warmth_score = max(0, min(100, (city.temp_winter + 30) / 60 * 100))

# 透气需求:夏季温度越高,透气需求越高

breathability_score = max(0, min(100, (city.temp_summer - 10) / 30 * 100))

# 防潮需求:湿度越高,防潮需求越高

moisture_score = city.humidity

# 防晒需求:日照越强/海拔越高,防晒需求越高

uv_score = city.sunshine

if city.is_plateau:

uv_score += 20

if city.is_coastal and city.climate_zone == ClimateZone.TROPICAL:

uv_score += 15

return {

'warmth': warmth_score,

'breathability': breathability_score,

'moisture': moisture_score,

'uv_protection': min(100, uv_score)

}

def _calculate_climate_match(self, city: CityProfile, style: StyleProfile) -> float:

"""计算气候匹配度"""

city_norm = self._normalize_city_climate(city)

# 计算各项气候特征的匹配度(差值越小越好)

warmth_match = 100 - abs(city_norm['warmth'] - style.warmth_need)

breathability_match = 100 - abs(city_norm['breathability'] - style.breathability_need)

moisture_match = 100 - abs(city_norm['moisture'] - style.moisture_resistance)

uv_match = 100 - abs(city_norm['uv_protection'] - style.uv_protection_need)

# 加权平均

climate_score = (

warmth_match * self.climate_feature_weights['warmth'] +

breathability_match * self.climate_feature_weights['breathability'] +

moisture_match * self.climate_feature_weights['moisture'] +

uv_match * self.climate_feature_weights['uv_protection']

)

return max(0, min(100, climate_score))

def _calculate_culture_match(self, city: CityProfile, style: StyleProfile) -> float:

"""计算文化匹配度"""

# 审美适配:城市审美倾向 vs 风格优雅度

elegance_match = 100 - abs(city.aesthetic_tendency - style.elegance_match)

# 节奏适配:城市生活节奏 vs 风格节奏适配

pace_match = 100 - abs(city.life_pace - style.pace_match)

# 传统适配:城市历史底蕴 vs 风格传统度

tradition_match = 100 - abs(city.historical_depth - style.tradition_match)

# 前卫适配:城市时尚开放度 vs 风格前卫度

boldness_match = 100 - abs(city.fashion_openness - style.boldness_match)

# 加权平均

culture_score = (

elegance_match * self.culture_feature_weights['elegance'] +

pace_match * self.culture_feature_weights['pace'] +

tradition_match * self.culture_feature_weights['tradition'] +

boldness_match * self.culture_feature_weights['boldness']

)

return max(0, min(100, culture_score))

def recommend_for_city(self, city_name: str, season: str = 'winter') -> Dict:

"""

为指定城市生成推荐

Args:

city_name: 城市名称

season: 季节 (winter/spring/summer/autumn)

"""

if city_name not in self.city_db:

raise ValueError(f"城市 '{city_name}' 不在数据库中")

city = self.city_db[city_name]

results = []

# 季节调整系数

season_modifiers = {

'winter': {'warmth': 1.3, 'breathability': 0.7},

'spring': {'warmth': 1.0, 'breathability': 1.0},

'summer': {'warmth': 0.6, 'breathability': 1.4},

'autumn': {'warmth': 1.1, 'breathability': 0.9}

}

modifier = season_modifiers.get(season, {'warmth': 1.0, 'breathability': 1.0})

for style_tag, style in self.style_db.items():

# 计算基础匹配度

climate_match = self._calculate_climate_match(city, style)

culture_match = self._calculate_culture_match(city, style)

# 季节调整

adjusted_climate_match = (

climate_match * 0.7 +

climate_match * modifier['warmth'] * 0.15 +

climate_match * modifier['breathability'] * 0.15

)

# 综合得分

final_score = (

adjusted_climate_match * self.weights['climate'] +

culture_match * self.weights['culture']

)

results.append({

'city': city_name,

'season': season,

'style_tag': style_tag.value,

'style_description': style.description,

'climate_match': round(climate_match, 1),

'culture_match': round(culture_match, 1),

'final_score': round(final_score, 1),

'recommended_items': style.recommended_items,

'match_level': self._get_match_level(final_score)

})

# 按得分排序

results.sort(key=lambda x: x['final_score'], reverse=True)

return {

'city_profile': city,

'recommendations': results,

'top_recommendation': results[0],

'season': season

}

def _get_match_level(self, score: float) -> str:

"""根据得分返回匹配等级"""

if score >= 85:

return "⭐⭐⭐⭐⭐ 完美适配"

elif score >= 75:

return "⭐⭐⭐⭐ 高度适配"

elif score >= 65:

return "⭐⭐⭐ 中度适配"

elif score >= 55:

return "⭐⭐ 轻度适配"

else:

return "⭐ 勉强适配"

def batch_recommend(self, cities: List[str], season: str = 'winter') -> pd.DataFrame:

"""批量推荐"""

rows = []

for city in cities:

try:

result = self.recommend_for_city(city, season)

top = result['top_recommendation']

rows.append({

'城市': city,

'季节': season,

'推荐风格': top['style_tag'],

'综合得分': top['final_score'],

'气候匹配': top['climate_match'],

'文化匹配': top['culture_match'],

'匹配等级': top['match_level'],

'核心单品': '、'.join(top['recommended_items'][:3])

})

except ValueError as e:

print(f"警告: {e}")

return pd.DataFrame(rows)

# ──────────────────────────────────────────────

# 5. 可视化仪表盘模块

# ──────────────────────────────────────────────

class Dashboard:

"""地域穿搭推荐可视化仪表盘"""

STYLE_COLORS = {

'都市摩登': '#3498DB',

'北方御寒': '#2C3E50',

'江南淡雅': '#1ABC9C',

'巴蜀慵懒': '#E67E22',

'海滨度假': '#F1C40F',

'古都厚重': '#8B4513',

'先锋前卫': '#9B59B6'

}

@classmethod

def plot_dashboard(cls,

result: Dict,

batch_df: pd.DataFrame,

filename: str = "regional_style_dashboard.png"):

fig = plt.figure(figsize=(22, 18))

fig.suptitle(f'地域文化适配穿搭推荐分析 — {result["city"].city_name} ({result["season"]})',

fontsize=20, fontweight='bold', y=0.99)

city = result['city']

recs = result['recommendations']

# ── 图1:城市画像雷达图 ──

ax1 = fig.add_subplot(2, 3, 1, polar=True)

cls._plot_city_radar(ax1, city)

# ── 图2:风格匹配度对比 ──

ax2 = fig.add_subplot(2, 3, 2)

cls._plot_style_comparison(ax2, recs)

# ── 图3:气候-文化双因子分解 ──

ax3 = fig.add_subplot(2, 3, 3)

cls._plot_factor_decomposition(ax3, recs)

# ── 图4:全国城市推荐地图(简化版:柱状图) ──

ax4 = fig.add_subplot(2, 3, 4)

cls._plot_national_recommendations(ax4, batch_df)

# ── 图5:推荐单品词云(柱状图替代) ──

ax5 = fig.add_subplot(2, 3, 5)

cls._plot_item_recommendations(ax5, result['top_recommendation'])

# ── 图6:推荐报告摘要 ──

ax6 = fig.add_subplot(2, 3, 6)

cls._plot_summary_report(ax6, result)

plt.tight_layout(rect=[0, 0, 1, 0.96])

plt.savefig(filename, dpi=150, bbox_inches='tight')

plt.show()

print(f"[INFO] 仪表盘已保存: {filename}")

@classmethod

def _plot_city_radar(cls, ax, city: CityProfile):

"""城市画像雷达图"""

categories = ['历史底蕴', '审美倾向', '生活节奏', '时尚开放度',

'冬季温度', '夏季温度', '湿度', '日照']

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 8:57:11

Java var 关键字全面解析

var 是 Java 10(JDK 10,2018年,对应 JSR 286)正式引入的语法特性,全称为局部变量类型推断(Local Variable Type Inference,LVTI),Java 11 进一步扩展了它在 Lambda 表达式…

作者头像 李华
网站建设 2026/6/26 8:56:38

飞凌嵌入式ElfBoard-线程之线程清理

类似于atexit()函数注册进程终止处理函数,当进程调用 exit()退出时就会执行进程终止处理函数;当线程退出时也会调用线程清理的相关函数。在多线程编程中,当一个线程退出时,可以使用 pthread_cleanup_push()和 pthread_cleanup_pop…

作者头像 李华
网站建设 2026/6/26 8:55:22

UV色浆耐光性与耐候性评估:UV涂膜颜色持久性的保障

UV色浆的耐光性和耐候性是影响UV涂膜颜色持久性的关键指标。UV涂装以其高效率和高品质著称,但如果色浆耐光性不足,涂膜颜色在光照下逐渐褪变,将严重影响家具的外观品质和品牌形象。本文系统评估UV色浆的耐光性和耐候性。一、UV涂膜的耐光性特…

作者头像 李华
网站建设 2026/6/26 8:48:30

TypeTraits类型萃取全解,STL原生类型特性、编译期类型判断、属性萃取、迭代器特性、工程高阶泛型落地实战

0. 前言我们彻底吃透了 std::enable_if 条件模板体系,掌握了基于 SFINAE 的编译期条件筛选、三种约束写法、多条件组合匹配、类模板偏特化联动,以及 if constexpr 与 enable_if 的工程选型规范,彻底具备了可控、安全、零开销的泛型约束能力。…

作者头像 李华
网站建设 2026/6/26 8:47:29

HACS集成部署与故障排除技术指南:架构解析与性能优化方案

HACS集成部署与故障排除技术指南:架构解析与性能优化方案 【免费下载链接】integration HACS gives you a powerful UI to handle downloads of all your custom needs. 项目地址: https://gitcode.com/gh_mirrors/in/integration HACS(Home Assi…

作者头像 李华