#!/bin/bash
#
#

function print_usage() {
  echo "Usage:  `basename $0` COMMAND"
  echo
  echo "The following commands are available:"
  echo "  device      modem and sim information"
  echo "  connection  show current connection info"
  echo "  packet      current PDP"
  echo "  signal      signal strength"
  echo "  providers   list available cell providers"
  echo "  reconnect   reset and reconnect"
  exit 0
}

while getopts ":d:h" options; do
  case "${options}" in
    h)
      print_usage
      ;;
    *)
      print_usage
      ;;
  esac
done
shift $((OPTIND -1))

if ! command -v mmcli>/dev/null; then
  echo "ERROR: mmcli binary not found in path"
  exit 1
fi

# Exit on error:
set -e
trap 'echo "Error: device may not be ready ($?)"' ERR

MODEM_PATH=$(mmcli -L -K|grep "modem-list.value\[1\]"|cut -d: -f2|xargs)
if [ ! "$MODEM_PATH" ]; then
  echo "ERROR: no modem"
  exit 1
fi

# Basic state:
accesstech_count=0
while read -r line; do
  grep -q "modem.generic.state\s" <<< $line && MODEM_STATE=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.generic.bearers.length\s" <<< $line && bearers_count=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.generic.bearers.value\[${bearers_count}" <<< $line && BEARER_PATH=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.3gpp.operator-name" <<< $line && OPERATOR_NAME=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.3gpp.operator-code" <<< $line && OPERATOR_CODE=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.generic.access-technologies.length" <<< $line && accesstech_count=$(echo "$line"|cut -d: -f2|xargs)
  for (( i = 1; i <= accesstech_count; i++ )); do
    grep -q "modem.generic.access-technologies.value\[${i}" <<< $line && ACCESS_TECH[$i]=$(echo "$line"|cut -d: -f2|xargs)
  done
  grep -q "modem.generic.signal-quality.value" <<< $line && SIGNALQ_PCT=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.generic.manufacturer" <<< $line && DEV_MANUFACTURER=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.generic.model" <<< $line && DEV_MODEL=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.generic.revision" <<< $line && DEV_REVISION=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.3gpp.imei" <<< $line && DEV_IMEI=$(echo "$line"|cut -d: -f2|xargs)
  grep -q "modem.generic.sim\s" <<< $line && SIM_PATH=$(echo "$line"|cut -d: -f2|xargs)
done < <(mmcli -m ${MODEM_PATH} -K)

### Functions
# functions to do some more complicated bits
function signal_quality() {
  if [ "$MODEM_STATE" != "connected" ]; then
    echo "Not connected"
    return
  fi
  strength_dBm=0
  mmcli -m $MODEM_PATH --signal-setup=1 > /dev/null
  sleep 1
  while read -r line; do
    key=$(echo "$line"|cut -d: -f1|xargs)
    val=$(echo "$line"|cut -d: -f2|xargs)
    if [ "$val" != "--" ]; then
      shortkey="${key:13}"
      tmp=$(echo "$shortkey"|cut -d. -f1)
      if [ "$tmp" != "refresh" ] && [ "$tmp" != "threshold" ]; then
        echo "${shortkey} = ${val}"
        if [ $(echo "$shortkey"|cut -d. -f2) == "rssi" ]; then
          strength_dBm="${val#-}"
        fi
      fi
    fi
  done < <(mmcli -m $MODEM_PATH --signal-get -K)
  mmcli -m $MODEM_PATH --signal-setup=0 > /dev/null  # turn off
  if (( $(echo "$strength_dBm != 0"|bc -l) )); then
    if (( $(echo "$strength_dBm <= 79"|bc -l) )); then
      echo "(excellent)"
    elif (( $(echo "$strength_dBm <= 89"|bc -l) )); then
      echo "(good)"
    elif (( $(echo "$strength_dBm <= 99"|bc -l) )); then
      echo "(average)"
    elif (( $(echo "$strength_dBm <= 109"|bc -l) )); then
      echo "(poor)"
    elif (( $(echo "$strength_dBm <= 113"|bc -l) )); then
      echo "(very poor)"
    fi
  fi
}

# Get connection info: provider and technology, frequency
function connection() {
  if [ "$MODEM_STATE" != "connected" ]; then
    echo "Not connected (${MODEM_STATE})"
  elif [ "$bearers_count" -eq 0 ]; then
    echo "Connected but not configured (no bearer)"
  else
    echo "Operator: ${OPERATOR_NAME} (${OPERATOR_CODE})"
    echo -n "Connection technology:"
    for at in "${ACCESS_TECH[@]}"; do
      echo -n " ${at}"
    done
    echo ""
    echo "Signal strength: ${SIGNALQ_PCT}%"
  fi
}

function providers() {
  count=0  
  while read -r line; do
    grep -q "modem.3gpp.scan-networks.length" <<< $line && count=$(echo "$line"|cut -d: -f2|xargs)
    for (( i = 1; i <= count; i++ )); do
      grep -q "modem.3gpp.scan-networks.value\[${i}" <<< $line && echo "$line"|grep -o "operator-code.*"
    done
  done < <(mmcli -m $MODEM_PATH --3gpp-scan --timeout=120 -K)
}

function packet() {
  count=0
  if [ ! "$BEARER_PATH" ]; then
    echo "ERROR: no connection"
  else
    while read -r line; do
      grep -q "bearer.properties.apn " <<< $line && APN=$(echo "$line"|cut -d: -f2|xargs)
      grep -q "bearer.ipv4-config.address" <<< $line && IP4_ADDRESS=$(echo "$line"|cut -d: -f2|xargs)
      grep -q "bearer.ipv6-config.address" <<< $line && IP6_ADDRESS=$(echo "$line"|cut -d: -f2|xargs)
      grep -q "bearer.ipv4-config.dns.length" <<< $line && count=$(echo "$line"|cut -d: -f2|xargs)
      for (( i = 1; i <= count; i++ )); do
        grep -q "bearer.ipv4-config.dns.value\[${i}" <<< $line && DNS_ADDRESS[$i]=$(echo "$line"|cut -d: -f2|xargs)
      done
    done < <(mmcli -b $BEARER_PATH -K)
    echo "APN: ${APN}"
    echo "IP4 address: ${IP4_ADDRESS}"
    echo "IP6 address: ${IP6_ADDRESS}"
    echo -n "DNS: "
    for ad in "${DNS_ADDRESS[@]}"; do
      echo -n " ${ad}"
    done
    echo ""
  fi
}

function device () {
  echo "Manufacturer: ${DEV_MANUFACTURER}"
  echo "Model:        ${DEV_MODEL}"
  echo "Revision:     ${DEV_REVISION}"
  echo "IMEI:         ${DEV_IMEI}"
  while read -r line; do
    grep -q "sim.properties.imsi" <<< $line && IMSI=$(echo "$line"|cut -d: -f2|xargs)
    grep -q "sim.properties.iccid" <<< $line && ICCID=$(echo "$line"|cut -d: -f2|xargs)
  done < <(mmcli -i $SIM_PATH -K)
  echo "IMSI:         ${IMSI}"
  echo "ICCID:        ${ICCID}"
}

COMMAND=$1
if [ -z "$COMMAND" ]; then
  COMMAND="device"
fi

case $COMMAND in

  device)         # modem and sim information
    device
    ;;

  connection)     # show current connection info
    connection
    ;;

  packet)         # current PDP
    packet
    ;;
    
  signal)         # test signal strength
    signal_quality
    ;;

  providers)      # list available cell providers
    providers
    ;;

  reconnect)    # reset to allow reconnect
    mmcli -m $MODEM_PATH --simple-disconnect
    ;;

  *)
    echo "Error: unknown command."
    exit 1
    ;;

esac

