0

I am working on this ussd project that would just check the balance on a modem and print it out. Howeover, I am stuck to this point where I get "OK" printed to my screen. My ussd command returns only "OK" not the actual ussd response.

I am working pyserial. So Assuming I send *124# which is to check balance, I expect the balance but it ends up returning "OK"

what is wrong.

import glob
import time
import serial
from pdu import pdu_to_text, text_to_pdu


def list_ports():
    ports = glob.glob('/dev/ttyUSB*')
    for val, port in enumerate(ports):
        print(val, port)
    print('-----------------------')
    port = int(input('your desired port: '))
    print('You selected' + ports[port])
    return ports[port]


def command_maker():
    command = raw_input('enter ATCommand: ')
    return bytes(command.encode('utf-8'))

def ussd_maker():
    # return '1' is specified here to allow return of a casted string
    ussd_code = convert_text2pdu(raw_input('Input the USSD code: '))
    ussd_command = "at+cusd=1, " + str(ussd_code) + ', 15\r\n'
    print(ussd_command)
    return bytes(ussd_command.encode('utf8'))


def convert_pdu2text(pdu_encoded_data):
    """
    Convert pdu encoded data to text(string *utf-8*)
    """
    pdu_decoded_to_text = pdu_to_text(pdu_encoded_data)
    return pdu_decoded_to_text


def convert_text2pdu(unicode_string):
    """
    Convert text to pdu format to work with gsm modems and any other
    device that support pdu data format
    """
    text_encoded_to_pdu = text_to_pdu(unicode_string)
    return text_encoded_to_pdu


def app_run(port, atcmd):
    ser = serial.Serial()
    ser.port = (port)
    try:
        ser.open()
        time.sleep(0.5)
        ser.write(bytes(atcmd) + b'\r\n')
        out = b''
        time.sleep(3)
        while ser.inWaiting() > 0:
            out += ser.read(1)
        if out != '':
            print("------response--------\n" + out.decode("utf-8"))
        ser.close()
    except Exception as e:
        raise e


def app():
    select_option = raw_input('Select your desired option. \n1. Send raw AT command \n2. Send USSD code: \n')
    print(select_option)
    ls_ports = list_ports()

    if select_option == '1':
        cmd_maker = command_maker()
        app_run(ls_ports, cmd_maker)
    elif select_option == '2':
        ussd = ussd_maker()
        app_run(ls_ports, ussd)
    else:
        app()


if __name__ == "__main__":
    app()
saviour123
  • 1,095
  • 2
  • 13
  • 21
  • 3
    My understanding is that USSD commands are asynchronous - the `OK` is just saying that the command was accepted, the actual response will be received at an arbitrary time in the future (depending on how long it took the network to process the command). A longer timeout than 3 seconds would probably get the response, but I don't think there's any particular delay that would be *guaranteed* to get it. The proper way to do this is to keep reading until you see a line with the proper prefix (something like `+USSD:`, I think). – jasonharper Nov 07 '17 at 14:40
  • Thanks, do you think my reading loop is set up well? because I increased the time and i still got okay. – saviour123 Nov 07 '17 at 15:28
  • @jasonharper am i right with loop: I have made the loop an infinite loop and any command about the hardware returns "ok" and ussd returns okay with no output even while waiting for 5+ seconds... – saviour123 Nov 09 '17 at 16:33
  • @saviour123 I believe the logic will need to be more complicated than what you have. You read until there are bytes waiting in the serial port, but nothing guarantees that they arrive "instantly" together. For example, you could get `O`, then `K` and then `\r`, with some delays in between. So you should be reading until you get a reply terminated by a response you know that's final, like `OK' or 'ERROR` (or a variant of thereof). – Petr Nov 14 '17 at 19:44
  • so i did introduce `time.sleep(5); ser.read_all()` and I am okay now. – saviour123 Nov 14 '17 at 19:47
  • @saviour123 Furthermore, it seems that you're not enclosing the USSD string in double quotes, please see https://stackoverflow.com/q/15850819/1333025. I also doubt that there should be spaces in the command around commas, better check the specifications. Using `read_all()` seems to be incorrect and to work just by luck. What does 'all' mean here? The library doesn't know the modem commands, it doesn't know when it should stop reading, when you'll have 'all' data. You'll need to know the modem protocol and keep reading until you know the device returned full output. – Petr Nov 14 '17 at 19:52
  • Possible duplicate: [AT COMMANDS - USSD returns only OK](https://stackoverflow.com/q/29319976/1333025). – Petr Nov 14 '17 at 19:52
  • Possible duplicate of [AT COMMANDS - USSD returns only OK](https://stackoverflow.com/questions/29319976/at-commands-ussd-returns-only-ok) – Petr Nov 14 '17 at 19:53

0 Answers0