English 中文 Español Deutsch 日本語 Português
СМС-извещения о состоянии Советника

СМС-извещения о состоянии Советника

MetaTrader 4Примеры | 29 июля 2009, 07:59
4 800 36
Дмитрий
Дмитрий

Введение

Работа частенько отвлекает меня от того, чтобы быть рядом и наблюдать за Терминалом. Иногда это - 20-30 минут, иногда - сутки. Поэтому я решил организовать себе систему СМС-извещений о критических ситуациях, будь-то отключение света или если компьютер не смог "проснуться" после выходных. Уверен, что даже в том варианте готовности, в котором система представлена, она сможет помочь многим трейдерам, а те, кому её как таковой мало, смогут на базе этой идеи сформировать свой "шедевр".

В статье собираюсь продемонстрировать разработку рабочего решения поставленной задачи. Должен сделать оговорку: в Java разработке я не являюсь даже полупрофесионалом, настройку и вытягивание моего "вылетающего" кода мне помогал делать мой товарищ java-девелопер.


План

  1. Возможности Google Calendar
  2. Немного об установке Google Data API
  3. Блок-схема работы системы
  4. Код Java приложения
  5. Код .bat файла
  6. Код в Советнике
  7. Слабые стороны
  8. Заключение


Возможности Google Calendar

С целью создания СМС-извещений был выбран именно этот сервис, так как он позволяет создавать события в своем бесплатном Органайзере, а способом извещения о событии может служить СМС. Для целей системы я решил зарегистрировать отдельный, специальный, профиль на Google.

Если вкратце объяснить принцип работы, то выйдет так: если до 9:59 (по скриншоту) ничто не удалит данное событие, то есть если Терминал не выйдет на связь с Сервером Google и не заменит это событие на следующее, то на телефон отправится СМС с "тревогой".


Немного об установке Google Data API

Для программной работы со своими сервисами Google предоставляет документацию API данных Google.
Документация Java-разработчику по работе с Календарем находится по следующей ссылке Google Calendar APIs and Tools.

Для программирования вам потребуется установить Google Data Java Client Library. На этой же страничке есть ссылка на документацию о настройке библиотеки для Eclipse, сам использовал именно этот способ, поэтому и вам рекомендую Using Eclipse with Google Data APIs.


Блок-схема работы системы

Считаю нужным сперва немного прокомментировать блок-схему:

  • событие с заголовком StopTXT нужно, чтобы удаленно вручную можно было прекратить поток СМС на всякий случай;
  • событие с заголовком ReanimationTXT нужно для извещения о том, что по какой-то причине Терминал смог выйти на связь, а вам уже была отправлена СМС с "тревогой";



Код Java-приложения

Все исходники и дистрибутив, которыми я пользуюсь, есть в конце статьи.

package Calendar;
/* INSTRUCTION: This is a command line application. 
    So please execute this template with the following arguments:

                arg[0] = username
                arg[1] = password
*/

import com.google.gdata.client.GoogleService;
import com.google.gdata.client.Query;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarEventFeed;
import com.google.gdata.data.calendar.CalendarFeed;
import com.google.gdata.data.extensions.Reminder;
import com.google.gdata.data.extensions.When;
import com.google.gdata.data.extensions.Reminder.Method;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class Calendar {

    public static void main(String[] args) {

        try {
            //--- ВНЕШНИЕ ПЕРЕМЕННЫЕ ----------------------------
            String alertTxt = args[2];
            String reanimationTxt = args[3];
            String stopSMS = args[4];
            int timePeriod = Integer.parseInt(args[5]); // период в минутах, с которым терминал 
                                                        // будет выходить на связь
            int mode = Integer.parseInt(args[6]);
            int startHour = Integer.parseInt(args[7]);
            int startMin = Integer.parseInt(args[8]);
            //---------------------------------------------------
            //--- ВНУТРЕНИЕ ПЕРЕМЕННЫЕ --------------------------
            URL feedUrl = new URL("http://www.google.com/calendar/feeds/default/private/full");
            //ссылка для работы с событиями
            URL calendarUrl = new URL("http://www.google.com/calendar/feeds/default/allcalendars/full");
            //ссылка для работы с календарями   
            //---------------------------------------------------
            System.out.println(">>----------  Start   ----------<<");

            // Создаем новый Calendar service, коннект к Google
            CalendarService myService = new CalendarService("My Application");
            myService.setUserCredentials(args[0], args[1]);    // ЛОГИН И ПАРОЛЬ В КАЧЕСТВЕ АРГУМЕНТОВ

            // ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ ДЛЯ ПОИСКА СОБЫТИЯ
            Query myQuery = new Query(feedUrl);
            CalendarEventFeed myResultsFeed;
            CalendarEventEntry firstMatchEntry = null;
            String myEntryTitle;
            URL deleteUrl;
            When timeVar;
            SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
            Date newDate = new Date();
            CalendarEventEntry myEntry;
            When eventTimes = new When();
            DateTime startTime = null;
            DateTime endTime = null;
            int reminderMinutes;
            Method methodType = Method.SMS;
            Reminder reminder = new Reminder();
            CalendarEventEntry insertedEntry;

            // ГОТОВИМ ПОИСКОВЫЙ ЗАПРОС
            myQuery.setFullTextQuery(stopSMS);            // СОБЫТИЕ С ТЕКСТОМ stopSMS
            myResultsFeed = myService.query(myQuery, CalendarEventFeed.class);
            if (myResultsFeed.getEntries().size() > 0) {
                System.out.println(">> STOP event found. \n>> Finish");
                return;
            }

            // ГОТОВИМ ПОИСКОВЫЙ ЗАПРОС
            myQuery.setFullTextQuery(reanimationTxt);    // СОБЫТИЕ С ТЕКСТОМ reanimationTxt
            myResultsFeed = myService.query(myQuery, CalendarEventFeed.class);
            if (myResultsFeed.getEntries().size() > 0) {    // ЕСЛИ УДАЛОСЬ НАЙТИ
                System.out.println(">> REANIMATION event found");
                // У ПЕРВОГО ПОПАВШЕГОСЯ СОБЫТИЯ СПРАШИВАЕМ ЗАГОЛОВОК
                firstMatchEntry = (CalendarEventEntry) myResultsFeed.getEntries().get(0);
                myEntryTitle = firstMatchEntry.getTitle().getPlainText();

                // ЕСЛИ НАШЛИ СОБЫТИЕ reanimationTxt ТО УДАЛЯЕМ ЕГО
                deleteUrl = new URL(firstMatchEntry.getEditLink().getHref());
                myService.getRequestFactory().setHeader("If-Match", "*");
                myService.delete(deleteUrl);
                System.out.println(">> ...deleting REANIMATION event");
            }

            // ГОТОВИМ ПОИСКОВЫЙ ЗАПРОС
            myQuery.setFullTextQuery(alertTxt);            // СОБЫТИЕ С ТЕКСТОМ alertTxt
            myResultsFeed = myService.query(myQuery, CalendarEventFeed.class);
            if (myResultsFeed.getEntries().size() > 0) {    // ЕСЛИ УДАЛОСЬ НАЙТИ
                System.out.println(">>  >> ALERT event found");
                // У ПЕРВОГО ПОПАВШЕГОСЯ СОБЫТИЯ СПРАШИВАЕМ ЗАГОЛОВОК
                firstMatchEntry = (CalendarEventEntry) myResultsFeed.getEntries().get(0);
                myEntryTitle = firstMatchEntry.getTitle().getPlainText();

                timeVar = firstMatchEntry.getTimes().get(0);
                System.out.println(">>  >> event start&stop time         : " 
                        + timeVar.getStartTime() + "\n>>        >>                               : " 
                        + timeVar.getEndTime());
                System.out.println(">>  >> event start     (milliseconds): " 
                        + timeVar.getStartTime().getValue());
                System.out.println(">>  >> new event start (milliseconds): " 
                        + (newDate.getTime() - (1000 * 60 * timePeriod)));

                if (timeVar.getStartTime().getValue() > newDate.getTime() - (1000 * 60 * 0)) {    
                    // ЕСЛИ У СТАРОГО СОБЫТИЯ ВРЕМЯ НАЧАЛА МЕНЬШЕ ЧЕМ timePeriod МИНУТ НАЗАД
                    // УДАЛЯЕМ ЕГО
                    deleteUrl = new URL(firstMatchEntry.getEditLink().getHref());
                    myService.getRequestFactory().setHeader("If-Match", "*");
                    myService.delete(deleteUrl);
                    System.out.println(">>              >> event start > new event start");
                    System.out.println(">>              >> ...deleting event");
                    System.out.println(">>              >>    #M###      ##M    #M#  ");
                    System.out.println(">>              >>   ########    ###   ###   ");
                    System.out.println(">>              >>   ###  ###    ###  ###    ");
                    System.out.println(">>              >>  ###    ###   ### ###     ");
                    System.out.println(">>              >>  M##    ###   ######M     ");
                    System.out.println(">>              >>  ###    ###   #### ###    ");
                    System.out.println(">>              >>  ###    ###   ###  ###    ");
                    System.out.println(">>              >>  ###    ###   #M#   ###   ");
                    System.out.println(">>              >>   ###  ###    ###   ###   ");
                    System.out.println(">>              >>   ########    ###    ###  ");
                    System.out.println(">>              >>     ####      ###     ### ");
                } else {    // ВРЕМЯ БОЛЬШЕ ЧЕМ timePeriod МИНУТ НАЗАД, А ЗНАЧИТ смс УЖЕ УШЛА
                    // УДАЛЯЕМ ЕГО
                    deleteUrl = new URL(firstMatchEntry.getEditLink().getHref());
                    myService.getRequestFactory().setHeader("If-Match", "*");
                    myService.delete(deleteUrl);
                    System.out.println(">>              >> SMS has gone already");
                    System.out.println(">>              >> event start < new event start");
                    System.out.println(">>              >> ...deleting event");
                    System.out.println(">>              >>   .M####   M##M   ###M   .#####   ");
                    System.out.println(">>              >>  ########  ####   ####  ########  ");
                    System.out.println(">>              >>  ###  ###  ####   ####  #M#  ###  ");
                    System.out.println(">>              >>  ###       ###M# #####  ###       ");
                    System.out.println(">>              >>  #M####    ##### #####  ######    ");
                    System.out.println(">>              >>   ######   ### # # @##   #M####   ");
                    System.out.println(">>              >>     #####  ### # # ###     #####  ");
                    System.out.println(">>              >>  #M#  ###  ### # # ###  M##  ###  ");
                    System.out.println(">>              >>  ###  ###  ### ### ###  ###  ###  ");
                    System.out.println(">>              >>   ######   ### ### ###   ######   ");
                    System.out.println(">>              >>    ####    ###  #  ###    ####    ");
                    // СОЗДАЕМ НОВОЕ СОБЫТИЕ
                    myEntry = new CalendarEventEntry();
                    myEntry.setTitle(new PlainTextConstruct(reanimationTxt));  // ЗАДАЕМ ЕГО ЗАГОЛОВОК

                    newDate.setTime(newDate.getTime() + 1000 * 60 * 1); // ТЕКУЩЕЕ ВРЕМЯ + 1 МИНУТa
                    startTime = DateTime.parseDateTime(formater.format(newDate));        
                    // ВСТАВЛЯЕТ СТРОКУ ПО ШАБЛОНУ "2009-06-30T20:55:00"

                    System.out.println(">>              >> creating REANIMATION event");
                    System.out.println(">>              >> event starttime: " + formater.format(newDate));

                    newDate.setTime(newDate.getTime() + 1000 * 60 * 0); // ПРИБАВИМ ЕЩЕ РАЗ ТЕКУЩЕЕ ВРЕМЯ 
                                                                        // + 1 МИНУТa
                    endTime = DateTime.parseDateTime(formater.format(newDate));

                    System.out.println(">>              >> event stoptime : " + formater.format(newDate));

                    eventTimes.setStartTime(startTime);
                    eventTimes.setEndTime(endTime);
                    myEntry.addTime(eventTimes);

                    reminderMinutes = 0;  // ИЗВЕСТИТЬ ЗА 1 МИНУТУ

                    reminder.setMinutes(reminderMinutes);
                    reminder.setMethod(methodType);
                    myEntry.getReminder().add(reminder);

                    // СОЗДАЕМ НОВЫЙ Calendar service, КОННЕКТ К Google
                    CalendarService tempService = new CalendarService("My Application");
                    tempService.setUserCredentials(args[0], args[1]);     // ЛОГИН И ПАРОЛЬ В КАЧЕСТВЕ АРГУМЕНТОВ
                    // СТАВИМ СОБЫТИЕ В ОЧЕРЕДЬ НА ИСПОЛЕНЕНИЕ
                    tempService.insert(feedUrl, myEntry);
                }
            }

            // СОЗДАЕМ НОВЫЙ Calendar service, КОННЕКТ К Google
            CalendarService basicService = new CalendarService("basic Application");
            basicService.setUserCredentials(args[0], args[1]);             // ЛОГИН И ПАРОЛЬ В КАЧЕСТВЕ АРГУМЕНТОВ

            // СОЗДАЕМ НОВОЕ СОБЫТИЕ
            CalendarEventEntry basicEntry = new CalendarEventEntry();
            basicEntry.setTitle(new PlainTextConstruct(alertTxt));        // ЗАДАЕМ ЕГО ЗАГОЛОВОК

            if (mode == 0) {    // ОБЫЧНАЯ ДНЕВНАЯ СИТУАЦИЯ
                newDate.setTime(newDate.getTime() + 1000 * 60 * timePeriod);  // ТЕКУЩЕЕ ВРЕМЯ + timePeriod МИНУТ
                startTime = DateTime.parseDateTime(formater.format(newDate));
                // ВСТАВЛЯЕТ СТРОКУ ПО ШАБЛОНУ "2009-06-30T20:55:00"

                newDate.setTime(newDate.getTime() + 1000 * 60 * 0); // ПРИБАВИМ ЕЩЕ РАЗ ТЕКУЩЕЕ ВРЕМЯ
                                                                    // + timePeriod МИНУТ
                endTime = DateTime.parseDateTime(formater.format(newDate));
            }
            if (mode == 1) {    // СИТУАЦИЯ НАЗНАЧЕНИЯ СОБЫТИЯ НА СЛЕДУЮЩЕЕ УТРО, ИЛИ УТРО ПОНЕДЕЛЬНИКА
                Date curDate = new Date();
                GregorianCalendar gDate = new GregorianCalendar();
                gDate.setTime(curDate);
                // УСТАНАВЛИВАЕМ ЧАСЫ И МИНУТЫ В НЕОБХОДИМЫЕ
                gDate.set(GregorianCalendar.HOUR_OF_DAY, startHour);
                gDate.set(GregorianCalendar.MINUTE, startMin);
                gDate.set(GregorianCalendar.SECOND, 0);

                if (gDate.get(GregorianCalendar.DAY_OF_WEEK) < 6) {    // ПН - ЧТ
                    gDate.set(GregorianCalendar.DAY_OF_MONTH, gDate.get(GregorianCalendar.DAY_OF_MONTH) + 1);
                } else {    // ПТ
                    gDate.set(GregorianCalendar.DAY_OF_MONTH, gDate.get(GregorianCalendar.DAY_OF_MONTH) + 3);
                }
                // System.out.println("gDate "+ gDate.getTime());
                startTime = DateTime.parseDateTime(formater.format(gDate.getTime()));
                gDate.set(GregorianCalendar.MINUTE, gDate.get(GregorianCalendar.MINUTE) + timePeriod);
                endTime = DateTime.parseDateTime(formater.format(gDate.getTime()));
                System.out.println(">> nextday event should be created");
            }
            //System.out.println("создаю событие УПАЛ!");
            System.out.println(">> creating ALERT event");
            System.out.println(">> event starttime: " + startTime.toString());
            System.out.println(">> event stoptime : " + endTime.toString());

            eventTimes.setStartTime(startTime);
            eventTimes.setEndTime(endTime);
            basicEntry.addTime(eventTimes);

            reminderMinutes = 0;  // ИЗВЕСТИТЬ ЗА 1 МИНУТУ

            reminder.setMinutes(reminderMinutes);
            reminder.setMethod(methodType);
            basicEntry.getReminder().add(reminder);

            // СТАВИМ СОБЫТИЕ В ОЧЕРЕДЬ НА ИСПОЛЕНЕНИЕ
            basicService.insert(feedUrl, basicEntry);

            System.out.println(">>----------  Finish  ----------<<");
        }
        catch (AuthenticationException e) {
            e.printStackTrace();
        }
        catch (MalformedURLException e) {
            e.printStackTrace();
        }
        catch (ServiceException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Код .bat файла

Так как создание бат-файлов в MQL4 пока невозможно, то на практике я использую 2 бат-файла, которые отличаются Режимом(Mode).

@rem +------------------------------------------------------------------+
@rem |         Прикладное приложение производит отправку СМСок          |
@rem |      ------------------------------------------------------      |
@rem | Правила:                                                         |
@rem |                                                                  |
@rem | USER   -   учетная запись отправителя                            |
@rem | PASS   -   пароль отправителя                                    |
@rem | ALER   -   Alert, тестовка предупредительного сообщения          |
@rem |              (использовать только латиницу)                  |
@rem | REAN   -   Reanimated, текст сообщения о восстановлении связи    |
@rem |                  (использовать только латиницу)                  |
@rem | STOP   -   STOP, заголовок события, которое запрещает выполнение |
@rem |                  действий программы                              |
@rem |                  (использовать только латиницу)                  |
@rem | PERI   -   Period, период-таймер на отправку сообщения Alert     |
@rem | MODE   -   Режим                                                 |
@rem |                  (0 - обычная работа,                            |
@rem |                   1 - отправка сообщения на завтрашнее утро или  |
@rem |                        утро понедельника)                        |
@rem | HOUR   -   Час "завтрашнего утра, или утра понедельника", на     |
@rem |                   который необходимо поставить сообщение.        |
@rem | MINU   -   Minutes, минуты "завтрашнего утра..."                 |
@rem +------------------------------------------------------------------+

@rem ECHO off

set USER=forex.myaccount
set PASS=mypassword
set ALER=Terminal_Alert
set REAN=Trading_Resolved
set STOP=STOP
set PERI=5
set MODE=0
set HOUR=8
set MINU=20

set ARGS= %USER% %PASS% %ALER% %REAN% %STOP% %PERI% %MODE% %HOUR% %MINU%
     
    java -jar "d:\Documents\forex\Deltabank Trader 4\TerminalWatch\terminalWatcher.jar" %ARGS% 

@rem ECHO %ARGS%


Код в советнике

По правилам вашей Торговой Системы в блоке "действий по расписанию" вам понадобится вызывать функции, код которых приведен ниже.

Ну а в конце торговой сессии я вызываю функцию для установки СМС на следующее утро.

В ссылках используются именно ярлыки .lnk, чтобы можно было назначить режим вызова окошка консоли "Свернутое в значок", дабы не пугать своим выскакиванием.

//+------------------------------------------------------------------+
//| Отправляет статусное SMS                                         |
//+------------------------------------------------------------------+
int sendSMS()
{
      string destination = StringConcatenate(TerminalPath(),"\TerminalWatch\launch.lnk");
      ShellExecuteA(WindowHandle(Symbol(),0),"open", destination, NULL, NULL,1);
}
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Отправляет статусное SMS на следующее утро                       |
//+------------------------------------------------------------------+
int sendSMSnextDate()
{
      string destination = StringConcatenate(TerminalPath(),"\TerminalWatch\launch_next_date.lnk");
      ShellExecuteA(WindowHandle(Symbol(),0),"open", destination, NULL, NULL,1);
}
//+------------------------------------------------------------------+


Слабые стороны

Небольшая ложка дегтя - на практике очень трудно подстроится под синхронную работу часов на Терминале, на Сервер Котировок и на Сервере Google, поэтому в коде советника использую такую методику: каждые 5 минут устанавливаю смс с таймером через 8 минут. Такая тактика в 95% случаев работает хорошо, но пока я все еще сталкиваюсь с оставшимися 5% "дегтя".


Заключение

Всем, кому интересно, ну и кто не поленится заиметь себе аккаунт на Google, будет достаточно просто проверить, на что способна моя нехитрая система.

Повторюсь, многие детали Java-разработки мне не до конца понятны. Я использовал помощь моих товарищей девелоперов (Дима, большое спасибо!), так что не на все вопросы смогу ответить полноценно.

Большое спасибо за внимание!


Добавлено по результатом обсуждения статьи

В текущей версии учтено полезное замечание komposter по логике работы:

  • не удалять реанимационное сообщение, если оно не отправилось;

К статье прикреплен файл: TerminalWatch_03.rar

Прикрепленные файлы |
block-shema.rar (32.75 KB)
TerminalWatch_02.rar (1600.64 KB)
TerminalWatch_03.rar (1600.51 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (36)
Andrey Khatimlianskii
Andrey Khatimlianskii | 16 сент. 2009 в 18:00
vedroid:
Ладно, попробую реализовать, но сроков не буду говорить :-Р.

Если это - только для меня, не стоит этим заниматься.

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

И все равно спасибо )

Дмитрий
Дмитрий | 19 нояб. 2009 в 13:25

Сильно не вникал, но смотрю название статьи и сколько в ней кода, и начинает казаться что я решил такую же проблему с меньшей головной болью.


есть отличная программка SimpleSMSLight, которая запускается из командной строки (см. в гугле)

таким образом чтобы отправить смс, достаточно купить любой БУшный телефон со встроенным модемом, купить USB адаптер к нему с функцией подзарядки, пакет с симкартой с опцией "бесплатные смс" или что-нибудь просто подешевле

у меня работает:

- указанная программа simpleSMSLight

- к ПК подключен телефон CX70 (куплен за 170грн)

- кабель подключения USB - за 20грн

- симкарта 10 грн

- каждая смс стоит несколько копеек.

- три строчки кода в советнике или индикаторе

я туда даже не заглядываю, телефон слоем пыли покрылся за системным блоком, работает без сбоев.

дополнительная удобная фича - с этим же телефоном параллельно работает VentaFax (см. гугле) и иногда в отдельных случаях звонит мне на мой мобильный.

Ventafax так же можно запускать и отключать (чтобы она освобождала порт после звонка) из командной строки.


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

Дмитрий
Дмитрий | 19 нояб. 2009 в 15:22

Добрый вам день.

Ситуация ясна - каждому свое.

Спасибо, что осветили свой метод тут, может кому-то он окажется простым и удобным.

У меня ситуация другая: я арендую виртуальный выделенный сервер за 190 грн./месяц, который работает круглые сутки в 18 км. от точки, где я работаю, и 3 км., где я живу, а основная работа - "летать по встречам по Киеву".... поэтому что толку в смс-ке, если вам негде развернуть бекап терминала или законектится и разгребать ситуацию.

dimonsky писал(а):

Сильно не вникал, но смотрю название статьи и сколько в ней кода, и начинает казаться что я решил такую же проблему с меньшей головной болью.

Дмитрий
Дмитрий | 30 нояб. 2009 в 00:22
vedroid:

Добрый вам день.

Ситуация ясна - каждому свое.

Спасибо, что осветили свой метод тут, может кому-то он окажется простым и удобным.

У меня ситуация другая: я арендую виртуальный выделенный сервер за 190 грн./месяц, который работает круглые сутки в 18 км. от точки, где я работаю, и 3 км., где я живу, а основная работа - "летать по встречам по Киеву".... поэтому что толку в смс-ке, если вам негде развернуть бекап терминала или законектится и разгребать ситуацию.

dimonsky писал(а):

Сильно не вникал, но смотрю название статьи и сколько в ней кода, и начинает казаться что я решил такую же проблему с меньшей головной болью.

Чтобы законнектиться к терминалу(запущенному круглосуточно дома на другом конце города) со своего рабочего ПК я уже год использую TeamViewer. 


Прошу  прощения у автора, надеюсь я никаких правил не нарушаю, да и пригодиться может.

Ко мне обращаются с просьбой разъяснить как я реализовал отправку смс, поэтому я решил кратко описать мой метод здесь. Заодно и тему апнем. 


итак, берем в архиве прогарммку simplesmslite. я исполняемый файл переименовал в com, чтобы можно было создать файл настроек окна программы PIF (В котором прописал не всплывать поверх всех и т.п.)

1) в корень диска С кидаете файл "sendsms.bat" c текстом внутри:

START "---" c:\simplesmslite MSG="c:\Program Files\!Forex\Broco Trader 2\experts\files\msg.txt"

где c:\Program Files\!Forex\Broco Trader 2\ - путь к вашему торговому терминалу.

2) В корень диска С кидаете фалы из архива.

В SimpleSMSlite.Ini пишете эти строки:

[Device]
Comport=COM3
ComSpeed=19200
StepsTime=1000
WaitSteps=10
MaxWaitSteps=10
[Other]
Logfile=SimpleSMSlite.log
MSGfile=SimpleSMSlite.txt
SMSCenter=
GlobalLogEnable=1


при этом стока Comport=COM3 указывает, на каком порту висит ваш мобильный телефон (в качестве модема).

Чтобы узнать, идете "Пуск/Панель управления/ Система/ влкадка Оборудование/ кнопка Диспетчер устройств" и там смотрите ветка "Модемы". В ней должен висеть ваш мобильный телефон (у меня - как "Siemens Mobile Phone USB Modem"). Щелкаете по нему два раза, появляется окно. в нем - на вкладку "Модем" и в самом верху будет написан порт. У меня - COM3.

К слову, если такой группы "Модемы" нет, или в ней в открывающемся списке нет вашего телефона, значит он не установлен как модем. Или драйвера не стоят, или он вообще не подключен к ПК. Способ подключения к ПК зависит от модели телефона. У меня телефон сименс CX70, соответственно подключен он кабелем 510 (гугле в помощь, а также барахолки на рынке цифровых устройств, еще можно заказать в инете). Конечно, телефон по техописанию должен быть с модемом.

Так, идем далее.

в советнике или индикаторе пишем такой код:


#import "kernel32.dll"
int WinExec(string lpCmdLine,int uCmdShow); // импорт из внешней библиотеки
#import

extern string FileNameToSendSMS="c:\sendsms.bat"; //  это внешняя переменная
.....
..... // какой-то ваш код
......
void blablabla()
{
   string sms="Проверка связи";
   SendSMS(sms);
}

функция отправки 

void SendSMS(string txt1) 
{
   int handle;
   handle=FileOpen("msg.txt",FILE_WRITE); 
  
   if(handle>0)
   {
      
      if (txt1!="")
      {
         if (FileWrite(handle, "38050ХХХХХХХ;M;L;"+txt1)<0)
         {
            Alert("Ошибка записи в файл msg.txt"+GetLastError());
         }
      }
      FileClose(handle);
   }
   else
   {
      Alert("Ошибка открытия файла msg.txt"+GetLastError());
   }
   WinExec(FileNameToSendSMS,SW_HIDE);
   
}

конечно, вместо 38050ХХХХХХХ пишете номер телефона, накоторый надо отправить сообщение.


Вроде все....

Uri
Uri | 30 нояб. 2009 в 23:26

dimonsky писал(а):............................


конечно, вместо 38050ХХХХХХХ пишете номер телефона, накоторый надо отправить сообщение.


Вроде все....

Отлично, попробую. Только походу вопрос - отправка поисходит только на один номер или можно организовать на несколько разных номеров ????
Советник для торговли в канале Советник для торговли в канале
Советник прорисовывает линии канала. Верхняя и нижняя линии канала выступают в роли уровней сопротивления и поддержки. Советник ставит значки над реперными точками, оповещает звуком о моменте, когда цена достигает или пересекает линии канала, и наносит соответствующие значки. На последних барах при образовании фракталов появляются соответствующие стрелки. Прорывы линий могут обозначать вероятность нарастания тренда. Советник сопровождается подробными комментариями.
Файл Lite_EXPERT2.mqh - практические примеры реализации экспертов Файл Lite_EXPERT2.mqh - практические примеры реализации экспертов
В этой статье автор продолжает знакомство с функциями файла Lite_EXPERT2.mqh на конкретных примерах построения экспертов. Рассматривается идея использования динамически изменяющихся от сделки к сделке и плавающих отложенных ордеров, определяемых на основе значений индикатора Average True Range (ATR).
Простые методики прогнозирования направления японских свечей Простые методики прогнозирования направления японских свечей
Знаний о направлении движения цены достаточно для получения положительных результатов от торговых операций. Некоторые сведения о возможном направлении дают японские свечи. В данной статье рассматриваются несколько простых подходов к прогнозированию их направления.
Расширенный анализ торгового счета Расширенный анализ торгового счета
В статье подробно рассказывается об автоматической системе анализа любого торгового счета в терминале MetaTrader 4. Рассматриваются технические стороны создаваемого отчёта и интерпретация полученных результатов. После детального рассмотрения отчёта делаются выводы по улучшению факторов торговли. Для анализа применяется скрипт MQLab™ Graphic Report.