Collection of articles for working with Multitech devices in LoRaWAN networks.
The MTS Device WAN Manager provides automatic failover and load balancing across multiple WAN interfaces, ensuring continuous connectivity even when primary connections fail.
Configuration:
GET /api?fields=wanmngr # Get WAN manager configuration
PUT /api/wanmngr # Update WAN manager configuration
Status:
GET /api?fields=waninfo # Get current WAN status
# Login
curl -k -X POST https://gateway-ip/api/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"your-password"}' \
-c cookies.txt
# Get WAN status
curl -k -s "https://gateway-ip/api?fields=waninfo" -b cookies.txt | jq .
Example Response:
{
"code": 200,
"status": "success",
"result": {
"waninfo": {
"wans": [
{
"interface": "eth0",
"name": "eth0",
"type": "ETHERNET",
"ip": "172.16.33.111",
"subnet": "255.255.0.0",
"gateway": "",
"enabled": true,
"available": true,
"current": true
},
{
"interface": "ppp0",
"name": "ppp0",
"type": "CELLULAR",
"ip": "",
"enabled": true,
"available": true,
"current": false
}
]
}
}
}
Key Fields:
enabled: Interface is configured for WANavailable: Interface passed health checkscurrent: Interface is currently active for routingcurl -k -s "https://gateway-ip/api?fields=wanmngr" -b cookies.txt | jq .
See Configuration Examples below.
Use Case: High availability with automatic failover to backup WAN
Behavior:
Configuration:
{
"mode": "FAILOVER",
"wans": [
{
"interface": "eth0",
"priority": 1,
"monitor": { ... }
},
{
"interface": "ppp0",
"priority": 2,
"monitor": { ... }
}
]
}
Priority Rules:
Use Case: Distribute traffic across multiple WANs for increased bandwidth
Behavior:
Configuration:
{
"mode": "LOADBALANCE",
"wans": [
{
"interface": "eth0",
"weight": 3,
"monitor": { ... }
},
{
"interface": "ppp0",
"weight": 1,
"monitor": { ... }
}
]
}
Weight Rules:
Actively tests connectivity by sending probes.
Best for: General internet connectivity
{
"monitor": {
"mode": "ACTIVE",
"checkInterval": 60,
"active": {
"type": "ICMP",
"hostname": "www.google.com",
"icmpCount": 5
}
}
}
Parameters:
hostname: Target to ping (IP or domain)icmpCount: Number of pings per check (default: 5)checkInterval: Seconds between checks (default: 60)Health Criteria:
Recommendations:
icmpCount for cellular (10+) due to higher latencyBest for: Specific service availability
{
"monitor": {
"mode": "ACTIVE",
"checkInterval": 60,
"active": {
"type": "TCP",
"hostname": "api.example.com",
"tcpPort": 443
}
}
}
Parameters:
hostname: Target servertcpPort: Port to check (80, 443, etc.)Health Criteria:
Use Cases:
Not Recommended: Only checks if interface has IP address, doesn’t verify actual connectivity.
{
"monitor": {
"mode": "PASSIVE"
}
}
Scenario: Office gateway with wired ethernet primary and LTE backup
curl -k -X PUT https://gateway-ip/api/wanmngr \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"mode": "FAILOVER",
"wans": [
{
"interface": "eth0",
"priority": 1,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 30,
"active": {
"type": "ICMP",
"hostname": "8.8.8.8",
"icmpCount": 3
}
}
},
{
"interface": "ppp0",
"priority": 2,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 60,
"active": {
"type": "ICMP",
"hostname": "8.8.8.8",
"icmpCount": 10
}
}
}
]
}'
# Save configuration
curl -k -X POST https://gateway-ip/api/command/save -b cookies.txt
Behavior:
Scenario: Two ethernet connections for increased bandwidth
curl -k -X PUT https://gateway-ip/api/wanmngr \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"mode": "LOADBALANCE",
"wans": [
{
"interface": "eth0",
"priority": 1,
"weight": 2,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 60,
"active": {
"type": "ICMP",
"hostname": "www.google.com",
"icmpCount": 5
}
}
},
{
"interface": "eth1",
"priority": 1,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 60,
"active": {
"type": "ICMP",
"hostname": "www.google.com",
"icmpCount": 5
}
}
}
]
}'
curl -k -X POST https://gateway-ip/api/command/save -b cookies.txt
Behavior:
Scenario: Maximum availability with three WAN options
curl -k -X PUT https://gateway-ip/api/wanmngr \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"mode": "FAILOVER",
"wans": [
{
"interface": "eth0",
"priority": 1,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 30,
"active": {
"type": "ICMP",
"hostname": "8.8.8.8",
"icmpCount": 3
}
}
},
{
"interface": "wlan0",
"priority": 2,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 45,
"active": {
"type": "ICMP",
"hostname": "8.8.8.8",
"icmpCount": 5
}
}
},
{
"interface": "ppp0",
"priority": 3,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 60,
"active": {
"type": "ICMP",
"hostname": "8.8.8.8",
"icmpCount": 10
}
}
}
]
}'
curl -k -X POST https://gateway-ip/api/command/save -b cookies.txt
Behavior:
Scenario: Ensure connectivity to specific cloud API
curl -k -X PUT https://gateway-ip/api/wanmngr \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"mode": "FAILOVER",
"wans": [
{
"interface": "eth0",
"priority": 1,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 30,
"active": {
"type": "TCP",
"hostname": "api.myservice.com",
"tcpPort": 443
}
}
},
{
"interface": "ppp0",
"priority": 2,
"weight": 1,
"monitor": {
"mode": "ACTIVE",
"checkInterval": 60,
"active": {
"type": "TCP",
"hostname": "api.myservice.com",
"tcpPort": 443
}
}
}
]
}'
curl -k -X POST https://gateway-ip/api/command/save -b cookies.txt
Behavior:
# Get current WAN status
curl -k -s "https://gateway-ip/api?fields=waninfo&inactivity=true" \
-b cookies.txt | jq '.result.waninfo.wans[]'
Monitor These Fields:
current: Which WAN is activeavailable: Which WANs passed health checksenabled: Which WANs are configured#!/usr/bin/env python3
"""
WAN Failover Monitoring Script
Alerts on WAN changes and failures
"""
import requests
import time
import json
from datetime import datetime
class WANMonitor:
def __init__(self, gateway_url, username, password):
self.gateway_url = gateway_url
self.session = requests.Session()
self.login(username, password)
self.last_current = None
def login(self, username, password):
url = f"{self.gateway_url}/api/login"
data = {"username": username, "password": password}
response = self.session.post(url, json=data, verify=False)
if response.status_code == 200:
print(f"✓ Logged in to {self.gateway_url}")
def get_wan_status(self):
url = f"{self.gateway_url}/api?fields=waninfo&inactivity=true"
response = self.session.get(url, verify=False)
if response.status_code == 200:
return response.json().get('result', {}).get('waninfo', {})
return None
def check_wans(self):
wan_info = self.get_wan_status()
if not wan_info:
return
wans = wan_info.get('wans', [])
# Find current WAN
current_wan = None
available_wans = []
unavailable_wans = []
for wan in wans:
if wan.get('enabled'):
if wan.get('current'):
current_wan = wan['interface']
if wan.get('available'):
available_wans.append(wan['interface'])
else:
unavailable_wans.append(wan['interface'])
# Check for WAN change
if self.last_current and current_wan != self.last_current:
self.alert('WARNING',
f'WAN failover: {self.last_current} → {current_wan}')
self.last_current = current_wan
# Alert on unavailable WANs
if unavailable_wans:
self.alert('WARNING',
f'WANs unavailable: {", ".join(unavailable_wans)}')
# Log status
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(f"[{timestamp}] Current: {current_wan} | "
f"Available: {len(available_wans)} | "
f"Unavailable: {len(unavailable_wans)}")
def alert(self, level, message):
timestamp = datetime.now().isoformat()
print(f"[{timestamp}] {level}: {message}")
# TODO: Implement alerting (email, Slack, etc.)
def monitor_loop(self, interval=60):
print(f"Starting WAN monitoring (interval: {interval}s)")
while True:
try:
self.check_wans()
time.sleep(interval)
except KeyboardInterrupt:
print("\nMonitoring stopped")
break
except Exception as e:
print(f"Error: {e}")
time.sleep(interval)
# Usage
if __name__ == "__main__":
monitor = WANMonitor(
gateway_url="https://172.16.33.111",
username="admin",
password="admin2019!"
)
monitor.monitor_loop(interval=30)
#!/bin/bash
# Simple WAN monitoring script
GATEWAY="https://172.16.33.111"
COOKIES="/tmp/gateway-cookies.txt"
# Login
curl -k -X POST "$GATEWAY/api/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin2019!"}' \
-c "$COOKIES" -s > /dev/null
echo "Monitoring WAN status..."
LAST_CURRENT=""
while true; do
# Get WAN status
WAN_INFO=$(curl -k -s "$GATEWAY/api?fields=waninfo&inactivity=true" -b "$COOKIES")
# Extract current WAN
CURRENT=$(echo "$WAN_INFO" | jq -r '.result.waninfo.wans[] | select(.current==true) | .interface')
# Check for change
if [ -n "$LAST_CURRENT" ] && [ "$CURRENT" != "$LAST_CURRENT" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - ALERT: WAN changed from $LAST_CURRENT to $CURRENT"
fi
LAST_CURRENT="$CURRENT"
# Count available WANs
AVAILABLE=$(echo "$WAN_INFO" | jq '[.result.waninfo.wans[] | select(.enabled==true and .available==true)] | length')
UNAVAILABLE=$(echo "$WAN_INFO" | jq '[.result.waninfo.wans[] | select(.enabled==true and .available==false)] | length')
echo "$(date '+%Y-%m-%d %H:%M:%S') - Current: $CURRENT | Available: $AVAILABLE | Unavailable: $UNAVAILABLE"
sleep 60
done
Symptoms: Primary WAN fails but gateway doesn’t switch to backup
Possible Causes:
# Check monitor configuration
curl -k -s "https://gateway-ip/api?fields=wanmngr" -b cookies.txt | \
jq '.result.wanmngr.wans[].monitor'
Solution: Ensure mode: "ACTIVE" is set
# Check WAN availability
curl -k -s "https://gateway-ip/api?fields=waninfo" -b cookies.txt | \
jq '.result.waninfo.wans[] | {interface, available, enabled}'
Solution: Verify backup WAN is configured and has connectivity
Health check target unreachable
Solution: Use reliable targets (8.8.8.8, 1.1.1.1)
Symptoms: WAN switches back and forth repeatedly
Possible Causes:
Unstable connection
Solution: Increase checkInterval and icmpCount
{
"checkInterval": 120,
"active": {
"icmpCount": 10
}
}
Target host issues
Solution: Use multiple reliable targets or switch to TCP checks
Network congestion
Solution: Implement hysteresis (manual failback)
Symptoms: All traffic goes through one WAN
Possible Causes:
Mode set to FAILOVER instead of LOADBALANCE
Solution: Change mode
curl -k -X PUT https://gateway-ip/api/wanmngr \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"mode": "LOADBALANCE", ...}'
Only one WAN available
Solution: Verify all WANs pass health checks
Existing connections
Note: Load balancing only affects NEW connections. Existing long-lived connections stay on original WAN.
Symptoms: Configuration reverts after reboot
Solution: Always save after configuration changes
curl -k -X POST https://gateway-ip/api/command/save -b cookies.txt
✅ Good Targets:
8.8.8.8 (Google DNS)1.1.1.1 (Cloudflare DNS)www.google.com❌ Avoid:
Fast Failover (30-45s):
Normal (60s):
Conservative (120s+):
Cellular connections have higher latency and variability:
{
"interface": "ppp0",
"monitor": {
"checkInterval": 60,
"active": {
"type": "ICMP",
"icmpCount": 10,
"hostname": "8.8.8.8"
}
}
}
Key Points:
icmpCount to 10+checkInterval (60-120s)Recommended Priority Order:
# After any configuration change
curl -k -X POST https://gateway-ip/api/command/save -b cookies.txt
Manually test failover before relying on it:
Implement automated monitoring:
Keep records of:
Failover Configuration:
PUT /api/wanmngr
{
"mode": "FAILOVER",
"wans": [
{"interface": "eth0", "priority": 1, "monitor": {...}},
{"interface": "ppp0", "priority": 2, "monitor": {...}}
]
}
Check Status:
GET /api?fields=waninfo
Save Configuration:
POST /api/command/save
Document Version: 1.0
Last Updated: December 17, 2025
Tested On: MTCAP3, Firmware 7.4.0-BETA2, API 7.2.0