用希伯来语发送短信

问题描述 投票:0回答:3

我正在使用 sms1.cardboardfish.com 通过网络感知短信。我有这些数据编码方案可以使用: 0:闪光 1:正常 2:二进制 4:UCS2 5:闪存UCS2 6:闪光GSM 7:正常GSM 我想用希伯来语发送。现在我用 7: 正常 GSM 发送,结果是乱码..有人有想法吗?

sms
3个回答
4
投票

以UCS2发送,这是正常的UTF-16编码。

我认为这应该可以解决问题:

>>> a=u"שלום"
>>> a
u'\u05e9\u05dc\u05d5\u05dd'
>>> a.encode("utf_16_be").encode("hex")
'05e905dc05d505dd'

2
投票

请注意,当使用多字节字符集(例如 UCS2)时,每条消息的最大字符数将显着减少。众所周知的 160 个字符限制基于 7 位字符集,而使用 16 位字符集,您将被限制为 70 个字符。


0
投票

我创建了一个Python脚本作为调制解调器驱动程序来满足我的所有需求(以ascii或utf8(包括希伯来语)发送短信,拨打电话..),

先决条件: 从 cmd 运行命令:

pip install pyserial

将以下代码保存在文件中

gsm_modem.py

import serial.tools.list_ports
import time
import os
from utils import log
import threading


# read more here:
# https://www.smssolutions.net/tutorials/gsm/sendsmsat/
# https://www.smssolutions.net/tutorials/gsm/receivesmsat/


# constants to represent the GSM modem encoding modes (GSM, USC2)
GSM_MODE = 1 # GSM mode
UNICODE_MODE = 2 # UCS2 mode


# class to represent the GSM modem
class GSMModem:    
    # current encoding mode
    current_mode = GSM_MODE
    
    def __init__(self):
        # default port name, will be updated by find_modem_port functionבךד
        self.modem_port_name = 'COM9'
        # modem serial port object, used to communicate with the modem
        self.serial_port = None
        # flag to indicate if the modem is initialized
        self.is_modem_initialized = False

    
    def find_modem_port(self):
        ports = serial.tools.list_ports.comports()
        for port, desc, hwid in sorted(ports):
            log("[found port]  {}: {} [{}]".format(port, desc, hwid))
            if 'modem' in desc.lower():
                self.modem_port_name = port
                log(f"Found modem at port: {self.modem_port_name}")
                return
        
        raise Exception("No modem found.")


    def connect_to_modem(self):
        # Open serial connection to the modem
        log(f"Connecting to modem on port: {self.modem_port_name}")
        self.serial_port = serial.Serial(self.modem_port_name, 9600, timeout=2)
        # Wait for the modem to initialize
        time.sleep(2)
        if not self.serial_port.is_open:
            raise Exception(f"Failed to connect to modem, serial port: {self.modem_port_name} failed to open.")
        log("Successfully connected to modem")
   

    def at_command(self, command, expected_response=b'OK', wait_before_read=0.2):
        # send AT command to the modem
        log(f"AT Command: {command}")
        
        # if command is instance of string, encode it to bytes
        if isinstance(command, str):
            self.serial_port.write(command.encode('utf-8') + b'\r\n')
        else:
            self.serial_port.write(command)
        
        # allow the command to be precesed before reading the response
        time.sleep(wait_before_read)
    
        # Read response from modem, until timeout is reached or the requested bytes are read
        response = self.serial_port.read_all()
        log(f"AT Response: {response.decode('utf-8')}")
            
        # Check if modem returned the expected response
        if expected_response not in response:
            raise Exception("Error: Modem did not respond with the expected response, we expected: " + expected_response.decode('utf-8') + " but got: " + response.decode('utf-8') + " instead.")
        
        return response


    # this function will be called only once, when the first action is performed on the modem
    # it will initialize the modem and open the serial port
    # it will send some AT commands to the modem to initialize it
    # it will also set the is_modem_initialized flag to True
    def initialize_modem(self):        
        if self.is_modem_initialized:
            return
        
        self.find_modem_port() # Find the modem port
        self.connect_to_modem() # Open serial connection to the modem
        
        self.at_command('at', expected_response=b'') # Send some dummy message
        self.at_command(bytes([3]), wait_before_read=2, expected_response=b'')  # Send Ctrl+C character to cancel any send sms process
        self.at_command(bytes([26]), wait_before_read=2, expected_response=b'') # Send Ctrl+Z character to finish any sms process
        self.at_command('AT+CSCS="GSM"') # Set the modem to use GSM encoding
        self.at_command('ATE0') # Disable local echo
        self.at_command('AT') # Send AT command to test modem is ok
        self.at_command('ATH') # Hang up any existing connections
        self.at_command('ATZ') # Reset modem to default settings
        # Set the GSM modem to send SMS in text mode (and not PDU mode)
        self.at_command('AT+CMGF=1')
        # set the modem to read sms messages from the SIM card
        self.at_command('AT+CPMS="SM","SM","SM"')
        
        # Set modem initialization flag
        self.is_modem_initialized = True


    # this function will send an SMS message to the specified phone number
    # it will first initialize the modem if it's not initialized yet
    # then it will send the SMS message using the AT commands
    def send_sms(self, phone_number, message):
        # check if the message contains a utf-8 character
        try:
            # try to encode the message to ascii, if it fails, it means the message contains a utf-8 character
            message.encode('ascii')
            if self.current_mode == UNICODE_MODE:
                # if the current mode is unicode, we need to switch to GSM mode (7-bit Ascii encoding)
                self.at_command('AT+CSCS="GSM"', expected_response=b'OK')
                # set the modem to use ASCII encoding for the SMS message
                self.at_command('AT+CSMP=,,0,0', expected_response=b'OK')
                self.current_mode = GSM_MODE
        except UnicodeEncodeError:
            if self.current_mode == GSM_MODE:
                # if the current mode is GSM, we need to switch to UCS2 mode (UTF-16BE hex encoding)
                self.at_command('AT+CSCS="UCS2"', expected_response=b'OK')
                # set the modem to use UTF-8 encoding for the SMS message
                self.at_command('AT+CSMP=17,167,0,8', expected_response=b'OK')
                self.current_mode = UNICODE_MODE
            # if the message contains a utf-8 character, we need to encode it to utf-16
            phone_number = phone_number.encode('utf-16-be').hex().upper()
            message = message.encode('utf-16-be').hex().upper()

        # Set the phone number to send the SMS to
        self.at_command(f'AT+CMGS="{phone_number}"', expected_response=b'>')
        # set the sms message to send as bytes to prevent at_commannd function from adding \r\n to the message
        self.at_command(message.encode('utf-8'), expected_response=b'')
        # send the sms message by sending Ctrl+Z character
        self.at_command(bytes([26]), expected_response=b'', wait_before_read=3)  # Send Ctrl+Z character


    def hangup(self):
        # Hang up any existing connections
        self.at_command('ATH', wait_before_read=1)


    def call_phone(self, phone_number):
        # make a call to the recipient phone number
        self.at_command('ATD{};'.format(phone_number), expected_response=b'OK', wait_before_read=1)
        

    def check_modem_status(self):
        # Check modem status
        self.at_command('ATI') # returns the product identification information
        self.at_command('ATI3') # returns the product firmware version
        self.at_command('AT+CREG?', b'+CREG: 0,1', wait_before_read=1) # gives information about the registration status and access technology of the serving cell
        self.at_command('AT+CSQ', b'+CSQ:', wait_before_read=1) # Check signal quality
        self.at_command('AT+CGATT?', b'+CGATT: 1', wait_before_read=1) # Check if the device is attached to the packet domain service
        self.at_command('AT+CGREG?', b'+CGREG: 0,1', wait_before_read=1) # 
        self.at_command('AT+CGDCONT?', b'+CGDCONT:', wait_before_read=1) # check the modem PDP context parameter type
        self.at_command('AT+COPS?', b'+COPS:', wait_before_read=1) # check the current mode, registered operator, and radio access technology
        self.at_command('AT+CGACT?', b'+CGACT:', wait_before_read=1) # check the status of the PDP context (Activated or Deactivated)
        self.at_command('AT+CGPADDR=1', b'+CGPADDR:', wait_before_read=1) # returns the IP address(es) of the PDP context(s)


    def close_serial_port(self):
        if self.serial_port is not None:
            self.serial_port.close()
            self.serial_port = None
            log("Serial port closed")


    # my modem uses an app to communicate with the modem, so it needs to be up and running before sending AT commands
    def start_modem_app(self):
        # start the modem app
        log("Starting modem app...")
        os.system('start "" "C:\\Program Files\\4G LTE Modem\\App.exe"')
        # sleep for 5 seconds and allow the app to start
        time.sleep(5)
        
    
    # my modem uses an app to communicate with the modem, so i need to stop it first if it is running
    def stop_modem_app(self):
        # kill the modem app process
        log("Killing modem app process...")
        os.system('taskkill /f /im App.exe')
        # sleep for 5 seconds
        time.sleep(5)
        
        
    def restart_modem_app(self):
        self.stop_modem_app()
        self.start_modem_app()



####### test the GSMModem class #######
test_phone_number = "+972555111111" # replace with your phone number

modem = GSMModem()
# modem.restart_modem_app()
modem.initialize_modem()

start_time = time.time()
modem.send_sms(test_phone_number, "test 1")
print(time.time()-start_time)

start_time = time.time()
modem.send_sms(test_phone_number, "test 2")
print(time.time()-start_time)

start_time = time.time()
modem.send_sms(test_phone_number, "test 3")
print(time.time()-start_time)

# place a call to the phone number
modem.call_phone(test_phone_number)

# launch a thread that will hangup the call in 10 seconds
threading.Timer(10, modem.hangup).start()

备注:

  • test_phone_number
    替换为您的电话号码
  • 使用以下命令运行脚本:
    py .\gsm_modem.py
    进行测试
  • 您将收到3条短信,以及1个10秒后挂断的电话
  • 它会自动找到您的 USB 调制解调器所在的串行端口

为了将其用作驱动程序: 注释或删除所有测试行(从第195行到文件末尾) 从这一行开始:

####### test the GSMModem class #######
直到文件末尾

然后你可以从这样的代码中调用它:

modem = GSMModem()
modem.initialize_modem()
modem.send_sms(test_phone_number, "test 1")
modem.call_phone(test_phone_number)
modem.hangup()
© www.soinside.com 2019 - 2024. All rights reserved.