Перейти к содержанию
Fire Monkey от А до Я

d7d1cd

Пользователи
  • Постов

    277
  • Зарегистрирован

  • Посещение

  • Победитель дней

    7

Сообщения, опубликованные d7d1cd

  1. 1 час назад, Сысоев Максим сказал:
    
    uses
      System.Net.Socket;
    
    Procedure Sample;
    var
      Socket: TSocket;
      LBytes: TBytes;
    Begin
      Socket := TSocket.Create(TSocketType.TCP);
      try
        // ну только ваш ип
        Socket.Connect(TNetEndpoint.Create(192, 168, 1, 1, 8081));
        LBytes := [233, 123, 001, $FF];
        Socket.Send(LBytes);
      finally
        Socket.Free;
      end;
    End;
    { TvkDatabase }
    
    function TvkDatabase.getCit

     

    Вижу, что тут компонент TIdTCPClient вообще не используется. Так же здесь приведен пример отправки массива байт. А как получить ответ с этого же IP и порта?

  2. Все верно. Счетчик сам ничего послать не может. Он только дает ответы на запросы. Теперь понятно, мне нужен компонент TIdTCPClient. Спасибо за помощь.

    Теперь далее... При работе через СОМ порт я отправляю в него запросы в виде массивов байт. Подскажите, как теперь эти же массивы байт отправлять через компонент TIdTCPClient на определенный IP и порт?

  3. С тем, как работает роутер VR-006, понятно. Теперь вопрос какой именно компонент использовать: TIdTCPClient или TIdTCPServer? Вроде ранее обсуждалось, что прибор (то есть счетчик через VR-006) - это источник данных, поэтому надо использовать компонент Клиент. В последнем сообщении говорится, что надо использовать Клиент, а лучше Сервер. Исходя из того, что я никогда не работал ни с одним из указанных компонентов, то подскажите, что конкретно мне использовать?

  4. 22 часа назад, Сысоев Максим сказал:

    еще больше плагинов установите в студию)00))

    Не было установлено ни одного плагина. У кого-то из посетителей этой темы установлен C++Builder 10.1? Не Delphi 10.1!!!

  5. Ну не знаю как на месте. У меня вот так, как на картинке. Кстати, до добавления функции FormCreate на конструкторе формы злополучный плюсик был, а после добавления пропал. Причем если удалить добавленную функцию, то плюсик на конструкторе так и не появляется.

    Безымянный.png

  6. Приветствую. Установил Builder 10.1 Berlin и при открытии своего проекта, ранее созданного в Seattle, обнаружил, что в редакторе кода нельзя сложить тело функции (плюсик рядом с объявлением), а в окне Structure, когда открыт код, вообще ничего нет (когда открыт дизайнер, компоненты в этом окне есть). Пробовал создать новый проект, там сразу все нормально, но когда добавляются функции, то складывание тоже пропадает. Это вообще решаемо или это глюк новоиспеченной системы?

  7. 5 часов назад, Rusland сказал:

    d7d1cd, мне вот интересно, конечная цель - получить показания счетчика? 

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

  8. 14 минуты назад, brunnengi сказал:

    Да судя по фоткам по ссылке это и есть веб форма

    http://1.bp.blogspot.com/-eMMJrsM54Z0/ViTrRUDOHrI/AAAAAAAAFgg/TLtnAKYh9ek/s1600/6.png

    Ну раз нет, значит нет.

    Это не веб форма. Это интерфейс заводской программы для работы со счетчиками.

  9. 2 часа назад, brunnengi сказал:

    Давайте и я свои пять копеек внесу))

    Подскажи, ты когда на ВЕБ интерфейс выходишь, ты видишь данные оп счетчику которые тебе требуются?

    Я всё же голосую за работу через HTTP даже если придется парсить результат. Ибо HTTP это очень удачная надстройка над TCP/IP которая сама решает множество подводных камней сама. А при TCP/IP когда пойдут первые косяки (а они пойдут) тебе придется самому их отлавливать.

    Вообще если у подключенного устройства есть внешний IP по переходу на который можно выйти на веб форму, то я бы попросил тебя его скинуть. Ну и конечно с указанием данных которые тебе требуется. 

    Потом логин/пароль поменяешь.

    P.S. можешь в личку если хочешь

    Во первых, у меня пока нет устройства. Во вторых, производитель устройства ясно сказал, что при отправке данных на IP адрес они отправляются в таком же виде, как и при работе через COM порт. Отсюда делается вывод, что нельзя выйти на веб интерфейс через IP адрес.

  10. 3 минуты назад, dnekrasov сказал:

    Ну если канал прозрачный - то работайте как с COM-портом используя какой-либо TCP-клиент. Только не HTTP  а именно TCP.

    Подскажите тогда, какой компонент мне использовать? Чтобы было как можно проще.

  11. Ну что, получил ответ от производителя устройства. Вот текст моего письма:

    Цитата

    Здравствуйте. Сегодня посмотрел Вашу статью о подключении к счетчикам электроэнергии через TCP/IP посредством устройства VR-006. Как я понимаю, у данного устройства есть свой протокол обмена. То есть, запросы в счетчик и ответы от него идут не как при работе через COM порт. Такой вывод я сделал из того, что интерфейс счетчика может работать на разных скоростях и универсальный конфигуратор каким-то образом «сообщает» VR-006 на какой скорости работать со счетчиком. Скажите, возможно ли получить протокол обмена Вашего устройства VR-006?

    Получил такой ответ:

    Цитата

    Сейчас скорость зафиксирована 9600 бод, канал связи прозрачный. Т.е. конфигуратор знает протокол счетчика и работает через VR-006 по прозрачному каналу связи, ничего сообщать VR-006  не нужно.

    Из ответа я понял, что запросы для счетчика нужно отправлять на IP адрес так же, как и в COM порт. Правильно?

  12. А ведь можно еще попробовать сделать по-другому: с помощью какой-нибудь программы-монитора "подсмотреть" что отправляет существующее приложение по протоколу TCP/IP. Протокол обмена со счетчиком известен, поэтому, я думаю, будет несложно "разгадать" протокол обмена по веб-интерфейсу (ну если только там нет какого-нибудь шифрования).

  13. Само устройство является посредником. Так сказать интерфейсом связи. Оно принимает команду от удаленного компьютера через интернет и передает ее конечному прибору. Данный прибор отвечает на полученную команду. Устройство этот ответ отправляет на удаленный компьютер.

    Вообще для работы с конечным прибором существует готовое приложение. В этом приложении можно выбрать один из нескольких типов интерфейсов: COM-порт, Bluetooth и, в том числе, TCP/IP. При выборе последнего программа просит указать IP адрес, порт (фиксирован - 7001), а так же некоторые параметры, как при работе с COM-портом - скорость обмена с конечным устройством, четность, время ожидания ответа. Работать с конечным устройством через COM-порт я умею. Теперь хочу научиться работать через TCP/IP.

  14. У меня поставщик данных - это прибор. Получается, что он - сервер. Однако этот сервер не пришлет мне данные, пока я не отправлю ему запрос. Из всего этого я делаю вывод, что для решения моей задачи необходимо использовать только один компонент: TNetHTTPClient. Я правильно понимаю?

  15. Привет всем. Возникла необходимость через интернет работать с устройством: отправлять в него данные и получать данные от устройства. У устройства в сети есть статический IP адрес и строго задан порт для данных. Подскажите с помощью каких компонентов (функций, методов) можно решить мою задачу?

  16. Как я понимаю, MAC адрес будет только в том случае, если в компьютере есть сетевая карта. А мне надо сделать привязку к такому оборудованию, которое гарантированно есть в компьютере. Например к процессору. У него есть уникальный номер?

  17. Нашел готовый код:

    void GetWmiInfo(TStrings *lpList, wchar_t* wsQuery)
    {
        HRESULT hres;
        // устанавливаем контекст бехопасности
        hres =  CoInitializeSecurity(
                NULL,
                -1,                          // COM authentication
                NULL,                        // Authentication services
                NULL,                        // Reserved
                RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
                RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
                NULL,                        // Authentication info
                EOAC_NONE,                   // Additional capabilities
                NULL                         // Reserved
        );
    
        IWbemLocator *pWbemLocator = NULL;    // провайдер WMI
        // инициализируем провайдера
        if(CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pWbemLocator) == S_OK) {
            IWbemServices *pWbemServices = NULL;    // обьект, которому будем скармливать запрос (целевая машина)
            wchar_t* wsNamespace = (L"ROOT\\CIMV2"); // пространство имён
            // подключаемся к целевой машине
            if(pWbemLocator->ConnectServer(wsNamespace, NULL, NULL, NULL, 0, NULL, NULL, &pWbemServices) == S_OK){
                IEnumWbemClassObject *pEnumClassObject = NULL; // энумератор записей
                wchar_t* wsWQL=(L"WQL"); // язык запросов WQL
                //wchar_t* wsQuery=(L"select * from WIN32_diskdrive");//+wsClass; // сам запрос к классу
                // выполняем запрос
                if(pWbemServices->ExecQuery(wsWQL, wsQuery, WBEM_FLAG_RETURN_IMMEDIATELY,NULL, &pEnumClassObject) == S_OK){
                    // параметры для перебора коллекции записей
                    IWbemClassObject *pClassObject = NULL;
                    ULONG uCount = 1, uReturned = 0;
                    if(pEnumClassObject->Reset() == S_OK) { // ?????????
                        int iEnumIdx = 0;
                        hres = pEnumClassObject->Next(WBEM_INFINITE, uCount, &pClassObject, &uReturned);
                        // перебираем колекцию
                        while( hres == S_OK) {
                            lpList->Add("---------------- ["+IntToStr(iEnumIdx)+"] -----------------");
                            SAFEARRAY *pvNames = NULL;
                            if(pClassObject->GetNames(NULL, WBEM_FLAG_ALWAYS | WBEM_MASK_CONDITION_ORIGIN, NULL, &pvNames) == S_OK) {
                                long vbl, vbu;
                                SafeArrayGetLBound(pvNames, 1, &vbl);
                                SafeArrayGetUBound(pvNames, 1, &vbu);
                                for(long idx=vbl; idx<=vbu; idx++) {
                                    long aidx = idx;
                                    wchar_t *wsName = 0;
                                    VARIANT vValue;
                                    VariantInit(&vValue);
                                    SafeArrayGetElement(pvNames, &aidx, &wsName);
                                    BSTR bs = SysAllocString(wsName);
                                    HRESULT hRes = pClassObject->Get(bs, 0, &vValue, NULL, 0);
                                    SysFreeString(bs);
                                    if(hRes == S_OK) {
                                        AnsiString s;
                                        Variant v = *(Variant*)&vValue;
                                        if(v.IsArray()){
                                            for(int i=v.ArrayLowBound(); i<=v.ArrayHighBound(); i++){
                                                Variant a = v.GetElement(i);
                                                if(!s.IsEmpty()) s+=", ";
                                                s+=VarToStr(a);
                                            }
                                        } else {
                                            s = VarToStr(v);
                                        }
                                        lpList->Add(AnsiString(wsName)+"="+s);
                                    }
                                    VariantClear(&vValue);
                                    SysFreeString(wsName);
                                }
                            }
                            if(pvNames)SafeArrayDestroy(pvNames);
                            iEnumIdx++;
                            hres = pEnumClassObject->Next(WBEM_INFINITE, uCount, &pClassObject, &uReturned);
                        } // конец по WHILE
                        if(hres != S_OK) lpList->Add((hres&0xFFFF));
                    } // конец по pEnumClassObject->Reset()
                    if(pClassObject)pClassObject->Release();
                } // конец по выполнению запроса
                if(pEnumClassObject)pEnumClassObject->Release();
            } // конец по подключению
            if(pWbemServices)pWbemServices->Release();
        } // конец инициализации провайдера
        if(pWbemLocator)pWbemLocator->Release();
    }
    
    
    
    
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      Memo1->Lines->Add("================== [WMI WQL] =================");
    	wchar_t* ss=(L"Select * from Win32_MotherboardDevice");
        GetWmiInfo(Memo1->Lines, ss);
        Memo1->Lines->Add("");
    }
    

    Данный код выдает следующее:

     

    ================== [WMI WQL] =================

    ---------------- [0] -----------------
    Availability=
    Caption=Материнская плата
    ConfigManagerErrorCode=
    ConfigManagerUserConfig=
    CreationClassName=Win32_MotherBoardDevice
    Description=Материнская плата
    DeviceID=Motherboard
    ErrorCleared=
    ErrorDescription=
    InstallDate=
    LastErrorCode=
    Name=Материнская плата
    PNPDeviceID=
    PowerManagementCapabilities=
    PowerManagementSupported=
    PrimaryBusType=PCI
    RevisionNumber=
    SecondaryBusType=ISA
    Status=
    StatusInfo=
    SystemCreationClassName=Win32_ComputerSystem
    SystemName=EG-TA-CHSN
    1
     

    Так и не смог понять где тут UUID...

  18. Подготовщик пишет в реестр случайную последовательность. Каждый раз - случайную (если он не видит записанное ранее значение).

    Эту же случайную последовательность в закодированном виде пользователь передает вам.

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

    Программа проверяет совпадение того, что в реестре с тем, что зашито в коде.

     

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

     

    Какая же это не-защита?

     

    kami, прошу прощения. Сразу не внимательно прочитал. А что, Ваш вариант мне подходит. Видимо его и буду использовать.

     

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

  19. Самое простое (да, это просто обходится любым,кто знаком с ProcessMonitor):

    программа-"подготовщик" запускается с правами админа и записывает в HKLM случайно сгенерированное довольно длинное значение. Она же выдает его пользователю в читабельном виде (например - через Base64).

    Рабочее приложение читает это значение (на чтение HKLM доступен) и сравнивает с эталоном, который хранится "внутри" нее.

    Но ведь пользователь может запустить программу-"подготовщик" на любом количестве компьютеров и потом запускать там рабочее приложение. Какая же это защита?

  20. проще привязаться к серийнику винта, он редко меняется. 

    Как это сделать?

     

    И вообще, может быть у кого-то есть решение как сделать простую защиту программы не используя UUID и интернет?

×
×
  • Создать...