📄 adsmodem.pas
字号:
FInterCmdDelay := adsmDefInterCmdDelay;
FTildeDelay := adsmDefTildeDelay;
FExtendTime := adsmDefExtendTime;
FRetryWaitTime := adsmDefRetryWaitTime;
FUpdateStatusTime := adsmDefUpdateStatusTime;
FAutoRetryDial := adsmDefAutoRetryDial;
FForceHangup := adsmDefForceHangup;
FMaxDialAttempts := adsmDefMaxDialAttempts;
FShowStatus := adsmDefShowStatus;
end;
procedure TApdCustomSModem.RefreshModemStatus;
{Refresh the modem status dialog and call the user event (if hooked)}
var
TimeRemaining : Longint;
begin
{Update the modem info class}
with FStatusInfo, FComPort do begin
if FModemState = smsUnknown then
Exit;
msiModemState := FModemState;
case FModemState of
smsDialWait :
begin
Dispatcher.TimerTicksRemaining(msTimeoutTrigger, TimeRemaining);
SetInfoDialWait(FPhoneNumber, FDialAttempt, FMaxDialAttempts,
Ticks2Secs(TimeRemaining));
end;
smsDialCycle :
begin
Dispatcher.TimerTicksRemaining(msTimeoutTrigger, TimeRemaining);
SetInfoDialCycle(FPhoneNumber, FDialAttempt+1, FMaxDialAttempts,{!!.01}
Ticks2Secs(TimeRemaining));
end;
smsAnswerWait :
begin
Dispatcher.TimerTicksRemaining(msTimeoutTrigger, TimeRemaining);
SetInfoAnswerWait(Ticks2Secs(TimeRemaining));
end;
smsAutoAnswerWait :
begin
SetInfoAutoAnswerWait(FAnswerOnRing, msRingReceiveCount);
end;
end;
{Show/Hide the status display if appropriate}
if FShowStatus and
Assigned(FStatusDisplay) then begin
case FModemState of
smsReady, smsAutoAnswerBackground, smsConnected:
if msStatusVisible and
((FModemStateFlags and smsBatchInProgress) = 0) then begin
msStatusVisible := False;
FStatusDisplay.Hide;
end;
else
begin
if not msStatusVisible then begin
msStatusVisible := True;
FStatusDisplay.Show;
FStatusDisplay.Repaint;
end;
FStatusDisplay.UpdateDisplay(FStatusInfo);
end;
end;
end;
{Call the user's status hook}
if Assigned(FConnectionStatus) then
FConnectionStatus(Self, FStatusInfo);
end;
end;
procedure TApdCustomSModem.SetModemState(ModemState : TApdSModemStates);
{Update the modem state variable and call any procedures hooked on status}
begin
if ModemState <> FModemState then begin
FModemState := ModemState;
if (FModemState = smsReady) or
(FModemState = smsUnknown) then
{Disable status trigger}
FComPort.Dispatcher.SetTimerTrigger(msUpdateStatusTrigger,
Secs2Ticks(FUpdateStatusTime), False)
else
{Enable status trigger}
FComPort.Dispatcher.SetTimerTrigger(msUpdateStatusTrigger,
Secs2Ticks(FUpdateStatusTime), True);
if (FModemState = smsDialWait) or
(FModemState = smsDialCycle) and
(not FStatusDisplay.msButtonCycle.Enabled) then begin
FStatusDisplay.msButtonCycle.Enabled := True;
FStatusDisplay.Repaint;
end else if (FStatusDisplay.msButtonCycle.Enabled) then begin
FStatusDisplay.msButtonCycle.Enabled := False;
FStatusDisplay.Repaint;
end;
if (FModemState <> smsUnknown) then
RefreshModemStatus;
end;
end;
function TApdCustomSModem.msResponseMatches(StringToMatch : String) : Boolean;
{Check if the latest modem response contains string to match}
begin
if (pos(StringToMatch, msModemResponse) > 0) then begin
Result := True;
FStatusInfo.AddSendRecvData('[recv] ' + StringToMatch);
end else
Result := False;
end;
function TApdCustomSModem.msResponseIsBusy : Boolean;
{Check if the latest modem response contains BusyMsg}
begin
Result := msResponseMatches(FBusyMsg);
end;
procedure TApdCustomSModem.msCheckForResponseTags;
{Check if the connect responses contain ErrorCompression, DataCompression
or ConnectSpeed tags}
var
S,
TempStr,
ErrorCorrection,
DataCompression : String;
CommaPos : Integer;
begin
S := FErrorCorrectionMsg + ',';
while Length(S) > 0 do begin
CommaPos := Pos(',', S);
if CommaPos = 0 then CommaPos := Length(S);
TempStr := Copy(S, 1, CommaPos-1);
if Pos(TempStr, S) > 0 then begin
If Length(ErrorCorrection) > 0 then ErrorCorrection := ErrorCorrection + ',';
ErrorCorrection := ErrorCorrection + TempStr;
end;
S := Copy(S, CommaPos + 1, Length(S));
end;
S := FDataCompressionMsg + ',';
while Length(S) > 0 do begin
CommaPos := Pos(',', S);
if CommaPos = 0 then CommaPos := Length(S);
TempStr := Copy(S, 1, CommaPos-1);
if Pos(TempStr, S) > 0 then begin
If Length(DataCompression) > 0 then DataCompression := DataCompression + ',';
DataCompression := DataCompression + TempStr;
end;
S := Copy(S, CommaPos + 1, Length(S));
end;
if Length(msModemResponse) > Length(FConnectMsg) then begin
TempStr := Copy(msModemResponse, Length(FConnectMsg) + 1, Length(msModemResponse));
S := msModemResponse;
FConnectSpeed := StrToIntDef(msModemResponse, 0);
end;
FStatusInfo.SetInfoConnected(ErrorCorrection, DataCompression, FConnectSpeed);
end;
function TApdCustomSModem.msResponseIsConnect : Boolean;
{Check if the latest modem response contains ConnectMsg}
begin
Result := msResponseMatches(FConnectMsg);
if Result then begin
{check for error correction, data compression tags in connect responses}
msCheckForResponseTags;
end;
end;
function TApdCustomSModem.msResponseIsError : Boolean;
{Check if the latest modem response contains ErrorMsg}
begin
Result := msResponseMatches(FErrorMsg);
end;
function TApdCustomSModem.msResponseIsNoCarrier : Boolean;
{Check if the latest modem response contains NoCarrierMsg}
begin
Result := msResponseMatches(FNoCarrierMsg);
end;
function TApdCustomSModem.msResponseIsNoDialTone : Boolean;
{Check if the latest modem response contains NoDialToneMsg}
begin
Result := msResponseMatches(FNoDialToneMsg);
end;
function TApdCustomSModem.msResponseIsOk : Boolean;
{Check if the latest modem response contains OkMsg}
begin
Result := msResponseMatches(FOkMsg);
end;
function TApdCustomSModem.msResponseIsRing : Boolean;
{Check if the latest modem response contains RingMsg}
begin
Result := msResponseMatches(FRingMsg);
end;
procedure TApdCustomSModem.msPrepareForResponse(TimeoutTicks : Cardinal);
{Reset a response timer and initialize the response string}
begin
msModemResponse := '';
msCRLFIndex := 0;
FComPort.SetTimerTrigger(msTimeoutTrigger, TimeoutTicks, True);
end;
procedure TApdCustomSModem.msPrepareForCmdResponse;
begin
msPrepareForResponse(FCmdTimeout);
end;
procedure TApdCustomSModem.msPrepareForDialResponse;
begin
msPrepareForResponse(Secs2Ticks(FDialTimeout));
end;
procedure TApdCustomSModem.msPrepareForAnswerResponse;
begin
msPrepareForResponse(Secs2Ticks(FAnswerTimeout));
end;
procedure TApdCustomSModem.msPrepareForAutoAnswerResponse;
begin
msPrepareForResponse(FRingWaitTimeout);
end;
procedure TApdCustomSModem.msPrepareForConnectInfoResponse;
begin
msPrepareForResponse(FConnectInfoTimeout);
end;
procedure TApdCustomSModem.DisplayWaitForResult(Responses : String; Index : Cardinal);
var
Rsp : String;
i : Integer;
j : Cardinal;
begin
Rsp := '';
i := 1;
j := 1;
while (i < Length(Responses)) and
(j < Index) do begin
if (Responses[i] = MultiResponseSeparator) then
inc(j);
inc(i);
end;
if (j = Index) then begin
while (i < Length(Responses)) and
(Responses[i] <> MultiResponseSeparator) do begin
Rsp := Rsp + Responses[i];
inc(i);
end;
end;
FStatusInfo.AddSendRecvData('[recv] ' + Rsp);
FStatusDisplay.UpdateDisplay(FStatusInfo);
end;
procedure TApdCustomSModem.Answer;
{Answer the modem immediately -- not documented for general use}
begin
if (FModemStateFlags and smsWaitForInProgress) <> 0 then
{modem is already waiting for data; prevent reentrancy}
raise EModemBusy.Create(ecModemBusy, False);
{make sure modem is ready}
VerifyStarted;
FComPort.FlushInBuffer;
FStatusDisplay.msEraseAllValues;
{If already dialing, then we have an implied Cancel; if already
connected, then we have an implied Hangup}
FModemStateFlags := FModemStateFlags or smsBatchInProgress;
Hangup;
{If Initialize failed, exit}
FModemStateFlags := FModemStateFlags and not smsBatchInProgress;
if (FModemState <> smsReady) then
Exit;
{Send the answer command and let the state machine handle the response}
msPrepareForAnswerResponse;
PutStringModem(FAnswerCmd);
SetModemState(smsAnswerWait);
end;
procedure TApdCustomSModem.AutoAnswer(RingCount : Byte);
{Tell modem to auto answer on Nth ring}
begin
if (FModemStateFlags and smsWaitForInProgress) <> 0 then
{modem is already waiting for data; prevent reentrancy}
raise EModemBusy.Create(ecModemBusy, False);
{If already dialing, then we have an implied Cancel; if already
connected, then we have an implied Hangup}
FModemStateFlags := FModemStateFlags or smsBatchInProgress;
Hangup;
Initialize;
FModemStateFlags := FModemStateFlags and not smsBatchInProgress;
if (FModemState <> smsReady) then
Exit;
msPrepareForCmdResponse;
SetModemState(smsAutoAnswerBackground);
msRingReceiveCount := 0;
FAnswerOnRing := RingCount;
end;
procedure TApdCustomSModem.Cancel;
{Cancel current modem operation (e.g., dialing)}
var
ExpectedResponses : String;
begin
if (FModemStateFlags and smsWaitForInProgress) <> 0 then
{modem is already waiting for data; prevent reentrancy}
raise EModemBusy.Create(ecModemBusy, False);
{make sure modem is ready}
VerifyStarted;
with FComPort do begin
{If connected, then Cancel implies Hangup}
If (msModemStatusTrigger <> 0) then
Hangup
else begin
{Cancel any active timers}
Dispatcher.SetTimerTrigger(msTimeoutTrigger, 0, False);
if (FModemState = smsDialWait) or
(FModemState = smsAnswerWait) then begin
{Need to cancel the dial or answer in progress}
FModemStateFlags := FModemStateFlags or smsWaitForInProgress;
SetModemState(smsCancel);
ExpectedResponses := OkMsg + #13+#10 + MultiResponseSeparator +
ErrorMsg + #13#10 + MultiResponseSeparator +
NoCarrierMsg + #13#10 + MultiResponseSeparator +
FDialCancelCmd;
{Send the cancel command}
{$IFDEF Win32}
PrepareWait;
{$ENDIF}
PutStringModem(FDialCancelCmd);
{Wait for a response from the modem or a timeout}
WaitForMultiString(ExpectedResponses, CmdTimeout, FAllowYielding,
IgnoreCase, MultiResponseSeparator);
FModemStateFlags := FModemStateFlags and not smsWaitForInProgress;
end;
FComPort.FlushInBuffer;
SetModemState(smsReady);
end;
end;
end;
procedure TApdCustomSModem.Dial(AutoRetry : Boolean);
{Attempt connection}
begin
if (FModemStateFlags and smsWaitForInProgress) <> 0 then
{modem is already waiting for data; prevent reentrancy}
raise EModemBusy.Create(ecModemBusy, False);
if (FPhoneNumber <> '') then begin
FStatusDisplay.msEraseAllValues;
FDialAttempt := 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -