From 96ccc75a7178996ba5f91f1c716ff82230903169 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Sun, 20 Nov 2022 04:27:59 +0100 Subject: [PATCH] Add support for newer SIMCom devices This patch adds support to event driven calls for newer SIMCom devices such as the SIM7100, SIM7500, and SIM7600. These devices support the command "AT+CLCC=1" which sets the modem to print the CLCC output on every call status change. I made an effort to to probe modem upport for automatic reporting by trying setting AT+CLCC to 1. The untested assumption is that the command will fail if the modem does not support it. The regular expressions used for _handleCallAnswered, _handleCallInitiated, and _handleCallEnded are simply a copy and paste from the regular expression used for CLCC, replacing what was on the third group by a fixed number representing the call status. For example, using the number 6 to indicate that the call was disconnected. To detect the newer devices I used the availability of the +SIMCOMATI command but I am not really sure how reliable this is. My concern is of false positives for devices that could support the +SIMCOMATI and not support the automatic reporting of "AT+CLCC=1". This was tested on an SIM7600G. Signed-off-by: Peter Senna Tschudin --- gsmmodem/modem.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/gsmmodem/modem.py b/gsmmodem/modem.py index 1272190..11fd36e 100644 --- a/gsmmodem/modem.py +++ b/gsmmodem/modem.py @@ -255,6 +255,8 @@ def connect(self, pin=None, waitingForModemToStartInSeconds=0): enableWind = True elif '+ZPAS' in commands: callUpdateTableHint = 3 # ZTE + if '+SIMCOMATI' in commands: + callUpdateTableHint = 4 # SIMCom else: # Try to enable general notifications on Wavecom-like device enableWind = True @@ -323,6 +325,38 @@ def connect(self, pin=None, waitingForModemToStartInSeconds=0): self._waitForCallInitUpdate = False # ZTE modems do not provide "call initiated" updates if commands == None: # ZTE uses standard +VTS for DTMF Call.dtmfSupport = True + elif callUpdateTableHint == 4: # SIMCom (Tested on SIM7600) + self.log.info('Loading SIMCOM call state update table') + self._mustPollCallStatus = False + Call.dtmfSupport = True + try: + # Enables automatic reporting of the list of current calls + # when the call status changes + self.write('AT+CLCC=1') + except CommandError: + # Modem does not support automatic reporting of the list of + # current calls when the call status changes + self.log.info('Will use polling for call state updates') + self._mustPollCallStatus = True + + # This works well with the SIM7600G for example + if not self._mustPollCallStatus: + # Using the field of the AT+CLCC command. Notice the + # numbers between groups 1 and 2 on the following regexes + # + # The possible values are: + # 0 – active + # 1 – held + # 2 – dialing (MO call) + # 3 – alerting (MO call) + # 4 – incoming (MT call) + # 5 – waiting (MT call) + # 6 – disconnect + self._callStatusUpdates = ( + (re.compile('^\+CLCC:\s+(\d+),(\d),0,(\d),([^,]),"([^,]*)",(\d+)$'), self._handleCallAnswered), + (re.compile('^\+CLCC:\s+(\d+),(\d),2,(\d),([^,]),"([^,]*)",(\d+)$'), self._handleCallInitiated), + (re.compile('^\+CLCC:\s+(\d+),(\d),6,(\d),([^,]),"([^,]*)",(\d+)$'), self._handleCallEnded), + (re.compile('^BUSY$'), self._handleCallRejected)) else: # Unknown modem - we do not know what its call updates look like. Use polling instead self.log.info('Unknown/generic modem type - will use polling for call state updates') @@ -567,7 +601,7 @@ def supportedCommands(self): except (TimeoutException, CommandError): # Try interactive command recognition commands = [] - checkable_commands = ['^CVOICE', '+VTS', '^DTMF', '^USSDMODE', '+WIND', '+ZPAS', '+CSCS', '+CNUM'] + checkable_commands = ['^CVOICE', '+VTS', '^DTMF', '^USSDMODE', '+WIND', '+ZPAS', '+CSCS', '+CNUM', '+SIMCOMATI'] # Check if modem is still alive try: