Further command updates

More commands added. A few efficiency updates. command() not accepts non AT commands. Timeouts localised. Non blocking power on/off option now available.
tildatorch
Alistair MacDonald 2018-08-22 13:48:42 +01:00 committed by GitHub
parent f2a3b23872
commit f900bb320f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 100 additions and 55 deletions

View File

@ -4,7 +4,7 @@ import time
uart_port = 1 uart_port = 1
uart_default_baud = 115200 uart_default_baud = 115200
uart_timeout = 28 uart_timeout = 28
default_responce_timeout = 8000 default_responce_timeout = 2000
status_pin = Pin(6, Pin.IN) status_pin = Pin(6, Pin.IN)
ringer_pin = Pin(8, Pin.IN) ringer_pin = Pin(8, Pin.IN)
@ -24,7 +24,7 @@ def isringing():
# Identify if this was a positive responce # Identify if this was a positive responce
def ispositive(responce): def ispositive(responce):
return (responce=="OK") or responce.startswith("CONNECT") return (responce=="OK") or responce.startswith("CONNECT") or responce.startswith("> ")
# Identify if this was a negative responce # Identify if this was a negative responce
def isnegative(responce): def isnegative(responce):
@ -45,21 +45,26 @@ def readline():
# If we time out we are at the end of a line # If we time out we are at the end of a line
if charin is None: if charin is None:
return stringin return stringin
# Look for all EOL chars just in case settigns were changed # We this the end of the line?
elif (charin == b'\n') or (charin == b'\r'): elif (charin == b'\r'):
if (stringin!=""): if (stringin!=""):
return stringin return stringin
# This will be part of the string then # This will be part of the string then
else: elif not (charin == b'\n'):
stringin += str(charin, "ASCII") stringin += str(charin, "ASCII")
# Execute a command on the module # Execute a command on the module
# command is the AT command without the AT or CR/LF, responce_timeout (in ms) is how long to wait for completion, custom_endofdata is to wait for a non standard bit of # command is the AT command without the AT or CR/LF, responce_timeout (in ms) is how long to wait for completion, custom_endofdata is to wait for a non standard bit of
def command(command="", responce_timeout=default_responce_timeout, custom_endofdata=None): def command(command="AT", responce_timeout=default_responce_timeout, custom_endofdata=None):
global dirtybuffer
# Empty the buffer # Empty the buffer
uart.read() uart.read()
# Do not bother if we are powered off
if not ison():
dirtybuffer = False
return ["POWERED OFF"]
# Send the command # Send the command
uart.write("AT" + command + "\r\n") uart.write(command + "\r")
# Read the results # Read the results
result = [] result = []
complete = False complete = False
@ -82,45 +87,46 @@ def command(command="", responce_timeout=default_responce_timeout, custom_endofd
# We ran out of time # We ran out of time
# set the dirty buffer flag is an out of date end of responcs cound end up in the buffer # set the dirty buffer flag is an out of date end of responcs cound end up in the buffer
if custom_endofdata is None: if custom_endofdata is None:
global dirtybuffer
dirtybuffer = True dirtybuffer = True
result.append("TIMEOUT") result.append("TIMEOUT")
return result return result
# Power on the SIN800 # Power on the SIM800 (True=on, False=off, returns true when on)
def poweron(): def power(onoroff, async):
# Only power on if we are off # Get to a stable state if not async
if not ison(): if not async and pwr_key_pin.value():
# Check that the power pin has not beel left high
if (pwr_key_pin.value()):
pwr_key_pin.off()
time.sleep(1)
pwr_key_pin.on()
time.sleep(3)
pwr_key_pin.off() pwr_key_pin.off()
# Send a command to autonigotiate UART speed
command()
time.sleep(2)
uart.read() # Empty the buffer
# Power off the SIN800
def poweroff():
# Only power off if we are on
if (status_pin.value()):
# Check that the power pin has not beel left high
if (pwr_key_pin.value()):
pwr_key_pin.off()
time.sleep(1)
pwr_key_pin.on()
time.sleep(3) time.sleep(3)
# Press the virtual power key if we are off
if not (ison()==onoroff):
pwr_key_pin.on()
if not async:
time.sleep(3)
# Have we just turned on?
isonnow = ison()
if (isonnow==onoroff) and pwr_key_pin.value():
# Stop pressing the virtual key
pwr_key_pin.off() pwr_key_pin.off()
uart.read() # Empty the buffer # Clear the buffer
uart.read()
dirtybuffer = False dirtybuffer = False
# Send a command to autonigotiate UART speed
if isonnow:
command("AT")
return isonnow
# Power on the SIM800 (returns true when on)
def poweron(async=False):
power(True, async)
# Power off the SIM800
def poweroff(async=False):
power(False, async)
# Change the speed on the communication # Change the speed on the communication
def uartspeed(newbaud): def uartspeed(newbaud):
global uart global uart
command("+IPR=" + str(newbaud)) command("AT+IPR=" + str(newbaud))
uart.deinit() uart.deinit()
if (newbaud==0): if (newbaud==0):
uart = machine.UART(uart_port, uart_default_baud, mode=UART.BINARY, timeout=uart_timeout) uart = machine.UART(uart_port, uart_default_baud, mode=UART.BINARY, timeout=uart_timeout)
@ -129,50 +135,81 @@ def uartspeed(newbaud):
# Make a voice call # Make a voice call
def call(number): def call(number):
command("D" + str(newbaud) + ";") command("ATD" + str(number) + ";", 20000)
# Answer a voice call # Answer a voice call
def answer(number): def answer():
command("A") command("ATA", 20000)
# End a voice call # End a voice call
def handup(): def hangup():
command("H") command("ATH")
# Redial the last number
def redial():
command("ATDL")
# Play DTMF tone(s) on a call
def dtmf(number):
validdigits = '1234567890#*ABCD'
for digit in str(number).upper():
if (digit in validdigits):
command("AT+VTS=" + digit)
elif (digit==','):
time.sleep(1)
# Send an SMS message
def sendsms(number, message):
# Swith to text mode
command("AT+CMGF=1")
# Switch to ASCII(ish)
command("AT+CSCS=\"8859-1\"")
# Send the message
command("AT+CMGS=\"" + str(number) + "\"")
return command(message + "\x1a", 60000)
# Get the IMEI number of the SIM800
def imei():
responce = command("AT+GSN")
if (len(responce)>=2):
return responce[len(responce)-2]
else:
return ""
# Get/Set ringer volume (0-100) # Get/Set ringer volume (0-100)
def ringervolume(level=None): def ringervolume(level=None):
# Set the new leve if we have one to set # Set the new leve if we have one to set
if level is not None: if level is not None:
command("+CRSL=" + str(level)) command("AT+CRSL=" + str(level))
# Retieve the set level to report back # Retieve the set level to report back
responce = command("+CRSL?") responce = command("AT+CRSL?")
return int(extractval("+CRSL:", responce, 0)) return int(extractval("+CRSL:", responce, 0))
# Get/Set speaker volume (0-100) # Get/Set speaker volume (0-100)
def speakervolume(level=None): def speakervolume(level=None):
# Set the new leve if we have one to set # Set the new leve if we have one to set
if level is not None: if level is not None:
command("+CLVL=" + str(level)) command("AT+CLVL=" + str(level))
# Retieve the set level to report back # Retieve the set level to report back
responce = command("+CLVL?") responce = command("AT+CLVL?")
return int(extractval("+CLVL:", responce, 0)) return int(extractval("+CLVL:", responce, 0))
# Is the battery charging (0=no, 1=yes, 2=full) # Is the battery charging (0=no, 1=yes, 2=full)
def batterycharging(): def batterycharging():
responce = command("+CBC") responce = command("AT+CBC")
vals = extractval("+CBC:", responce, "0,0,0").split(",") vals = extractval("+CBC:", responce, "0,0,0").split(",")
return int(vals[0]) return int(vals[0])
# How full is the battery (1-100) # How full is the battery (1-100)
def batterycharge(): def batterycharge():
responce = command("+CBC") responce = command("AT+CBC")
vals = extractval("+CBC:", responce, "0,0,0").split(",") vals = extractval("+CBC:", responce, "0,0,0").split(",")
return int(vals[1]) return int(vals[1])
# List the available operator (returns list of [0=?,1=available,2=current,3=forbidden], 0=long name, 1=short name, 2=GSMLAI ) # List the available operator (returns list of [0=?,1=available,2=current,3=forbidden], 0=long name, 1=short name, 2=GSMLAI )
def listoperators(available_only=True): def listoperators(available_only=True):
delim = "||||" delim = "||||"
responce = command("+COPS=?", 45000) responce = command("AT+COPS=?", 45000)
responcedata = extractval("+COPS:", responce, "").split(",,")[0] responcedata = extractval("+COPS:", responce, "").split(",,")[0]
responcelist = responcedata.replace("),(",delim)[1:-1].split(delim) responcelist = responcedata.replace("),(",delim)[1:-1].split(delim)
results = [] results = []
@ -186,8 +223,8 @@ def listoperators(available_only=True):
# Get the current operator (format 0=long name, 1=short name, 2=GSMLAI) # Get the current operator (format 0=long name, 1=short name, 2=GSMLAI)
def currentoperator(format=0): def currentoperator(format=0):
command("+COPS=3," + str(format)) command("AT+COPS=3," + str(format))
responce = command("+COPS?") responce = command("AT+COPS?")
responcedata = extractval("+COPS:", responce, "").split(",") responcedata = extractval("+COPS:", responce, "").split(",")
if (len(responcedata)>=3): if (len(responcedata)>=3):
return responcedata[2].strip("\"") return responcedata[2].strip("\"")
@ -201,23 +238,31 @@ def soperator(mode, format=None, operator=None):
params += "," + str(format) params += "," + str(format)
if operator is not None: if operator is not None:
params += "," + str(operator) params += "," + str(operator)
command("+COPS=" + str(mode) + params, 120000) command("AT+COPS=" + str(mode) + params, 120000)
# Get the activity status (returns 0=ready, 2=unknown, 3=ringing, 4=call in progress) # Get the activity status (returns 0=ready, 2=unknown, 3=ringing, 4=call in progress)
def getstatus(): def getstatus():
responce = command("+CPAS") responce = command("AT+CPAS")
vals = extractval("+CPAS:", responce, "2") vals = extractval("+CPAS:", responce, "2")
return int(extractval("+CPAS:", responce, "2")) return int(extractval("+CPAS:", responce, "2"))
# Request Unstructured Supplementary Service Data from network
def ussd(ussdstring, timeout=8000):
responce = command("AT+CUSD=1,\"" + ussdstring + "\"", timeout, "+CUSD:")
return extractval("+CUSD:", responce, "")
# Get my number # Get my number (only works on some networks)
def getmynumber(): def getmynumber():
responce = command("+CUSD=1,\"*#100#\"", 8000, "+CUSD:") responcedata = ussd("*#100#", 8000).split(",")
responcedata = extractval("+CUSD:", responce, "").split(",")
if (len(responcedata)>=2): if (len(responcedata)>=2):
return responcedata[1].strip().strip("\"") return responcedata[1].strip().strip("\"")
else: else:
return "" return ""
# Turn on the SIM800
poweron()
# Start turning on the SIM800
poweron(True)