🐟 智能喂鱼器:基于 BMKG 天气的自动喂食系统
中级
这是一个Engineering、Multimodal AI领域的自动化工作流,包含 13 个节点。主要使用 If、Set、Code、Merge、Telegram 等节点。 🐟 智能喂鱼器:基于 BMKG 天气和 Telegram 提醒的自动喂食系统
前置要求
- •Telegram Bot Token
- •可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "ZWdJS9zTlAfcE8QW",
"meta": {
"instanceId": "b14f5dd921befc4584084cc386aea593f73c7c2b00b50933075d7967a4d1c502"
},
"name": "🐟 智能喂鱼器:基于 BMKG 天气的自动喂食系统",
"tags": [],
"nodes": [
{
"id": "da547149-76e6-455a-970c-3bbe3aa4c0be",
"name": "Cron:05:30 & 16:30 WIB",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
528,
304
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
},
{
"id": "c024b1c2-5fc5-42f8-9f41-5de6c9a39a82",
"name": "配置",
"type": "n8n-nodes-base.set",
"position": [
720,
304
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "locationName",
"name": "locationName",
"type": "string",
"value": "Main Pond"
},
{
"id": "lat",
"name": "lat",
"type": "string",
"value": "-6.2000"
},
{
"id": "lon",
"name": "lon",
"type": "string",
"value": "106.8166"
},
{
"id": "bmkgUrlTemplate",
"name": "bmkgUrlTemplate",
"type": "string",
"value": "https://api.bmkg.go.id/publik/prakiraan-weather?adm4={{ADM4}}"
},
{
"id": "bmkgApiKey",
"name": "bmkgApiKey",
"type": "string",
"value": "{{PLACEHOLDER}}"
},
{
"id": "telegramBotToken",
"name": "telegramBotToken",
"type": "string",
"value": "{{PLACEHOLDER}}"
},
{
"id": "telegramChatId",
"name": "telegramChatId",
"type": "string",
"value": "{{PLACEHOLDER}}"
},
{
"id": "esp8266WebhookUrl",
"name": "esp8266WebhookUrl",
"type": "string",
"value": "{{PLACEHOLDER}}"
},
{
"id": "adm4",
"name": "adm4",
"type": "string",
"value": "31.71.03.1001"
},
{
"id": "thresholdProb",
"name": "thresholdProb",
"type": "string",
"value": "60"
},
{
"id": "reducePercent",
"name": "reducePercent",
"type": "string",
"value": "-20"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e72ef26d-d37a-4d33-a485-cbbb2352554a",
"name": "构建天气预报 URL",
"type": "n8n-nodes-base.code",
"position": [
896,
304
],
"parameters": {
"jsCode": "// Build BMKG API URL with error handling\ntry {\n const adm4 = $input.item(0).json.adm4;\n const urlTemplate = $input.item(0).json.bmkgUrlTemplate;\n \n if (!adm4 || !urlTemplate) {\n throw new Error('Missing required parameters: adm4 or urlTemplate');\n }\n \n const url = urlTemplate.replace('{{ADM4}}', adm4);\n \n return {\n json: { \n url,\n timestamp: new Date().toISOString(),\n location: $input.item(0).json.locationName\n }\n };\n} catch (error) {\n return {\n json: {\n error: error.message,\n url: 'https://api.bmkg.go.id/publik/prakiraan-weather?adm4=31.71.03.1001'\n }\n };\n}"
},
"typeVersion": 2
},
{
"id": "1e132997-bd59-4dce-b2c8-4b60d92aa1ea",
"name": "HTTP:BMKG 天气预报",
"type": "n8n-nodes-base.httpRequest",
"position": [
1072,
304
],
"parameters": {
"url": "={{ $json.url }}",
"options": {
"timeout": 30000,
"response": {
"response": {
"neverError": true
}
}
}
},
"typeVersion": 4.2
},
{
"id": "f37bd636-4f38-4300-8909-f16cd91f7423",
"name": "解析与评分天气(6-12小时)",
"type": "n8n-nodes-base.code",
"position": [
1280,
304
],
"parameters": {
"jsCode": "// Enhanced weather parsing with better error handling\ntry {\n const data = $input.item(0).json;\n const configData = $('Config').item(0).json;\n \n let rain_hours = 0, rain_prob_max6h = 0, rain_prob_avg12h = 0;\n let items = [];\n \n // Handle different API response structures\n if (data.data && Array.isArray(data.data)) {\n items = data.data;\n } else if (data.lokasi && data.lokasi[0] && data.lokasi[0].weather) {\n items = data.lokasi[0].weather;\n } else if (Array.isArray(data)) {\n items = data;\n }\n \n let rain_count = 0, rain_sum = 0, max6h = 0, total = 0;\n let weather_conditions = [];\n \n // Process weather data for next 12 hours (4 periods of 3 hours)\n for (let i = 0; i < Math.min(items.length, 4); i++) {\n const item = items[i];\n let rainProb = 0;\n \n // Extract rain probability from different possible fields\n if (item.hu) rainProb = parseFloat(item.hu) || 0;\n if (item.rain_prob) rainProb = parseFloat(item.rain_prob) || 0;\n if (item.weather && item.weather.toLowerCase().includes('rain')) rainProb = 80;\n if (item.weather_desc && item.weather_desc.toLowerCase().includes('rain')) rainProb = 75;\n \n // Estimate probability from weather description\n if (item.weather_desc) {\n const desc = item.weather_desc.toLowerCase();\n if (desc.includes('heavy rain') || desc.includes('thunderstorm')) rainProb = Math.max(rainProb, 85);\n else if (desc.includes('rain') && desc.includes('thunder')) rainProb = Math.max(rainProb, 80);\n else if (desc.includes('rain')) rainProb = Math.max(rainProb, 70);\n else if (desc.includes('clouds') && desc.includes('thick')) rainProb = Math.max(rainProb, 40);\n }\n \n rain_sum += rainProb;\n if (i < 2 && rainProb > max6h) max6h = rainProb; // First 6 hours (2 periods)\n if (rainProb > 0) rain_count++;\n total++;\n \n weather_conditions.push({\n period: i + 1,\n time: item.local_datetime || item.weatherTime || `Period ${i + 1}`,\n rain_prob: rainProb,\n weather: item.weather_desc || item.weather || 'N/A',\n temp: item.t || item.tempC || 'N/A'\n });\n }\n \n if (total > 0) {\n rain_prob_avg12h = Math.round(rain_sum / total);\n rain_prob_max6h = max6h;\n }\n \n const final_rain_prob = Math.max(rain_prob_avg12h, rain_prob_max6h);\n const threshold = parseInt(configData.thresholdProb) || 60;\n const feed_ratio = final_rain_prob >= threshold \n ? parseInt(configData.reducePercent) || -20\n : 0;\n \n return {\n json: {\n rain_prob: final_rain_prob,\n rain_prob_max6h: rain_prob_max6h,\n rain_prob_avg12h: rain_prob_avg12h,\n feed_ratio: feed_ratio,\n weather_conditions: weather_conditions,\n analysis_time: new Date().toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }),\n location: configData.locationName\n }\n };\n \n} catch (error) {\n return {\n json: {\n error: error.message,\n rain_prob: 0,\n rain_prob_max6h: 0,\n rain_prob_avg12h: 0,\n feed_ratio: 0,\n weather_conditions: [],\n analysis_time: new Date().toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' })\n }\n };\n}"
},
"typeVersion": 2
},
{
"id": "381e3f06-03ee-4c8c-a2d3-d60798c2ccb7",
"name": "IF:高降雨概率",
"type": "n8n-nodes-base.if",
"position": [
1472,
304
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "rain_condition",
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ $json.rain_prob }}",
"rightValue": "={{ $('Config').item(0).json.thresholdProb }}"
}
]
}
},
"typeVersion": 2
},
{
"id": "a089a86b-fe8e-44b9-8c5e-677018c53b97",
"name": "设置:减少喂食量 20%",
"type": "n8n-nodes-base.set",
"position": [
1680,
224
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "note",
"name": "note",
"type": "string",
"value": "🌧️ WARNING: High rain probability ({{ $('Parse & Score Weather (6-12h)').item(0).json.rain_prob }}%)\\n\\n📉 Reduce feed by 20%\\n⚡ Turn on aerator (15-20 menit/jam)\\n🔍 Check DO & observe fish appetite\\n🐟 Monitor fish health"
},
{
"id": "feed_ratio",
"name": "feed_ratio",
"type": "number",
"value": "={{ $('Parse & Score Weather (6-12h)').item(0).json.feed_ratio }}"
},
{
"id": "action_type",
"name": "action_type",
"type": "string",
"value": "reduce_feed"
},
{
"id": "esp8266_command",
"name": "esp8266_command",
"type": "string",
"value": "FEED_REDUCE_20"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "fb16bf68-b431-417f-9443-3bbb2cdd2f2f",
"name": "设置:正常喂食量 0%",
"type": "n8n-nodes-base.set",
"position": [
1680,
384
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "note",
"name": "note",
"type": "string",
"value": "☀️ Weather is relatively safe ({{ $('Parse & Score Weather (6-12h)').item(0).json.rain_prob }}%)\\n\\n🐟 Normal feed - no reduction\\n✅ Continue monitoring water quality\\n📊 Monitor pond parameters routinely"
},
{
"id": "feed_ratio",
"name": "feed_ratio",
"type": "number",
"value": 0
},
{
"id": "action_type",
"name": "action_type",
"type": "string",
"value": "normal_feed"
},
{
"id": "esp8266_command",
"name": "esp8266_command",
"type": "string",
"value": "FEED_NORMAL"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "33f96e3a-8a4b-4260-93d8-75b803fe1d76",
"name": "合并分支",
"type": "n8n-nodes-base.merge",
"position": [
1920,
304
],
"parameters": {
"mode": "chooseBranch"
},
"typeVersion": 2.1
},
{
"id": "74cacc40-b5b7-4939-949c-eaeabef1223f",
"name": "ESP8266 喂鱼器控制",
"type": "n8n-nodes-base.httpRequest",
"position": [
2128,
304
],
"parameters": {
"url": "={{ $('Config').item(0).json.esp8266WebhookUrl }}",
"method": "POST",
"options": {
"timeout": 10000
},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "command",
"value": "={{ $json.esp8266_command }}"
},
{
"name": "feed_ratio",
"value": "={{ $json.feed_ratio }}"
},
{
"name": "rain_prob",
"value": "={{ $('Parse & Score Weather (6-12h)').item(0).json.rain_prob }}"
},
{
"name": "timestamp",
"value": "={{ new Date().toISOString() }}"
},
{
"name": "location",
"value": "={{ $('Config').item(0).json.locationName }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "User-Agent",
"value": "n8n-bmkg-feeder/1.0"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "8cf99c87-530a-4180-b0f6-4bd53043f07e",
"name": "Telegram:发送报告",
"type": "n8n-nodes-base.telegram",
"position": [
2352,
304
],
"webhookId": "bc9aff86-c2b7-429a-ba93-0c6bcee94c3d",
"parameters": {
"text": "=🐟 **{{ $('Config').item(0).json.locationName }}** - **Automatic Feeding Schedule**\n\n📅 **Time**: {{ new Date().toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }) }}\n\n🌤️ **BMKG Weather Analysis:**\n• 12-hour rain probability: **{{ $('Parse & Score Weather (6-12h)').item(0).json.rain_prob }}%**\n• 6-hour rain probability: **{{ $('Parse & Score Weather (6-12h)').item(0).json.rain_prob_max6h }}%**\n• 12-hour average: **{{ $('Parse & Score Weather (6-12h)').item(0).json.rain_prob_avg12h }}%**\n\n🎯 **Feeding Decision:**\n• Feed ratio: **{{ $json.feed_ratio }}%**\n• ESP8266 Status: {{ $('ESP8266 Fish Feeder Control').item(0).json ? '✅ Sent' : '❌ Failed' }}\n\n{{ $json.note }}\n\n---\n*Powered by BMKG API + ESP8266 + n8n*\n*Next feeding: {{ new Date(Date.now() + (new Date().getHours() < 12 ? (16 - new Date().getHours()) * 3600000 : (29 - new Date().getHours()) * 3600000)).toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }) }}*",
"chatId": "={{ $('Config').item(0).json.telegramChatId }}",
"additionalFields": {
"parse_mode": "Markdown",
"disable_notification": false
}
},
"credentials": {
"telegramApi": {
"id": "5UNbimarOaH1QxRo",
"name": "Telegram account 2"
}
},
"typeVersion": 1.2
},
{
"id": "8cb2be2c-6718-4d50-a896-fe472f037e22",
"name": "活动记录器",
"type": "n8n-nodes-base.code",
"position": [
2576,
304
],
"parameters": {
"jsCode": "// Log activity and prepare summary\nconst weatherData = $('Parse & Score Weather (6-12h)').item(0).json;\nconst feedData = $input.item(0).json;\nconst configData = $('Config').item(0).json;\nconst esp8266Response = $('ESP8266 Fish Feeder Control').item(0).json;\n\nconst logEntry = {\n timestamp: new Date().toISOString(),\n location: configData.locationName,\n rain_probability: weatherData.rain_prob,\n feed_ratio: feedData.feed_ratio,\n action_type: feedData.action_type,\n esp8266_status: esp8266Response ? 'success' : 'failed',\n weather_summary: weatherData.weather_conditions?.slice(0, 2) || [],\n bmkg_analysis_time: weatherData.analysis_time\n};\n\nreturn {\n json: logEntry\n};"
},
"typeVersion": 2
},
{
"id": "901a9809-bdc3-4616-a17a-5abf5f465902",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 464,
"height": 5312,
"content": "# 📝 N8N 工作流安装指南 - 自动喂鱼器"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "b4a60651-e4ef-4bfd-813c-919f7a46d219",
"connections": {
"Config": {
"main": [
[
{
"node": "Build Forecast URL",
"type": "main",
"index": 0
}
]
]
},
"Merge Branches": {
"main": [
[
{
"node": "ESP8266 Fish Feeder Control",
"type": "main",
"index": 0
}
]
]
},
"Build Forecast URL": {
"main": [
[
{
"node": "HTTP: Forecast BMKG",
"type": "main",
"index": 0
}
]
]
},
"HTTP: Forecast BMKG": {
"main": [
[
{
"node": "Parse & Score Weather (6-12h)",
"type": "main",
"index": 0
}
]
]
},
"Set: Normal Feed 0%": {
"main": [
[
{
"node": "Merge Branches",
"type": "main",
"index": 1
}
]
]
},
"Set: Reduce Feed 20%": {
"main": [
[
{
"node": "Merge Branches",
"type": "main",
"index": 0
}
]
]
},
"Telegram: Send Report": {
"main": [
[
{
"node": "Activity Logger",
"type": "main",
"index": 0
}
]
]
},
"Cron: 05:30 & 16:30 WIB": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"IF: High Rain Probability": {
"main": [
[
{
"node": "Set: Reduce Feed 20%",
"type": "main",
"index": 0
}
],
[
{
"node": "Set: Normal Feed 0%",
"type": "main",
"index": 0
}
]
]
},
"ESP8266 Fish Feeder Control": {
"main": [
[
{
"node": "Telegram: Send Report",
"type": "main",
"index": 0
}
]
]
},
"Parse & Score Weather (6-12h)": {
"main": [
[
{
"node": "IF: High Rain Probability",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
这是一个中级难度的工作流,适用于Engineering、Multimodal AI等场景。适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
智能求职专家
通过 Gemini AI、Notion 追踪和多平台搜索实现职位申请的自动化
If
Set
Code
+8
16 节点Tegar karunia ilham
Content Creation
AI驱动视频创作与上传至Instagram、TikTok和YouTube
从云端硬盘进行AI驱动视频创作并上传至Instagram、TikTok和YouTube
If
Set
Code
+14
53 节点DevCode Journey
Content Creation
每日体育摘要
使用Google Gemini、Kokoro TTS和FFmpeg将RSS源转换为播客
If
Set
Code
+12
34 节点Jonas
Content Creation
使用 Apify、AI 筛选和 Telegram 提醒发现 Threads 上的招聘帖子
通过 Apify、AI 筛选和 Telegram 提醒发现 Threads 上的招聘帖子
If
Set
Code
+9
19 节点A Z
Content Creation
Telegram论坛脉搏:使用Gemini和Groq AI模型的社区监控
Telegram论坛脉搏:使用Gemini和Groq AI模型的社区监控
If
Set
Code
+13
59 节点Nguyen Thieu Toan
Miscellaneous
交易机器人ICT 2025智能货币概念
使用ICT方法、GPT-4o和Coinbase的自动化加密货币交易机器人
If
Set
Code
+6
15 节点Tegar karunia ilham
Miscellaneous
工作流信息
难度等级
中级
节点数量13
分类2
节点类型8
作者
Tegar karunia ilham
@tegarkaruniailhamHelping business owners & marketers automate their processes with n8n. Specialist in custom workflows, API integrations, and template development. 📈 100+ successful automation projects 🔧 Premium n8n templates available 💡 Free consultation for custom automation Book a consultation for your business digital transformation!"
外部链接
在 n8n.io 上查看 →
分享此工作流