From 8c0e3b51cc6782dd0f03290edfd2c7e9f6d95e81 Mon Sep 17 00:00:00 2001 From: gitea Date: Mon, 1 Jan 2001 00:00:00 +0000 Subject: [PATCH] Add Muscle Building Analyzer.json --- Muscle Building Analyzer.json | 1350 +++++++++++++++++++++++++++++++++ 1 file changed, 1350 insertions(+) create mode 100644 Muscle Building Analyzer.json diff --git a/Muscle Building Analyzer.json b/Muscle Building Analyzer.json new file mode 100644 index 0000000..3635e2e --- /dev/null +++ b/Muscle Building Analyzer.json @@ -0,0 +1,1350 @@ +{ + "updatedAt": "2026-04-03T16:02:46.397Z", + "createdAt": "2026-04-03T13:37:06.873Z", + "id": "D5vTBspoT8Ag5q67", + "name": "Muscle Building Analyzer", + "active": true, + "isArchived": false, + "nodes": [ + { + "parameters": {}, + "id": "manual-id-001", + "name": "ManualTrigger", + "position": [ + 0, + 144 + ], + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1 + }, + { + "parameters": { + "values": { + "string": [ + { + "name": "folder_id", + "value": "18Bhudb1KaJdJnIw-z0US2p8ScJjiliTo" + }, + { + "name": "ha_weight_entity", + "value": "sensor.prasanna_weight_correct" + } + ] + }, + "options": {} + }, + "id": "config-id-001", + "name": "Config", + "position": [ + 208, + 144 + ], + "type": "n8n-nodes-base.set", + "typeVersion": 1 + }, + { + "parameters": { + "rule": { + "interval": [ + { + "field": "weeks", + "triggerAtDay": [ + 1 + ], + "triggerAtHour": 9 + } + ] + } + }, + "id": "node-schedule-001", + "name": "Every Monday Morning", + "type": "n8n-nodes-base.scheduleTrigger", + "typeVersion": 1.3, + "position": [ + 0, + 0 + ] + }, + { + "parameters": { + "authentication": "serviceAccount", + "resource": "fileFolder", + "queryString": "strong", + "filter": {}, + "options": {} + }, + "id": "node-drive-list-001", + "name": "Sync: List CSVs", + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 400, + -208 + ], + "credentials": { + "googleApi": { + "id": "BHZe7DHLZJ4mRYHz", + "name": "Google Service Account account" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT file_id FROM processed_files WHERE file_id = $1", + "options": { + "queryReplacement": "={{ [$json.id] }}" + } + }, + "id": "node-pg-check-001", + "name": "Check if Processed", + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 608, + -208 + ], + "alwaysOutputData": true, + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 3 + }, + "conditions": [ + { + "id": "condition-file-id-empty", + "leftValue": "={{ $json.file_id }}", + "operator": { + "operation": "empty", + "type": "string", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "id": "node-if-new-001", + "name": "Is New File?", + "type": "n8n-nodes-base.if", + "typeVersion": 2.3, + "position": [ + 800, + -208 + ] + }, + { + "parameters": { + "authentication": "serviceAccount", + "operation": "download", + "fileId": "={{ $node[\"Sync: List CSVs\"].json[\"id\"] }}", + "options": {} + }, + "id": "node-drive-download-001", + "name": "Download File", + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 1008, + -304 + ], + "credentials": { + "googleApi": { + "id": "BHZe7DHLZJ4mRYHz", + "name": "Google Service Account account" + } + } + }, + { + "parameters": { + "fileFormat": "csv", + "options": { + "delimiter": ";", + "readAsString": true + } + }, + "id": "node-spreadsheet-001", + "name": "CSV to JSON", + "type": "n8n-nodes-base.spreadsheetFile", + "typeVersion": 2, + "position": [ + 1200, + -304 + ] + }, + { + "parameters": { + "values": { + "number": [ + { + "name": "set_order", + "value": "={{ parseInt($json[\"Set Order\"]) || 0 }}" + }, + { + "name": "weight", + "value": "={{ parseFloat($json[\"Weight\"]) || 0 }}" + }, + { + "name": "reps", + "value": "={{ parseInt($json[\"Reps\"]) || 0 }}" + } + ], + "string": [ + { + "name": "workout_date", + "value": "={{ $json[\"Date\"] }}" + }, + { + "name": "exercise_name", + "value": "={{ $json[\"Exercise Name\"] }}" + }, + { + "name": "duration", + "value": "={{ $json[\"Workout Duration\"] }}" + } + ] + }, + "options": {} + }, + "id": "node-set-format-001", + "name": "Format Rows", + "type": "n8n-nodes-base.set", + "typeVersion": 1, + "position": [ + 1408, + -304 + ] + }, + { + "parameters": { + "operation": "executeQuery", + "query": "INSERT INTO gym_results (workout_date, exercise_name, set_order, weight, reps, duration) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (workout_date, exercise_name, set_order) DO UPDATE SET weight = EXCLUDED.weight, reps = EXCLUDED.reps", + "options": { + "queryBatching": "independently", + "queryReplacement": "={{ [$json.workout_date, $json.exercise_name, $json.set_order, $json.weight, $json.reps, $json.duration] }}" + } + }, + "id": "node-pg-upsert-001", + "name": "Upsert Results", + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1600, + -304 + ], + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "INSERT INTO processed_files (file_id, file_name) VALUES ($1, $2) ON CONFLICT (file_id) DO NOTHING", + "options": { + "queryReplacement": "={{ [$json.id, $json.name] }}" + } + }, + "id": "node-pg-mark-001", + "name": "Mark Processed", + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1808, + -304 + ], + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT * FROM gym_results WHERE workout_date >= (CURRENT_DATE - INTERVAL '14 days') ORDER BY workout_date DESC;", + "additionalFields": {} + }, + "id": "node-pg-fetch-001", + "name": "Fetch 14d Workouts", + "type": "n8n-nodes-base.postgres", + "typeVersion": 1, + "position": [ + 400, + 208 + ], + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "jsonBody": "={{ JSON.stringify({ entity_id: 'input_text.n8n_summary', value: $json.content.parts[0].text.slice(0, 255) }) }}", + "method": "POST", + "options": {}, + "sendBody": true, + "specifyBody": "json", + "url": "http://192.168.178.111:8123/api/services/input_text/set_value" + }, + "id": "node-ha-notify-001", + "name": "HA Set Summary", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 1152, + 304 + ], + "credentials": { + "httpHeaderAuth": { + "id": "OBwOm2Ixqr6biMwc", + "name": "homeAssistant" + } + } + }, + { + "parameters": { + "messages": { + "values": [ + { + "content": "=You are a fitness coach. Analyze the last 14 days.\n\nWORKOUT DATA:\n{{ JSON.stringify($json.workouts) }}\n\nWEIGHT (kg, chronological):\n{{ JSON.stringify($json.weights) }}\n\nRespond with EXACTLY 3 lines, each starting with a bullet (•). Total must be under 255 characters.\nLine 1: Weight trend + body composition estimate (muscle/fat gain or fat loss).\nLine 2: Top training focus for next weeks.\nLine 3: Top nutrition focus for next weeks.\nNo markdown, no bold, no extra text." + } + ] + }, + "modelId": { + "__rl": true, + "cachedResultName": "Gemini 2.5 Flash (Guideline)", + "mode": "list", + "value": "models/gemini-2.5-flash" + } + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 864, + 304 + ], + "id": "f8489e65-7ea1-4fea-b1d3-0df0824479de", + "name": "Message a model", + "credentials": { + "googlePalmApi": { + "id": "EWlC0h6CFPDYaxlJ", + "name": "Google Gemini(PaLM) Api account" + } + } + }, + { + "parameters": { + "jsCode": "const workouts = $items(\"Fetch 14d Workouts\");\nconst weightRaw = $items(\"Get Weight History\");\n\n// HA history API returns [[{state, last_changed, ...}, ...]]\nlet weights = [];\ntry {\n if (weightRaw.length > 0) {\n const firstJson = weightRaw[0].json;\n if (Array.isArray(firstJson) && firstJson.length > 0 && Array.isArray(firstJson[0])) {\n weights = firstJson[0].map(item => ({\n state: item.state,\n last_changed: item.last_changed\n })).filter(w => w.state !== 'unavailable' && w.state !== 'unknown');\n } else if (Array.isArray(firstJson)) {\n weights = firstJson.map(item => ({\n state: item.state,\n last_changed: item.last_changed\n })).filter(w => w.state !== 'unavailable' && w.state !== 'unknown');\n }\n }\n} catch(e) {\n weights = [];\n}\n\nreturn [{\n json: {\n workouts: workouts.map(i => i.json),\n weights: weights\n }\n}];" + }, + "id": "code-agg-001", + "name": "Prepare Analysis Data", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 704, + 304 + ], + "executeOnce": true + }, + { + "parameters": { + "path": "trigger-muscle-now", + "options": {} + }, + "id": "547435b3-0c02-4efe-89ba-c65ea8359cf5", + "name": "TriggerWebhook", + "type": "n8n-nodes-base.webhook", + "typeVersion": 2.1, + "position": [ + 0, + 288 + ], + "webhookId": "c376190f-52c2-4586-ad8e-31501d60aa5b" + }, + { + "parameters": { + "mode": "chooseBranch" + }, + "id": "merge-wait-001", + "name": "Wait for Upsert", + "type": "n8n-nodes-base.merge", + "typeVersion": 3.2, + "position": [ + 1712, + -144 + ] + }, + { + "parameters": {}, + "id": "merge-analysis-001", + "name": "Analysis Merge", + "type": "n8n-nodes-base.merge", + "typeVersion": 3.2, + "position": [ + 560, + 304 + ] + }, + { + "parameters": { + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "options": { + "response": { + "response": { + "neverError": true + } + } + }, + "queryParameters": { + "parameters": [ + { + "name": "filter_entity_id", + "value": "sensor.prasanna_weight_correct" + }, + { + "name": "minimal_response", + "value": "true" + }, + { + "name": "end_time", + "value": "={{ $now.toISO() }}" + } + ] + }, + "sendQuery": true, + "url": "={{ 'http://192.168.178.111:8123/api/history/period/' + $now.minus({days: 14}).toISO() }}" + }, + "id": "node-ha-history-001", + "name": "Get Weight History", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 400, + 352 + ], + "credentials": { + "httpHeaderAuth": { + "id": "OBwOm2Ixqr6biMwc", + "name": "homeAssistant" + } + } + } + ], + "connections": { + "ManualTrigger": { + "main": [ + [ + { + "index": 0, + "node": "Config", + "type": "main" + } + ] + ] + }, + "Every Monday Morning": { + "main": [ + [ + { + "node": "Config", + "type": "main", + "index": 0 + } + ] + ] + }, + "Config": { + "main": [ + [ + { + "node": "Sync: List CSVs", + "type": "main", + "index": 0 + }, + { + "node": "Fetch 14d Workouts", + "type": "main", + "index": 0 + }, + { + "node": "Get Weight History", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sync: List CSVs": { + "main": [ + [ + { + "node": "Check if Processed", + "type": "main", + "index": 0 + }, + { + "node": "Wait for Upsert", + "type": "main", + "index": 0 + } + ] + ] + }, + "Check if Processed": { + "main": [ + [ + { + "node": "Is New File?", + "type": "main", + "index": 0 + } + ] + ] + }, + "Is New File?": { + "main": [ + [ + { + "node": "Download File", + "type": "main", + "index": 0 + } + ] + ] + }, + "Download File": { + "main": [ + [ + { + "node": "CSV to JSON", + "type": "main", + "index": 0 + } + ] + ] + }, + "CSV to JSON": { + "main": [ + [ + { + "node": "Format Rows", + "type": "main", + "index": 0 + } + ] + ] + }, + "Format Rows": { + "main": [ + [ + { + "node": "Upsert Results", + "type": "main", + "index": 0 + } + ] + ] + }, + "Message a model": { + "main": [ + [ + { + "node": "HA Set Summary", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare Analysis Data": { + "main": [ + [ + { + "node": "Message a model", + "type": "main", + "index": 0 + } + ] + ] + }, + "TriggerWebhook": { + "main": [ + [ + { + "node": "Config", + "type": "main", + "index": 0 + } + ] + ] + }, + "Upsert Results": { + "main": [ + [ + { + "node": "Wait for Upsert", + "type": "main", + "index": 1 + } + ] + ] + }, + "Wait for Upsert": { + "main": [ + [ + { + "node": "Mark Processed", + "type": "main", + "index": 0 + } + ] + ] + }, + "Fetch 14d Workouts": { + "main": [ + [ + { + "node": "Analysis Merge", + "type": "main", + "index": 0 + } + ] + ] + }, + "Analysis Merge": { + "main": [ + [ + { + "node": "Prepare Analysis Data", + "type": "main", + "index": 0 + } + ] + ] + }, + "Get Weight History": { + "main": [ + [ + { + "node": "Analysis Merge", + "type": "main", + "index": 1 + } + ] + ] + } + }, + "settings": { + "executionOrder": "v1", + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all", + "saveManualExecutions": true, + "saveExecutionProgress": true, + "callerPolicy": "workflowsFromSameOwner", + "availableInMCP": false, + "binaryMode": "separate" + }, + "staticData": { + "node:Every Monday Morning": { + "recurrenceRules": [] + } + }, + "meta": { + "templateCredsSetupCompleted": true + }, + "pinData": {}, + "versionId": "9c73e87e-c0f8-4073-ae2e-cf3484bcc550", + "activeVersionId": "9c73e87e-c0f8-4073-ae2e-cf3484bcc550", + "triggerCount": 2, + "shared": [ + { + "updatedAt": "2026-04-03T13:37:06.876Z", + "createdAt": "2026-04-03T13:37:06.876Z", + "role": "workflow:owner", + "workflowId": "D5vTBspoT8Ag5q67", + "projectId": "cSAaWNJydnksD5EB" + } + ], + "activeVersion": { + "updatedAt": "2026-04-03T16:02:46.398Z", + "createdAt": "2026-04-03T16:02:46.398Z", + "versionId": "9c73e87e-c0f8-4073-ae2e-cf3484bcc550", + "workflowId": "D5vTBspoT8Ag5q67", + "nodes": [ + { + "parameters": {}, + "id": "manual-id-001", + "name": "ManualTrigger", + "position": [ + 0, + 144 + ], + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1 + }, + { + "parameters": { + "values": { + "string": [ + { + "name": "folder_id", + "value": "18Bhudb1KaJdJnIw-z0US2p8ScJjiliTo" + }, + { + "name": "ha_weight_entity", + "value": "sensor.prasanna_weight_correct" + } + ] + }, + "options": {} + }, + "id": "config-id-001", + "name": "Config", + "position": [ + 208, + 144 + ], + "type": "n8n-nodes-base.set", + "typeVersion": 1 + }, + { + "parameters": { + "rule": { + "interval": [ + { + "field": "weeks", + "triggerAtDay": [ + 1 + ], + "triggerAtHour": 9 + } + ] + } + }, + "id": "node-schedule-001", + "name": "Every Monday Morning", + "type": "n8n-nodes-base.scheduleTrigger", + "typeVersion": 1.3, + "position": [ + 0, + 0 + ] + }, + { + "parameters": { + "authentication": "serviceAccount", + "resource": "fileFolder", + "queryString": "strong", + "filter": {}, + "options": {} + }, + "id": "node-drive-list-001", + "name": "Sync: List CSVs", + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 400, + -208 + ], + "credentials": { + "googleApi": { + "id": "BHZe7DHLZJ4mRYHz", + "name": "Google Service Account account" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT file_id FROM processed_files WHERE file_id = $1", + "options": { + "queryReplacement": "={{ [$json.id] }}" + } + }, + "id": "node-pg-check-001", + "name": "Check if Processed", + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 608, + -208 + ], + "alwaysOutputData": true, + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 3 + }, + "conditions": [ + { + "id": "condition-file-id-empty", + "leftValue": "={{ $json.file_id }}", + "operator": { + "operation": "empty", + "type": "string", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "id": "node-if-new-001", + "name": "Is New File?", + "type": "n8n-nodes-base.if", + "typeVersion": 2.3, + "position": [ + 800, + -208 + ] + }, + { + "parameters": { + "authentication": "serviceAccount", + "operation": "download", + "fileId": "={{ $node[\"Sync: List CSVs\"].json[\"id\"] }}", + "options": {} + }, + "id": "node-drive-download-001", + "name": "Download File", + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 1008, + -304 + ], + "credentials": { + "googleApi": { + "id": "BHZe7DHLZJ4mRYHz", + "name": "Google Service Account account" + } + } + }, + { + "parameters": { + "fileFormat": "csv", + "options": { + "delimiter": ";", + "readAsString": true + } + }, + "id": "node-spreadsheet-001", + "name": "CSV to JSON", + "type": "n8n-nodes-base.spreadsheetFile", + "typeVersion": 2, + "position": [ + 1200, + -304 + ] + }, + { + "parameters": { + "values": { + "number": [ + { + "name": "set_order", + "value": "={{ parseInt($json[\"Set Order\"]) || 0 }}" + }, + { + "name": "weight", + "value": "={{ parseFloat($json[\"Weight\"]) || 0 }}" + }, + { + "name": "reps", + "value": "={{ parseInt($json[\"Reps\"]) || 0 }}" + } + ], + "string": [ + { + "name": "workout_date", + "value": "={{ $json[\"Date\"] }}" + }, + { + "name": "exercise_name", + "value": "={{ $json[\"Exercise Name\"] }}" + }, + { + "name": "duration", + "value": "={{ $json[\"Workout Duration\"] }}" + } + ] + }, + "options": {} + }, + "id": "node-set-format-001", + "name": "Format Rows", + "type": "n8n-nodes-base.set", + "typeVersion": 1, + "position": [ + 1408, + -304 + ] + }, + { + "parameters": { + "operation": "executeQuery", + "query": "INSERT INTO gym_results (workout_date, exercise_name, set_order, weight, reps, duration) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (workout_date, exercise_name, set_order) DO UPDATE SET weight = EXCLUDED.weight, reps = EXCLUDED.reps", + "options": { + "queryBatching": "independently", + "queryReplacement": "={{ [$json.workout_date, $json.exercise_name, $json.set_order, $json.weight, $json.reps, $json.duration] }}" + } + }, + "id": "node-pg-upsert-001", + "name": "Upsert Results", + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1600, + -304 + ], + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "INSERT INTO processed_files (file_id, file_name) VALUES ($1, $2) ON CONFLICT (file_id) DO NOTHING", + "options": { + "queryReplacement": "={{ [$json.id, $json.name] }}" + } + }, + "id": "node-pg-mark-001", + "name": "Mark Processed", + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1808, + -304 + ], + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT * FROM gym_results WHERE workout_date >= (CURRENT_DATE - INTERVAL '14 days') ORDER BY workout_date DESC;", + "additionalFields": {} + }, + "id": "node-pg-fetch-001", + "name": "Fetch 14d Workouts", + "type": "n8n-nodes-base.postgres", + "typeVersion": 1, + "position": [ + 400, + 208 + ], + "credentials": { + "postgres": { + "id": "VyZORXHG4fXznguO", + "name": "Postgres account" + } + } + }, + { + "parameters": { + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "jsonBody": "={{ JSON.stringify({ entity_id: 'input_text.n8n_summary', value: $json.content.parts[0].text.slice(0, 255) }) }}", + "method": "POST", + "options": {}, + "sendBody": true, + "specifyBody": "json", + "url": "http://192.168.178.111:8123/api/services/input_text/set_value" + }, + "id": "node-ha-notify-001", + "name": "HA Set Summary", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 1152, + 304 + ], + "credentials": { + "httpHeaderAuth": { + "id": "OBwOm2Ixqr6biMwc", + "name": "homeAssistant" + } + } + }, + { + "parameters": { + "messages": { + "values": [ + { + "content": "=You are a fitness coach. Analyze the last 14 days.\n\nWORKOUT DATA:\n{{ JSON.stringify($json.workouts) }}\n\nWEIGHT (kg, chronological):\n{{ JSON.stringify($json.weights) }}\n\nRespond with EXACTLY 3 lines, each starting with a bullet (•). Total must be under 255 characters.\nLine 1: Weight trend + body composition estimate (muscle/fat gain or fat loss).\nLine 2: Top training focus for next weeks.\nLine 3: Top nutrition focus for next weeks.\nNo markdown, no bold, no extra text." + } + ] + }, + "modelId": { + "__rl": true, + "cachedResultName": "Gemini 2.5 Flash (Guideline)", + "mode": "list", + "value": "models/gemini-2.5-flash" + } + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 864, + 304 + ], + "id": "f8489e65-7ea1-4fea-b1d3-0df0824479de", + "name": "Message a model", + "credentials": { + "googlePalmApi": { + "id": "EWlC0h6CFPDYaxlJ", + "name": "Google Gemini(PaLM) Api account" + } + } + }, + { + "parameters": { + "jsCode": "const workouts = $items(\"Fetch 14d Workouts\");\nconst weightRaw = $items(\"Get Weight History\");\n\n// HA history API returns [[{state, last_changed, ...}, ...]]\nlet weights = [];\ntry {\n if (weightRaw.length > 0) {\n const firstJson = weightRaw[0].json;\n if (Array.isArray(firstJson) && firstJson.length > 0 && Array.isArray(firstJson[0])) {\n weights = firstJson[0].map(item => ({\n state: item.state,\n last_changed: item.last_changed\n })).filter(w => w.state !== 'unavailable' && w.state !== 'unknown');\n } else if (Array.isArray(firstJson)) {\n weights = firstJson.map(item => ({\n state: item.state,\n last_changed: item.last_changed\n })).filter(w => w.state !== 'unavailable' && w.state !== 'unknown');\n }\n }\n} catch(e) {\n weights = [];\n}\n\nreturn [{\n json: {\n workouts: workouts.map(i => i.json),\n weights: weights\n }\n}];" + }, + "id": "code-agg-001", + "name": "Prepare Analysis Data", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 704, + 304 + ], + "executeOnce": true + }, + { + "parameters": { + "path": "trigger-muscle-now", + "options": {} + }, + "id": "547435b3-0c02-4efe-89ba-c65ea8359cf5", + "name": "TriggerWebhook", + "type": "n8n-nodes-base.webhook", + "typeVersion": 2.1, + "position": [ + 0, + 288 + ], + "webhookId": "c376190f-52c2-4586-ad8e-31501d60aa5b" + }, + { + "parameters": { + "mode": "chooseBranch" + }, + "id": "merge-wait-001", + "name": "Wait for Upsert", + "type": "n8n-nodes-base.merge", + "typeVersion": 3.2, + "position": [ + 1712, + -144 + ] + }, + { + "parameters": {}, + "id": "merge-analysis-001", + "name": "Analysis Merge", + "type": "n8n-nodes-base.merge", + "typeVersion": 3.2, + "position": [ + 560, + 304 + ] + }, + { + "parameters": { + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "options": { + "response": { + "response": { + "neverError": true + } + } + }, + "queryParameters": { + "parameters": [ + { + "name": "filter_entity_id", + "value": "sensor.prasanna_weight_correct" + }, + { + "name": "minimal_response", + "value": "true" + }, + { + "name": "end_time", + "value": "={{ $now.toISO() }}" + } + ] + }, + "sendQuery": true, + "url": "={{ 'http://192.168.178.111:8123/api/history/period/' + $now.minus({days: 14}).toISO() }}" + }, + "id": "node-ha-history-001", + "name": "Get Weight History", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 400, + 352 + ], + "credentials": { + "httpHeaderAuth": { + "id": "OBwOm2Ixqr6biMwc", + "name": "homeAssistant" + } + } + } + ], + "connections": { + "ManualTrigger": { + "main": [ + [ + { + "index": 0, + "node": "Config", + "type": "main" + } + ] + ] + }, + "Every Monday Morning": { + "main": [ + [ + { + "node": "Config", + "type": "main", + "index": 0 + } + ] + ] + }, + "Config": { + "main": [ + [ + { + "node": "Sync: List CSVs", + "type": "main", + "index": 0 + }, + { + "node": "Fetch 14d Workouts", + "type": "main", + "index": 0 + }, + { + "node": "Get Weight History", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sync: List CSVs": { + "main": [ + [ + { + "node": "Check if Processed", + "type": "main", + "index": 0 + }, + { + "node": "Wait for Upsert", + "type": "main", + "index": 0 + } + ] + ] + }, + "Check if Processed": { + "main": [ + [ + { + "node": "Is New File?", + "type": "main", + "index": 0 + } + ] + ] + }, + "Is New File?": { + "main": [ + [ + { + "node": "Download File", + "type": "main", + "index": 0 + } + ] + ] + }, + "Download File": { + "main": [ + [ + { + "node": "CSV to JSON", + "type": "main", + "index": 0 + } + ] + ] + }, + "CSV to JSON": { + "main": [ + [ + { + "node": "Format Rows", + "type": "main", + "index": 0 + } + ] + ] + }, + "Format Rows": { + "main": [ + [ + { + "node": "Upsert Results", + "type": "main", + "index": 0 + } + ] + ] + }, + "Message a model": { + "main": [ + [ + { + "node": "HA Set Summary", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare Analysis Data": { + "main": [ + [ + { + "node": "Message a model", + "type": "main", + "index": 0 + } + ] + ] + }, + "TriggerWebhook": { + "main": [ + [ + { + "node": "Config", + "type": "main", + "index": 0 + } + ] + ] + }, + "Upsert Results": { + "main": [ + [ + { + "node": "Wait for Upsert", + "type": "main", + "index": 1 + } + ] + ] + }, + "Wait for Upsert": { + "main": [ + [ + { + "node": "Mark Processed", + "type": "main", + "index": 0 + } + ] + ] + }, + "Fetch 14d Workouts": { + "main": [ + [ + { + "node": "Analysis Merge", + "type": "main", + "index": 0 + } + ] + ] + }, + "Analysis Merge": { + "main": [ + [ + { + "node": "Prepare Analysis Data", + "type": "main", + "index": 0 + } + ] + ] + }, + "Get Weight History": { + "main": [ + [ + { + "node": "Analysis Merge", + "type": "main", + "index": 1 + } + ] + ] + } + }, + "authors": "Prasanna Ranjan", + "name": null, + "description": null, + "autosaved": false + }, + "tags": [] +} \ No newline at end of file