Пользователь
0,0
рейтинг
7 ноября 2015 в 20:07

Разработка → Бюджетная рассылка СМС

Python*, C++*
Приветствую всех хаброжителей!

Конечно, зализанная тема про рассылку смс сообщений, но как говориться: «много — не мало». Как-то так получилось, что именно она меня постоянно преследует: то одни, то другие добрые люди попросят принять участие (советом, например) в реализации бюджетной рассылки сообщений. И поэтому чтобы не пропадать накопленному добру, оставлю здесь, а вдруг кому-то пригодится…

Итак-с… Опускаем все варианты реализации на базе обычного компа и оси семейства NT. А перейдем сразу к «автономным» системам.

Чем может похвастаться arduino в этом направлении? Отвечу сразу, ОНО работает, но есть нюансы, о которых напишу ниже. Вообщем, имеем китайский вариант arduino 2560 (было перепробовано практически вся линейка) и два дополнительных модуля — сеть W5100 (наиболее стабильный вариант) и GSM SIM 900. Выглядит это все дело как-то так.

image

Задача была следующая:
— устройство должно уметь общаться по http
— отправлять сообщение
— выдавать результат в формате json

Гугл делится всей необходимой информацией, и на выходе получаем следующий код:

Скетч
#include <SPI.h>
#include <Ethernet.h>

#include <String.h>

#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

byte mac[] = { 0x90, 0xA2, 0x00, 0x00, 0x00, 0x01 };    
IPAddress ip(192,168,34,139);                              

EthernetServer server(80);

char char_in = 0;    
String HTTP_req;    

SMSGSM sms;

boolean started=false;
bool power = false;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {

  Serial.begin(9600);       
  
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.print("INIT GSM...");
  lcd.setCursor(0,1);
  lcd.print("WAIT!!!");
  
  //powerUp();
  gsm.forceON();
  
  if (gsm.begin(4800)) {
    Serial.println("\nstatus=READY");
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("READY");    
    started=true;  
  }
  else {
    Serial.println("\nstatus=IDLE");
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("IDLE");
  }
  
  Ethernet.begin(mac, ip); 
  server.begin();         
  
}

void software_reset() {
  asm volatile ("  jmp 0");  
} 

void loop() {
  EthernetClient client = server.available();

  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char_in = client.read();  //
        HTTP_req += char_in;      

        if (char_in == '\n') {  
          
          Serial.println(HTTP_req);
          
          if(HTTP_req.indexOf("GET /res") >= 0) {
            reset_processing(&HTTP_req, &client);
            break;
          }

          if(HTTP_req.indexOf("GET /sms") >= 0) {
            sms_processing(&HTTP_req, &client);
            break;
          }    

          if(HTTP_req.indexOf("GET /test") >= 0) {
            test_processing(&HTTP_req, &client);
            break;
          }   
          else {
            client_header(&client);  
            break;
          }     
        }
      }
    }
    HTTP_req = "";    
    client.stop();
  } 
  
  if(power) {
    delay(1000);
    software_reset();
  }
}

char* string2char(String command) {
  if(command.length()!=0){
    char *p = const_cast<char*>(command.c_str());
    return p;
  }
}

void parse_data(String *data) {
  data->replace("GET /sms/","");
  data->replace("GET /test/", "");

  int lastPost = data->indexOf("\r");
  *data = data->substring(0, lastPost);
  data->replace(" HTTP/1.1", "");
  data->replace(" HTTP/1.0", "");
  data->trim();
}

// explode
 String request_value(String *data, char separator, int index) {
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data->length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++) {
    if(data->charAt(i)==separator || i==maxIndex) {
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }
  return found>index ? data->substring(strIndex[0], strIndex[1]) : "";
}

bool gsm_status() {
  bool result = false;
  switch(gsm.CheckRegistration()) {
    case 1:
      result = true;
      break;
    default:
      break;
  }
  return result;
}

bool gsm_send(char *number_str, char *message_str) {
  bool result = false;
  switch(sms.SendSMS(number_str, message_str)) {
    case 1:
      result = true;
      break;
    default:
      break;
  } 
  return result; 
}

void reset_processing(String *data, EthernetClient *cl) {
  client_header(cl);    
  cl->println("\{\"error\": 0, \"message\": \"restarting...\"\}");  

  power = true;   
}

void test_processing(String *data, EthernetClient *cl) {
  parse_data(data);
  
  if(started) {
    client_header(cl);
    cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":0" + ",\"message\":\"test success\"\}");   
  }
}

void sms_processing(String *data, EthernetClient *cl) {
  parse_data(data);

  if(started) {
    if (gsm_send(string2char(request_value(data, '/', 1)), string2char(request_value(data, '/', 2)))) {
      client_header(cl);
      cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":0" + ",\"message\":\"success\"\}");
    }
    else {
      if(!gsm_status()) {
        client_header(cl);
        cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":2" + ",\"message\":\"gsm not registered\"\}");   
        power = true;
      }
      else {
        client_header(cl);
        cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":1" + ",\"message\":\"fail\"\}");     
      }
    }
  }
}

void client_header(EthernetClient *cl) {
  cl->println("HTTP/1.1 200 OK");
  cl->println("Content-Type: text/plain");
  cl->println("Connection: close");  
  cl->println();
}



Заливаем, упаковываем в коробочку. Вроде бы выглядит красиво, отдаем добрым людям.

image

Что получилось в коде:
— подняли простенький http
— обрабатываем простые GET
— отправляем полученные данные через SERIAL на SIM 900
— отвечаем с помощью «JSON»

И вот тут есть один большой нюанс, перед умными людьми стоит задача реализовать какой-нибудь сервис, чтобы научиться отправлять через это устройство сразу пачку сообщений, но это уже не мои проблемы. В производстве устройство себя повело удовлетворительно.

Наращиваем мощности… Задача полностью аналогичная: повторение — мать учения. Умные люди уже создали классный сервис для работы с предыдущим устройством: очередь, история и прочие полезности.

Итак, на руках имеем raspberry pi, такой же модуль SIM 900 (был взят только ради экспериментов, потому что линукс прекрасно работает с 3g-модемами через USB) и сам 3g-modem huawei e-линейки

image

Снова задаем гуглу нужные вопросы, читаем результаты, определяемся с языком реализации — python — быстро, просто, надежно…

скрипт
import serial, time
from flask import Flask
import RPi.GPIO as GPIO

app = Flask(__name__)


def sim900_on():
    gsm = serial.Serial('/dev/ttyAMA0', 115200, timeout=1)
    gsm.write('ATZ\r')
    time.sleep(0.05)

    abort_after = 5
    start = time.time()
    output = ""

    while True:
        output = output + gsm.readline()
        if 'OK' in output:
            gsm.close()
            return True
        delta = time.time() - start
        if delta >= abort_after:
            gsm.close()
            break


    #GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)                
    GPIO.setup(11, GPIO.OUT)                
    GPIO.output(11, True)                 
    time.sleep(1.2)
    GPIO.output(11, False) 
    return False


def gsm_send(id, port, phone, msg):

    delay = False
    if 'AMA' in port:
        delay = True


    msg = msg.replace('\\n', '\n')
    msg = msg.replace('\s', ' ')

    gsm = serial.Serial('/dev/tty%s' % port, 115200, timeout=1)
    gsm.write('ATZ\r')

    if delay:
        time.sleep(0.05)

    gsm.write('AT+CMGF=1\r\n')

    if delay:
        time.sleep(0.05)

    gsm.write('AT+CMGS="%s"\r\n' % phone)

    if delay:
        time.sleep(0.05)

    gsm.write(msg + '\r\n')

    if delay:
        time.sleep(0.05)

    gsm.write(chr(26))

    if delay:
        time.sleep(0.05)

    abort_after = 15
    start = time.time()
    output = ""

    while True:

        output = output + gsm.readline()
        #print output
        if '+CMGS:' in output:
            print output
            gsm.close()
            return '{"id":%s,"error":0,"message":"success", "raw":"%s"}' % (id, output)
        if 'ERROR' in output:
            print output
            gsm.close()
            return '{"id":%s,"error":0,"message":"fail", "raw":"%s"}' % (id, output)

        delta = time.time() - start
        if delta >= abort_after:
            gsm.close()
            return '{"id":%s,"error":1,"message":"timeout", "raw":"%s"}' % (id, output)

@app.route('/sms/<id>/<port>/<phone>/<msg>',methods=['GET'])
def get_data(id, port, phone, msg):
    return gsm_send(id, port, phone, msg)

@app.route('/',methods=['GET'])
def index():
    return "Hello World"

if __name__ == "__main__":
    sim900_on()
    app.run(host="0.0.0.0", port=8080, threaded=True)



Скармливаем питону, запускаем с помощью «start-stop-daemon», придаем дружелюбный вид, отдаем добрым людям…

image

Получилось практически один в один, только за счет шины USB систему можно расширять. В производстве претензий вообще не оказалось — все были ОЧЕНЬ довольны.

Устройство получилось настолько удачным, что появилось желание использовать это дело в «личных» интересах, а именно внедрить в систему мониторинга данный аппарат. Но надо было избавиться от главного нюанса — отсутствие очереди сообщений. Принцип реализации я взял у одного известного вендора (он предлагал программно-аппаратный комлекс, часть которого поднимала smtp-сервер для обработки уведомлений и отправки ее на gsm-устройство). Такая схема встраивается в любую систему мониторинга.

Итак, нужные знания уже давно получены, приступаем к реализации.

SMTP-демон
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import smtpd
import asyncore
import email
import MySQLdb
import subprocess

def InsertNewMessage(phone, msg):
    conn = MySQLdb.connect(host="localhost", # your host, usually localhost
                     user="sms", # your username
                      passwd="sms", # your password
                      db="sms") # name of the data base
    c = conn.cursor()
    c.execute('insert into message_queue (phone, message) values ("%s", "%s")' % (phone, msg))
    conn.commit()
    conn.close()

class CustomSMTPServer(smtpd.SMTPServer):

    def process_message(self, peer, mailfrom, rcpttos, data):

        msg = email.message_from_string(data)
        phone = rcpttos[0].split('@',1)[0]
        addr = mailfrom

        for part in msg.walk():
            if part.get_content_type() == "text/plain": # ignore attachments/html
                body = part.get_payload(decode=True)


        InsertNewMessage(phone, str(body))

subprocess.Popen("/home/pi/daemons/sms/pygsmd.py", shell=True)

server = CustomSMTPServer(('0.0.0.0', 25), None)

asyncore.loop()



Демонизация происходит, как я уже писал выше, с помощью «start-stop-daemon», а сам smtp скрипт запускает подпроцесс для работы с базой сообщений.

gsm скрипт
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import serial
import time
import MySQLdb
import commands


def gsm_send(port, phone, msg):

    print 'Sending message: %s to: %s' % (msg, phone)
    gsm = serial.Serial('/dev/tty%s' % port,
                        460800,
                        timeout=5,
                        xonxoff = False,
                        rtscts = False,
                        bytesize = serial.EIGHTBITS,
                        parity = serial.PARITY_NONE,
                        stopbits = serial.STOPBITS_ONE )
    gsm.write('ATZ\r\n')
    time.sleep(0.05)
    gsm.write('AT+CMGF=1\r\n')
    time.sleep(0.05)
    gsm.write('''AT+CMGS="''' + phone + '''"\r''')
    time.sleep(0.05)
    gsm.write(msg + '\r\n')
    time.sleep(0.05)
    gsm.write(chr(26))
    time.sleep(0.05)

    abort_after = 15
    start = time.time()
    output = ""


    while True:

        output = output + gsm.readline()
        #print output
        if '+CMGS:' in output:
            #print output
            gsm.close()
            return 0
        if 'ERROR' in output:
            #print output
            gsm.close()
            return 1

        delta = time.time() - start
        if delta >= abort_after:
            gsm.close()
            return 1

def msg_delete(list):
    conn = MySQLdb.connect(host="localhost",
                     user="sms",
                      passwd="sms",
                      db="sms")
    c = conn.cursor()
    c.execute("delete from  message_queue where id in %s;" % list)
    conn.commit()
    conn.close()

def msg_hadle():
    list = tuple()
    conn = MySQLdb.connect(host="localhost",
                     user="sms",
                      passwd="sms",
                      db="sms")
    c = conn.cursor()
    c.execute("select * from message_queue")

    numrows = int(c.rowcount)
    if numrows > 0:
        for row in c.fetchall():
            result = gsm_send('USB0', ('+' +  row[1]),  row[2])
            if result == 0:
                list +=(str(row[0]),)

    conn.close()

    if len(list) == 1:
        qlist = str(list).replace(',','')

    if len(list) > 1:
        qlist = str(list)

    if len(list) > 0:
        msg_delete(qlist)

    del list

while True:
    try:
        msg_hadle()
    except:
        print "mysql error"

    time.sleep(10)



В связке с моей системой мониторинга устройство ведет себя адекватно, хотя работает не так давно. Надеюсь, материал будет полезен кому-нибудь.
Олег @ol_x
карма
8,0
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (64)

  • 0
    Дык конкретика-то где?
    Где железку такую дают? если в статье написано, сорри — далек я от этого, просьба ткнуть пальцем.

    Вообще, комплекс такой иметь было бы, пожалуй, интересно.
    • +1
      Девайсы все написаны ;) Arduino Mega 2560 + ethernet shield w5100 + gsm shield SIM 900. Raspberry Pi + SIM 900. На ebay все есть
      • 0
        А в кучке? 8-)
        • 0
          а кто его знает
        • 0
          Если использовать внешний свисток, то виртурилка подходит.
          • 0
            была у меня виндовая служба, а сама винда под esxi 5.1, пересылка через свисток часто вываливалась по таймауту, потом это все дело переехало на обычную машину и все стало хорошо. Видимо, там есть нюансы…
            • 0
              Думается имелось ввиду железо virt2real, а не виртуальная машина.
              • 0
                Именно так.
          • 0
            спасибо.
          • +1
            Подходит, то она подходит, но цена на нее довольно высока для такой задачи.
            • 0
              Вопрос был про коробочное решение. У вас есть варианты коробочных решений с промышленными диапазонами температур?
        • 0
          Кстати еще продукция IRZ вроде умела это все. А в новой линейке как раз WiFi появился.
  • +14
    Не касательно проделанной работы, почему во всех ховтушках на эту тему какой-то страшный комбайн из макетных плат, а не покупка и рутование китайфона на андроиде баксов за 30 с двумя симками и телевизором? Автономность, есть wifi и bt, софт пишется с пол пинка или находится готовый и хоть оботсылайся смсками, в качестве бонуса тачскрин, компактный корпус и автономность на пару суток.
    • 0
      WiFi сеть требует от администратора больше внимания. А вообще на вкус и цвет ;)
    • +31
      image
      • 0
        Это плавленый сыр на крыше? А зачем ПВА? А палочке от суши?
      • +14
        Какой то новый троллейбус. Сами собирали?
        • 0
          Найдено на просторах интернета :)
      • +1
        Красиво…
    • 0
      еще бюджетнее — любая звонилка за 500 рублей с microusb + PC
      sms отправляются через AT-команды, система горизонтально масштабируется покупкой дополнительных звонилок.
      • 0
        Ключевое +РС, задача была без РС, с компом хватит и одного модема.
      • +1
        Первый вариант обсуждать не буду, но во втором всё почти также.

        Вместо компа — raspberry. Полноценная linux машинка c ethernet и usb на борту. И крайне невысоким потреблением.
        Вместо звонилки — USB модем. При желании их (немного б/у) можно купить пачками с ценой за штуку по 200-400 рублей.

        Вот только не пойму зачем городить огород с питоном, когда на малинке великолепно запускается… да хоть kannel или asterisk (!!!), у которых есть штатный функционал по работе с SMS.
        А в случае с астериском можно ещё и звонить :)
        • 0
          почему сразу огород, для работы с апи астериска надо будет что-то писать, так что тут разницы нет
          • 0
            Справедливости ради… у астериска есть встроенный HTTP сервер, с его помощью можно тоже отправлять SMS.
            Астериск привёл скорее в качестве казуса, если надо быстро и нет опыта программирования, то kannel самый лучший вариант. Если же опыт есть, то ваш вариант очень неплох.

        • 0
          Опередили. =) У меня эта связка (paspberry pi и модем) была СМС-ретранслятором, реализованном на одном PHP скрипте в десяток строк…
    • 0
      Назовите для примера какой-то конкретный смартфон, точно позволяющий из линукса после рутования обращаться к телефонной части девайса и отправлять смс.

      Не из вредности спрашиваю, а реально пригодилось бы, если такое есть и испробованно на практике вами.
      • +1
        Да вообще на любом андроиде даже без рута ставятся приложухи типа play.google.com/store/apps/details?id=eu.apksoft.android.smsgateway на маркете много разных. Я рутовал лично jiayu g3, но там надо было свой софт засунуть для создания вотчдога, но если нужен тупо гейт, то вообще на любом хламе будет работать с готовым софтом из маркета.
        • 0
          Спасибо. О существовании таких вот приложений-гейтов, с которыми можно работать, например, через http-запросы — не знал. Благодаря вам стало ясно, что делать с древними девайсами :-)
        • 0
          С тем же успехом можно скрипты почти на всех современных свистках размещать.
          • 0
            Свисток стоит как китайфон, требует отдельного питания и аккумулятора, часто требует разлочки от оператора, а так да, можно. Но на телефоне у нас есть акум, полноценная ОС с кучей готового софта и как говориться зачем платить больше? Я вот ленивый и иду по пути наименьшего сопротивления, если можно обойтись без макеток и колхоза еще и дешевле, то незачем городить велосипед.
            • 0
              Это где такой китайфон с полноценным окружением и дешевле свистка?
              • 0
                Посмотрите на али модели 2х летней давности и старше. Вот в районе 30 баксов ru.aliexpress.com/item/Original-lenovo-A278t-smartphone-with-Dual-sim-card-1500mAh-battery-3-5-inch-screen-Free-shipping/1855071823.html?ws_ab_test=searchweb201556_1_79_78_77_91_80,searchweb201644_5,searchweb201560_9 В городе куча магазинов кто распродает похожие модельки дешевле 2К рублей по разным акциям. Покажите свисток ощутимо дешевле, который потом не надо разлочивать от оператора.
                • 0
                  ZTE MF823D ) А что плохого в разлочке, если она занимает 1 минуту?
                  А так куча модемов Huawei, которые работают в rndis режиме (хотя зачем оно?). Почти к любому современному модему можно подключиться с помощью ADB. Тут вам 4pda больше в помощь.
  • +3
    У меня вопрос из другой области: а что, делать смс-рассылки через реальную симку — это бюджетно?
    • +1
      в нашем случае получается дешевле того, что предлагается на рынке
      • 0
        Да но скорее всего нелегально, симки которые продают просто для абонементов не предполагают их использование в рассылках, серый бизнес на них давно существует, но нелегально ;(
    • +1
      Вполне.
      Сейчас стоимость коммерческой отправки SMS может оказаться в 3-5 раз выше, чем цена для розничного клиента.
      Для сравнения — отправка коммерческой SMS на крупных операторов — от 1 рубля, пакетные предложения тех же операторов (100+ SMS) при полном использовании пакета могут дать цену в 20-30 копеек за штуку.
      • +2
        O tempora, o mores!
      • +1
        Есть тарифы, где смс вообще не лимитированы.
    • 0
      Если пользоваться официальными ценниками — через обычную симку отправлять дешевле. А вот если как следует договориться, то отправка с указанием имени отправителя может быть и 5 копеек, вместо официального минимума в 50 копеек. Просто тогда (3,5 года назад) были планы на многомиллионные рассылки и возможность сказать «мы внучка всем известной компании, так что всё будет офигенно».
  • +1
    Кому нужно еще более бюджетно — есть модуль Neoway m590 по цене $5. Отлично работает, проверено. По такой цене даже б/у модем не купить (за редким исключением).

    Телефон б/у с гарантией работы и отсутствием геммора с аккумулятором/зарядкой тоже за $5 не купить.
  • 0
    На Электрониксе в каждой такой теме заказа девайса для sms-рассылок знатоки объясняют, что как только начнёте массово рассылать смски, вам отрубят симку, ОПСОСы не любят конкурентов, и вроде бы это уже незаконно.
    • +1
      не вижу логики, деньги оператор свои получает
    • +1
      Если на Вас будут жаловаться за спам или на содержание смсок (подходящие под УК) — это не законно и оператор может заблокировать Вам симку.

      Если же никаких жалоб не будет — никто Вам ничего не запретит и уж тем более не отключит сим-карту.

      Есть вопросы, если Вы начнете оказывать услуги по рассылке, и то не факт что смогут доказать и что-то сделать.

      Если Вы рассылаете смс-ки своим абонента и есть пункт про это в договоре или они дали на это свое согласие — вообще никто не докопается.

      Вобщем, чушь полная. У нас стоят такие рассылальщики на M590 и на базе андрюши уже очень давно — ни каких вопросов. от 60-100 смс-ок в день с каждого.

      P.S. Ну и если даже — купить пачку анонимных симок — копейки сейчас — так что тоже не проблема.
      • 0
        За что купил, за то и продал. И я сказал «массово», 60 смсок с одной симки — это пшик. На проблемы жаловались люди, у которых батареи в несколько десятков модулей с суточной рассылкой десятков тысяч смс.
  • +5
    c.execute('insert into message_queue (phone, message) values ("%s", "%s")' % (phone, msg))


    SQL-инъекции через СМС — это оригинально. Замените на следующее хотя бы:

    c.execute('insert into message_queue (phone, message) values ("%s", "%s")', (phone, msg))

    • 0
      Возьму на заметку… но в моем случае это не критично, все входящие либо закрыто, либо открыто только для того, кого нужно
      • +6
        но в моем случае это не критично


        Вы усложняете на ровном месте. Вместо того, чтобы один раз запомнить «никогда не вставлять raw user input в sql-запросы», вы вводите дополнительную оценку OPASNO и в зависимости от нее делаете либо правильно либо нет (причем трудозатраты на оба варианта эквивалентны). Зачем?
  • +2
    Я уже несколько лет использую Андроид (аппарат S2, хотя не суть важно) и SMSGateway. Тут вам не только уже все готово + батарея на случай падения электричества, так еще и все устанавливается и настраивается за 5 мин. Я совсем не против ардуино и велосипедов, но по ценам тут совсем не адекват.
  • –1
    К raspberry никто не мешает прикрутить аккумулятор — энергопотребление там такое же низкое, как и на андрофоне. Что касается цен, то достаточно изучить рынок аналогичных устройств для продакшена, там ценник в разы выше.
  • 0
    Боже-ж ты мой!
    Зачем Вы изобретали то, что давным давно уже есть.

    Во-первых любой телефон с поставленным спец. софтом делает тз него SMS-Gate, софта куча бесплатного искать все по той-же фразе «sms gate».
    Во-вторых: M590

    Обсосана сверху до низу, стоит 350 рублей!
    По ссылке вообще по 325. Цепляйте хоть к ардуино, хоть к роутеру, хоть к PC.

    А расберри тут как стрельба гаубицей по воробьям.
    • +1
      А M590, который опять же для arduino, это не велосипед? )
      • 0
        Я вроде бы два варианта привел, нет?
        Вы почему-то увидели только один.

        Кроме того, M590 гораздо меньший велосипед, чем то, что в статье — он напрямую может быть подцеплен к роутеру или PC (а не только к ардуино) и работать сразу-же без плясок с бубнами, доп шилдов и т.д.
  • 0
    Я, конечно, понимаю, что мой комментарий находится в несколько иной плоскости от этого технического поста, но на мой личный персональный взгляд проще приобрести какой-нибудь тариф от Мегафона на подобие «миллион бесплатных СМС, зато звонки адски дорогие» и воспользоваться, например, программой Фабрика СМС, которая осуществляет сложные параметрические рассылки с рекурсиями, итерациями, блек-джеком и куртизанками только силами и средствами самого телефона и сим-карты. Не?
  • +1
    К примеру, у мегафна есть нормальный человеческий SOAP API для отправки SMS (использование шлюза стоит рубль в день, смс по вашему тарифу)
    sms.megafon.ru:8443/index.jsp

    Шлём примерно 50-100 штук в день
    • 0
      Круто, а если связи не будет?
      • 0
        За несколько лет было три неуспешных попытки (повтор через 30-180 секунд решил проблему).
        При использовании коробки логически аналогичной вашей (модем вставленный в сервер) неуспешных попыток было 100-200 (БС отрубалась стабильно раз в 1-2 месяца на 10-60 минут, пару раз поймали этот момент за уши и таки да, это не глюк модема, мобилки тоже были без связи).
        Собственно схема с XML пришла на смену модему, т.к. модемная схема показала себя как ненадёжная.А у нас это смски мониторинга.
        • 0
          У нас как раз-таки все наоборот, не успешные попытки практически сводятся к нулю. Выбор зависит строго от условий. Но лично я предпочитаю, когда оборудование находится рядом с системой мониторинга.
          • +2
            Мы тоже так думали (выглядит логично). Но как только профилактика БС пару раз вылилась в финансовые потери решили уйти от кустарного решения.
            По поводу канала связи с API: модем в сервере остался, если с API или каналом всё плохо(>30 секунд), будет попытка через модем.
            • 0
              Дублирование, на мой взгляд, самое правильное решение, не стоит обходиться только одним способом.
      • 0
        Сделать сообщению статус доставки(в БД — всего лишь одно поле) — и сделать по крону попытки отправить сообщения.
        Нет связи — не доставилось, следующее событие крона — отправится, если сможет.
        Можно добавить Fail-counter — 3 раза не отправилось, и не отправляем.

        Вполне себе легко реализуется.
  • 0
    Самое бюджетное — использовать Telegram-бота для таких целей) Если что — могу помочь с ботом.
    • 0
      Может это достойно статьи? С удовольствием почитал бы.
      • 0
        Хорошая идея)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.