SMS Server Tools 3
 Menu
Basic information:
Additional information:
Support:
Get SMS Server Tools 3:
Additional Options

 Sponsored links

 Search
Custom Search

 Visitor locations
 
 SMS Server Tools 3 Community
Welcome, Guest. The forum is currently read-only, but will open soon. Sat Oct 12, 2024 08:34
SMSTools3 Community » Sample scripts / setups Bottom

Sample config and script for regular_run and balance of prepaid SIM using USSD

Login and Post Reply

Page:  Previous  1  2

Author Post
Member
Registered:
Sep 2017
Location: Munich, Germany
I have solved the above and some other problems and would like to share the outcome. The script below will
* work on FreeBSD (like FreeNAS 9)
* support different ESSD commands for account balance and expiration date (like Aldi Talk)
* accept character encodings with German umlauts
* fix some misleading debug output

German users: check out the smsd.config file with German provider settings in this forum.

#!/usr/local/bin/bash

###########################################################################
# Global settings:

get_balance_after=5 # 1 = get the balance after at least one message is sent.

max_age=24 # an integer for hours, 0 = disable periodic checking.

alert_balance=5 # an integer for "euros".

alert_expiration=14 # an integer for days.

# set to "" for no notification
alert_to="491771401303"

###########################################################################
# Device depended settings:

# Comment out the next command if a DEVICENAME setting should be taken from
# the name of this file (which can be a symbolic link). For example:
# /var/spool/sms/regular_run/GSM1.sh
#DEVICENAME="GSM1"

[ -z "$DEVICENAME" ] && tmp=${0##*/} && DEVICENAME=${tmp%%.*}
balance_file="/var/spool/sms/stats/${DEVICENAME}.balance"
counter_file="/var/spool/sms/stats/${DEVICENAME}.counter"
get_balance_flagfile="/var/spool/sms/stats/get.${DEVICENAME}.balance"
regular_run_cmdfile="/var/spool/sms/regular_run/${DEVICENAME}.cmdfile"
regular_run_statfile="$2"
outgoing="/var/spool/sms/outgoing"

###########################################################################
# START OF OPERATOR SPECIFIC SETTINGS

# If more than one modem is used and they have different operator specific
# settings, move this section to the files for each modem and include the
# file here using the following command:
# . /var/spool/sms/regular_run/${DEVICENAME}.operator_settings.sh

# The USSD commands to output to the modem
# several commands may be concatenated with "\n"
# first command should be for balance, optional second for expiration date
ussd_command="AT+CUSD=1,\"*100#\",15\nAT+CUSD=1,\"*102#\",15"
 
# This is an example result for the query:
# 2010-05-09 14:16:11,5, GSM1: CMD: AT+CUSD=1,"*100#": OK +CUSD: 2, ...
# ... "Liittym�si saldo on 22.36 EUR. Puheaikasi vanhenee 27.04.2011.",15

# Defines how balance can be found from the result:
balance_prefix="Ihr Guthaben beträgt: "

# Defines how the balance amount part ends (NOT the radix symbol):
balance_suffix=" ."

# Defines how the expiration date can be found.
# With an empty setting the expiration is not checked.
balance_expiration="endet am "

# Helper function for converting date from the answer to the format yyyy-mm-dd
# Modify this if necessary.
extract_expiration()
{
  # datestamp to format yyyy-mm-dd
  echo "${1:6:4}-${1:3:2}-${1:0:2}"
}

: <<COMMENTBLOCK

Example 2:
..."Balance subscription is EUR 22.36. Your allotted time expires 04/27/2011."

balance_prefix="EUR "
balance_suffix="."
balance_expiration="expires "
Command in extract_expiration(): echo "${1:6:4}-${1:0:2}-${1:3:2}"

Example 3:
..."The balance is 34.84 B. & valid until 26/07/10 "

balance_prefix="is "
balance_suffix="."
balance_expiration="until "
Command in extract_expiration(): echo "20${1:6:2}-${1:3:2}-${1:0:2}"

Example 4:
...Ihr Restguthaben ist CHF 18,87

balance_prefix="CHF "
balance_suffix=","
balance_expiration=""

COMMENTBLOCK


# END OF OPERATOR SPECIFIC SETTINGS
###########################################################################

substr()
{
  local string=$1
  local prefix=$2
  local suffix=$3

  local ppref=${string%${prefix}*}

  # Changed 2010-11-02:
  if [[ "$ppref" == *${prefix}* ]]
  then
    string=${string//\"/}

    local position=$(echo | awk '{
      print index("'
"${string}"'", "'"${prefix}"'")
    }'
)

    if [ $position -gt 0 ]; then
      ppref=${string:0:$(($position - 1))}
    fi
  fi
  # -------------------

  local ssuff=${string#*${suffix}}
  local nopref=${string#${ppref}${prefix}}
  echo ${nopref%${suffix}${ssuff}}
}

#--------------------------------------------------------------------------
date2stamp()
{
  case `uname` in
    FreeBSD)
      if [ ${#1} -gt 10 ]; then
        date -juf "%Y-%m-%d %H:%M:%S" "$1" +%s
      else
        date -juf "%Y-%m-%d" "$1" +%s
      fi
      ;;
    Darwin)
      date -juf "%Y-%m-%d %H:%M:%S" "$1" +%s
      ;;
    *)
      date --utc --date "$1" +%s
      ;;
  esac
}

#--------------------------------------------------------------------------
dateDiff()
{
  local sec=0

  case $1 in
    -s) sec=1; shift;;
    -m) sec=60; shift;;
    -h) sec=3600; shift;;
    -d) sec=86400; shift;;
    *) sec=86400;;
  esac

  local dte1=$(date2stamp "$1")
  local dte2=$(date2stamp "$2")
  local diffSec=$((dte2-dte1))

  echo $((diffSec/sec))
}

###########################################################################

test -e "$counter_file" || exit 1

# triggering balance based on number of SMSes sent requires stats: in smsd.conf place
# stats = <directory of this script>
messages=$(formail -zx ${DEVICENAME}: < "$counter_file")

if [ "$1" = "PRE_RUN" ]; then

  get_balance=0

  # Get the balance if it was requested:
  [ -w "$get_balance_flagfile" ] && get_balance=1 && \
     unlink "$get_balance_flagfile"

  if [ -r "$balance_file" ]; then
    # Get the balance if a defined number of messages were sent.
    messagesb=$(formail -zx Messages: < "$balance_file")
    [ $(($messages - $messagesb)) -ge $get_balance_after ] && get_balance=1
  else
    # Get the balance because the previous value is not known.
    get_balance=1
  fi

  # Check the age of the last query if necessary:
  if [ $get_balance = 0 ] && [ $max_age -gt 0 ]; then
    last_query=$(formail -zx Last_query: < "$balance_file")
    age=$(dateDiff -h "$last_query" "$(date +"%Y-%m-%d %T")")
    [ $age -ge $max_age ] && get_balance=1
  fi

  # NOTE: option -e necessary for bash on FreeBSD to process '\n' between commands
  [ $get_balance -gt 0 ] && echo -e "$ussd_command" > "$regular_run_cmdfile"
 
 

else

  # 2011-06-29: Check that USSD command is found:
  result=""
  if [ -r "$regular_run_statfile" ]; then
    tmp=${ussd_command%%"\n"*} # throw away all but first ussd command
    tmp=${tmp//\"/\\\"} # escape double quotes
    tmp=${tmp//\*/\\*} # escape asterisks
    # concatenate responses and check if it contains the first command
    result=$(tr -d "\n\r" < "$regular_run_statfile" | grep "$tmp")
  fi

  if [ -n "$result" ]; then

    balance_low=-1 # Initial value means unknown.
    balance=-1
    balance_alerted=""
    expiration_low=-1
    expiration=-1
    expiration_alerted=""
    sms_alert=""
    current_alert=""

    # 2010-11-02: Change Ctrl-B to $
    result=$(echo "${result//$'\x02'/$}")

    # Check that required words exists:
    if [[ "$result" == *${balance_prefix}* ]] && \
       [[ "$result" == *${balance_suffix}* ]]
    then
      # Get the balance and check it:
      balance=$(substr "$result" "$balance_prefix" "$balance_suffix")
      balance_low=0
     
      if [ $(expr "$balance" + 1 2> /dev/null) ]; then
        [ $balance -le $alert_balance ] && balance_low=1
      else
        #echo "Error while parsing an integer: $balance"
        echo "Balance $balance is above warning threshold $alert_balance"
      fi
    else
      echo "Error while parsing the answer (balance): $result"
    fi

    # Get the expiration date if defined, and check it:
    if [ -n "$balance_expiration" ]; then
      if [[ "$result" == *${balance_expiration}* ]]; then
        expiration_low=0
        expiration=$(substr "$result" "$balance_expiration" "")
        expiration=$(extract_expiration "$expiration")
        expiration=$(dateDiff -d "$(date +"%Y-%m-%d")" "$expiration")
        echo "time until expiration in days is $expiration days"
        [ $expiration -le $alert_expiration ] && expiration_low=1
      else
        echo "Error while parsing the answer (expiration): $result"
      fi
    fi



    if [ -e "$balance_file" ]; then
      # Get previous values:
      current_alert=$(formail -zx Current_alert: < "$balance_file")
      balance_alerted=$(formail -zx Balance_alerted: < "$balance_file")
      expiration_alerted=$(formail -zx Expiration_alerted: < "$balance_file")
    fi

    balance_gone_low=0 # added 2010-11-03
    # If not yet alerted and the balance has gone low, alert now:
    if [ -z "$balance_alerted" ] && [ $balance_low = 1 ]; then
      balance_gone_low=1
      balance_alerted=$(date +"%Y-%m-%d %T")
      tmp="The balance has gone low ($balance)."
      echo "$tmp" # This message goes to the smsd.log
      [ -z "$sms_alert" ] && sms_alert="Alert:"
      sms_alert="${sms_alert} ${tmp}"

      # If the expiration is already alerted, but the issue is still active,
      # include it in the message:
      if [ -n "$expiration_alerted" ] && [ $expiration_low = 1 ]; then
        sms_alert="${sms_alert} The expiration is also near ($expiration days)."
      fi
    fi

    # Remove an outdated alert:
    [ -n "$balance_alerted" ] && [ $balance_low = 0 ] && balance_alerted=""

    # If not yet alerted and the expiration is near, alert now:
    if [ -z "$expiration_alerted" ] && [ $expiration_low = 1 ]; then
      expiration_alerted=$(date +"%Y-%m-%d %T")
      tmp="The expiration is near ($expiration days)."
      echo "$tmp" # This message goes to the smsd.log
      [ -z "$sms_alert" ] && sms_alert="Alert:"
      sms_alert="${sms_alert} ${tmp}"

      # If the balance is already alerted, but the issue is still active,
      # include it in the message:
      if [ -n "$balance_alerted" ] && [ $balance_low = 1 ]; then
        if [ $balance_gone_low -eq 0 ]; then
          sms_alert="${sms_alert} The balance is also low ($balance)."
        fi
      fi
    fi

    # Remove an outdated alert:
    [ -n "$expiration_alerted" ] && [ $expiration_low = 0 ] && \
       expiration_alerted=""

    [ -z "$balance_alerted" ] && [ -z "$expiration_alerted" ] && \
       current_alert=""

    if [ -n "$sms_alert" ] && [ -n "$alert_to" ]; then
      # Send the SMS:
      FILE=$(mktemp /tmp/alert_XXXXXX)
      echo "To: $alert_to" >> $FILE
      echo "" >> $FILE
      echo "$DEVICENAME $sms_alert" >> $FILE
      FILE2=$(mktemp "${outgoing}/send_XXXXXX")
      mv $FILE "$FILE2"
    fi

    # Save the details:
    DATE=$(date +"%Y-%m-%d %T")
    echo "Last_query: $DATE" > "$balance_file"
    [ -n "$sms_alert" ] && current_alert="${DATE}, $sms_alert"
    [ -n "$current_alert" ] && \
       echo "Current_alert: $current_alert" >> "$balance_file"
    echo "Messages: $messages" >> "$balance_file"
    echo "Balance: $balance" >> "$balance_file"
    [ -n "$balance_expiration" ] && \
       echo "Expiration: $expiration" >> "$balance_file"
    [ -n "$balance_alerted" ] && \
       echo "Balance_alerted: $balance_alerted" >> "$balance_file"
    [ -n "$expiration_alerted" ] && \
       echo "Expiration_alerted: $expiration_alerted" >> "$balance_file"
    #echo "" >> "$balance_file"
    #echo "$result" >> "$balance_file"
  fi
fi

exit 0
 
 
'bash' Syntax Highlight powered by GeSHi



Enjoy!

Member
Registered:
Aug 2018
Location: Queluz, Portugal
Hi,

Can't get it to work. The script is returning " 1 ".

The balance message is "O seu saldo sâ–’o e8.81. Obrigado por escolher a Lycamobile.", so no expiration date.
The code to get the balance is "*123#" and this is a Huawei E220 HSDPA Modem connected to an OpenWRT router.

I changed the settings accordingly but still no luck.
Could it be because the modem device is /dev/ttyUSB0 and balance is being reported to /dev/ttyUSB1 ?

My settings:



So far I have a manual, painful, way of checking the balance (see below) so using this automated script would help a lot.
The errors I'm getting:



My procedure to check balance on a Huawei E220 HSDPA Modem (assuming that the modem is using /dev/ttyUSB0 and /dev/ttyUSB1):
1) Open two terminals (let's say A and B).
2) Terminal A: stty -F /dev/ttyUSB1 9600
3) Terminal A: cat /dev/ttyUSB0 (keep it going)
4) Terminal B: Open minicom, configure serial port to: /dev/ttyUSB0, 9600 8N1)
5) Terminal B: In minicom, write: AT+CUSD=1,"*123#",15
6) Check the balance in terminal A. Among several "^BOOT:xxxxx,x,x,x" messages, you shoud have the balance message.


Any hint what might be wrong on the script?
Thanks!

Member
Registered:
Aug 2018
Location: Queluz, Portugal
For whoever is interested, I've spend a few hours doing a much simpler script that fits my needs.
Tested on a Huawei E220 HSDPA Modem with a LYCA Mobile Portugal SIM.
You may need to adapt it to your case, so use with caution.


#!/bin/bash

############################################################
#
# SIMPLE CHECK BALANCE V1
#
# Sends a "get balance" request to USBDEVICE_TOASK
# Reads the answer from USBDEVICE_TOREAD
# Can work in parallel with SMSTOOLS3
# Works with Huawei E220 HSDPA Modem
#
# JOAO SILVA 2019 - PORTUGAL
#
###########################################################

USBDEVICE_TOREAD=/dev/ttyUSB1
USBDEVICE_TOASK=/dev/ttyUSB0
GETBALANCE="'AT+CUSD=1,"*123#",15\r'"

# THIS GETBALANCE STRING IS FOR LYCA MOBILE PORTUGAL


##########################################################
# VERBOSE FLAG
##########################################################
if [ -z "$1" ]; then  # TESTS VERBOSE - Any argument will make it verbose
 #echo "No argument supplied"
 verbose=0
else
 verbose=1
 echo "verbose ON. No message means everything is OK"
fi

##########################################################
# VERBOSE FUNCTION
##########################################################
verbose()
{
 if [ "$verbose" = "1" ]; then
  echo $1
 else
  sleep 0;
 fi
}

##########################################################
# LISTENING DAEMON FUNCTION
##########################################################

ListeningDaemon()
{
    while read line
    do
     alarm=`echo $line | awk -F ':' '{print $1}'`
     case $alarm in
        "+CUSD")
          saldo=`echo $line | awk '{print $6}'`
          verbose "SALDO: $saldo"
          echo "$saldo"
          exit 0
        ;;
    esac
   done
}


# MAIN
# set baudrate for USB1
stty -F /dev/ttyUSB1 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts

#Send the "get balance" command to USBDEVICE_TOASK
echo -e -n $GETBALANCE > $USBDEVICE_TOASK #/dev/ttyUSB0

#Immediately try to read the answer in USBDEVICE_TOREAD
ListeningDaemon <$USBDEVICE_TOREAD
 
 
'bash' Syntax Highlight powered by GeSHi


Member
Registered:
Aug 2018
Location: Queluz, Portugal
Also made an adaptation to be able to re-charge the car with the prepaid vouchers:

#!/bin/bash

############################################################
#
# SIMPLE RECHARGE SCRIPT V1
#
# Sends a "get balance" request to USBDEVICE_TOASK
# Reads the answer from USBDEVICE_TOREAD
# Can work in parallel with SMSTOOLS3
# Works with Huawei E220 HSDPA Modem
#
# JOAO SILVA 2019 - PORTUGAL
#
###########################################################

USBDEVICE_TOREAD=/dev/ttyUSB1
USBDEVICE_TOASK=/dev/ttyUSB0
GETBALANCE="'AT+CUSD=1,"*123#",15\r'"
VOUCHERCODE=$1
RECHARGE="'AT+CUSD=1,"*123*$VOUCHERCODE#",15\r'"
CHECKBALANCE="/bin/check-balance.sh"

# THIS GETBALANCE & RECHARGE STRINGS ARE FOR LYCA MOBILE PORTUGAL


##########################################################
# VERBOSE FLAG
##########################################################
if [ -z "$1" ]; then  # TESTS VERBOSE - Any argument will make it verbose
 echo "No argument supplied. You need to specify the voucher code as argument like:"
 echo "# recharge-lyca.sh <voucher-code>"
 verbose=0
 exit
else
 verbose=1
 #echo "verbose ON. No message means everything is OK"
 echo "Charging LYCA card with voucher code $1"
fi

##########################################################
# VERBOSE FUNCTION
##########################################################
verbose()
{
 if [ "$verbose" = "1" ]; then
  echo $1
 else
  sleep 0;
 fi
}

##########################################################
# LISTENING DAEMON FUNCTION
##########################################################

ListeningDaemon()
{
    while read line
    do
     alarm=`echo $line | awk -F ':' '{print $1}'`
     #alarm=`echo $line `
     case $alarm in
        "+CUSD")
          saldo=`echo $line `
          verbose "Result: $saldo"
          #echo "$saldo"
          exit 0
        ;;
    esac
   done
}


# MAIN

CURRENTBALANCE=`$CHECKBALANCE`
echo -e "Current Balance is $CURRENTBALANCE\n"

read -p "Are you sure you want to recharge SIM with voucher $VOUCHERCODE? " -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    # do dangerous stuff
    echo -e "\nRecharging with code $VOUCHERCODE"



# set baudrate for USB1
stty -F /dev/ttyUSB1 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts

#Send the "get balance" command to USBDEVICE_TOASK
echo -e -n $RECHARGE > $USBDEVICE_TOASK #/dev/ttyUSB0

#Immediately try to read the answer in USBDEVICE_TOREAD
ListeningDaemon <$USBDEVICE_TOREAD

fi

echo "Canceling... bye"
 
 
'bash' Syntax Highlight powered by GeSHi


Login and Post Reply

Page:  Previous  1  2

SMSTools3 Community » Sample scripts / setups Top

 
Time in this board is UTC.  

Privacy Policy   SMS Server Tools 3 Copyright © Keijo Kasvi.