西门子iRZ ES75iT GSM调制解调器发送含AT命令短信技术咨询
Alright, let's tackle this problem head-on. The core issue here is that your GSM modem will misinterpret any AT-prefixed text in your message as an actual AT command (instead of part of the SMS content). Below are two reliable solutions, along with fixes for your existing Python script.
Why This Happens
When using text mode (the default for many simple SMS scripts), the modem listens for AT sequences even while you're inputting message content. So if your SMS says something like "Check AT+CMGF settings", the modem will try to run AT+CMGF as a command instead of sending it as text.
Solution 1: Escape AT Sequences in Text Mode (Quick Fix)
If you want to stick with text mode (the approach your current script uses), you just need to add an escape character before any AT in your message. For Siemens modems, the standard escape character is a backslash (\).
Here's your modified sendsms function with this fix, plus some debug improvements to help you troubleshoot:
import serial import time def sendsms(to, message): # Replace @ with null char (as your original script does) message = message.replace('@', '\0') # Escape AT sequences so the modem treats them as plain text message = message.replace('AT', '\\AT') # Trim message to GSM text mode limit (160 chars max for 7-bit encoding) if len(message) > 160: message = message[:160] print("Connecting to modem...") ser = serial.Serial('/dev/ttyS0', 115200, timeout=12) time.sleep(1) # Send AT command to check modem connectivity ser.write('AT\r') time.sleep(1) print("AT command response:", ser.read_all().decode('utf-8').strip()) # Explicitly set text mode (avoids default mode inconsistencies) ser.write('AT+CMGF=1\r') time.sleep(1) print("Text mode setup response:", ser.read_all().decode('utf-8').strip()) # Delete old SMS (as your original script does) ser.write('AT+CMGD="ALL"\r') time.sleep(2) print("Delete SMS response:", ser.read_all().decode('utf-8').strip()) # Send the SMS ser.write(f'AT+CMGS="{to}"\r') time.sleep(1) # Send message content, then end with Ctrl+Z (ASCII 26) to trigger send ser.write(message.encode('utf-8') + b'\x1A') time.sleep(3) response = ser.read_all().decode('utf-8').strip() print("SMS send response:", response) ser.close()
Solution 2: Switch to PDU Mode (More Reliable)
Text mode is prone to edge cases like this. For any SMS with special content (including AT commands, non-ASCII characters), PDU mode is the better choice. It encodes the message as binary, so the modem never confuses content with commands.
Here's a complete script using PDU mode, with a simplified encoding function for GSM 7-bit text:
import serial import time def encode_gsm_pdu(phone_number, message): """Encode SMS content and phone number into a PDU string (GSM 7-bit encoding).""" # Process phone number (E.164 format, reversed nibbles) num = phone_number.lstrip('+') if len(num) % 2 != 0: num += 'F' # Pad with F if length is odd encoded_num = ''.join([num[i+1] + num[i] for i in range(0, len(num), 2)]) # Process message content (GSM 7-bit character set) encoded_msg = '' for char in message: # Map standard ASCII to GSM 7-bit code (simplified for common characters) gsm_code = ord(char) if 0x20 <= gsm_code <= 0x7E: encoded_msg += format(gsm_code, '02X') # Add handling for special GSM characters (like €, ñ) if needed # Build full PDU string msg_length = len(encoded_msg) // 2 pdu = f'0011000D91{encoded_num}0000{format(msg_length, "02X")}{encoded_msg}' return pdu, len(pdu) // 2 # Return PDU string and its length in bytes def sendsms(to, message): print("Connecting to modem...") ser = serial.Serial('/dev/ttyS0', 115200, timeout=12) time.sleep(1) # Verify modem connectivity ser.write('AT\r') time.sleep(1) print("AT response:", ser.read_all().decode('utf-8').strip()) # Switch to PDU mode ser.write('AT+CMGF=0\r') time.sleep(1) print("PDU mode setup response:", ser.read_all().decode('utf-8').strip()) # Clear old SMS ser.write('AT+CMGD="ALL"\r') time.sleep(2) print("Clear SMS response:", ser.read_all().decode('utf-8').strip()) # Encode message to PDU pdu_str, pdu_byte_len = encode_gsm_pdu(to, message) # Send SMS via PDU command ser.write(f'AT+CMGS={pdu_byte_len}\r') time.sleep(1) ser.write(pdu_str.encode('utf-8') + b'\x1A') time.sleep(3) response = ser.read_all().decode('utf-8').strip() print("SMS send response:", response) ser.close()
Key Notes for Success
- Debug with Responses: Always read the modem's response after each AT command (like I did in the scripts). A response of
OKmeans success;ERRORmeans something went wrong (check your command syntax or modem settings). - Baud Rate Check: Confirm your modem uses 115200 baud. If not, query the current rate with
AT+IPR?and adjust theserial.Serialparameter. - Character Limits: Text mode supports up to 160 7-bit characters; PDU mode supports the same, or 70 characters if using UCS2 encoding (for non-ASCII text like Chinese).
内容的提问来源于stack exchange,提问作者Programming Lover

