智能绿植养护提醒,按植物品种环境,自动提醒浇水晒太阳,提高成活率,好养不枯萎。
智能绿植养护提醒系统一、实际应用场景描述随着城市生活节奏加快越来越多人在办公室或家中养植绿植来净化空气、缓解压力。然而很多上班族经常忘记给植物浇水、调整光照导致心爱的绿植因缺水、缺光而枯萎。本系统针对这一场景通过Python编程实现智能绿植养护提醒根据植物品种、环境条件自动计算浇水和晒太阳的时间并通过桌面通知或日志方式提醒用户帮助新手也能轻松养活绿植。二、引入痛点1. 忘记浇水工作繁忙容易忽略植物需求导致干旱死亡2. 光照不当不了解植物喜阴喜阳特性摆放位置错误3. 养护知识缺乏新手不知道不同植物的浇水频率差异4. 无法量化管理凭感觉养护缺乏科学的时间规划三、核心逻辑讲解3.1 植物养护规则引擎┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐│ 植物品种选择 │ → │ 环境参数采集 │ → │ 养护规则匹配 ││ (多肉/绿萝/龟背竹)│ │(温度/湿度/光照强度)│ │(浇水周期/光照时长)│└─────────────────┘ └──────────────────┘ └─────────────────┘↓┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐│ 定时任务调度 │ ← │ 提醒消息生成 │ ← │ 养护需求计算 ││ (APScheduler) │ │(桌面通知/日志) │ │(当前时间vs上次) │└─────────────────┘ └──────────────────┘ └─────────────────┘3.2 核心算法公式浇水需求判断是否需要浇水 (当前时间 - 上次浇水时间) 植物基础浇水周期 × 环境修正系数环境修正系数 1 (25 - 当前温度)/100 (50 - 当前湿度)/200光照需求判断是否需要光照 (当前时间 - 上次光照时间) 植物每日所需光照时长光照时段判断 喜阳植物: 8:00-17:00 | 喜阴植物: 9:00-16:00四、代码模块化实现4.1 项目结构smart_plant_care/├── main.py # 程序入口├── config.py # 配置文件├── plant_manager.py # 植物管理模块├── environment.py # 环境监测模块├── reminder.py # 提醒服务模块├── scheduler.py # 定时调度模块├── utils.py # 工具函数├── data/│ └── plants.json # 植物数据库├── logs/│ └── care_log.txt # 养护日志├── requirements.txt # 依赖包└── README.md # 项目说明4.2 核心代码实现config.py - 配置文件配置模块 - 存储系统全局配置参数核心知识点配置集中化管理、常量定义from dataclasses import dataclassfrom typing import Dict, Listdataclassclass PlantConfig:植物基础配置类name: str # 植物名称water_cycle: int # 基础浇水周期天light_hours: int # 每日所需光照时长小时light_preference: str # 光照偏好sunny/shadymin_temp: float # 适宜最低温度max_temp: float # 适宜最高温度humidity_range: tuple # 适宜湿度范围 (min, max)# 植物数据库 - 包含常见易养植物的养护参数PLANT_DATABASE: Dict[str, PlantConfig] {多肉植物: PlantConfig(name多肉植物,water_cycle7, # 7天浇水一次light_hours6, # 每天需6小时光照light_preferencesunny, # 喜阳min_temp10,max_temp30,humidity_range(30, 60)),绿萝: PlantConfig(name绿萝,water_cycle3, # 3天浇水一次light_hours4, # 每天需4小时散射光light_preferenceshady, # 喜阴min_temp15,max_temp28,humidity_range(40, 70)),龟背竹: PlantConfig(name龟背竹,water_cycle4, # 4天浇水一次light_hours5, # 每天需5小时光照light_preferenceshady, # 喜半阴min_temp18,max_temp25,humidity_range(50, 80)),吊兰: PlantConfig(name吊兰,water_cycle3, # 3天浇水一次light_hours4, # 每天需4小时光照light_preferenceshady, # 喜阴min_temp12,max_temp26,humidity_range(45, 75)),仙人掌: PlantConfig(name仙人掌,water_cycle14, # 14天浇水一次耐旱light_hours8, # 每天需8小时强光照light_preferencesunny, # 极喜阳min_temp15,max_temp35,humidity_range(20, 50))}# 系统运行配置SYSTEM_CONFIG {check_interval_minutes: 60, # 检查间隔分钟notification_enabled: True, # 是否启用桌面通知log_enabled: True, # 是否记录日志data_file: data/plants.json # 植物数据文件路径}plant_manager.py - 植物管理模块植物管理模块 - 负责植物的增删改查及状态管理核心知识点面向对象设计、JSON数据持久化、异常处理import jsonimport osfrom datetime import datetime, timedeltafrom typing import Optional, Dict, Listfrom dataclasses import asdict, dataclass, fieldfrom enum import Enumimport logging# 配置日志logging.basicConfig(levellogging.INFO)logger logging.getLogger(__name__)class CareType(Enum):养护类型枚举WATERING wateringLIGHTING lightingdataclassclass CareRecord:养护记录类care_type: CareType # 养护类型timestamp: str # 操作时间戳notes: str # 备注信息dataclassclass Plant:植物实体类 - 封装植物所有属性和行为id: str # 植物唯一IDname: str # 植物名称species: str # 植物品种water_cycle: int # 浇水周期天light_hours: int # 每日光照需求小时light_preference: str # 光照偏好last_watered: str # 上次浇水时间last_lit: str # 上次光照时间care_history: List[CareRecord] field(default_factorylist) # 养护历史def to_dict(self) - dict:转换为字典格式用于JSON序列化return {id: self.id,name: self.name,species: self.species,water_cycle: self.water_cycle,light_hours: self.light_hours,light_preference: self.light_preference,last_watered: self.last_watered,last_lit: self.last_lit,care_history: [{care_type: record.care_type.value,timestamp: record.timestamp,notes: record.notes}for record in self.care_history]}classmethoddef from_dict(cls, data: dict) - Plant:从字典创建植物对象care_history [CareRecord(care_typeCareType(record[care_type]),timestamprecord[timestamp],notesrecord.get(notes, )) for record in data.get(care_history, [])]return cls(iddata[id],namedata[name],speciesdata[species],water_cycledata[water_cycle],light_hoursdata[light_hours],light_preferencedata[light_preference],last_watereddata[last_watered],last_litdata[last_lit],care_historycare_history)class PlantManager:植物管理器 - 单例模式管理所有植物核心功能植物CRUD、状态检查、数据持久化_instance Nonedef __new__(cls, *args, **kwargs):单例模式确保全局只有一个管理器实例if cls._instance is None:cls._instance super().__new__(cls)return cls._instancedef __init__(self, data_file: str data/plants.json):self.data_file data_fileself.plants: Dict[str, Plant] {}self._load_data()def _load_data(self) - None:从JSON文件加载植物数据try:if os.path.exists(self.data_file):with open(self.data_file, r, encodingutf-8) as f:data json.load(f)for plant_data in data:plant Plant.from_dict(plant_data)self.plants[plant.id] plantlogger.info(f成功加载 {len(self.plants)} 株植物数据)except Exception as e:logger.error(f加载数据失败: {e})self.plants {}def _save_data(self) - None:保存植物数据到JSON文件try:# 确保目录存在os.makedirs(os.path.dirname(self.data_file), exist_okTrue)data [plant.to_dict() for plant in self.plants.values()]with open(self.data_file, w, encodingutf-8) as f:json.dump(data, f, ensure_asciiFalse, indent2)logger.debug(植物数据保存成功)except Exception as e:logger.error(f保存数据失败: {e})def add_plant(self, name: str, species: str,custom_config: Optional[dict] None) - Plant:添加新植物Args:name: 植物昵称species: 植物品种需在PLANT_DATABASE中存在custom_config: 自定义配置覆盖默认值Returns:创建的植物对象from config import PLANT_DATABASEif species not in PLANT_DATABASE:raise ValueError(f不支持的植物品种: {species}可选品种: {list(PLANT_DATABASE.keys())})# 生成唯一IDplant_id f{species}_{datetime.now().strftime(%Y%m%d%H%M%S)}# 获取基础配置base_config PLANT_DATABASE[species]# 应用自定义配置if custom_config:water_cycle custom_config.get(water_cycle, base_config.water_cycle)light_hours custom_config.get(light_hours, base_config.light_hours)else:water_cycle base_config.water_cyclelight_hours base_config.light_hours# 创建植物对象now datetime.now().isoformat()plant Plant(idplant_id,namename,speciesspecies,water_cyclewater_cycle,light_hourslight_hours,light_preferencebase_config.light_preference,last_waterednow,last_litnow)self.plants[plant_id] plantself._save_data()logger.info(f成功添加植物: {name} ({species}))return plantdef remove_plant(self, plant_id: str) - bool:删除植物if plant_id in self.plants:del self.plants[plant_id]self._save_data()logger.info(f已删除植物: {plant_id})return Truereturn Falsedef get_plant(self, plant_id: str) - Optional[Plant]:获取单个植物return self.plants.get(plant_id)def list_plants(self) - List[Plant]:列出所有植物return list(self.plants.values())def update_care_record(self, plant_id: str, care_type: CareType,notes: str ) - bool:更新养护记录Args:plant_id: 植物IDcare_type: 养护类型浇水/光照notes: 备注信息Returns:更新是否成功plant self.get_plant(plant_id)if not plant:logger.warning(f植物不存在: {plant_id})return Falsenow datetime.now().isoformat()record CareRecord(care_typecare_type, timestampnow, notesnotes)plant.care_history.append(record)# 更新对应时间戳if care_type CareType.WATERING:plant.last_watered nowelif care_type CareType.LIGHTING:plant.last_lit nowself._save_data()logger.info(f更新{plant.name}的{care_type.value}记录)return Truedef check_water_needed(self, plant_id: str,temperature: float 25.0,humidity: float 50.0) - tuple:检查植物是否需要浇水Args:plant_id: 植物IDtemperature: 当前环境温度摄氏度humidity: 当前环境湿度百分比Returns:(是否需要浇水, 距离下次浇水天数, 提醒消息)plant self.get_plant(plant_id)if not plant:return False, 0, # 计算环境修正系数# 温度越高、湿度越低浇水周期越短temp_factor max(0, (25 - temperature) / 100) # 温度低于25度增加浇水频率humidity_factor max(0, (50 - humidity) / 200) # 湿度低于50%增加浇水频率env_correction 1 temp_factor humidity_factor# 计算调整后的浇水周期adjusted_cycle plant.water_cycle / env_correction# 计算距离上次浇水的天数last_watered datetime.fromisoformat(plant.last_watered)days_since_water (datetime.now() - last_watered).daysneeds_water days_since_water adjusted_cycle# 生成提醒消息message (f {plant.name} 需要浇水啦\nf品种: {plant.species}\nf上次浇水: {plant.last_watered[:10]}\nf已过去 {days_since_water} 天\nf建议浇水周期: {adjusted_cycle:.1f} 天\nf当前环境: {temperature}°C, {humidity}%湿度)return needs_water, round(adjusted_cycle - days_since_water, 1), messagedef check_light_needed(self, plant_id: str,current_hour: int None) - tuple:检查植物是否需要光照Args:plant_id: 植物IDcurrent_hour: 当前小时0-23默认使用系统时间Returns:(是否需要光照, 建议光照开始时间, 提醒消息)plant self.get_plant(plant_id)if not plant:return False, , if current_hour is None:current_hour datetime.now().hour# 根据植物光照偏好确定最佳光照时段if plant.light_preference sunny:optimal_start 8 # 喜阳植物8:00开始optimal_end 17 # 17:00结束else:optimal_start 9 # 喜阴植物9:00开始optimal_end 16 # 16:00结束# 计算距离上次光照的小时数last_lit datetime.fromisoformat(plant.last_lit)hours_since_light (datetime.now() - last_lit).total_seconds() / 3600# 判断是否在光照时段内in_light_period optimal_start current_hour optimal_end# 判断是否超过每日光照需求needs_light hours_since_light plant.light_hours or (not in_light_period and hours_since_light plant.light_hours * 0.8)# 生成建议光照时间if current_hour optimal_start:suggested_time f{optimal_start}:00elif current_hour optimal_end:suggested_time f明天 {optimal_start}:00else:suggested_time f现在至{optimal_end}:00# 生成提醒消息emoji ☀️ if plant.light_preference sunny else ️message (f{emoji} {plant.name} 需要光照啦\nf品种: {plant.species} ({喜阳 if plant.light_preference sunny else 喜阴})\nf每日需光: {plant.light_hours} 小时\nf上次光照: {plant.last_lit[:10]} {plant.last_lit[11:16]}\nf已过去 {hours_since_light:.1f} 小时\nf建议光照时间: {suggested_time})return needs_light, suggested_time, messageenvironment.py - 环境监测模块环境监测模块 - 模拟或获取环境参数核心知识点传感器数据读取、API调用、数据校验import randomfrom datetime import datetimefrom typing import Dict, Tupleimport logginglogging.basicConfig(levellogging.INFO)logger logging.getLogger(__name__)class EnvironmentSensor:环境监测器 - 获取温度和湿度数据支持模拟模式和真实传感器模式def __init__(self, simulation_mode: bool True):Args:simulation_mode: True为模拟模式False为真实传感器模式self.simulation_mode simulation_modeself.min_temperature 18.0 # 室内最低温度阈值self.max_temperature 32.0 # 室内最高温度阈值self.min_humidity 30.0 # 室内最低湿度阈值self.max_humidity 80.0 # 室内最高湿度阈值def read_temperature(self) - float:读取当前环境温度Returns:温度值摄氏度if self.simulation_mode:# 模拟温度变化白天较高夜晚较低hour datetime.now().hourbase_temp 24.0 # 基础温度# 模拟日间升温8:00-16:00if 8 hour 16:variation random.uniform(-2, 5)# 模拟夜间降温22:00-6:00elif hour 22 or hour 6:variation random.uniform(-5, 2)else:variation random.uniform(-3, 3)temperature base_temp variationelse:# TODO: 接入真实温度传感器如DHT22# temperature sensor.read_temperature()temperature random.uniform(20, 28)# 确保温度在安全范围内temperature max(self.min_temperature, min(self.max_temperature, temperature))logger.debug(f当前温度: {temperature:.1f}°C)return round(temperature, 1)def read_humidity(self) - float:读取当前环境湿度Returns:湿度值百分比if self.simulation_mode:# 模拟湿度变化雨季较高晴天较低humidity random.uniform(40, 65)else:# TODO: 接入真实湿度传感器# humidity sensor.read_humidity()humidity random.uniform(45, 70)# 确保湿度在安全范围内humidity max(self.min_humidity, min(self.max_humidity, humidity))logger.debug(f当前湿度: {humidity:.1f}%)return round(humidity, 1)def get_environment_status(self) - Dict:获取完整环境状态Returns:包含温度、湿度和状态的字典temperature self.read_temperature()humidity self.read_humidity()# 评估环境适宜度status self._evaluate_environment(temperature, humidity)return {temperature: temperature,humidity: humidity,status: status,timestamp: datetime.now().isoformat(),suggestion: self._get_suggestion(status)}def _evaluate_environment(self, temperature: float, humidity: float) - str:评估环境是否适宜植物生长temp_ok 18 temperature 28humidity_ok 40 humidity 70if temp_ok and humidity_ok:return optimal # 最佳elif temp_ok or humidity_ok:return acceptable # 可接受else:return poor # 较差def _get_suggestion(self, status: str) - str:根据环境状态生成建议suggestions {optimal: 当前环境非常适合植物生长,acceptable: ⚠️ 环境基本适宜建议适当调整温湿度。,poor: ❄️ 当前环境不适宜建议开启空调或加湿器。}return suggestions.get(status, )reminder.py - 提醒服务模块提醒服务模块 - 负责发送各类提醒通知核心知识点桌面通知、日志记录、多渠道通知import platformimport subprocessimport loggingfrom datetime import datetimefrom typing import Optionalimport oslogging.basicConfig(levellogging.INFO)logger logging.getLogger(__name__)class NotificationService:通知服务 - 支持多种通知方式1. 桌面通知跨平台2. 日志文件记录3. 控制台输出def __init__(self, log_file: str logs/care_log.txt):self.log_file log_fileself._setup_notification()def _setup_notification(self) - None:根据操作系统设置通知方式self.system platform.system()logger.info(f检测到操作系统: {self.system})def send_desktop_notification(self, title: str, message: str,icon: str ) - bool:发送桌面通知Args:title: 通知标题message: 通知内容icon: 图标emojiReturns:发送是否成功try:full_title f{icon} {title}if self.system Darwin: # macOScmd [osascript, -e,fdisplay notification {message} with title {full_title}]subprocess.run(cmd, checkTrue, capture_outputTrue)elif self.system Windows: # Windowstry:from win10toast import ToastNotifiertoaster ToastNotifier()toaster.show_toast(full_title, message, duration10)except ImportError:logger.warning(win10toast未安装使用备用方案)self._send_windows_fallback(title, message)elif self.system Linux: # Linuxtry:subprocess.run([notify-send, full_title, message], checkTrue)except FileNotFoundError:logger.warning(notify-send不可用使用备用方案)print(f\n{*50})print(f {full_title})print(message)print(f{*50}\n)else:logger.warn利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛

相关新闻

最新新闻

日新闻

周新闻

月新闻