Автоматизация сбора информации о балансе с GSM-шлюзов AddPac AP-GS1002
В этой статье я расскажу о том, как реализовать автоматическое выполнение USSD-запросов для получения информации о балансе вашего лицевого счета у сотового оператора на GSM-Шлюзе AddPac AP-GS1002, а так же отсылки этой информации по электронной почте. Такого рода вещи отлично получаются на платформах *nix, в которых есть перл, а так же шлюзы снабжены telnet’ом. В моем случае есть Windows server 2008 R2 64bit без перла, но зато с Visual-Basic’ом.
Механизм
В планировщике задач через необходимый интервал времени должен запускаться VBS-скрипт, который подключается через telnet к шлюзу, задает ему определенные команды, слушает и обрабатывает ответы, формирует и отправляет email-сообщение.
Rhs.Telnet
Для того чтобы наш скрипт работал с telnet’ом нам понадобится внешняя компонента RhsTelnet, которую накатал один добрый англичанин. Забираем ее отсюда. Вытаскиваем из архива RhsTelnet.dll и кладем ее в надежное место. Затем выполняем
regsvr32 RhsTelnet.dll
из того места, куда вы положили dll-ку. Рекомендую прочитать из архива RhsTelnet.txt, чтобы понимать что это такое.
Скрипт
Теперь пишем сам скрипт.
'balance.vbs 'Created by Stepleer '27.09.2011 const SVR1 = "192.168.0.5" 'адрес шлюза в сети dim telnet, s, i, resp dim data, data1, data2 dim balance1, balance2 data1 = "" data2 = "" balance1 = "" balance2 = "" set telnet = CreateObject("Rhs.Telnet") 'создаем телнет telnet.Startup() telnet.Connect SVR1, 23 'подключаемся do while telnet.Readline(s, 5000) 'этот цикл я вставил, чтобы шлюз смог успеть нам выдать loop 'все свои пригласительные сообщения telnet.Writeline "root" 'передаем логин telnet.Writeline "router" 'передаем пароль telnet.Writeline "ena" 'дальше идут команды самому шлюзу telnet.Writeline "terminal monitor" telnet.Writeline "debug gsm all event" telnet.Writeline "gsm 0 0 ussd send *105#" 'вот команда на выполнение USSD-запроса 'в шлюзе стоят 2 симки tele2, запрос - *105# '0 0 - это адрес первой симки resp = "" do while telnet.Readline(s, 5000) 'получаем ответы от шлюза If InStr(s, "EVENT=(+CUSD:") > 0 Then resp = s 'ждем строку, в которой содержится ответ от tele2 loop firstq = InStr(resp, """") 'ответ будет содержать 16-ричный текст заключенный 'в кавычки lastq = InStr(firstq+1, resp, """") If lastq > firsq Then data1 = Mid(resp, firstq+1, lastq-firstq-1) 'вытаскиваем ответ из кавычек 'If тут для того, что не всегда может придти 'ответ от оператора, и оператор Mid() с пустой 'строкой выдаст ошибку скрипта telnet.Writeline "gsm 0 1 ussd send *105#" 'выполняем запрос на второй симке resp = "" do while telnet.Readline(s, 5000) '5000 - это задержка, подбирается экспериментально 'для каждого устройства в миллисекундах, чтобы дать 'возможность шлюзу успеть "высказаться" If InStr(s, "EVENT=(+CUSD:") > 0 Then resp = s loop firstq = InStr(resp, """") lastq = InStr(firstq+1, resp, """") If lastq > firsq Then data2 = Mid(resp, firstq+1, lastq-firstq-1) telnet.Disconnect() 'Отключаемся telnet.Cleanup() If data1 <> "" Then 'Перекодируем ответ сети из 16-ричного формата в строковый for i = 1 to len(data1) Code = Mid(data1, i, 2) If Code <> "00" Then 'Почему-то от tele2 перед каждым символов вставляет пустой 'символ с кодом "00", он нам не нужен balance1 = balance1 & Chr("&H" & Code) 'Собираем строку End If i = i + 1 next End If If data2 <> "" Then for i = 1 to len(data2) Code = Mid(data2, i, 2) If Code <> "00" Then balance2 = balance2 & Chr("&H" & Code) End If i = i + 1 next End If Message = "Шлюз 1 Порт 0 (+790ХХХХХХХХ) - " & balance1 & vbcrlf 'Пишем письмо, vbcrlf - это перевод 'строки в VB Message = Message & "Шлюз 1 Порт 1 (+790ХХХХХХХХ) - " & balance2 & vbcrlf Message = Message & "Письмо создано " & Now 'Вставляем время emailTo = "admin@habra.ru; av@mail.ru" 'Можно послать нескольким получателям emailSubject= "Баланс" set oMSG = CreateObject("CDO.Message") 'Отправлять будем через Microsoft CDO for Windows 2000 set oConfig = CreateObject("CDO.Configuration") 'лишнего ничего не спрашивает и четко работает set CFields = oConfig.Fields oMSG.Configuration = oConfig CFields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 CFields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.mail.ru" 'Параметры SMTP CFields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1 CFields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25 CFields("http://schemas.microsoft.com/cdo/configuration/sendusername") = "robot@mail.ru" CFields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "lN1qxFmXRuXgE" CFields("urn:schemas:mailheader:content-language") = "windows-1251" CFields.Update oMSG.To = emailTo oMSG.From = "robot@mail.ru" oMSG.Subject = emailSubject oMSG.BodyPart.Charset = "windows-1251" 'oMSG.AddAttachment "c:\photos\кисо.jpg" 'Можно прицепить фотку жены oMSG.TextBody = Message oMSG.Send 'Отправили.
Вот такой вот скрипт у меня получился.
Планировщик
Казалось бы, что осталось запихнуть этот скрипт в планировщик и всё… Но к сожалению, по неизвестной мне причине сервер сценариев выдавал ошибку «Невозможно создание объекта контейнером ActiveX (»Rhs.Telnet”) “. Как оказалось, выполнения regsvr32 RhsTelnet.dll
недостаточно. Необходимо выполнить регистрацию компоненты RhsTelnet.dll в качестве приложения COM+.
Для этого:
- запустите утилиту Component Services;
- создайте пустое COM+ приложение с:
- Activation type — Server application;
- именем, например, tel;
- укажите имя пользователя Windows, от имени которого компонента будет запускаться специальный процесс dllhost.exe;
- в ветке Components добавьте новую компоненту RhsTelnet.dll из каталога, куда вы его положили.
В результате при создании приложения COM+ на компьютере будет запущен специальный системный процесс dllhost.exe, и в нем будет создан объект Rhs.Telnet.
Не забудте юзера, из под которого будет выполняться задание в планировщике добавить в политику «Вход в качестве пакетного задания» и «Локальный вход в систему».