{
  "id": "GgljsaB2JuKMMNl6Y4C4p",
  "name": "Dynamic traffic alarm via Google Maps and Twilio",
  "tags": [],
  "nodes": [
    {
      "id": "3d24e1b2-f320-4245-9c66-bfcfd90c9aee",
      "name": "Check if date is today",
      "type": "n8n-nodes-base.if",
      "position": [
        64,
        16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9a86b36a-dc3d-414c-8c77-17d5e90e7a23",
              "operator": {
                "type": "dateTime",
                "operation": "equals"
              },
              "leftValue": "={{ $json.date }}",
              "rightValue": "={{ $('Get today\\'s date').item.json.date }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "5d0b8c6d-9ba2-4bf5-a0bc-dad5986adeb2",
      "name": "Get date & status of alarm",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -160,
        16
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit?usp=drivesdk",
          "cachedResultName": "Alarm Status"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "340cce90-eece-4a94-b696-010c49b8b122",
      "name": "Update alarm date & status",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        288,
        240
      ],
      "parameters": {
        "columns": {
          "value": {
            "date": "={{ $('Get today\\'s date').item.json.date }}",
            "status": "ini",
            "row_number": 2
          },
          "schema": [
            {
              "id": "date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "44526584-4e1e-4a57-9442-3ece0827e7ac",
      "name": "Get Latitude/Longitude of Origin Address",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        784,
        -192
      ],
      "parameters": {
        "url": "=https://maps.googleapis.com/maps/api/geocode/json?address={{ $json.start_address }}&key=<redacted-credential>",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "e85c214f-b017-4e6f-93dd-de4b334bed2b",
      "name": "Get Latitude/Longitude of End Address",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        784,
        224
      ],
      "parameters": {
        "url": "=https://maps.googleapis.com/maps/api/geocode/json?address={{ $json.end_address }}&key=<redacted-credential>",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "45e8ffbe-34f4-4464-9f4a-30dd6d707b27",
      "name": "Merge all trajectories",
      "type": "n8n-nodes-base.merge",
      "position": [
        1024,
        -16
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "8b7fa748-d09f-4ea7-920f-450dfda9821b",
      "name": "Total duration < 9:00 AM?",
      "type": "n8n-nodes-base.if",
      "position": [
        1680,
        -16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0bcb1f06-76b7-4cef-a0c2-74d594683682",
              "operator": {
                "type": "dateTime",
                "operation": "afterOrEquals"
              },
              "leftValue": "={{\n  $now.plus({\n    seconds: parseInt($json.routes[0].duration, 10) \n  }).toISO()\n}}\n",
              "rightValue": "={{ $now.set({ hour: 9, minute: 00, second: 0, millisecond: 0 }) }}"
            }
          ]
        },
        "looseTypeValidation": "={{ false }}"
      },
      "typeVersion": 2.3
    },
    {
      "id": "0fef8889-4f9b-441e-b7a0-bcdfb23b1ab2",
      "name": "Get real duration between the two addresses",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1360,
        -16
      ],
      "parameters": {
        "url": "https://routes.googleapis.com/directions/v2:computeRoutes",
        "body": "={\n  \"origin\": {\n    \"location\": {\n      \"latLng\": {\n        \"latitude\": {{ $('Get Latitude/Longitude of Origin Address').item.json.results[0].geometry.location.lat }},\n        \"longitude\": {{ $('Get Latitude/Longitude of Origin Address').item.json.results[0].geometry.location.lng }}\n      }\n    }\n  },\n  \"destination\": {\n    \"location\": {\n      \"latLng\": {\n        \"latitude\": {{ $('Get Latitude/Longitude of End Address').item.json.results[0].geometry.location.lat }},\n        \"longitude\": {{ $('Get Latitude/Longitude of End Address').item.json.results[0].geometry.location.lng }}\n      }\n    }\n  },\n  \"travelMode\": \"DRIVE\",\n  \"routingPreference\": \"TRAFFIC_AWARE_OPTIMAL\",\n  \"trafficModel\": \"PESSIMISTIC\",\n  \"departureTime\": \"{{ $now.plus({ minutes: 20 }) }}\"\n}\n",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "X-Goog-Api-Key",
              "value": "AIzaYOUR_GOOGLE_API_KEY_HERE"
            },
            {
              "name": "X-Goog-FieldMask",
              "value": "routes.duration,routes.distanceMeters,routes.polyline.encodedPolyline"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "89288705-706c-4741-a577-d9e71ed33711",
      "name": "Check date & status of alarm",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2016,
        -128
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "9a26afd1-a01e-47ca-9e42-1af16b972be4",
      "name": "Check if status is equal to 'ini'",
      "type": "n8n-nodes-base.if",
      "position": [
        2320,
        -128
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "061e0ba5-9cda-4b3b-b8e5-936c035f7abd",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "ini"
            },
            {
              "id": "20f0c3e6-6303-4e02-9ac9-55e848c0cef0",
              "operator": {
                "type": "dateTime",
                "operation": "equals"
              },
              "leftValue": "={{ $json.date }}",
              "rightValue": "={{ $('Get today\\'s date').item.json.date }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "bff63481-b15d-4457-b005-cdca42ed27e0",
      "name": "Update alarm status",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2960,
        -240
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "end",
            "row_number": 2
          },
          "schema": [
            {
              "id": "date",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/113zCJmMgMftz-SI5qIy19wVObIDnegf4T7bS8hPjrZo/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "837eab33-1a62-4c65-b373-a8720c5a7edf",
      "name": "Send an SMS/MMS/WhatsApp message",
      "type": "n8n-nodes-base.twilio",
      "position": [
        2688,
        -240
      ],
      "parameters": {
        "to": "=",
        "from": "=",
        "message": "Wake Up!",
        "options": {}
      },
      "credentials": {
        "twilioApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cbb3dcb0-a3c9-4e0b-911e-d13e8acf2d45",
      "name": "Define Origin and Destination addresses",
      "type": "n8n-nodes-base.set",
      "position": [
        528,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "6d0a8bc2-d1b4-4b43-8a20-03e21f875208",
              "name": "start_address",
              "type": "string",
              "value": ""
            },
            {
              "id": "e357394f-8d43-4520-a657-4c7613daed5c",
              "name": "end_address",
              "type": "string",
              "value": ""
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "bfcf218b-691c-4dbe-a3b4-bc240f3dda65",
      "name": "Get today's date",
      "type": "n8n-nodes-base.set",
      "position": [
        -448,
        16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c7414348-e46d-4099-9969-7859e5fdae28",
              "name": "date",
              "type": "string",
              "value": "={{ $now.toFormat('yyyy-MM-dd') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "27a57bba-3950-4e3e-99b7-bc4a860f242c",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1472,
        -432
      ],
      "parameters": {
        "width": 540,
        "height": 1080,
        "content": "# \ud83d\ude80 Workflow Overview\nThis automation bridges the gap between your schedule and the unpredictable reality of morning traffic.\n\nHow it works:\nSchedule Check: The workflow triggers every morning starting at an hour of your choice and checks whether it is time to wake up to be on time at your work, school, etc..\n\nTraffic Analysis: Using the Google Maps Distance Matrix API, it calculates the current travel time between your home and destination based on real-time congestion.\n\nNotification: Once the time matches, Twilio sends a SMS to your iPhone.\n\n(Optional) Device Trigger: An iOS Shortcut detects the specific phrase in the SMS (e.g., \"Wake up!\") and triggers a physical alarm or Focus mode on your phone.\n\n\n\n# \ud83d\udee0\ufe0f Configuration Requirements\n1. Google Sheets Setup\nCreate a spreadsheet with the following columns to act as the \"status\" of your schedule:\n\nDate: The day of the event (YYYY-MM-DD).\n\nStatus: Use ini for the start time of your work/school and end for the finish time.\n\n2. Google Maps API\nYou will need a Google Cloud Project with the Distance Matrix API enabled. This provides the \"duration_in_traffic\" value, which is more accurate than a standard distance calculation.\n\n3. Twilio Integration\nInput your Account SID, Auth Token, and \"From\" number. The \"To\" number should be your personal mobile device.\n\n4. iPhone Automation (Shortcuts App) - Optional\nTo make this \"fully automated,\" set up a Personal Automation on your iPhone:\n\nTrigger: \"When I receive a message containing 'Wake up!'\"\n\nAction: \"Set Alarm\"\n\nThank me later for waking up on time! -- Yorgo Haber"
      },
      "typeVersion": 1
    },
    {
      "id": "2889ec4a-b196-44a9-86da-962908013452",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        -384
      ],
      "parameters": {
        "color": 7,
        "width": 688,
        "height": 791,
        "content": "## The origin and destination addresses to be filled based on your preferences\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f296b955-f5db-44a2-b182-a416c0f88071",
      "name": "Triggers at 7 AM till 8 AM every minute on weekdays ",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -752,
        16
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "* 7 * * 1-5"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "2bcb5c4c-6bb3-4998-9f71-4181d99880eb",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1568,
        -368
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 663,
        "content": "## Time to be at the destination location. To be filled based on your preferences\n"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "ef397889-e9ce-4e23-9cfc-78044d759d56",
  "connections": {
    "Get today's date": {
      "main": [
        [
          {
            "node": "Get date & status of alarm",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if date is today": {
      "main": [
        [
          {
            "node": "Define Origin and Destination addresses",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update alarm date & status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge all trajectories": {
      "main": [
        [
          {
            "node": "Get real duration between the two addresses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Total duration < 9:00 AM?": {
      "main": [
        [
          {
            "node": "Check date & status of alarm",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get date & status of alarm": {
      "main": [
        [
          {
            "node": "Check if date is today",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update alarm date & status": {
      "main": [
        [
          {
            "node": "Define Origin and Destination addresses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check date & status of alarm": {
      "main": [
        [
          {
            "node": "Check if status is equal to 'ini'",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send an SMS/MMS/WhatsApp message": {
      "main": [
        [
          {
            "node": "Update alarm status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if status is equal to 'ini'": {
      "main": [
        [
          {
            "node": "Send an SMS/MMS/WhatsApp message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Latitude/Longitude of End Address": {
      "main": [
        [
          {
            "node": "Merge all trajectories",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Define Origin and Destination addresses": {
      "main": [
        [
          {
            "node": "Get Latitude/Longitude of End Address",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Latitude/Longitude of Origin Address",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Latitude/Longitude of Origin Address": {
      "main": [
        [
          {
            "node": "Merge all trajectories",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get real duration between the two addresses": {
      "main": [
        [
          {
            "node": "Total duration < 9:00 AM?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Triggers at 7 AM till 8 AM every minute on weekdays ": {
      "main": [
        [
          {
            "node": "Get today's date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}