#!/bin/sh
# Recovery trigger, through the router's REST API. One action per 3 minutes.
#   ?lte     restart the LTE connection (interface off and on)
#   ?reboot  reboot the whole router
#   ?5g-off  switch 5G off (LTE only), ?5g-on switch it back on
#   (none)   power-cycle the LTE modem
# After any LTE change or a power-cycle it restarts the router's GPS reader if it got stuck.
LOCK=/tmp/modem-cycle.last
LTE=lte1
[ -f /tmp/cycle.env ] && . /tmp/cycle.env
[ -n "$API" ] || API=$(sed -n 's/^API="\(http:[^"]*\/rest\).*/\1/p' /nmea/run.sh)

post() { # post <path> <json>
  wget -q -O - --header 'Content-Type: application/json' --post-data "$2" "$API/$1"
}

if [ "$1" = gps ]; then
  # Background part: if the GPS reader gets no data, switch GPS off and on
  # (this also resends the init string to the modem). Up to about 4 minutes.
  for i in 1 2 3 4 5 6 7 8; do
    sleep 20
    case "$(post system/gps/monitor '{"once":""}')" in
      *'"data-age":"never"'*|'') ;;
      *) exit 0 ;;
    esac
    post system/gps/set '{"enabled":"no"}' >/dev/null
    post system/gps/set '{"enabled":"yes"}' >/dev/null
    sleep 10
  done
  exit 1
fi

gps_watch() {
  if command -v setsid >/dev/null; then
    setsid /bin/sh "$0" gps </dev/null >/dev/null 2>&1 &
  else
    /bin/sh "$0" gps </dev/null >/dev/null 2>&1 &
  fi
}

now=$(cut -d. -f1 /proc/uptime)
last=$(cat "$LOCK" 2>/dev/null || echo -1000)
printf 'Content-Type: text/plain\r\n\r\n'
if [ $((now - last)) -lt 180 ]; then
  echo "busy: last action $((now - last)) s ago, try again in $((180 - now + last)) s"
  exit 0
fi
echo "$now" > "$LOCK"

case "$QUERY_STRING" in
  lte)
    if post interface/lte/disable "{\"numbers\":\"$LTE\"}" >/dev/null; then
      sleep 5
      post interface/lte/enable "{\"numbers\":\"$LTE\"}" >/dev/null
      echo "ok: LTE restarted, internet is back in about 20 s"
      gps_watch
    else
      rm -f "$LOCK"
      echo "error: router API call failed"
    fi
    ;;
  5g-off|5g-on)
    # Reads the modem's network-mode and removes or adds only "5g". RouterOS reconnects LTE by itself.
    mode=$(wget -q -O - "$API/interface/lte?name=$LTE" | sed -n 's/.*"network-mode":"\([^"]*\)".*/\1/p')
    if [ -z "$mode" ]; then
      rm -f "$LOCK"
      echo "error: router API call failed"
      exit 0
    fi
    new=$(echo ",$mode," | sed 's/,5g,/,/; s/^,//; s/,$//')
    [ -n "$new" ] || new=lte
    [ "$QUERY_STRING" = 5g-on ] && new="$new,5g"
    if post interface/lte/set "{\"numbers\":\"$LTE\",\"network-mode\":\"$new\"}" >/dev/null; then
      if [ "$QUERY_STRING" = 5g-on ]; then
        echo "ok: 5G on, internet is back in about 20 s"
      else
        echo "ok: 5G off, LTE only until you switch it back on. Internet is back in about 20 s"
      fi
      gps_watch
    else
      rm -f "$LOCK"
      echo "error: router API call failed"
    fi
    ;;
  reboot)
    # The router answers, then reboots. No answer within 10 s: it was refused or is already going down.
    if wget -q -T 10 -O /dev/null --header 'Content-Type: application/json' \
      --post-data '{}' "$API/system/reboot"; then
      echo "ok: router is rebooting, back in about 2 minutes"
    else
      rm -f "$LOCK"
      echo "error: reboot refused or no answer. Does the nmea group have the reboot permission?"
    fi
    ;;
  *)
    if post system/routerboard/usb/power-reset '{"duration":"5s"}' >/dev/null; then
      echo "ok: modem power-cycled, LTE is back in about a minute, GPS fix a few minutes later"
      gps_watch
    else
      rm -f "$LOCK"
      echo "error: router API call failed"
    fi
    ;;
esac
