🐟 Alimentateur intelligent de poissons : système d'alimentation automatique basé sur le temps météorologique de BMKG
Ceci est unEngineering, Multimodal AIworkflow d'automatisation du domainecontenant 13 nœuds.Utilise principalement des nœuds comme If, Set, Code, Merge, Telegram. 🐟 Alimentateur intelligent pour pois : système d'alimentation automatique basé sur la météo BMKG et les rappels Telegram
- •Token Bot Telegram
- •Peut nécessiter les informations d'identification d'authentification de l'API cible
Nœuds utilisés (13)
Catégorie
{
"id": "ZWdJS9zTlAfcE8QW",
"meta": {
"instanceId": "b14f5dd921befc4584084cc386aea593f73c7c2b00b50933075d7967a4d1c502"
},
"name": "🐟 Smart Fish Feeder: BMKG Weather-Based Automated Feeding System",
"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": "Config",
"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": "Construire l'URL de Prévision",
"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 : Prévision 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": "Analyser & Noter la Météo (6-12h)",
"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": "SI : Forte Probabilité de Pluie",
"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": "Définir : Réduire Nourriture 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": "Définir : Nourriture Normale 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": "Fusionner les Branches",
"type": "n8n-nodes-base.merge",
"position": [
1920,
304
],
"parameters": {
"mode": "chooseBranch"
},
"typeVersion": 2.1
},
{
"id": "74cacc40-b5b7-4939-949c-eaeabef1223f",
"name": "Contrôle Distributeur 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 : Envoyer Rapport",
"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": "Journal d'Activité",
"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": "Note Adhésive",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 464,
"height": 5312,
"content": "# 📝 N8N WORKFLOW INSTALLATION GUIDE - AUTOMATIC FISH FEEDER\n\n## 🚀 STEP 1: INITIAL SETUP\n\n### 1️⃣ Install n8n\n```bash\n# Via NPM (Easiest method)\nnpm install -g n8n\n\n# Via Docker (Recommended for production) \ndocker run -it --rm --name n8n -p 5678:5678 n8nio/n8n\n```\n\n### 2️⃣ Run n8n\n```bash\n# Start n8n\nn8n start\n\n# Open browser: http://localhost:5678\n```\n\n---\n\n## 🔧 STEP 2: CREDENTIALS CONFIGURATION\n\n### 📱 Setup Telegram Bot\n1. Chat with @BotFather on Telegram\n2. Type `/newbot` \n3. Follow instructions, save the TOKEN\n4. In n8n: Settings → Credentials → Add → Telegram\n5. Enter Bot Token\n\n### 🌤️ Setup BMKG API (Optional)\n- BMKG API is usually free without API key\n- If key required, register at portal.bmkg.go.id\n\n---\n\n## 📥 STEP 3: IMPORT WORKFLOW\n\n### Method 1: Import JSON\n1. Copy entire workflow JSON \n2. In n8n: Menu → Import from File\n3. Paste JSON → Import\n\n### Method 2: Via File Upload\n1. Save JSON as .json file\n2. Drag & drop to n8n workspace\n3. Click Import\n\n---\n\n## ⚙️ STEP 4: WORKFLOW CONFIGURATION\n\n### 🏠 Edit \"Config\" Node\n```\nlocationName: \"Main Pond\" (change according to your pond)\nlat: \"-6.2000\" (latitude coordinates of location)\nlon: \"106.8166\" (longitude coordinates of location)\nadm4: \"31.71.03.1001\" (BMKG area code)\nthresholdProb: \"60\" (rain threshold %, default 60%)\nreducePercent: \"-20\" (feed reduction %, default -20%)\n```\n\n### 📱 Setup Telegram Node\n1. Click \"Telegram: Send Report\" node\n2. Select the credential you created\n3. Fill Chat ID:\n - Forward message to @userinfobot\n - Copy the Chat ID that appears\n\n### 🔗 Setup ESP8266 Webhook\n1. Edit esp8266WebhookUrl in Config node\n2. Format: `http://ESP8266_IP/webhook` \n3. Example: `http://192.168.1.100/webhook`\n\n---\n\n## 📡 STEP 5: ESP8266 CONFIGURATION\n\n### Arduino Code Setup\n```cpp\n// Add to ESP8266 Arduino code\n#include <ESP8266WebServer.h>\nESP8266WebServer server(80);\n\nvoid setup() {\n // Setup WiFi connection\n // Setup servo, LCD, sensors\n // Setup webhook endpoint\n server.on(\"/webhook\", HTTP_POST, handleWebhook);\n server.begin();\n}\n\nvoid handleWebhook() {\n String command = server.arg(\"command\");\n if(command == \"FEED_NORMAL\") {\n // Normal feed 100%\n feedFish(100);\n }\n else if(command == \"FEED_REDUCE_20\") {\n // Feed reduced by 20%\n feedFish(80); \n }\n server.send(200, \"application/json\", \"{\\\"status\\\":\\\"ok\\\"}\");\n}\n```\n\nOr check here: https://github.com/TegarDev9/fish-feed-esp8266.git\n\n---\n\n## ⏰ STEP 6: SET AUTOMATIC SCHEDULE\n\n### Configure Cron Node\n1. Click \"Cron: 05:30 & 16:30 WIB\" node\n2. Set timezone: \"Asia/Jakarta\"\n3. Set time: 05:30 and 16:30 (or as desired)\n\n---\n\n## ✅ STEP 7: TESTING & ACTIVATION\n\n### 🧪 Manual Test\n1. Click first node (Cron)\n2. Select \"Execute Node\" \n3. View results in each node\n4. Make sure there are no red errors\n\n### 🔍 Check Connections\n- ✅ BMKG API response OK\n- ✅ ESP8266 webhook response 200\n- ✅ Telegram message sent\n\n### 🚀 Activate Workflow\n1. Click \"Active\" toggle at top right\n2. Workflow will run automatically on schedule\n\n---\n\n## 🛠️ COMMON TROUBLESHOOTING\n\n### ❌ Error \"Node not found\"\n**Solution:** Update n8n to latest version\n```bash\nnpm update -g n8n\n```\n\n### ❌ Telegram error \"Unauthorized\"\n**Solution:** \n- Check Bot Token is correct\n- Ensure Chat ID is valid\n- Bot already started with /start\n\n### ❌ ESP8266 not responding\n**Solution:**\n- Check ESP8266 IP address\n- Ensure ESP8266 and n8n are on same network \n- Manual test: `curl -X POST http://IP/webhook`\n\n### ❌ BMKG API timeout\n**Solution:**\n- Check internet connection\n- Change timeout from 30000 to 60000ms\n- Use valid ADM4\n\n---\n\n## 📊 MONITORING & LOGS\n\n### 📈 View Execution History\n1. Menu → Executions\n2. View status of each run\n3. Click for error details\n\n### 📱 Telegram Notifications \nAutomatic message format:\n```\n🐟 Main Pond - Automatic Feed Schedule\n📅 Time: 17/09/2025 17:30:00\n🌤️ BMKG Weather Analysis:\n• Rain prob. 12 hours: 45%\n🎯 Feed Decision:\n• Feed ratio: 100%\n• ESP8266 Status: ✅ Sent\n```\n\n---\n\n## 🔄 UPDATE & MAINTENANCE\n\n### Update Workflow\n1. Export old workflow (backup)\n2. Import new workflow \n3. Copy old credentials\n4. Test before activation\n\n### Backup Credentials\n1. Settings → Export\n2. Save backup file\n3. Include credentials: YES\n\n---\n\n## 📞 TECHNICAL SUPPORT\n\n### Log Error Checking\n```bash\n# Check n8n logs\ndocker logs n8n\n\n# Or if installed via npm\n~/.n8n/logs/n8n.log\n```\n\n### Performance Tips\n- Use Docker for stability\n- Set sufficient memory limit\n- Monitor disk space for logs"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "b4a60651-e4ef-4bfd-813c-919f7a46d219",
"connections": {
"c024b1c2-5fc5-42f8-9f41-5de6c9a39a82": {
"main": [
[
{
"node": "e72ef26d-d37a-4d33-a485-cbbb2352554a",
"type": "main",
"index": 0
}
]
]
},
"33f96e3a-8a4b-4260-93d8-75b803fe1d76": {
"main": [
[
{
"node": "74cacc40-b5b7-4939-949c-eaeabef1223f",
"type": "main",
"index": 0
}
]
]
},
"e72ef26d-d37a-4d33-a485-cbbb2352554a": {
"main": [
[
{
"node": "1e132997-bd59-4dce-b2c8-4b60d92aa1ea",
"type": "main",
"index": 0
}
]
]
},
"1e132997-bd59-4dce-b2c8-4b60d92aa1ea": {
"main": [
[
{
"node": "f37bd636-4f38-4300-8909-f16cd91f7423",
"type": "main",
"index": 0
}
]
]
},
"fb16bf68-b431-417f-9443-3bbb2cdd2f2f": {
"main": [
[
{
"node": "33f96e3a-8a4b-4260-93d8-75b803fe1d76",
"type": "main",
"index": 1
}
]
]
},
"a089a86b-fe8e-44b9-8c5e-677018c53b97": {
"main": [
[
{
"node": "33f96e3a-8a4b-4260-93d8-75b803fe1d76",
"type": "main",
"index": 0
}
]
]
},
"8cf99c87-530a-4180-b0f6-4bd53043f07e": {
"main": [
[
{
"node": "8cb2be2c-6718-4d50-a896-fe472f037e22",
"type": "main",
"index": 0
}
]
]
},
"da547149-76e6-455a-970c-3bbe3aa4c0be": {
"main": [
[
{
"node": "c024b1c2-5fc5-42f8-9f41-5de6c9a39a82",
"type": "main",
"index": 0
}
]
]
},
"381e3f06-03ee-4c8c-a2d3-d60798c2ccb7": {
"main": [
[
{
"node": "a089a86b-fe8e-44b9-8c5e-677018c53b97",
"type": "main",
"index": 0
}
],
[
{
"node": "fb16bf68-b431-417f-9443-3bbb2cdd2f2f",
"type": "main",
"index": 0
}
]
]
},
"74cacc40-b5b7-4939-949c-eaeabef1223f": {
"main": [
[
{
"node": "8cf99c87-530a-4180-b0f6-4bd53043f07e",
"type": "main",
"index": 0
}
]
]
},
"f37bd636-4f38-4300-8909-f16cd91f7423": {
"main": [
[
{
"node": "381e3f06-03ee-4c8c-a2d3-d60798c2ccb7",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Intermédiaire - Ingénierie, IA Multimodale
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
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!"
Partager ce workflow