Реализация отправки sms-уведомлений

    В виду достаточно большого парка серверов/свитчей/модемов и иного активного оборудования в конторе, была установленная система мониторинга zabbix и успешно использовалась продолжительное время. Zabbix имеет замечательную возможность отправки уведомлений о возникших проблемах.
    Для этого был написан скрипт отправки sms сообщений через шлюз email-to-sms оператора связи, ограничение по количеству смс с одного адреса в сутки было обойдено путем ротации исходящих адресов, работало более или мение сносно, но в последнее время смс сообщения через данный шлюз начали доходить с задержкой порядка 10-15 минут, что уже не очень нравилось.
    Итак, было решено организовать отправку уведомлений через собственный GSM-терминал, порывшись в прайсах поставщиков и не обнаружив там подходящих по цене и характеристикам GSM модемов весьма огорчился.
    И тут вспомнилось что дома валяется старый Siemens CX65 да еще и data-кабель к нему, после подключения телефона и курения доков по отправке sms сообщений пришел к не очень радостному выводу, оказывается siemens не поддерживает отправку sms в текстовом режиме, команда AT+CMGF=1 возвращает error.
    Отправка сообщений в данных аппаратах возможна только в режиме PDU, ради спортивного интереса и для размятия мозгов было решено реализовать эту систему, был написан скрипт для перекодировки в PDU формат сообщений и отправки через телефон.

    Мануал по системе отправки сообщений можно найти здесь: dreamfabric.com/sms
    Сам получившийся скрипт:
    #!/usr/bin/python
    
    import os
    import sys
    import time
    
    def dectobin(i):
    	b = ''
    	while i > 0:
    		j = i & 1
    		b = str(j) + b
    		i >>= 1
    	return b
    
    def SendSMS(dev,number,text):
    	pdu_data = '00'
    	pdu_data += '11' #SMS-SUBMIT
    	pdu_data += '00' #TP-Message-Reference
    	pdu_data += '0B' #Address-Length
    	pdu_data += '91' #Address-Length
    	'''Convert telephone number'''
    	number += 'F'
    	pdu_number = ''
    	for i in range(0,len(number)):
    		if i%2==0:
    			continue
    		pdu_number += number[i] + number[i-1]
    	pdu_data += pdu_number
    	pdu_data += '00' #TP-Protocol identifier
    	pdu_data += '00' #TP-Data coding scheme
    	pdu_data += 'AA' #TP-Validity-Period
    	
    	'''Convert text to binary format'''
    	pdu_text_bin = []
    	for i in text:
    		dec_s=ord(i)
    		if dec_s == 95:
    			dec_s = 17
    		if dec_s == 94:
    			dec_s = 1
    		if dec_s == 64:
    			dec_s = 0
    		if dec_s == 36:
    			dec_s = 2
    		if dec_s == 123:
    			dec_s = 40
    		if dec_s == 125:
    			dec_s = 41
    		if dec_s == 124:
    			dec_s = 64
    		if dec_s == 126:
    			dec_s = 61
    		if dec_s == 92:
    			dec_s = 47
    		if dec_s == 91:
    			dec_s = 60
    		if dec_s == 93:
    			dec_s = 62
    		bin = dectobin(dec_s)
    		le = len(bin)
    		while le<7:
    			bin='0'+bin
    			le = len(bin)		
    		pdu_text_bin.append(bin)
    	
    	'''Encode binary to PDU format'''
    	pdu_text_bin_cp = []
    	n=0
    	for i in range(0,len(text)):
    		if (i>0) & ((i+1)%8==0):
    			continue
    		n+=1
    		if n==8:
    			n=1
    		if i==len(text)-1:
    			cp = pdu_text_bin[i][0:8-n]
    		else:
    			cp = str(pdu_text_bin[i+1][7-n:7] + pdu_text_bin[i])[0:8]
    		pdu_text_bin_cp.append(cp)
    			
    	'''Convert PDU to hex'''
    	pdu_text=''
    	for i in pdu_text_bin_cp:
    		hexi = str(hex(int(i,2)))[2:4].upper()
    		if len(hexi) == 1:
    			hexi = '0' + str(hexi)
    		pdu_text += hexi
    	
    	'''Calculate text length'''
    	len_hex = hex(len(text))[2:4].upper()
    	if len(len_hex) == 1:
    		len_hex = '0' + str(len_hex)
    		
    	'''Calculate PDU length'''
    	pdu_data+=len_hex+pdu_text
    	pdu_len = str(len(pdu_data)/2-1)
    	
    	if True:
    		fd = os.open(dev, os.O_RDWR)
    		os.write(fd, "AT+CMGF=0 \015")
    		time.sleep(1)
    		os.write(fd, "AT+CMGS=" + pdu_len + "\015")
    		time.sleep(1)
    		os.write(fd, pdu_data + "\032")
    		os.close(fd)
    	
    def main(argv):
    	SendSMS("/dev/ttyUSB0",argv[1],argv[2] + '\r\n' + argv[3])
    	return 0
    
    if __name__ == '__main__': main(sys.argv)

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

    Телефон подключается при помощи data-кабеля, который представляет собой usb-serial переходник, основанный на чипе Prolific pl2303, данный чип стабильно работает в linux, никаких нареканий на работу связки телефон-комп нет.
    Для корректной работы скрипта необходимо перед началом работы выставить нужные параметры ком-порта.
    Для этого в /etc/udev/rules.d/50-udev.rules была добавлена следующая строчка:
    KERNEL=="ttyUSB[0-9]", RUN+="/bin/stty -F /dev/%k speed 9600 -brkint -icrnl ixoff -imaxbel -opost -onlcr -isig -icanon -echo -echoe"
    Теперь при каждом подключении кабеля параметры com-порта выставляются автоматически, нет необходимости запускать приложения вручную.
    Далее в zabbix не сложная настройка и система отправки уведомлений готова, бюджетный вариант с GSM-терминалом работает гораздо лучше чем сервисы email-to-sms, плюс может отправлять уведомления о том что упал канал в инет, ранее после падения инета отправка соответственно не могла быть осуществлена.

    Возможно данный материал будет кому либо полезен, старая мобилка наверняка валяется у каждого дома, а покупать gsm-модем стоймостью более 8000 рублей не очень хочется.
    Поделиться публикацией

    Похожие публикации

    Комментарии 44

      0
      Дешевле же через какой-нибудь clickatell.com. не через email, а напрямую. не?
      А телефон — не выбрасывайте, еще можно использовать как GPRS-модем.
        0
        Понятно что можно, но во первых это стоит денег, во вторых если пропадает инет то я об этом не узнаю )
          +3
          SMS через телефон тоже стоит денег. А у сервиса — $0.027 ~ 90 коп. / сообщение
          Тем более что на тестовый режим они дают 10 сообщений опробовать сервис.
          Вариантов API выбирай на цвет и вкус: http(s) get/post, xml rpc/soap, smpp, smtp, dcom, даже ftp api

          Про интернет. Думаю, раз уж вы так насчет SMS конкренто разобрались, то использовать сотик как модем и подавно.
            +2
            Смартс, смски по 10копеек )
          0
          спасибо, искал такой сервис.
      • НЛО прилетело и опубликовало эту надпись здесь
          +3
          Я для этих целей использовал свою старую нокию и библиотеку mCore.
          Очень удобно создавать и отправлять сообщение.

          mCore.SMS objSMS = new mCore.SMS();

          // Настройка подключения и проверка
          // что подключение уже установлено
          private void SendSms()
          {
              if (!objSMS.IsConnected)
              {
                objSMS.Port = "COM4";
                objSMS.BaudRate = mCore.BaudRate.BaudRate_19200;
                objSMS.DataBits = mCore.DataBits.Eight;
                objSMS.Parity = mCore.Parity.None;
                objSMS.StopBits = mCore.StopBits.One;
                objSMS.FlowControl = mCore.FlowControl.None;
                objSMS.DisableCheckPIN = false;// chkDisableCheckPIN.Checked;
                objSMS.Encoding = mCore.Encoding.Unicode_16Bit;
              }
              string strSendResult = objSMS.SendSMS("+7921XXXXXXX", "MS SQL сервер упал!", false);
          }


          * This source code was highlighted with Source Code Highlighter.


          Поддерживает кучу мобильных телефонов, и довольно много всяких интересных функций, таких как USSD запросы, получение и чтение входящих SMS и другое.

          Единственный минус, конечно, что она платная. Зато есть триальная версия. Ограничение триала в том, что ко всем SMS'кам будет дописывать строчка внизу, что SMS отправлено с помощью этой библиотеки.

            0
            А ещё вместо отправки email'а можно сделать скрипт типа wget -O /dev/null sms_.../sendsms.php?login=123&pass=123&message=text
            Почти у всех смс-провайдеров есть такая штука.
              +2
              Угу, а еще попросить юзеров ввести капчу =)
                0
                Если у вас платный аккаунт у смс-провайдера, то капчу не надо — я же указал в качестве параметра логин и пароль.
                Ведь смс через телефон тоже не бесплатная.
                  0
                  Смс через телефон стоит 10 копеек, и работает даже когда инет пропадает.
                  Я прекрасно понимаю что есть куча сервисов, но отправка через мобилу уже реализована и работает понадежнее сервисов.
                    –2
                    Вы бы тогда сразу подписали внизу статьи: «Никакие альтернативные реализации в этом топике не принимаются».
                      0
                      Пока все альтернативы имели меньшую функциональность ;-)
              0
              Обожаю такие топики, когда в комментариях предлагают еще десяток своих вариантов решения вопроса.
              Посоветуйте способ организовать отправку смс через телефон на виндах, что то типа www.lissyara.su/?id=1787
                0
                Кстати интересный вариант по ссылке, а он отправляет через PDU?
                  0
                  Не в курсе, только бегло просмотрел, так как он для никсов.
                • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    Записал себе как вариант. Небольшое уточнение: он подключается именно через ком порт? Не USB?
                    • НЛО прилетело и опубликовало эту надпись здесь
                    –1
                    делаем
                      0
                      Что делаете?
                        –1
                        отправку смс через телефон на виндах
                          0
                          Вы не многословны. Может посвятите в детали? Кто Вы такие, как именно делаете, какие условия, цены?
                            –1
                            вот будет готово, тогда и расскажу. черкните мне в личку, чтобы Ваш контакт у меня остался. как будет релиз, я Вам отпишусь.
                    0
                    '/usr/bin/printf $NOTIFICATIONTYPE$\n\nService | /usr/local/bin/scmxx --device /dev/ttyU0 --number $CONTACTPAGER$ --send --sms --direct — > /var/log/scmxx.log 2>&1'
                    вот такое у нас стоит в Nagios. Отправляет sms через какой-то старенький Siemens. посредством утилиты scmxx
                      0
                      Вообще если вы посмотрите, в zabbix есть поддержка отправки уведомлений, но она умеет работать только с теми телефонами что позволяют отправлять sms без PDU.
                        0
                        Именно об этом и заметка, отправка текстом не сложна в настройке.
                        0
                        Кто что знает про www.visualgsm.com? При беглом осмотре есть бесплатная версия, я только не нашел в чем ее триальность заклчается.
                          0
                          GPRS/EDGE-модемы, которые сейчас предлагают многие операторы мобильной связи по 2000-3000тр, имеют возможность отправки СМС. Возможно, что с таким девайсом систему оповещения сожно реализовать проще и без перекодирования в PDU.
                          • НЛО прилетело и опубликовало эту надпись здесь
                              0
                              Kannel наше всё
                                0
                                будущее здесь? Компьютеры будут общаться с нами? Echelon Conspiracy :)
                                  0
                                  Я купил ком модем с gprs за 65$, откуда вы взяли 8к, не понятно, это было год назад.
                                    0
                                    Сорри, температура, немного ступил, использовал я его как раз для получения и отправки смс. Дёшево и сердито.
                                    +1
                                    Хех я вот pymobile.sourceforge.net/ использовал.
                                      0
                                      О, спасибо за подсказку, сам что-то не нашел этого проекта.
                                        0
                                        Его реально трудно найти, я надыбал одно сообщение на каком-то испанском форуме, проверил — подошло.
                                      0
                                      А в чём прикол смс? Просто смс у меня ассоциируется с MTV. Через push какой нибудь себе на мыло уведомления нельзя сделать?
                                        0
                                        Можно использовать какой-нибудь модем от Билайн.Интернет Дома
                                          0
                                          ага, а покажи две классические трудоемкие добавки (можно во второй части):
                                          1) русские буквы
                                          2) concatenated messages
                                          :)
                                            0
                                            Да, это былобы интересно, но пока совершенно нет необходимости, хотя при наличии свободного времени можно заняться)
                                            0
                                            В своё время делал отправку СМС на основе SprutNet (Описание в PDF)
                                            Цена вопроса 2500р, в комплекте антена.
                                            Умеет GPRS, так что если кто что накосячил в настройках роутера можно через него зайти (правда это тоже настраивать надо)
                                              0
                                              Извиняюсь, я конечно не гуру программирования, но объясните, зачем это условие? %)
                                              if True:
                                              fd = os.open(dev, os.O_RDWR)
                                              . . .

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

                                              Самое читаемое