Sistema de monitoreo del clima de BMKG y alertas de Telegram
Este es unautomatización que contiene 14 nodos.Utiliza principalmente nodos como If, Code, Telegram, HttpRequest, ManualTrigger. Envío automático de alertas climáticas de Indonesia usando datos de BMKG y notificaciones de Telegram
- •Bot Token de Telegram
- •Pueden requerirse credenciales de autenticación para la API de destino
Nodos utilizados (14)
Categoría
{
"id": "oezF9oCv3tPecrSv",
"meta": {
"instanceId": "b14f5dd921befc4584084cc386aea593f73c7c2b00b50933075d7967a4d1c502",
"templateCredsSetupCompleted": true
},
"name": "BMKG Weather Monitoring & Telegram Alert System",
"tags": [
{
"id": "5elPMuYGw7BLPyD5",
"name": "Weather Monitoring EN",
"createdAt": "2025-10-15T00:58:29.022Z",
"updatedAt": "2025-10-15T00:58:29.022Z"
}
],
"nodes": [
{
"id": "a7760673-0f36-4693-b0e2-b12ec5319247",
"name": "Activador Programado",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-448,
-16
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"typeVersion": 1.1
},
{
"id": "bf292408-48a2-4fb8-baf5-38c7b5f36862",
"name": "Obtener Datos Meteorológicos del BMKG",
"type": "n8n-nodes-base.httpRequest",
"position": [
112,
192
],
"parameters": {
"url": "https://api.bmkg.go.id/publik/prakiraan-cuaca",
"options": {}
},
"typeVersion": 4.1
},
{
"id": "af473f94-7a67-4023-94b5-3bdf8015280a",
"name": "Procesar Datos Meteorológicos",
"type": "n8n-nodes-base.code",
"position": [
304,
0
],
"parameters": {
"jsCode": "// Process BMKG weather data\nconst inputData = $input.all();\nconst weatherData = inputData[0].json;\n\n// Check if data exists\nif (!weatherData || !weatherData.data || !weatherData.data[0] || !weatherData.data[0].cuaca) {\n return [{\n json: {\n success: false,\n error: 'Weather data not available from BMKG API',\n timestamp: new Date().toISOString()\n }\n }];\n}\n\n// Extract location information\nconst location = weatherData.lokasi || {};\nconst cuacaData = weatherData.data[0].cuaca;\n\n// Process current and upcoming weather\nlet processedData = {\n success: true,\n timestamp: new Date().toISOString(),\n location: {\n desa: location.desa || 'Unknown',\n kecamatan: location.kecamatan || 'Unknown',\n kotkab: location.kotkab || 'Unknown',\n provinsi: location.provinsi || 'Unknown',\n lat: location.lat || 0,\n lon: location.lon || 0,\n timezone: location.timezone || 'Asia/Jakarta'\n },\n current_weather: {},\n forecast_24hour: [],\n summary: {\n avg_temperature: 0,\n avg_humidity: 0,\n dominant_condition: '',\n warnings: []\n }\n};\n\n// Process current weather (first data point)\nif (cuacaData[0] && cuacaData[0][0]) {\n const current = cuacaData[0][0];\n processedData.current_weather = {\n time: current.local_datetime || current.datetime,\n temperature: current.t || 0,\n humidity: current.hu || 0,\n condition: current.weather_desc || current.weather_desc_en || 'Unknown',\n wind_speed: current.ws || 0,\n wind_direction: current.wd || 'N/A',\n visibility: current.vs_text || 'N/A',\n cloud_cover: current.tcc || 0,\n rain_probability: current.tp || 0,\n icon_url: current.image || ''\n };\n}\n\n// Process 24-hour forecast\nlet totalTemperature = 0;\nlet totalHumidity = 0;\nlet count = 0;\nlet conditionCount = {};\n\n// Collect data from first day (today)\nif (cuacaData[0]) {\n cuacaData[0].forEach(jam => {\n if (jam && jam.t !== undefined) {\n processedData.forecast_24hour.push({\n time: jam.local_datetime || jam.datetime,\n temperature: jam.t,\n humidity: jam.hu || 0,\n condition: jam.weather_desc || jam.weather_desc_en || 'Unknown',\n wind_speed: jam.ws || 0,\n wind_direction: jam.wd || 'N/A',\n rain_probability: jam.tp || 0,\n icon_url: jam.image || ''\n });\n \n totalTemperature += jam.t;\n totalHumidity += jam.hu || 0;\n count++;\n \n const condition = jam.weather_desc || jam.weather_desc_en || 'Unknown';\n conditionCount[condition] = (conditionCount[condition] || 0) + 1;\n }\n });\n}\n\n// Calculate averages and dominant condition\nif (count > 0) {\n processedData.summary.avg_temperature = Math.round(totalTemperature / count * 10) / 10;\n processedData.summary.avg_humidity = Math.round(totalHumidity / count);\n}\n\n// Find dominant weather condition\nlet maxCount = 0;\nfor (const [condition, conditionNum] of Object.entries(conditionCount)) {\n if (conditionNum > maxCount) {\n maxCount = conditionNum;\n processedData.summary.dominant_condition = condition;\n }\n}\n\n// Generate warnings\nconst warnings = [];\nif (processedData.summary.avg_temperature > 35) {\n warnings.push('⚠️ Very hot temperature, avoid outdoor activities');\n}\nif (processedData.summary.avg_temperature < 20) {\n warnings.push('🧥 Cold temperature, wear warm clothes');\n}\n\n// Check for rain probability\nconst avgRainProb = processedData.forecast_24hour.reduce((sum, item) => sum + (item.rain_probability || 0), 0) / processedData.forecast_24hour.length;\nif (avgRainProb > 60) {\n warnings.push('☔ High rain probability, bring umbrella or raincoat');\n}\nif (avgRainProb > 30 && avgRainProb <= 60) {\n warnings.push('🌦️ Possible rain, prepare rain gear');\n}\n\nprocessedData.summary.warnings = warnings;\n\nreturn [{ json: processedData }];"
},
"typeVersion": 2
},
{
"id": "1ef3b9f1-5837-4ca4-90e6-b39bc37b778d",
"name": "Formatear Mensaje Telegram",
"type": "n8n-nodes-base.code",
"position": [
608,
16
],
"parameters": {
"jsCode": "// Format weather data for Telegram message\nconst data = $input.all()[0].json;\n\nif (!data.success) {\n return [{\n json: {\n telegram_message: `❌ *BMKG Weather Monitoring Error*\\n\\n${data.error}\\n\\nTime: ${data.timestamp}\\n\\n_Powered by BMKG API & n8n_`,\n parse_mode: 'Markdown'\n }\n }];\n}\n\n// Create beautiful Telegram message\nlet message = `🌤️ *BMKG Weather Report*\\n`;\nmessage += `📍 *${data.location.desa}, ${data.location.kecamatan}*\\n`;\nmessage += `🏙️ ${data.location.kotkab}, ${data.location.provinsi}\\n\\n`;\n\n// Current weather\nmessage += `🌡️ *Current Weather*\\n`;\nmessage += `• Temperature: *${data.current_weather.temperature}°C*\\n`;\nmessage += `• Condition: ${data.current_weather.condition}\\n`;\nmessage += `• Humidity: ${data.current_weather.humidity}%\\n`;\nmessage += `• Wind: ${data.current_weather.wind_speed} km/h from ${data.current_weather.wind_direction}\\n`;\nmessage += `• Visibility: ${data.current_weather.visibility}\\n`;\n\nif (data.current_weather.rain_probability > 0) {\n message += `• Rain Prob.: ${data.current_weather.rain_probability}%\\n`;\n}\nmessage += `\\n`;\n\n// Summary\nmessage += `📊 *24 Hour Summary*\\n`;\nmessage += `• Average Temperature: *${data.summary.avg_temperature}°C*\\n`;\nmessage += `• Average Humidity: ${data.summary.avg_humidity}%\\n`;\nmessage += `• Dominant Condition: ${data.summary.dominant_condition}\\n\\n`;\n\n// Warnings\nif (data.summary.warnings.length > 0) {\n message += `⚠️ *Warnings & Suggestions:*\\n`;\n data.summary.warnings.forEach(warning => {\n message += `• ${warning}\\n`;\n });\n message += `\\n`;\n}\n\n// Next few hours forecast (first 6 hours)\nmessage += `⏰ *6 Hour Forecast:*\\n`;\nconst nextHours = data.forecast_24hour.slice(0, 6);\nnextHours.forEach((forecast, index) => {\n const time = new Date(forecast.time).toLocaleTimeString('en-US', { \n hour: '2-digit', \n minute: '2-digit',\n timeZone: data.location.timezone \n });\n message += `• ${time}: ${forecast.temperature}°C, ${forecast.condition}`;\n if (forecast.rain_probability > 30) {\n message += ` (☔${forecast.rain_probability}%)`;\n }\n message += `\\n`;\n});\n\nmessage += `\\n📅 Updated: ${new Date(data.timestamp).toLocaleString('en-US', {\n timeZone: data.location.timezone,\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n})} ${data.location.timezone}`;\n\nmessage += `\\n\\n_🤖 Automated by n8n | 📡 Data: BMKG_`;\n\nreturn [{\n json: {\n telegram_message: message,\n parse_mode: 'Markdown',\n weather_data: data\n }\n}];"
},
"typeVersion": 2
},
{
"id": "ddc33a20-96a8-40bc-9788-6e12f40f88ef",
"name": "Enviar Reporte Meteorológico",
"type": "n8n-nodes-base.telegram",
"position": [
1264,
400
],
"webhookId": "594b5594-af4a-4dfd-8a93-15a5683919cd",
"parameters": {
"text": "={{ $json.telegram_message }}",
"chatId": "{{TELEGRAM_CHAT_ID}}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"id": "5UNbimarOaH1QxRo",
"name": "Telegram account 2"
}
},
"typeVersion": 1.1
},
{
"id": "fdd12bf7-a818-41ef-9c94-65638fd9dac4",
"name": "Prueba Manual",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-480,
240
],
"parameters": {},
"typeVersion": 1
},
{
"id": "3d011775-063e-4a17-ae84-c6c45bc5f3f1",
"name": "Verificar Éxito",
"type": "n8n-nodes-base.if",
"position": [
368,
224
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.success }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "bfd54738-c07c-4f0e-9acf-e96971e21210",
"name": "Manejador de Errores",
"type": "n8n-nodes-base.code",
"position": [
624,
224
],
"parameters": {
"jsCode": "// Log error details\nconst inputData = $input.all()[0].json;\n\nconsole.error('Weather monitoring error:', inputData);\n\nlet errorMessage = `❌ *Weather Monitoring System Error*\\n\\n`;\nerrorMessage += `🕐 Time: ${new Date().toLocaleString('en-US')}\\n`;\nerrorMessage += `❗ Details: ${inputData.error || 'Unknown error'}\\n\\n`;\nerrorMessage += `_System will try again on next schedule_`;\n\nreturn [{\n json: {\n telegram_message: errorMessage,\n parse_mode: 'Markdown',\n error_logged: true\n }\n}];"
},
"typeVersion": 2
},
{
"id": "c80c80f8-6f09-4112-8928-9552b6a6ee04",
"name": "Enviar Alerta de Error",
"type": "n8n-nodes-base.telegram",
"position": [
864,
400
],
"webhookId": "ed4ebdc5-39cf-4d7c-9c52-1a3b9008b28c",
"parameters": {
"text": "={{ $json.telegram_message }}",
"chatId": "{{TELEGRAM_CHAT_ID}}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"id": "5UNbimarOaH1QxRo",
"name": "Telegram account 2"
}
},
"typeVersion": 1.1
},
{
"id": "c84af71c-e6b8-465e-b968-9f7eda7f4eaf",
"name": "Nota Adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1312,
-64
],
"parameters": {
"width": 432,
"height": 416,
"content": "## 🎓 **LEARNING RESOURCES**\n\n### **n8n Documentation:**\n- **Official Docs**: https://docs.n8n.io\n- **Node Reference**: https://docs.n8n.io/integrations/\n- **Workflow Examples**: https://n8n.io/workflows/\n\n### **BMKG API Information:**\n- **API Documentation**: https://api.bmkg.go.id\n- **Region Codes**: Available in API response\n- **Data Format**: JSON structure documentation\n\n### **Telegram Bot API:**\n- **Bot Creation**: https://core.telegram.org/bots\n- **API Reference**: https://core.telegram.org/bots/api\n\n***\n\n"
},
"typeVersion": 1
},
{
"id": "2581be27-b445-43ba-bc5d-534febc19d38",
"name": "Nota Adhesiva1",
"type": "n8n-nodes-base.stickyNote",
"position": [
48,
-160
],
"parameters": {
"width": 784,
"height": 80,
"content": "## 🌤️ **BMKG WEATHER MONITORING & TELEGRAM ALERT SYSTEM**"
},
"typeVersion": 1
},
{
"id": "889ea56c-10e2-4901-9889-868ed741bf48",
"name": "Nota Adhesiva2",
"type": "n8n-nodes-base.stickyNote",
"position": [
848,
-64
],
"parameters": {
"width": 512,
"height": 560,
"content": "### **Create Your Bot**\n- Open Telegram and find @BotFather\n\n- Start a chat and send /newbot\n\n- Follow instructions to set bot name and username\n\n- Copy the Bot Token provided (format: 123456789:ABCdef...)\n\n- Save the token securely for configuration\n\n### **Get Your Chat ID**\n- Start a chat with your new bot and send any message\n\n- Visit https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates in a browser (replace <YOUR_BOT_TOKEN> with your bot token)\n\n- Find the Chat ID number in the JSON response under \"chat\": {\"id\": 123456789, ...}\n\n- Copy the Chat ID for use in your workflow or configuration"
},
"typeVersion": 1
},
{
"id": "f496550d-b5ea-4d73-bf9b-a38ea9ec3027",
"name": "Nota Adhesiva3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-864,
-64
],
"parameters": {
"width": 528,
"height": 288,
"content": "\n### **Enable Automatic Mode:**\n1. **Click workflow name** at top of canvas\n2. **Toggle \"Active\" switch** to ON position\n3. **Workflow status** should show \"Active\"\n4. **Schedule Trigger** will run every 6 hours automatically\n\n### **Schedule Settings:**\n- **Default**: Every 6 hours (4 reports per day)\n- **Modify timing**: Edit \"Schedule Trigger\" node\n- **Options**: 1, 3, 6, 12, or 24 hours\n- **Peak times**: 6AM, 12PM, 6PM, 12AM (with 6-hour interval)"
},
"typeVersion": 1
},
{
"id": "13d5c622-9b20-46b6-861a-36cb9babcb1c",
"name": "Nota Adhesiva4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-304,
-64
],
"parameters": {
"width": 528,
"height": 368,
"content": "### **Update Chat IDs**\nReplace {{TELEGRAM_CHAT_ID}} with your actual Chat ID in both \"Send Weather Report\" and \"Send Error Alert\" nodes (e.g., 123456789).\n\n### **Link Telegram Credentials**\n**Select your saved Telegram credential in the \"Credential\" dropdown of both \"Send Weather Report\" and \"Send Error Alert\" nodes.**\n\n### **Configure Location (Optional)**\n**In \"Get BMKG Weather Data\" node, add a Query parameter named adm4 with your BMKG region code (e.g., 31.71.03.1001).**"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "c83de10d-8b0b-48ed-bb16-f095f85580fe",
"connections": {
"fdd12bf7-a818-41ef-9c94-65638fd9dac4": {
"main": [
[
{
"node": "bf292408-48a2-4fb8-baf5-38c7b5f36862",
"type": "main",
"index": 0
}
]
]
},
"3d011775-063e-4a17-ae84-c6c45bc5f3f1": {
"main": [
[
{
"node": "1ef3b9f1-5837-4ca4-90e6-b39bc37b778d",
"type": "main",
"index": 0
}
],
[
{
"node": "bfd54738-c07c-4f0e-9acf-e96971e21210",
"type": "main",
"index": 0
}
]
]
},
"bfd54738-c07c-4f0e-9acf-e96971e21210": {
"main": [
[
{
"node": "c80c80f8-6f09-4112-8928-9552b6a6ee04",
"type": "main",
"index": 0
}
]
]
},
"a7760673-0f36-4693-b0e2-b12ec5319247": {
"main": [
[
{
"node": "bf292408-48a2-4fb8-baf5-38c7b5f36862",
"type": "main",
"index": 0
}
]
]
},
"af473f94-7a67-4023-94b5-3bdf8015280a": {
"main": [
[
{
"node": "3d011775-063e-4a17-ae84-c6c45bc5f3f1",
"type": "main",
"index": 0
}
]
]
},
"bf292408-48a2-4fb8-baf5-38c7b5f36862": {
"main": [
[
{
"node": "af473f94-7a67-4023-94b5-3bdf8015280a",
"type": "main",
"index": 0
}
]
]
},
"1ef3b9f1-5837-4ca4-90e6-b39bc37b778d": {
"main": [
[
{
"node": "ddc33a20-96a8-40bc-9788-6e12f40f88ef",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Intermedio
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
Tegar karunia ilham
@tegarkaruniailhamDeveloper | Flowgrammer | Promt Engineering | Helping business owners & marketers automate their processes with n8n. Specialist in custom workflows, API integrations, and template development.
Compartir este flujo de trabajo