Форум

Исправляем кодировку вывода SMS в SMPP

На основе прошлой статьи пришло несколько отзывов, что поддерживается только латиница. Ну давайте добавлять кириллицу, и заодно поддержку эмодзи.

Создаем файл app.py. Вводим:

Код
import smpplib.clientimport smpplib.constsimport smpplib.gsmimport smpplib.exceptionsfrom flask import Flask, jsonify, render_templatefrom flask_sqlalchemy import SQLAlchemyimport threadingimport atexit
# Настройки Flask и базы данныхapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sms.db'app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)
# Модель для хранения SMS сообщенийclass SMSMessage(db.Model):    id = db.Column(db.Integer, primary_key=True)    source = db.Column(db.String(20))    destination = db.Column(db.String(20))    message = db.Column(db.String(160))    timestamp = db.Column(db.DateTime, default=db.func.current_timestamp())
# Создаем таблицы в базе данныхwith app.app_context():    db.create_all()
# Данные для подключения к SMPP серверуSMPP_SERVER = "smpp.exolve.ru"SMPP_PORT = 2775SYSTEM_ID = "логин"PASSWORD = "пароль"
# Функция для обработки входящих сообщенийdef handle_message(pdu):    try:        # Попытка декодировать сообщение с разными кодировками        try:            if pdu.data_coding == 0x08:  # UCS2 кодировка                message = pdu.short_message.decode('utf-16-be')            else:                message = pdu.short_message.decode('utf-8')        except UnicodeDecodeError:            # Если не удалось, пробуем GSM 7-бит (возможные латинские символы)            try:                message = smpplib.gsm.decode(pdu.short_message)            except:                # Если ничего не помогло, сохраняем как есть                message = pdu.short_message.decode('latin1')
        source = pdu.source_addr.decode('utf-8') if isinstance(pdu.source_addr, bytes) else pdu.source_addr        destination = pdu.destination_addr.decode('utf-8') if isinstance(pdu.destination_addr, bytes) else pdu.destination_addr
        # Создаем контекст приложения Flask        with app.app_context():            # Сохраняем сообщение в базе данных            sms = SMSMessage(source=source, destination=destination, message=message)            db.session.add(sms)            db.session.commit()
        print(f"Received message: {message}")        print(f"From: {source}")        print(f"To: {destination}")
    except UnicodeDecodeError as e:        print(f"Ошибка декодирования сообщения: {e}")    except smpplib.exceptions.ConnectionError as e:        print("Connection lost with SMPP server:", e)
# Создаем клиента SMPPclient = smpplib.client.Client(SMPP_SERVER, SMPP_PORT)
# Включаем логирование (опционально)client.set_message_received_handler(handle_message)
# Функция для корректного закрытия SMPP клиентаdef close_smpp_client():    if client:        try:            client.unbind()        finally:            client.disconnect()
# Регистрация функции закрытия соединения при завершении работы приложенияatexit.register(close_smpp_client)
# Подключаемся и регистрируемся как приемник (только для получения сообщений)client.connect()client.bind_receiver(system_id=SYSTEM_ID, password=PASSWORD)
# Запуск прослушивания SMPP сообщений в отдельном потокеlistener_thread = threading.Thread(target=client.listen, daemon=True)listener_thread.start()
# Веб-интерфейс для отображения полученных SMS@app.route('/')def index():    return render_template('index.html')
# Маршрут для получения сообщений в формате JSON@app.route('/get_messages', methods=['GET'])def get_messages():    messages = SMSMessage.query.order_by(SMSMessage.timestamp.desc()).all()    messages_data = []    for sms in messages:        messages_data.append({            "source": sms.source.decode('utf-8') if isinstance(sms.source, bytes) else sms.source,            "destination": sms.destination.decode('utf-8') if isinstance(sms.destination, bytes) else sms.destination,            "message": sms.message,            "timestamp": sms.timestamp.strftime('%Y-%m-%d %H:%M:%S')        })    return jsonify(messages_data)
# Запуск веб-приложения на порту 5001if __name__ == '__main__':    try:        app.run(debug=True, port=5001)    finally:        close_smpp_client()
И тут давайте сразу напишем обновленный index.html
Код
<!DO CTYPE html><ht ml lang="ru"><head>    <met a charset="UTF-8">    <met a name="viewport" content="width=device-width, initial-scale=1.0">    <title>Полученные SMS сообщения</title>    <st yle>        .message-text {            color: green;            font-weight: bold;        }    </style>    <sc ript>        // Функция для загрузки сообщений        function loadMessages() {            fetch('/get_messages')                .then(response => response.json())                .then(data => {                    const messageList = document.getElementById('message-list');                    messageList.innerHTML = '';  // Очищаем список сообщений                    data.forEach(sms => {                        const listItem = document.createElement('li');                        listItem.innerHTML = `<span class="message-text">${sms.message}</span> <strong>От:</strong> ${sms.source} <strong>Кому:</strong> ${sms.destination} <strong>Получено в:</strong> ${sms.timestamp}`;                        messageList.appendChild(listItem);                    });                })                .catch(error => console.error('Error loading messages:', error));        }
        // Обновляем сообщения каждые 5 секунд        setInterval(loadMessages, 5000);
        // Загрузка сообщений при загрузке страницы        window.onl oad = loadMessages;    </sc ript></head><body>    <h1>Полученные SMS сообщения</h1>
    <h2>Сообщения</h2>    <ul id="message-list">        <!-- Сообщения будут динамически добавляться сюда -->    </ul></body></html>


Объяснение работы кода

app.py

1. Инициализация Flask и SQLAlchemy:
  • Приложение Flask и база данных SQLAlchemy инициализируются в начале кода.
  • Создается модель SMSMessage, которая определяет структуру данных для хранения SMS-сообщений в базе данных.
2. Подключение к SMPP серверу:
  • Устанавливается подключение к SMPP серверу с использованием предоставленных учетных данных (IP-адрес, порт, SYSTEM_ID, PASSWORD).
  • Клиент регистрируется как приемник сообщений с использованием методаbind_receiver.
3. Обработка входящих сообщений:
  • Функция handle_message обрабатывает входящие сообщения.
  • В зависимости от кодировки (data_coding) определяется, как декодировать сообщение.
  • Декодированные сообщения сохраняются в базе данных.
4. Запуск прослушивания сообщений:
  • Прослушивание входящих сообщений выполняется в отдельном потоке, чтобы не блокировать работу веб-сервера Flask.
  • В случае завершения работы приложения, соединение с SMPP сервером корректно закрывается с помощью функции close_smpp_client.
5. Веб-маршруты:
  • Главная страница (/) возвращает HTML-шаблон.
  • Маршрут /get_messages возвращает список сообщений в формате JSON, которые затем отображаются на веб-странице.
index.html

1. Интерфейс пользователя:
  • Страница содержит заголовок и список сообщений, который будет динамически обновляться.
2. CSS стили:
  • Сообщение (sms.message) отображается первым и выделено зеленым цветом с использованием класса message-text.
3. Jav * aScript:
  • Вызов функции loadMessages происходит каждые 5 секунд для загрузки новых сообщений с сервера.
  • Сообщения отображаются на странице без необходимости перезагрузки страницы.
Как это работает:
  • Когда приходит новое SMS-сообщение, оно декодируется и сохраняется в базе данных.
  • Веб-интерфейс каждые 5 секунд отправляет запрос на сервер для получения списка сообщений и обновляет отображение.
  • Если SMS-сообщение содержит кириллические символы, они корректно декодируются и отображаются благодаря обработке в функции handle_message.
Этот подход обеспечивает стабильную работу с SMS-сообщениями, содержащими символы на разных языках, включая кириллицу и латиницу.
2
135
Открытая тема
0 баллов

Для того, чтобы оставлять комментарии, необходимо пройти авторизацию

Авторизоваться
эмодзи  :D  :D  :D  
oleg
oleg
0 баллов
14 дней назад в 04:35
Интересно следить за развитием проекта!
moderator
moderator
0 баллов
10 дней назад в 12:16