首页龙虾技能列表 › Weather Api 1 — 施工天气查询

Weather Api 1 — 施工天气查询

v1.0.1

一键获取历史与 forecast 天气数据,为户外施工排程提供风险评分与建议,减少停工损失。

0· 1,049·4 当前·4 累计
by @phucanh08·MIT-0
下载技能包
License
MIT-0
最后更新
2026/2/28
安全扫描
VirusTotal
无害
查看报告
OpenClaw
安全
medium confidence
该技能的代码和指令与其声明的目的(获取和评估天气数据)一致,没有请求无关的凭据或安装;内部逻辑一致。
评估建议
该技能在获取和评估建筑施工天气方面内部一致。安装前注意:(1)它向公共天气API(Open-Meteo)发出出站HTTP请求,并会传输位置坐标——如果位置隐私是一个问题,请避免分享精确坐标;(2)提供的Python代码依赖于包(requests、pandas),运行时必须有这些包;(3)包含的_meta.json中有小的元数据/版本不匹配;(4)如任何调用外部服务的技能一样,验证您信任源和运行时的网络策略。如果需要离线操作或更严格的隐私,请请求一个运行在内部天气服务或记录数据保留/使用的变体。...
详细分析 ▾
用途与能力
名称/描述(建筑天气、历史/预报/风险评估)与提供的调用公共天气API(Open-Meteo)的Python客户端代码和包含建筑特定风险阈值一致。没有请求无关的环境变量、二进制文件或配置路径。小提示:_meta.json版本(1.0.0)与注册表版本(1.0.1)不同——可能是包装元数据不匹配,但不是安全红旗。
指令范围
SKILL.md包含一个完整的Python实现,只执行对公共天气API的HTTP调用、解析响应和计算风险评估。指令/代码不指示读取任意主机文件、其他凭据或无关系统状态。它会在API请求中发送位置坐标(预期用于天气查询)——用户应该意识到位置数据被传输到天气API。
安装机制
这是一个指令-only技能,没有安装规格和没有由安装程序执行的代码文件。这降低了安装风险。代码依赖于Python包(requests、pandas),这些包没有被声明为所需的二进制文件——代理/运行时必须已经提供它们;这是一个运营考虑但不是不一致。
凭证需求
没有请求环境变量、凭据或配置路径。技能明智地不要求无关的秘密。它执行对公共API(Open-Meteo)的网络调用,这种实现不需要API密钥。
持久化与权限
技能不请求持久存在(always: false)并且不尝试修改其他技能或系统范围的设置。模型调用被启用(默认),这是用户可调用技能的正常情况。
安全有层次,运行前请审查代码。

License

MIT-0

可自由使用、修改和再分发,无需署名。

运行时依赖

无特殊依赖

版本

latestv1.0.12026/2/9

内部元数据在_meta.json中更新。没有用户面向或功能变化。

● 无害

安装命令 点击复制

官方npx clawhub@latest install weather-api-1
镜像加速npx clawhub@latest install weather-api-1 --registry https://cn.clawhub-mirror.com

技能文档

概述

天气影响 50% 的建筑活动。此技能可获取天气数据,用于调度安排、风险评估和生产率调整。

import requests
import pandas as pd
from typing import Dict, Any, List, Optional
from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import Enum

class WeatherRisk(Enum): """Weather risk levels for construction.""" LOW = "low" MODERATE = "moderate" HIGH = "high" CRITICAL = "critical"

@dataclass class WeatherCondition: """Weather condition at a point in time.""" timestamp: datetime temperature: float # Celsius humidity: float # Percent wind_speed: float # m/s precipitation: float # mm conditions: str

@dataclass class WorkabilityAssessment: """Assessment of weather workability.""" date: datetime risk_level: WeatherRisk workable_hours: int affected_activities: List[str] recommendations: List[str]

class WeatherAPIClient: """Client for weather APIs.""" # Free tier endpoints OPEN_METEO_BASE = "https://api.open-meteo.com/v1"

def __init__(self, api_key: Optional[str] = None): self.api_key = api_key

def get_forecast(self, latitude: float, longitude: float, days: int = 7) -> List[WeatherCondition]: """Get weather forecast.""" url = f"{self.OPEN_METEO_BASE}/forecast" params = { 'latitude': latitude, 'longitude': longitude, 'hourly': 'temperature_2m,relative_humidity_2m,wind_speed_10m,precipitation', 'forecast_days': days } response = requests.get(url, params=params) if response.status_code != 200: raise Exception(f"API error: {response.status_code}") data = response.json() return self._parse_forecast(data)

def get_historical(self, latitude: float, longitude: float, start_date: str, end_date: str) -> List[WeatherCondition]: """Get historical weather data.""" url = f"{self.OPEN_METEO_BASE}/archive" params = { 'latitude': latitude, 'longitude': longitude, 'start_date': start_date, 'end_date': end_date, 'hourly': 'temperature_2m,relative_humidity_2m,wind_speed_10m,precipitation' } response = requests.get(url, params=params) if response.status_code != 200: raise Exception(f"API error: {response.status_code}") data = response.json() return self._parse_forecast(data)

def _parse_forecast(self, data: Dict) -> List[WeatherCondition]: """Parse API response to WeatherCondition list.""" conditions = [] hourly = data.get('hourly', {}) times = hourly.get('time', []) temps = hourly.get('temperature_2m', []) humidity = hourly.get('relative_humidity_2m', []) wind = hourly.get('wind_speed_10m', []) precip = hourly.get('precipitation', [])

for i in range(len(times)): conditions.append(WeatherCondition( timestamp=datetime.fromisoformat(times[i]), temperature=temps[i] if i < len(temps) else 0, humidity=humidity[i] if i < len(humidity) else 0, wind_speed=wind[i] if i < len(wind) else 0, precipitation=precip[i] if i < len(precip) else 0, conditions=self._describe_conditions( temps[i] if i < len(temps) else 0, precip[i] if i < len(precip) else 0, wind[i] if i < len(wind) else 0 ) )) return conditions

def _describe_conditions(self, temp: float, precip: float, wind: float) -> str: """Generate weather description.""" conditions = [] if temp < 0: conditions.append("Freezing") elif temp > 35: conditions.append("Extreme heat") elif temp > 30: conditions.append("Hot") elif temp < 10: conditions.append("Cold")

if precip > 10: conditions.append("Heavy rain") elif precip > 2: conditions.append("Rain") elif precip > 0: conditions.append("Light rain")

if wind > 15: conditions.append("Strong winds") elif wind > 10: conditions.append("Windy")

return ", ".join(conditions) if conditions else "Clear"

def to_dataframe(self, conditions: List[WeatherCondition]) -> pd.DataFrame: """Convert conditions to DataFrame.""" data = [{ 'timestamp': c.timestamp, 'temperature': c.temperature, 'humidity': c.humidity, 'wind_speed': c.wind_speed, 'precipitation': c.precipitation, 'conditions': c.conditions } for c in conditions] return pd.DataFrame(data)

class ConstructionWeatherRisk: """Assess weather risk for construction activities.""" # Activity-specific thresholds THRESHOLDS = { 'concrete_pour': { 'min_temp': 5, 'max_temp': 35, 'max_wind': 12, 'max_precip': 0.5 }, 'crane_work': { 'min_temp': -10, 'max_temp': 40, 'max_wind': 10, 'max_precip': 5 }, 'exterior_paint': { 'min_temp': 10, 'max_temp': 35, 'max_wind': 8, 'max_precip': 0 }, 'roofing': { 'min_temp': 5, 'max_temp': 38, 'max_wind': 12, 'max_precip': 0 }, 'earthwork': { 'min_temp': -5, 'max_temp': 40, 'max_wind': 20, 'max_precip': 10 } }

def assess_workability(self, condition: WeatherCondition, activities: List[str] = None) -> WorkabilityAssessment: """Assess workability for given conditions.""" if activities is None: activities = list(self.THRESHOLDS.keys())

affected = [] recommendations = []

for activity in activities: if activity in self.THRESHOLDS: thresh = self.THRESHOLDS[activity] reasons = []

if condition.temperature < thresh['min_temp']: reasons.append(f"Too cold ({condition.temperature}°C)") if condition.temperature > thresh['max_temp']: reasons.append(f"Too hot ({condition.temperature}°C)") if condition.wind_speed > thresh['max_wind']: reasons.append(f"High wind ({condition.wind_speed} m/s)") if condition.precipitation > thresh['max_precip']: reasons.append(f"Precipitation ({condition.precipitation} mm)")

if reasons: affected.append(activity) recommendations.append(f"{activity}: " + ", ".join(reasons))

# Determine overall risk level if len(affected) >= len(activities) 0.8: risk = WeatherRisk.CRITICAL workable = 0 elif len(affected) >= len(activities) 0.5: risk = WeatherRisk.HIGH workable = 4 elif len(affected) > 0: risk = WeatherRisk.MODERATE workable = 6 else: risk = WeatherRisk.LOW workable = 8

return WorkabilityAssessment( date=condition.timestamp, risk_level=risk, workable_hours=workable, affected_activities=affected, recommendations=recommendations )

def weekly_forecast_risk(self, conditions: List[WeatherCondition], activities: List[str] = None) -> pd.DataFrame: """Assess risk for week of weather data.""" # Group by date daily_conditions = {} for c in conditions: date = c.timestamp.date() if date not in daily_conditions: daily_conditions[date] = [] daily_conditions[date].append(c)

assessments = [] for date, day_conditions in daily_conditions.items(): # Use midday condition as representative midday = [c for c in day_conditions if 10 <= c.timestamp.hour <= 16] representative = midday[len(midday)//2] if midday else day_conditions[0]

assessment = self.assess_workability(representative, activities) assessments.append({ 'date': date, 'risk_level': assessment.risk_level.value, 'workable_hours': assessment.workable_hours, 'affected_count': len(assessment.affected_activities) })

return pd.DataFrame(assessments)

常见用例

1. 施工进度规划

conditions = weather.get_forecast(52.52, 13.41, days=14)
risk = ConstructionWeatherRisk() # Check concrete pour window
for c in conditions:
    assessment = risk.assess_workability(c, ['concrete_pour'])
    if assessment.risk_level == WeatherRisk.LOW:
        print(f"Good for concrete: {c.timestamp}")

2. 历史数据分析

historical = weather.get_historical(52.52, 13.41, '2024-01-01', '2024-03-31')
df = weather.to_dataframe(historical)
# Count rain days
rain_days = df[df['precipitation'] > 2]['timestamp'].dt.date.nunique()
print(f"Rain days in Q1: {rain_days}")

资源

  • DDC 书籍:第 2.2 章 - 开放数据集成
  • Open-Meteo API:https://open-meteo.com/
数据来源:ClawHub ↗ · 中文优化:龙虾技能库
OpenClaw 技能定制 / 插件定制 / 私有工作流定制

免费技能或插件可能存在安全风险,如需更匹配、更安全的方案,建议联系付费定制

了解定制服务