You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python结合AT命令模拟GSM Modem余额并触发短信发送?

GSM调制解调器模拟余额并关联短信发送解决方案

我想用Python通过GSM调制解调器发送AT命令,模拟或修改调制解调器的余额,让代码识别这个模拟余额后给指定手机号发短信。目前已经实现了短信发送和余额查询功能,但没办法完成余额模拟及关联短信发送的部分。

原代码

# Configure the serial port (replace with your specific port)
ser = serial.Serial('COM3', 9600, timeout=1)

import serial
import time
def read_phone_numbers(filename):
    with open(filename, 'r') as file:
        phone_numbers = [line.strip() for line in file]
    return phone_numbers

def send_sms(phone_number, message):
    try:
        # Send SMS using AT commands
        ser.write(b'AT\r')
        time.sleep(1)
        ser.write(b'AT+CMGF=1\r')  # Set SMS mode to text
        time.sleep(1)
        ser.write(f'AT+CMGS="{phone_number}"\r'.encode())
        time.sleep(1)
        ser.write(message.encode() + b'\x1A')  # Send the message and Ctrl+Z to end
        time.sleep(1)
        print(f'SMS sent to {phone_number}')

        # Read the modem response (optional)
        response = ser.read(ser.in_waiting).decode('utf-8')
        print('Modem response:', response)
    except serial.SerialException as se:
        print('Serial port exception:', str(se))
    except Exception as e:
        print('Failed to send SMS:', str(e))
    finally:
        # Close the serial port
        ser.close()

# Usage
phone_numbers = read_phone_numbers('phone_numbers.txt')
message = 'This is a test message from Python using GSM modem.'

for phone_number in phone_numbers:
    send_sms(phone_number, message) 

# 余额查询代码
import serial
import time

# Configure the serial port (replace with your specific port)
ser = serial.Serial('COM3', 9600, timeout=1)

def check_balance():
    try:
        # Send AT command to check balance (hypothetical example)
        ser.write(b'AT+CUSD=1,"*123#",15\r')
        time.sleep(1)

        # Read and print the modem response
        response = ser.read(ser.in_waiting).decode('utf-8')
        print('Balance response:', response)
    except Exception as e:
        print('Failed to check balance:', str(e))
    finally:
        # Close the serial port
        ser.close()

# Usage
check_balance()

核心思路

GSM调制解调器的实际余额由运营商服务器管控,无法通过AT命令直接修改。我们可以在代码层面实现本地模拟余额,替代真实的余额查询结果,然后基于这个模拟余额判断是否执行短信发送操作。

修改后的完整代码

import serial
import time

# 配置串口(替换为你的实际端口)
SERIAL_PORT = 'COM3'
BAUD_RATE = 9600
TIMEOUT = 1

# 模拟余额设置
LOCAL_BALANCE = 5.0  # 初始模拟余额,单位:元
SMS_COST = 0.1        # 每条短信的费用

def read_phone_numbers(filename):
    with open(filename, 'r') as file:
        phone_numbers = [line.strip() for line in file]
    return phone_numbers

def check_simulated_balance():
    """返回模拟余额"""
    global LOCAL_BALANCE
    return LOCAL_BALANCE

def deduct_balance():
    """发送短信后扣除对应费用"""
    global LOCAL_BALANCE
    LOCAL_BALANCE -= SMS_COST
    print(f"已扣除短信费用 {SMS_COST} 元,当前模拟余额: {LOCAL_BALANCE:.2f} 元")

def send_sms(ser, phone_number, message):
    try:
        # 设置短信模式为文本
        ser.write(b'AT+CMGF=1\r')
        time.sleep(0.5)
        # 指定接收手机号
        ser.write(f'AT+CMGS="{phone_number}"\r'.encode())
        time.sleep(0.5)
        # 发送短信内容+结束符Ctrl+Z
        ser.write(message.encode() + b'\x1A')
        time.sleep(1)
        # 读取调制解调器响应
        response = ser.read(ser.in_waiting).decode('utf-8', errors='ignore')
        if "OK" in response:
            print(f"SMS成功发送至 {phone_number}")
            deduct_balance()
        else:
            print(f"SMS发送至 {phone_number} 失败,响应: {response}")
    except serial.SerialException as se:
        print(f"串口异常: {str(se)}")
    except Exception as e:
        print(f"发送SMS失败: {str(e)}")

def main():
    ser = None
    try:
        # 打开串口
        ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=TIMEOUT)
        time.sleep(2)  # 等待调制解调器初始化
        # 测试串口连通性
        ser.write(b'AT\r')
        time.sleep(0.5)
        response = ser.read(ser.in_waiting).decode('utf-8')
        if "OK" not in response:
            print("调制解调器未响应,请检查串口配置")
            return
        
        # 读取手机号列表
        phone_numbers = read_phone_numbers('phone_numbers.txt')
        message = '这是一条来自Python+GSM调制解调器的测试短信。'
        
        # 检查模拟余额
        current_balance = check_simulated_balance()
        print(f"当前模拟余额: {current_balance:.2f} 元")
        
        # 遍历手机号发送短信(仅当余额足够时)
        for phone_number in phone_numbers:
            if check_simulated_balance() >= SMS_COST:
                send_sms(ser, phone_number, message)
            else:
                print(f"模拟余额不足,无法给 {phone_number} 发送短信")
                break  # 余额不足时停止发送
    except Exception as e:
        print(f"程序异常: {str(e)}")
    finally:
        # 关闭串口
        if ser and ser.is_open:
            ser.close()
            print("串口已关闭")

if __name__ == "__main__":
    main()

关键说明

  • 模拟余额管理:通过LOCAL_BALANCE变量模拟余额,发送短信后自动扣除SMS_COST设定的费用
  • 串口优化:统一在main函数中打开和关闭串口,避免原代码中每次调用函数都关闭串口导致的后续操作失败
  • 余额判断逻辑:发送短信前检查模拟余额,余额不足时停止发送流程
  • 响应处理:增加了对调制解调器响应的判断,确保短信发送成功后才扣除余额

内容的提问来源于stack exchange,提问作者Strong Imade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 14:00:54