Olá pessoal,
estou fazendo testes para utilizar o acbrsms e me deparei com o seguinte problema:
Utilizei algumas das funcoes do exemplo criado pelo Regys para montar um serviço rodando em um servidor.
O mesmo projeto desenvolvi um aplicativo, que funciona perfeitamente. Só que no modo serviço, ele informa que esta sincronizando, ativando e até em linha, mas quando vai enviar a mensagem aparece o erro Communication error 9997: Timeout during operation. Alguem poderia me ajudar ? Obrigado.
Segue o codigo fonte do serviço.
unit frmprincipal;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
ExtCtrls, ACBrSMSClass, ACBrBase, ACBrSMS, WideStrings, DbxDatasnap, SqlExpr,
DB, DBClient, DSConnect;
type
TAeonService = class(TService)
AtivaMSG: TTimer;
ACB: TACBrSMS;
DSPSS0: TDSProviderConnection;
upd: TClientDataSet;
bd: TClientDataSet;
dSMS: TSQLConnection;
procedure ServiceExecute(Sender: TService);
procedure ServiceAfterInstall(Sender: TService);
procedure ServiceAfterUninstall(Sender: TService);
procedure ServiceBeforeInstall(Sender: TService);
procedure ServiceBeforeUninstall(Sender: TService);
procedure ServiceContinue(Sender: TService; var Continued: Boolean);
procedure ServiceCreate(Sender: TObject);
procedure ServiceDestroy(Sender: TObject);
procedure ServicePause(Sender: TService; var Paused: Boolean);
procedure ServiceShutdown(Sender: TService);
procedure ServiceStart(Sender: TService; var Started: Boolean);
procedure ServiceStop(Sender: TService; var Stopped: Boolean);
procedure AtivaMSGTimer(Sender: TObject);
private
FLogado: Boolean;
{ Private declarations }
public
Function GetServiceController: TServiceController; override;
Function ConexaoComOServidor: Boolean;
Function LocalizacaoDoBancoDeDados(PathFile: String): boolean;
Function enviarMSG :string;
Function RemoveAcento(sEntrada: String): String;
{ Public declarations }
end;
procedure doSaveLog(msg: string);
var
AeonService: TAeonService;
cservidor : string;
cport : string;
portaCOM : string;
Velocidade : integer;
modelo : string;
ctimeout : integer;
implementation
{$R *.DFM}
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
AeonService.Controller(CtrlCode);
end;
function TAeonService.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;
procedure TAeonService.ServiceAfterInstall(Sender: TService);
begin
doSaveLog('ServiceAfterInstall');
end;
procedure TAeonService.ServiceAfterUninstall(Sender: TService);
begin
doSaveLog('ServiceAfterUninstall');
end;
procedure TAeonService.ServiceBeforeInstall(Sender: TService);
begin
doSaveLog('ServiceBeforeInstall');
end;
procedure TAeonService.ServiceBeforeUninstall(Sender: TService);
begin
doSaveLog('ServiceBeforeUninstall');
end;
procedure TAeonService.ServiceContinue(Sender: TService;
var Continued: Boolean);
begin
doSaveLog('ServiceContinue');
end;
procedure TAeonService.ServiceCreate(Sender: TObject);
begin
doSaveLog('ServiceCreate');
end;
procedure TAeonService.ServiceDestroy(Sender: TObject);
begin
doSaveLog('ServiceDestroy');
end;
procedure TAeonService.ServicePause(Sender: TService; var Paused: Boolean);
begin
doSaveLog('ServicePause');
end;
procedure TAeonService.ServiceShutdown(Sender: TService);
begin
doSaveLog('ServiceShutdown');
end;
procedure TAeonService.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
doSaveLog('ServiceStop');
end;
procedure TAeonService.ServiceExecute(Sender: TService);
begin
doSaveLog('ServiceExecute');
ativaMSG.Enabled := true;
while (not self.Terminated) do
ServiceThread.ProcessRequests(true);
end;
/////////////////////////////////////////////////////
// //
//Log de events //
// //
/////////////////////////////////////////////////////
procedure doSaveLog(msg: string);
var
loLista : TStringList;
begin
try
loLista := Tstringlist.Create;
try
if FileExists('c:\log.log') then
loLista.LoadFromFile('C:\log.log');
loLista.Add(datetimetostr(now)+ ':' + msg);
except
on e:exception do
loLista.Add(datetimetostr(now)+ ': Erro '+ e.Message);
end;
finally
loLista.SaveToFile('c:\log.log');
loLista.Free;
end;
end;
procedure TAeonService.ServiceStart(Sender: TService; var Started: Boolean);
begin
Started := Localizacaodobancodedados('AEONSMS.INI');
doSaveLog('ServiceStart');
if not ACB.Ativo then
begin
// ACB.Modelo := TACBRSMSModelo(strtoint(modelo)); // TACBrSMSModelo(cbxModelo.ItemIndex);
ACB.Device.Porta := portacom;
ACB.Device.Baud := Velocidade;
ACB.IntervaloEntreMensagens := 5000;
ACB.QuebraMensagens := true;
ACB.ATTimeOut := ctimeout;
try
acb.Ativar;
except on e:exception do
doSaveLog('Erro: SMS não ativado - '+e.message);
end;
doSaveLog('SMS Ativado');
end;
end;
// Conecta a aplicação ao banco de dado existente no caminho previsto
Function TAeonService.conexaoComOServidor: Boolean;
begin
dSMS.Connected := false;
Result := False;
dSMS.Params.Values['HOSTNAME'] := cServidor;
dSMS.Params.Values['PORT'] := cPort;
try
dSMS.Open;
Except on E:Exception do
doSaveLog('Falha de conexao ao BD '+e.Message);
end;
If dSMS.Connected then
Result := True
else
doSaveLog('Falha de conexao ao dSMS');
end;
//Funcao para localizar os parametros do banco de dados através do path que gerou o thread
//
//
//
//
Function TAeonService.LocalizacaoDoBancoDeDados(PathFile: String): boolean;
var
F :TextFile;
Path : String;
begin
AssignFile(F, ExtractFilePath(ParamStr(0)) + PathFile);
Reset(f); //abre o arquivo para leitura;
While not eof(F) do
begin
Readln(F,Path); //Lê do arquivo e desce uma linha. O conteúdo lido é transferido para a variável linha
if Copy(Path,1,9)=UPPERCASE('database=') then
cServidor := Trim(Copy(Path,10,50));
if Copy(Path,1,5)=UPPERCASE('port=') then
cPort := Trim(Copy(Path,6,50));
if Copy(Path,1,8)=UPPERCASE('NMODELO=') then
modelo := Trim(Copy(Path,9,50));
if Copy(Path,1,6)=UPPERCASE('PORTA=') then
portaCOM := Trim(Copy(Path,7,50));
if Copy(Path,1,11)=UPPERCASE('VELOCIDADE=') then
Velocidade := StrToInt(Copy(Path,12,50));
if Copy(Path,1,9)=UPPERCASE('ATIVAMSG=') then
ativaMSG.Interval := StrToInt(Copy(Path,10,50));
if Copy(Path,1,8)=UPPERCASE('TIMEOUT=') then
cTimeout := StrToInt(Copy(Path,9,50));
end;
Closefile(F);
if (trim(cservidor)<>'') and (trim(cport)<>'') then
begin
doSaveLog('BD configurado == '+cServidor+'|'+cPort+'|'+MODELO+'|'+PortaCom+'|'+inttostr(velocidade)+'|'+
inttostr(ativaMSG.Interval)+'|'+inttostr(ctimeout));
Result := true;
end
else
Result :=false;
end;
procedure TAeonService.AtivaMSGTimer(Sender: TObject);
var
Sinc: TACBrSMSSincronismo;
begin
if not ACB.Ativo then
begin
doSaveLog('Ativando ACB...');
// ACB.Modelo := TACBRSMSModelo(strtoint(modelo)); // TACBrSMSModelo(cbxModelo.ItemIndex);
ACB.Device.Porta := portaCOM;
ACB.Device.Baud := Velocidade;
ACB.IntervaloEntreMensagens := 5000;
ACB.QuebraMensagens := false;
ACB.ATTimeOut := ctimeout;
try
acb.Ativar;
except on e:exception do
doSaveLog('Servico SMS não ativado ' +e.Message);
end;
end;
if ACB.Ativo=true then
begin
Sinc := ACB.EstadoSincronismo;
if Sinc <> sinSincronizado then
begin
doSaveLog('Erro: SMS nao sincronizado');
exit;
end;
end
else
exit;
//aqui setar os valores para o banco de dados
Try
dSMS.Connected := true;
except on e:exception do
doSaveLog('Erro: conexao com dSMS');
End;
if conexaocomoservidor then
begin
if bd.Active then
bd.Close;
bd.Params.ParamByName('ini').Value := 0;
bd.Params.ParamByName('fim').Value := 0;
bd.Open;
bd.First;
if (acb.EmLinha) and (Sinc = sinSincronizado) then
doSaveLog('SMS em linha e sincronizado')
else
begin
doSaveLog('ERRO: SMS fora de linha');
exit;
end;
if ACB.Ativo=true then
doSaveLog('ACB ativado. SMS a enviar: '+ inttostr(bd.RecordCount))
else
doSaveLog('Erro: ACB não pode ser ativado');
ativamsg.Enabled := false;
if not bd.Eof then
enviarMSG;
acb.Ativo := false;
acb.Desativar;
ativamsg.Enabled := true;
bd.Close;
end;
dSMS.Connected := false;
end;
//Funcao para enviar mensagens registradas no banco de dados
//
//
//
Function TAeonService.enviarMSG :string;
var
status : integer;
indices: String;
destino: string;
mensagem:string;
begin
try
while not BD.Eof do
begin
destino := trim(BD.FieldByName('SMS_DESTINO').Text);
mensagem := RemoveAcento(trim(BD.FieldByName('SMS_MENSAGEM').Text));
doSaveLog('Enviando '+bd.FieldByName('SMS_DESTINO').Text);
try
try
ACB.EnviarSMS(destino,mensagem,Indices);
except
on e:Exception do
begin
doSaveLog('Erro : Falha ao enviar mensagem ->' +e.Message);
exit;
end;
end;
Finally
if trim(indices)<>'' then
status:= 1
else
status:= 0;
doSavelog(trim(indices));
try
upd.Active:=false;
upd.Params.ParamByName('codigo').Value := bd.FieldByName('SMS_COD').Value;
upd.Params.ParamByName('status').Value := status;
upd.Params.ParamByName('envia').AsDate := now;
upd.Params.ParamByName('hora').AsTime := time;
upd.Params.ParamByName('indice').Text := indices;
upd.Params.ParamByName('erro').text := ACB.UltimaResposta;
upd.Params.ParamByName('tentativa').Value := bd.FieldByName('SMS_TENTA').Value + 1;
upd.Execute;
except
on e:exception do
begin
doSaveLog('Erro: gravação do banco de dados falhou. Atualize status :' + e.Message);
// flogado := false;
end;
end;
end;
bd.Next;
destino := '';
mensagem := '';
end;
finally
upd.Close;
bd.Close;
end;
end;
//Funcao para retirar acentos das mensagens SMS. Previne erros de processamento
//pela operadora de telefonia
Function TAeonService.RemoveAcento(sEntrada: String): String;
Const ComAcento = 'áàâäãéèêëíìîïóòôöõúùûüçÁÀÂÄÃÉÈÊËÍÌÎÏÓÒÔÖÕÚÙÛÜÇ+';
SemAcento = 'aaaaaeeeeiiiiooooouuuucAAAAAEEEEIIIIOOOOOUUUUC...';
Var I: Integer;
Begin
For I := 1 To Length(sEntrada) Do
If Pos(sEntrada, ComAcento) <> 0 Then
sEntrada := SemAcento[Pos(sEntrada, ComAcento)];
Result := sEntrada;
End;