When a defined number of messages are sent, balance is asked using USSD. The response is saved to the file and it's also logged. It is also possible to ask the balance "on demand", by creating a "flag file": touch /var/spool/sms/stats/get.GSM1.balance.
When the balance goes too low, an alert SMS is sent. Also, the expiration time is checked and alert is sent if necessary.
If the balance was not asked for a long time, the script will ask it by itself. The setting max_age defaults to 24 hours. This is for systems where messages are sent very rarely, and therefore the balance and expiration are not checked and the SIM may expire accidentally.
Notice that even when this sample is using stats directory, it is not required that the statistics functionality (libmm) is available.
The config:
devices = GSM1
logfile = /var/log/smsd.log
loglevel = notice
smart_logging = yes
stats = /var/spool/sms/stats
[default]
regular_run_interval = 10
regular_run_logfile = /var/log/smsd_regular_run.log
[GSM1]
device = /dev/ttyUSB0
incoming = yes
pin = ignore
regular_run = /var/spool/sms/regular_run/GSM1.sh
regular_run_post_run = /var/spool/sms/regular_run/GSM1.sh
regular_run_cmdfile = /var/spool/sms/regular_run/GSM1.cmdfile
regular_run_statfile = /var/spool/sms/regular_run/GSM1.statfile
logfile = /var/log/smsd.log
loglevel = notice
smart_logging = yes
stats = /var/spool/sms/stats
[default]
regular_run_interval = 10
regular_run_logfile = /var/log/smsd_regular_run.log
[GSM1]
device = /dev/ttyUSB0
incoming = yes
pin = ignore
regular_run = /var/spool/sms/regular_run/GSM1.sh
regular_run_post_run = /var/spool/sms/regular_run/GSM1.sh
regular_run_cmdfile = /var/spool/sms/regular_run/GSM1.cmdfile
regular_run_statfile = /var/spool/sms/regular_run/GSM1.statfile
'smsdconf' Syntax Highlight powered by GeSHi
The script /var/spool/sms/regular_run/GSM1.sh:
#!/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.
alert_to="358401234567" # "" = no SMS is sent.
###########################################################################
# 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
# Fix this if a different command is required in your network:
ussd_command="AT+CUSD=1,\"*100#\""
# 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="saldo on "
# Defines how the "euros" part ends:
balance_suffix="."
# Defines how the expiration date can be found.
# With an empty setting the expiration is not checked.
balance_expiration="vanhenee "
# 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
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
messages=$(formail -zx ${DEVICENAME}: < "$counter_file")
if [ "$1" = "PRE_RUN" ]; then
get_balance=0
# Get the balance if it was wanted:
[ -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 are 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
[ $get_balance -gt 0 ] && echo "$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//\"/\\\"}
tmp=${tmp//\*/\\*}
result=$(cat "$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"
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")
[ $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
###########################################################################
# 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.
alert_to="358401234567" # "" = no SMS is sent.
###########################################################################
# 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
# Fix this if a different command is required in your network:
ussd_command="AT+CUSD=1,\"*100#\""
# 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="saldo on "
# Defines how the "euros" part ends:
balance_suffix="."
# Defines how the expiration date can be found.
# With an empty setting the expiration is not checked.
balance_expiration="vanhenee "
# 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
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
messages=$(formail -zx ${DEVICENAME}: < "$counter_file")
if [ "$1" = "PRE_RUN" ]; then
get_balance=0
# Get the balance if it was wanted:
[ -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 are 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
[ $get_balance -gt 0 ] && echo "$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//\"/\\\"}
tmp=${tmp//\*/\\*}
result=$(cat "$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"
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")
[ $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
« Last edit by keke on Wed Jun 29, 2011 10:18, 163 months ago. »