基于SMS的天气警报(OpenWeather + Twilio)
中级
这是一个Personal Productivity, Multimodal AI领域的自动化工作流,包含 9 个节点。主要使用 If, Code, Cron, Twilio, HttpRequest 等节点。 基于SMS的天气警报(OpenWeather + Twilio)
前置要求
- •可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "2000c64071c20843606b95c63795bb0797c41036047055a6586498e855b96efc"
},
"nodes": [
{
"id": "9ababe8e-1ba5-4255-b97c-1b4e9e79ef99",
"name": "设置说明",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
-16
],
"parameters": {
"width": 712,
"height": 680,
"content": "🌤️ **需要设置:**"
},
"typeVersion": 1
},
{
"id": "31bcbe91-559b-4ad4-bd3a-d0b470c7eda4",
"name": "每 6 小时检查",
"type": "n8n-nodes-base.cron",
"position": [
144,
304
],
"parameters": {},
"typeVersion": 1
},
{
"id": "fef45e7b-e895-43f6-9101-a8aa879304d5",
"name": "获取当前天气",
"type": "n8n-nodes-base.httpRequest",
"position": [
352,
304
],
"parameters": {
"url": "https://api.openweathermap.org/data/2.5/weather",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "New York,US"
},
{
"name": "appid",
"value": "YOUR_OPENWEATHER_API_KEY"
},
{
"name": "units",
"value": "imperial"
}
]
}
},
"typeVersion": 4.1
},
{
"id": "3b0b3916-e46d-4bb3-bc43-660e3da9ac98",
"name": "获取天气预报",
"type": "n8n-nodes-base.httpRequest",
"position": [
352,
448
],
"parameters": {
"url": "https://api.openweathermap.org/data/2.5/forecast",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "New York,US"
},
{
"name": "appid",
"value": "YOUR_OPENWEATHER_API_KEY"
},
{
"name": "units",
"value": "imperial"
},
{
"name": "cnt",
"value": "8"
}
]
}
},
"typeVersion": 4.1
},
{
"id": "f1ec579d-ca05-4ab2-bdcb-ba13e43fe32c",
"name": "分析天气数据",
"type": "n8n-nodes-base.code",
"position": [
544,
384
],
"parameters": {
"jsCode": "// Normalize weather data and determine if alerts are needed\nconst currentWeather = $('Get Current Weather').item.json;\nconst forecast = $('Get Weather Forecast').item.json;\n\n// Current weather analysis\nconst current = {\n temperature: Math.round(currentWeather.main.temp),\n feels_like: Math.round(currentWeather.main.feels_like),\n humidity: currentWeather.main.humidity,\n description: currentWeather.weather[0].description,\n main_condition: currentWeather.weather[0].main.toLowerCase(),\n wind_speed: Math.round(currentWeather.wind.speed),\n city: currentWeather.name,\n country: currentWeather.sys.country\n};\n\n// Forecast analysis (next 24 hours)\nconst upcoming = [];\nforecast.list.slice(0, 8).forEach(item => {\n upcoming.push({\n time: new Date(item.dt * 1000).toLocaleString(),\n temp: Math.round(item.main.temp),\n condition: item.weather[0].main.toLowerCase(),\n description: item.weather[0].description,\n rain_probability: Math.round((item.pop || 0) * 100)\n });\n});\n\n// Alert conditions\nconst alerts = [];\n\n// Temperature alerts\nif (current.temperature >= 95) {\n alerts.push(`🔥 EXTREME HEAT: ${current.temperature}°F (feels like ${current.feels_like}°F)`);\n} else if (current.temperature <= 20) {\n alerts.push(`🥶 EXTREME COLD: ${current.temperature}°F (feels like ${current.feels_like}°F)`);\n}\n\n// Severe weather alerts\nif (['thunderstorm', 'tornado'].includes(current.main_condition)) {\n alerts.push(`⛈️ SEVERE WEATHER: ${current.description}`);\n}\n\n// Precipitation alerts\nif (['rain', 'drizzle'].includes(current.main_condition)) {\n alerts.push(`🌧️ RAIN ALERT: ${current.description}`);\n} else if (current.main_condition === 'snow') {\n alerts.push(`❄️ SNOW ALERT: ${current.description}`);\n}\n\n// Wind alerts\nif (current.wind_speed >= 25) {\n alerts.push(`💨 HIGH WINDS: ${current.wind_speed} mph`);\n}\n\n// Check upcoming severe weather\nconst upcomingBad = upcoming.filter(item => \n ['thunderstorm', 'snow', 'rain'].includes(item.condition) || \n item.rain_probability >= 70\n);\n\nif (upcomingBad.length > 0) {\n alerts.push(`⚠️ UPCOMING: ${upcomingBad[0].description} at ${upcomingBad[0].time.split(',')[1]} (${upcomingBad[0].rain_probability}% chance)`);\n}\n\nconst weatherData = {\n location: `${current.city}, ${current.country}`,\n current_weather: current,\n forecast_24h: upcoming,\n alerts: alerts,\n has_alerts: alerts.length > 0,\n alert_count: alerts.length,\n timestamp: new Date().toLocaleString()\n};\n\nconsole.log(`Weather check for ${weatherData.location}: ${weatherData.alert_count} alerts found`);\n\nreturn {\n json: weatherData\n};"
},
"typeVersion": 2
},
{
"id": "5524be11-f80e-4710-85cf-3eb5f6ee8cf8",
"name": "需要警报吗?",
"type": "n8n-nodes-base.if",
"position": [
752,
384
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition-1",
"operator": {
"type": "boolean",
"operation": "equal"
},
"leftValue": "={{ $json.has_alerts }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "e903afab-78c9-424a-aa6a-8a985abc8aae",
"name": "格式化短信警报",
"type": "n8n-nodes-base.code",
"position": [
944,
272
],
"parameters": {
"jsCode": "// Format weather alert SMS message\nconst weatherData = $input.first().json;\n\nlet smsMessage = `🌤️ WEATHER ALERT - ${weatherData.location}\\n\\n`;\n\n// Add current conditions\nsmsMessage += `NOW: ${weatherData.current_weather.temperature}°F, ${weatherData.current_weather.description}\\n\\n`;\n\n// Add alerts\nsmsMessage += `🚨 ALERTS (${weatherData.alert_count}):\\n`;\nweatherData.alerts.forEach(alert => {\n smsMessage += `${alert}\\n`;\n});\n\n// Add next few hours preview\nconst next3Hours = weatherData.forecast_24h.slice(0, 3);\nsmsMessage += `\\n📅 NEXT 3 HOURS:\\n`;\nnext3Hours.forEach(forecast => {\n const time = forecast.time.split(' ')[1]; // Get just time part\n smsMessage += `${time}: ${forecast.temp}°F, ${forecast.description}\\n`;\n});\n\nsmsMessage += `\\n⏰ Alert sent: ${weatherData.timestamp}`;\n\n// Keep SMS under 160 characters if possible, or split into multiple\nconst formattedAlert = {\n message: smsMessage,\n location: weatherData.location,\n alert_type: weatherData.alerts[0] ? weatherData.alerts[0].split(':')[0] : 'GENERAL',\n urgency: weatherData.alerts.some(alert => \n alert.includes('EXTREME') || alert.includes('SEVERE')\n ) ? 'HIGH' : 'MEDIUM'\n};\n\nconsole.log(`Formatted SMS alert (${formattedAlert.urgency} urgency):`, formattedAlert.alert_type);\n\nreturn {\n json: formattedAlert\n};"
},
"typeVersion": 2
},
{
"id": "49355489-755c-47b7-ba89-a1a9254dd2ef",
"name": "发送天气短信",
"type": "n8n-nodes-base.twilio",
"position": [
1152,
272
],
"parameters": {
"message": "={{ $json.message }}",
"options": {}
},
"typeVersion": 1
},
{
"id": "daa67817-5a38-4865-a686-4d94862eecdc",
"name": "记录已发送警报",
"type": "n8n-nodes-base.code",
"position": [
1344,
272
],
"parameters": {
"jsCode": "// Log successful weather alert\nconst alertData = $('Format SMS Alert').item.json;\n\nconsole.log(`✅ Weather alert sent successfully!`);\nconsole.log(`📍 Location: ${alertData.location}`);\nconsole.log(`⚠️ Alert Type: ${alertData.alert_type}`);\nconsole.log(`🔥 Urgency: ${alertData.urgency}`);\n\nreturn {\n json: {\n status: 'sent',\n alert_summary: `Weather alert sent for ${alertData.location} - ${alertData.alert_type}`,\n urgency: alertData.urgency,\n timestamp: new Date().toISOString()\n }\n};"
},
"typeVersion": 2
}
],
"pinData": {},
"connections": {
"Alert Needed?": {
"main": [
[
{
"node": "Format SMS Alert",
"type": "main",
"index": 0
}
]
]
},
"Format SMS Alert": {
"main": [
[
{
"node": "Send Weather SMS",
"type": "main",
"index": 0
}
]
]
},
"Send Weather SMS": {
"main": [
[
{
"node": "Log Alert Sent",
"type": "main",
"index": 0
}
]
]
},
"Check Every 6 Hours": {
"main": [
[
{
"node": "Get Current Weather",
"type": "main",
"index": 0
},
{
"node": "Get Weather Forecast",
"type": "main",
"index": 0
}
]
]
},
"Get Current Weather": {
"main": [
[
{
"node": "Analyze Weather Data",
"type": "main",
"index": 0
}
]
]
},
"Analyze Weather Data": {
"main": [
[
{
"node": "Alert Needed?",
"type": "main",
"index": 0
}
]
]
},
"Get Weather Forecast": {
"main": [
[
{
"node": "Analyze Weather Data",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 个人效率, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
每日禅语励志名言推送至Slack频道
每日从ZenQuotes获取励志名言并推送到Slack频道
Code
Cron
Slack
+2
5 节点David Olusola
个人效率
比特币和以太坊加密货币下跌警报(Telegram、Slack 和 SMS)
通过 Telegram、Slack 和 SMS 发送比特币和以太坊加密货币下跌警报
If
Code
Slack
+5
8 节点David Olusola
加密货币交易
使用 CoinGecko 通过邮件/SMS 监控比特币和以太坊价格告警
使用 CoinGecko 通过邮件/SMS 监控比特币和以太坊价格告警
If
Code
Gmail
+4
8 节点David Olusola
加密货币交易
每周LinkedIn联系人同步与分析(使用Apify和Google Sheets)
每周LinkedIn联系人同步与分析(使用Apify和Google Sheets)
If
Code
Cron
+4
13 节点David Olusola
潜在客户开发
YouTube新视频→自动发布链接到Slack
将YouTube视频通知自动化发送到Slack
Code
Cron
Slack
+2
6 节点David Olusola
社交媒体
使用OpenWeatherMap和Gmail发送每日天气报告到邮箱
使用OpenWeatherMap和Gmail发送每日天气报告到邮箱
Code
Cron
Gmail
+2
6 节点David Olusola
个人效率
工作流信息
难度等级
中级
节点数量9
分类2
节点类型6
作者
David Olusola
@dae221I help ambitious businesses eliminate operational bottlenecks and scale faster with AI automation. My clients typically see 40-60% efficiency gains within 90 days. Currently accepting 3 new projects this quarter - david@daexai.com
外部链接
在 n8n.io 查看 →
分享此工作流