Бюджетная рассылка СМС

    Приветствую всех хаброжителей!

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

    Итак-с… Опускаем все варианты реализации на базе обычного компа и оси семейства 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)



    В связке с моей системой мониторинга устройство ведет себя адекватно, хотя работает не так давно. Надеюсь, материал будет полезен кому-нибудь.
    Метки:
    Поделиться публикацией
    Комментарии 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
                                                                Может это достойно статьи? С удовольствием почитал бы.

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