Correct encoding selection, better locking and returned accidently deleted copyright.
authorkibergus <kibergus@gmail.com>
Sat, 6 Feb 2010 13:58:42 +0000 (13:58 +0000)
committerkibergus <kibergus@gmail.com>
Sat, 6 Feb 2010 13:58:42 +0000 (13:58 +0000)
git-svn-id: file:///svnroot/ussd-widget/trunk@21 d197f4d6-dc93-42ad-8354-0da1f58e353f

ussd-common/build_ussd-common.py
ussd-common/src/usr/bin/ussdquery.py
ussd-common/src/usr/lib/python2.5/gsmdecode.py

index c15da53..40d40ac 100644 (file)
@@ -38,9 +38,9 @@ if __name__ == "__main__":
 chmod +s /usr/bin/pnatd
 """ #Set here your post install script
 
-    version = "0.0.5"
+    version = "0.0.6"
     build = "0" 
-    changeloginformation = "command line parameters rearranged, bugfixes." 
+    changeloginformation = "Correct encoding selection. Better locking." 
    
     dir_name = "src"     
 
index e414752..9c42633 100755 (executable)
@@ -16,6 +16,9 @@ import fcntl
 import os
 import stat
 
+# Needed for correct output of utf-8 symbols.
+sys.stdout=file("/dev/stdout", "wb")
+
 def check_number(number):
        if number == "":
                return False
@@ -28,11 +31,81 @@ if len(sys.argv) == 1:
     print "Usage:\nussdquery.py <ussd number> [options]\nussdquery.py interactive [options]\n"+\
 "Options:\n-l language. Allowed languages: German, English, Italian, French, Spanish, Dutch, Swedish, Danish, Portuguese, Finnish, Norwegian, Greek, Turkish, Reserved1, Reserved2, Unspecified\n"+\
 "-r retry count. 0 default. Use -1 for infinite.\n-f If specified, errors, which occur on last query are threated as fatal\n"+\
-"-t timeout in seconds. Default 30. Timeout is considered to be critical error because you can't be shure answer for what request was returned.\n"+\
+"-t timeout in seconds. Default 30. Timeout is considered to be critical error because you can't be sure answer for what request was returned.\n"+\
 "-d delimeter. Default is '\\n> '"+\
-"For USSD menu navigation divide USSD number via spacebars for every nex menu selection. Type exit in interactive mode to exit."
+"For USSD menu navigation divide USSD number via spacebars for every next menu selection. Type exit in interactive mode to exit."
     sys.exit()
 
+lockf = None
+
+def gain_lock ():
+       global lockf
+       lockf = open("/tmp/ussdquery.lock", 'a')
+       fcntl.flock(lockf,fcntl.LOCK_EX)
+       try:
+               os.chmod("/tmp/ussdquery.lock", stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH)
+       except:
+               None
+
+def release_lock ():
+       global lockf
+       fcntl.flock(lockf,fcntl.LOCK_UN)
+       lockf.close()
+
+def init_modem(modem):
+       # We have only one modem, simultaneous acces wouldn't bring anything good
+       gain_lock()
+       response = ""
+       init_retry = 5
+       while response != "OK" and init_retry > 0 :
+               if modem == None :
+                       # OK response should be recieved shortly
+                       modem = pexpect.spawn('pnatd', [], 2)
+               try :
+                       modem.send('at\r');
+                       # Read our "at" command
+                       modem.readline();
+                       # Read OK response
+                       response = modem.readline().strip()
+               except pexpect.TIMEOUT:
+                       modem.kill(9)
+                       modem = None
+                       response = ""
+               if response != "OK" :
+                       time.sleep(0.5)
+                       init_retry -= 1
+               else:
+                       try:
+                               # Switch output encoding to GSM default encoding
+                               modem.send('at+cscs="GSM"\r');
+                               # Read our command
+                               modem.readline();
+                               # Read OK response
+                               response = modem.readline().strip()
+                       except pexpect.TIMEOUT:
+                               modem.kill(9)
+                               modem = None
+                               response = ""
+                       
+               if response != "OK" :
+                       time.sleep(0.5)
+                       init_retry -= 1
+
+       if response != "OK" :
+               print >> sys.stderr, "Couldn't init modem."
+               if modem != None:
+                       modem.kill(9)
+               release_lock()
+               sys.exit (-1)
+
+       modem.timeout = timeout
+       return modem
+
+def close_modem (modem):
+       modem.sendeof()
+       modem.kill(9)
+       release_lock()
+
 retry = 0
 allow_last_error = True
 delimiter = "\n> "
@@ -124,7 +197,7 @@ while arg < len(sys.argv)-1:
                                retry = int(sys.argv[arg])
                                if retry < -1:
                                        print >> sys.stderr, "Number of allowed errors must be >= -1. -1 assumed."
-                                       retry = -1
+                               retry = -1
                        except:
                                print >> sys.stderr, "Retry must be an integer."
                                sys.exit(-5)
@@ -146,56 +219,22 @@ if retry == -1:
 else:
        retry_forever = False
 
-# We have only one modem, simultaneous acces wouldn't bring anything good
-lockf = open("/tmp/ussdquery.lock", 'a')
-fcntl.flock(lockf,fcntl.LOCK_EX)
-try:
-       os.chmod("/tmp/ussdquery.lock", stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH)
-except:
-       None
-child = None
-response = ""
-init_retry = 5
-while response != "OK" and init_retry > 0 :
-       if child == None :
-               # OK response should be recieved shortly
-               child = pexpect.spawn('pnatd', [], 2)
-       try :
-               child.send('at\r');
-               # Read our "at" command
-               child.readline();
-               # Read OK response
-               response = child.readline().strip()
-       except pexpect.TIMEOUT:
-               child.kill(9)
-               child = None
-               response = ""
-       if response != "OK" :
-               time.sleep(0.5)
-               init_retry -= 1
-
-if response != "OK" :
-       print >> sys.stderr, "Couldn't init modem."
-       if child != None:
-               child.kill(9)
-        fcntl.flock(lockf,fcntl.LOCK_UN)
-        lockf.close()
-       sys.exit (-1)
-
-child.timeout = timeout
+modem = None
+
 # Now we are ready to send commands
 
 stage = 0
 if number == "interactive":
        sys.stdout.write(delimiter)
 while number == "interactive" or stage < len(number):
+       if modem == None:
+               modem = init_modem(modem)
+
        if number == "interactive":
                cnumber = sys.stdin.readline().strip()
                if cnumber == "exit":
-                       child.kill(9)
-                       fcntl.flock(lockf,fcntl.LOCK_UN)
-                       lockf.close()
-                       sys.exit (-2)
+                       close_modem (modem)
+                       sys.exit (0)
                if not check_number (cnumber):
                        sys.stdout.write ("Sintax error in USSD number"+delimiter)
                        continue
@@ -207,20 +246,18 @@ while number == "interactive" or stage < len(number):
                break
 
        try :
-               child.send('at+cusd=1,"'+cnumber+'",'+str(language)+'\r')
+               modem.send('at+cusd=1,"'+cnumber+'",'+str(language)+'\r')
                # Read our query echoed back
-               child.readline()
+               modem.readline()
 
                #Read and parse reply
-               replystring = child.readline().decode('string_escape')
+               replystring = modem.readline().decode('string_escape')
                # This will read out unneeded info from modem
-               child.readline()
-               child.readline()
+               modem.readline()
+               modem.readline()
        except pexpect.TIMEOUT:
                print >> sys.stderr, "Timeout. Modem didn't reply."
-               child.kill(9)
-               fcntl.flock(lockf,fcntl.LOCK_UN)
-               lockf.close()
+               close_modem (modem)
                sys.exit (-2)
 
        if replystring.strip() == "ERROR" :
@@ -229,14 +266,36 @@ while number == "interactive" or stage < len(number):
                continue
 
        try:
-               reresult = re.match("(?s)^\\+CUSD: \\d+,\"(.*)\",(\\d+)$", replystring.strip())
-               reply = reresult.group(1)
-               encoding = reresult.group(2)
+               reresult = re.match("(?s)^\\+CUSD: (\\d+),\"(.*)\",(\\d+)$", replystring.strip())
+
+               # 0 no further user action required (network initiated USSD-Notify, or no further information needed after mobile initiated operation)
+               # 1 further user action required (network initiated USSD-Request, or further information needed after mobile initiated operation)
+               # 2 USSD terminated by network
+               # 3 other local client has responded
+               # 4 operation not supported
+               # 5 network time out
+               reply_status=reresult.group(1)
+               reply = reresult.group(2)
+               # See GSM 07.07 and GSM 03.38
+               encoding = reresult.group(3)
        except:
                retry -= 1
-               print >> sys.stderr, "Couldn't parse modem answer."
+               print >> sys.stderr, "Couldn't parse modem answer: "+replystring
                continue
 
+       if reply_status == 0:
+               # May be somebody else needs it
+               close_modem(modem)
+               modem = None
+       elif reply_status == 2:
+               print >> sys.stderr, "USSD terminated by network."
+        elif reply_status == 3:
+                print >> sys.stderr, "Error: other local client has responded."
+        elif reply_status == 4:
+                print >> sys.stderr, "Operation not supported."
+        elif reply_status == 5:
+                print >> sys.stderr, "Network time out."
+
        # Decoding ansver
        reply = gsmdecode.decode(reply, int(encoding))
 
@@ -250,6 +309,5 @@ while number == "interactive" or stage < len(number):
        if not allow_last_error and namber != "interactive" and stage == len(number) - 1:
                retry = 0
 
-child.sendeof()
-fcntl.flock(lockf,fcntl.LOCK_UN)
-lockf.close()
+if modem != None:
+       close_modem (modem)
index 924c24a..152bff0 100644 (file)
@@ -1,4 +1,11 @@
-LANG_DE = 0x0
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published
+## by the Free Software Foundation; version 2 and higer.
+##
+## Martin Grimme (martin.grimme # gmail.com) 2010LANG_DE = 0x0
+
 LANG_EN = 0x1
 LANG_IT = 0x2
 LANG_FR = 0x3