# sendToInternet Example - WhatsApp/Callmebot Integration

This example demonstrates how to use `mesh.sendToInternet()` to send data to Internet endpoints (like WhatsApp via Callmebot) from **any node** in the mesh network.

## ⚠️ Important: Understanding sendToInternet()

Regular mesh nodes do **NOT** have direct IP routing to the Internet. The `sendToInternet()` API routes your data **through a gateway node** that has Internet access.

```
┌─────────────┐                    ┌─────────────┐                    ┌─────────────┐
│ Sensor Node │ ──sendToInternet──▶│   Gateway   │ ──HTTP Request──▶  │  Internet   │
│  (no WiFi)  │                    │ (has WiFi)  │                    │  (Callmebot)│
└─────────────┘                    └─────────────┘                    └─────────────┘
       ▲                                  │                                  │
       │                                  │                                  │
       └──────────── ACK/Result ◀─────────┴──────────── HTTP Response ◀──────┘
```

**This is different from making direct HTTP requests** (which would fail on regular mesh nodes with "connection refused").

## Use Cases

- 🐟 **Fish farm sensors** sending O2 alarms to WhatsApp
- 🏭 **Industrial IoT** sending alerts to cloud APIs
- 🏠 **Smart home sensors** reporting to home automation servers
- 📊 **Remote monitoring** sending data to ThingsBoard, AWS IoT, etc.

## Prerequisites

1. **At least one node must be a bridge/gateway** with Internet access
2. **OR** use `initAsSharedGateway()` so all nodes have Internet
3. Enable the API after mesh init: `mesh.enableSendToInternet()`

## Setup for Callmebot WhatsApp

1. Get your API key from: https://www.callmebot.com/blog/free-api-whatsapp-messages/
2. Update the configuration in the sketch:

```cpp
#define WHATSAPP_PHONE  "+1234567890"    // Your phone with country code
#define WHATSAPP_APIKEY "your_api_key"   // Your Callmebot API key
```

## API Usage

### Basic Usage

```cpp
// Check if Internet is available via any gateway
if (mesh.hasInternetConnection()) {
  
  // Send data to Internet - routed through gateway automatically
  uint32_t msgId = mesh.sendToInternet(
    "https://api.callmebot.com/whatsapp.php?phone=+1234567890&apikey=KEY&text=Hello",
    "",  // Empty payload for GET (params in URL)
    [](bool success, uint16_t httpStatus, String error) {
      if (success) {
        Serial.printf("✅ Sent! HTTP: %d\n", httpStatus);
      } else {
        Serial.printf("❌ Failed: %s\n", error.c_str());
      }
    }
  );
}
```

### Sending JSON to REST API

```cpp
String payload = "{\"temperature\": 25.5, \"humidity\": 60}";

mesh.sendToInternet(
  "https://api.yourserver.com/sensors",
  payload,
  [](bool success, uint16_t httpStatus, String error) {
    Serial.printf("Result: %s, HTTP: %d\n", 
                  success ? "OK" : error.c_str(), httpStatus);
  },
  static_cast<uint8_t>(painlessmesh::gateway::GatewayPriority::PRIORITY_HIGH)
);
```

### Priority Levels

| Value | Enum | Use Case |
|-------|------|----------|
| 0 | `PRIORITY_CRITICAL` | Alarms, emergencies |
| 1 | `PRIORITY_HIGH` | Important alerts |
| 2 | `PRIORITY_NORMAL` | Regular sensor data |
| 3 | `PRIORITY_LOW` | Bulk/background data |

## Hardware Setup

### Option A: Bridge + Sensor Nodes

**Bridge Node** (has Internet):
```cpp
#define IS_BRIDGE_NODE true
// Update ROUTER_SSID and ROUTER_PASSWORD
```

**Sensor Nodes** (no direct Internet):
```cpp
#define IS_BRIDGE_NODE false
```

### Option B: Shared Gateway Mode

All nodes connect to the same router:
```cpp
mesh.initAsSharedGateway(
  MESH_PREFIX, MESH_PASSWORD,
  ROUTER_SSID, ROUTER_PASSWORD,  // Router credentials required!
  &userScheduler, MESH_PORT
);
mesh.enableSendToInternet();
```

## Common Issues

### "No Internet available - no gateway with Internet found"

- Make sure at least one node is initialized as a bridge with router credentials
- Check that the bridge has successfully connected to the router
- Use `mesh.hasInternetConnection()` to verify gateway availability

### "connection refused" when using HTTPClient directly

**DON'T do this on regular mesh nodes:**
```cpp
// This FAILS on regular mesh nodes!
HTTPClient http;
http.begin("https://api.callmebot.com/...");
```

**DO this instead:**
```cpp
// This works - routes through gateway
mesh.sendToInternet("https://api.callmebot.com/...", "", callback);
```

### WhatsApp message not received

1. Verify your Callmebot API key is correct
2. Ensure phone number includes country code (e.g., `+1234567890`)
3. Check HTTP status code in callback (200 = success)
4. URL-encode special characters in the message

### Gateway shows "no internet access" but WiFi is connected

**Symptom:** Error message "Router has no internet access - check WAN connection"

**Cause:** The gateway node is connected to WiFi but the router itself has no internet connectivity. This is detected through DNS resolution testing.

**Solutions:**
1. **Check router WAN connection:**
   - Verify router's internet LED indicator
   - Check router's WAN port cable connection
   - Ensure modem is powered and connected

2. **Check ISP service:**
   - Verify your internet service is active
   - Test internet on other devices connected to same router
   - Contact ISP if service is down

3. **Router configuration:**
   - Verify router has obtained WAN IP address
   - Check router's internet connection status page
   - Restart router if necessary

**Technical Details:**
The gateway performs two connectivity checks:
1. `WiFi.status() == WL_CONNECTED` - Verifies WiFi association
2. DNS resolution test - Verifies actual internet routing

If WiFi is connected but DNS fails, it indicates the router has no upstream internet connection. This prevents unnecessary HTTP request timeouts and provides early error detection.

### Understanding HTTP Status Codes

The callback provides `httpStatus` to indicate the result:

**SUCCESS (success = true):**
- `200 OK` - Standard success (most common for WhatsApp API)
- `201 Created` - Resource successfully created
- `202 Accepted` - Request accepted for processing
- `204 No Content` - Successful with no response body

**FAILURE (success = false):**
- `203 Non-Authoritative Information` - **Cached/proxied response, NOT actual delivery**
- `4xx` - Client error (bad request, unauthorized, not found, etc.)
- `5xx` - Server error (service unavailable, gateway timeout, etc.)

⚠️ **Important:** HTTP 203 is treated as **FAILURE** because it indicates the response came from a cache or proxy, not from the actual WhatsApp API server. If you see `HTTP Status: 203`, the message was **NOT delivered**.

## Files

- `sendToInternet.ino` - Main example sketch
- `README.md` - This documentation

## Related Examples

- [sharedGateway](../sharedGateway/) - All nodes with direct Internet access
- [bridge_failover](../bridge_failover/) - Automatic gateway failover
- [mqttBridge](../mqttBridge/) - MQTT integration
