Czy pod COM jest podpięte urządzenie?

0

Cześć, przepraszam za takie lame'owe pytanie, ale nie wiem za bardzo jak szukać.
Tworzę sobie klasę do obsługi portów COM opartą o boost. Problem jest taki. Jeśli otwieram port, na którym nie ma żadnego urządzenia, boost nie zwraca mi żadnego błędu i port jest otwarty. Teraz pytanie, w jaki sposób zorientować się, czy pod port jest podpięte jakieś urządzenie? Pewnie ma to związek z RTS, CTS i innymi esami, ale nie za bardzo mogę to ogarnąć. Jakieś wskazówki / gotowe rozwiązania?

0

Nie podałeś o jaki język chodzi. Dlatego podaje sprawdzone rozwiązanie pod Delphi dla TComPort:

function ShowPolishMsgDlg(Msg : string; DlgType : TMSgDlgType; Buttons : TMsgDlgButtons) : TModalResult;
var
  Dlg : TForm;
begin
  Dlg := CreateMessageDialog(Msg, DlgType, Buttons);
  Dlg.BorderIcons := [];
  Dlg.Caption := Application.Title;
  TButton(Dlg.FindComponent('Ok')).Caption := 'OK';
  TButton(Dlg.FindComponent('No')).Caption := '&Nie';
  TButton(Dlg.FindComponent('Yes')).Caption := '&Tak';
  TButton(Dlg.FindComponent('Help')).Caption := 'Pomoc';
  TButton(Dlg.FindComponent('Retry')).Caption := 'Ponów';
  TButton(Dlg.FindComponent('All')).Caption := 'Wszystko';
  TButton(Dlg.FindComponent('Cancel')).Caption := 'Anuluj';
  TButton(Dlg.FindComponent('Ignore')).Caption := 'Ignoruj';
  TButton(Dlg.FindComponent('NoToAll')).Caption := 'Nie na wszystko';
  TButton(Dlg.FindComponent('YesToAll')).Caption := 'Tak na wszystko';
  Dlg.ShowModal;
  Result := Dlg.ModalResult;
end;

function CheckCom(ComNumStr : string) : integer;
var
  FHandle : THandle;
begin
  Result := 0;
  FHandle := CreateFile(PChar(ComNumStr),
    GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if FHandle <> INVALID_HANDLE_VALUE then
  begin
    CloseHandle(FHandle)
  end
  else
  begin
    Result := GetLastError;
  end;
end;

procedure TMainForm.StecaConnectBtnClick(Sender : TObject);
var
  ComRes : integer;
begin
  with StecaComPort do
  begin
    if Trim(Port) = '' then
    begin
      StecaSettingsBtn.Click;
    end
    else
    begin
      ComRes := CheckCom(Port);
      case ComRes of
        ERROR_ACCESS_DENIED :
          begin
            ShowPolishMsgDlg(Format('Port: %s aktualnie w użyciu!', [Port]), mtWarning, [mbOk]);
          end;
        ERROR_FILE_NOT_FOUND :
          begin
            ShowPolishMsgDlg(Format('Port: %s nie istnieje!', [Port]), mtError, [mbOk]);
          end;
      end;
      if ComRes = 0 then
      begin
        Open;
        ChangeStateOfButtons;
      end;
    end;
  end;
end;
1

Napisałem, że używam boost, a więc założyłem, że będzie wiadomo, że chodzi o C++ ;) TComPort znam i używałem. I tam właśnie tak było - nie ma podpiętego urządzenia, zwracało wyjątek. Czyli CreateFile powinno rozwiązać sprawę?

2

To przetłumacz sobie na C++ funkcję CheckCom i tyle. Poza tym ja się mam nie znać na 453872782 do potęgi pierdyliard technologiach i IDE. To o jaki język chodzi, przede wszystkim powinien jasno określać tag wątku. Ale ludzie się tutaj głupio "wycwanili", że będą jak na złość umieszczać w tagach wszystko. Byle by tylko nie podać konkretnej informacji o języku. Co w przypadku podania konkretów, pozwala od razu zorientować się czy mogę pomóc. Mnie natomiast na ten wątek skierował sam tag comport, bo z nim miałem ostatnio do czynienia, także odpisałem pod kątem jak go używałem w Delphi, C++ nie ruszam.

0

Wydaje mi się, że to powinno wystarczyć:

bool basic_serial_port::is_open() const;

Rzuć okiem na przykład: http://boost.2283326.n4.nabble.com/Simple-serial-port-demonstration-with-boost-asio-asynchronous-I-O-td2582657.html

1

eeee a od kiedy to nie można otworzyć portu COM jeśli nic nie jest do niego podpięte??? Coś chyba ściemniacie. Jedyny znany mi 100% sposób to po otwarciu portu spróbować się skomunikować z urządzeniem. Ma to jednak jedną wadę - trzeba wiedzieć jakie urządzenie jest podpięte

0

Nie mówię, że nie można otworzyć, bo można. A ja nie chcę, żeby było można ;) No właśnie ta wada całkowicie przekreśla mi to, co chcę osiągnąć. Na pewno da się to uzyskać jakimiś RTSami itp, ale nie mam zielonego pojęcia jak to ugryźć. Próbowałem też kodu z CreateFile, ale to właśnie tak działa. Jeśli nie jest nic podpięte, to i tak nie zwraca żadnego błędu.

0

Skoro jesteś taki pewny... Weź tylko pod uwagę, że są urządzenia, i to całkiem sporo ich jest, które podpina się TYLKO trzema liniami - TxD, RxD i masa. Jak tutaj chcesz sprawdzać np. linie RTS?

0

@abrakadaber: trzeba kombinować mniej więcej tak, jak to pokazałem. Przynajmniej pod Delphi i z użyciem TComPort. Gdyż może on mieć we własnościach używany przez kogoś na przykład COM9 na jakimś innym niż nasz komputerze. I przy próbie łączenia bez zmiany ustawień załapiemy jakiś tam wyjątek. Którego wolałem w ten sposób pokazany powyżej uniknąć.

0

@olesio tylko, że to sprawdza czy dany port COM jest fizycznie obecny w systemie i czy nie jest otwarty (używany) a nie czy coś jest do niego podłączone.

BTW w ten sam sposób działa też LPT i niestety nic się na to nie poradzi. Zauważcie, że np. drukarki, które były podłączane pod LPT nie były Plug'n'Play - tam ją trzeba było ręcznie instalować (nie tak jak z USB). Po prostu taka jest specyfika tych dwóch portów i nic się na to nie poradzi.

A jeszcze zadam inne pytanie - jak mam do portu COM podpięty np. konwerter z RS232 na RS485 to czy system powinien to "widzieć" jako coś podpiętego czy nie? Bo taki konwerter, jak sama nazwa wskazuje :p, w żaden sposób nie komunikuje się z komputerem a jedynie zmienia jeden rodzaj sygnałów na inny i dopiero do niego są podpięte urządzenia.

0

Port COM nie daje możliwości, by w sposób pewny wykryć czy jest podłączone urządzenie - bez jakiejkolwiek wiedzy o tym urządzeniu.

Ale zakładając że łączysz się z konkretnym znanym tobie urządzeniem, to wysyłasz jakiś nieszkodliwy pakiet na który to urządzenie powinno odpowiedzieć i już.

0

nie musisz czekać za każdym razem. wysyłasz na wszystkie porty na raz, i na każdym nasłuchujesz. jeśli będzie konieczność, to w osobnych wątkach.

0

Chyba wpadłem na jedno rozwiązanie. Boost daje mi handla do otwartego portu, a więc mogę się posługiwać funkcjami WinApi. Zauważyłem, że jeśli wywołam GetCommState, to wtedy gdy nie mam żadnego urządzenia, baudrate zobaczę na 1200, RTSControl na 1(2, gdy mam urządzenie), a byte size na 7 (8, gdy mam urządzenie). I teraz zakładając, że będę obsługiwał raczej współczesne urządzenia, mogę założyć min. baudrate na 9600 i/lub byte size na 8. Tylko teraz pytanie, co będzie lepsze. Czy ta właśnie funkcja, czy może GetCommModemStatus i odczyt RLSD, CTS i DSR?

1 użytkowników online, w tym zalogowanych: 0, gości: 1