Skip to content

Instantly share code, notes, and snippets.

@weimzh
Last active November 19, 2023 11:31
Show Gist options
  • Save weimzh/66fb93b8aac11690ec2ab59f99d9b50a to your computer and use it in GitHub Desktop.
Save weimzh/66fb93b8aac11690ec2ab59f99d9b50a to your computer and use it in GitHub Desktop.
Quick and dirty code to read and send SMS messages for Huawei EC122 CDMA Modem. Might be buggy, use with caution.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2022, Wei Mingzhi <whistler_wmz@users.sf.net>.
# SPDX-License-Identifier: BSD-3-Clause
# https://spdx.org/licenses/BSD-3-Clause.html
#
# Quick and dirty code to read and send SMS messages for Huawei EC122 CDMA Modem.
#
# Most likely this will NOT work with any other GSM/CDMA phones/modems, as the AT
# commands of Huawei EC122 seem different from Nokia's or any other GSM modems.
#
# Please use a better solution like Gammu for supported modems:
# https://wammu.eu/
import serial
import sys
import re
import logging
logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
def _write_cmd(ser, cmd):
logging.debug('writing command: ' + cmd)
cmd = ('AT' + cmd).encode('ascii') + serial.CR + serial.LF
ser.write(cmd)
def _get_line(ser):
line = b''
line_began = False
while True:
ch = ser.read(size=1)
if not line_began:
if ch == serial.CR or ch == serial.LF:
continue
line_began = True
if ch == serial.CR:
ser.read(size=1) # skip LF
return line.decode('ascii')
line += ch
return line
def _unlock_pin(ser, pin):
_write_cmd(ser, '^CPIN="' + pin + '"')
while True:
line = _get_line(ser)
if line.startswith('OK'):
logging.debug('PIN unlocked')
break
elif line.startswith('+CMS ERROR'):
logging.error('PIN unlock error, exiting immediately to avoid SIM locking!!! ' + line)
sys.exit(255)
def read_all_sms_ec122(port, delete_sms=False, pin=None):
ser = serial.Serial(port=port, baudrate=19200)
try:
if pin is not None:
_unlock_pin(ser, pin)
sms_list = []
sms_text_list = []
logging.debug('getting sms list...')
_write_cmd(ser, '^HCMGL')
while True:
line = _get_line(ser)
if line.startswith('^HCMGL'):
line_split = re.split('[:,]', line)
index = int(line_split[1])
sms_list.append(index)
elif line.startswith('+CMS ERROR'):
logging.error('get sms list error: ' + line)
return None
elif line.startswith('OK'):
break
for index in sms_list:
_write_cmd(ser, '^HCMGR=' + str(index))
while True:
line = _get_line(ser)
if line.startswith('^HCMGR'):
line_split = re.split('[:,]', line)
(dummy, caller_id, year, month, day, hour, minute, second, lang, fmt, length, v3, v4, v5, v6) = line_split
sms_data = ser.read(size=int(length))
ser.read(size=3) # skip ^Z CR LF
fmt = int(fmt)
if fmt == 1:
sms_text = sms_data.decode('ascii')
elif fmt == 6:
sms_text = sms_data.decode('utf-16be')
else:
logging.info('unsupported sms format, skipping: ' + str(fmt))
break
stat_line = _get_line(ser)
if stat_line != 'OK':
logging.error('ending line is not OK: ' + stat_line)
else:
s = {}
s['Number'] = caller_id
s['Text'] = sms_text
s['DateTime'] = (int(year), int(month), int(day), int(hour), int(minute), int(second))
sms_text_list.append(s)
break
if delete_sms:
for index in sms_list:
_write_cmd(ser, '+CMGD=' + str(index))
while True:
line = _get_line(ser)
if line.startswith('OK'):
logging.debug('SMS deleted: ' + str(index))
break
elif line.startswith('+CMS ERROR'):
logging.error('SMS delete error: ' + str(index))
break
return sms_text_list
finally:
ser.close()
def send_sms_ec122(port, dest, text, pin=None):
ser = serial.Serial(port=port, baudrate=19200)
try:
if pin is not None:
_unlock_pin(ser, pin)
_write_cmd(ser, '^HCMGS="' + dest + '"')
ser.write(text.encode('utf-8'))
ser.write(int(26).to_bytes(1, 'big'))
while True:
line = _get_line(ser)
if line.startswith('+CMS ERROR'):
logging.error('send sms error: ' + line)
break
elif line.startswith('OK'):
logging.info('send sms ok')
break
finally:
ser.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment