webideclient.pp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. unit webideclient;
  2. {$mode objfpc}
  3. interface
  4. uses
  5. Classes, SysUtils, js, web;
  6. type
  7. TIDEClient = Class;
  8. TIDEResponseHandler = Procedure (aCode : Integer; aCodeText : String; aPayload : TJSObject) of object;
  9. { TIDERequest }
  10. TIDERequest = Class(TObject)
  11. Private
  12. FXHR : TJSXMLHttpRequest;
  13. FOnResponse: TIDEResponseHandler;
  14. Procedure ProcessResponse;
  15. procedure DoStateChange;
  16. Public
  17. Constructor Create(aMethod, aURl: String; aPayLoad: TJSObject; aOnResponse: TIDEResponseHandler);
  18. end;
  19. { TIDEClient }
  20. TCommandEvent = Procedure (Sender : TObject; aCommands : TJSArray) of object;
  21. TActionEvent = Procedure (Sender : TObject; aID : Int64; aName : String; aPayload : TJSObject) of object;
  22. TIDEClient = Class(TComponent)
  23. private
  24. FActionID : NativeInt;
  25. FOnActionResponse: TActionEvent;
  26. FPollID : NativeInt;
  27. FCommandPollInterval : Integer;
  28. FClientID: NativeInt;
  29. FIDEURL: String;
  30. FOnCommands: TCommandEvent;
  31. FLastPoll : TIDERequest;
  32. FStartPolling : Boolean;
  33. procedure DoCommandPoll;
  34. procedure OnActionSent(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  35. procedure OnClientRegistered(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  36. procedure OnCommandsReceived(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  37. Public
  38. Constructor Create(aOwner : TComponent); override;
  39. Procedure RegisterClient;
  40. Procedure UnRegisterClient;
  41. Procedure StartCommandPolling;
  42. Procedure StopCommandPolling;
  43. Function GetNextID : NativeInt;
  44. procedure SendAction(Const aName : String; aPayLoad : TJSObject);
  45. Property IDEURL : String read FIDEURL Write FIDEURL;
  46. Property ClientID : Int64 read FClientID Write FClientID;
  47. Property CommandPollInterval : Integer Read FCommandPollInterval Write FCommandPollInterval;
  48. Property OnCommands : TCommandEvent Read FOnCommands Write FOnCommands;
  49. Property OnActionResponse : TActionEvent Read FOnActionResponse Write FOnActionResponse;
  50. end;
  51. implementation
  52. { TIDEClient }
  53. procedure TIDEClient.DoCommandPoll;
  54. begin
  55. if Not Assigned(FLastPoll) then
  56. FLastPoll:=TIDERequest.Create('Get',IDEURL+'Command/'+IntToStr(ClientID)+'/',Nil,@OnCommandsReceived);
  57. end;
  58. procedure TIDEClient.OnActionSent(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  59. Var
  60. aID : NativeInt;
  61. aName : string;
  62. aActionPayload : TJSObject;
  63. begin
  64. if (aCode div 100)=2 then
  65. begin
  66. aID:=NativeInt(aPayLoad['id']);
  67. aName:=String(aPayLoad['name']);
  68. aActionPayLoad:=TJSObject(aPayLoad['payload']);
  69. If Assigned(OnActionResponse) then
  70. OnActionResponse(Self,aID,aName,aActionPayload);
  71. end;
  72. end;
  73. procedure TIDEClient.OnClientRegistered(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  74. begin
  75. if (aCode div 100)=2 then
  76. begin
  77. FClientID:=NativeInt(aPayload['id']);
  78. if FStartPolling then
  79. StartCommandPolling;
  80. end
  81. else
  82. FClientID:=0;
  83. end;
  84. procedure TIDEClient.OnCommandsReceived(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  85. Var
  86. A: TJSArray;
  87. begin
  88. FLastPoll:=Nil;
  89. if (aCode div 100)<>2 then
  90. exit;
  91. if Assigned(aPayload) and isArray(aPayload['commands']) then
  92. begin
  93. A:=TJSArray(aPayload['commands']);
  94. if (A.Length>0) then
  95. OnCommands(Self,A);
  96. end;
  97. end;
  98. constructor TIDEClient.Create(aOwner: TComponent);
  99. begin
  100. Inherited;
  101. FLastPoll:=Nil;
  102. IDEURL:='http://'+Window.location.hostname+':'+Window.location.port+'/IDE/';
  103. end;
  104. procedure TIDEClient.RegisterClient;
  105. Var
  106. P : TJSObject;
  107. Req : TIDERequest;
  108. begin
  109. P:=New(['url',window.locationString]);
  110. req:=TIDERequest.Create('POST',IDEURL+'Client',P,@OnClientRegistered);
  111. end;
  112. procedure TIDEClient.UnRegisterClient;
  113. Var
  114. Req : TIDERequest;
  115. begin
  116. Req:=TIDERequest.Create('DELETE',IDEURL+'Client/'+IntToStr(ClientID),Nil,@OnClientRegistered);
  117. end;
  118. procedure TIDEClient.StartCommandPolling;
  119. begin
  120. if ClientID<>0 then
  121. FPollID:=Window.setInterval(@DoCommandPoll,FCommandPollInterval)
  122. else
  123. FStartPolling:=True;
  124. end;
  125. procedure TIDEClient.StopCommandPolling;
  126. begin
  127. FStartPolling:=False;
  128. if (FPollID>0) then
  129. Window.clearInterval(FPollID);
  130. end;
  131. function TIDEClient.GetNextID: NativeInt;
  132. begin
  133. Inc(FActionID);
  134. Result:=FActionID;
  135. end;
  136. procedure TIDEClient.SendAction(const aName: String; aPayLoad: TJSObject);
  137. Var
  138. aAction : TJSObject;
  139. aID : NativeInt;
  140. req: TIDERequest;
  141. begin
  142. aID:=GetNextID;
  143. aAction:=New(['id',aID,
  144. 'name',aName,
  145. 'payload',aPayLoad]);
  146. req:=TIDERequest.Create('POST',IDEURL+'Action/'+IntToStr(ClientID)+'/'+IntToStr(aID),aAction,@OnActionSent);
  147. end;
  148. { TIDERequest }
  149. procedure TIDERequest.ProcessResponse;
  150. var
  151. P : TJSObject;
  152. begin
  153. if ((FXHR.Status div 100)=2) and (FXHR.ResponseHeaders['Content-Type']='application/json') then
  154. P:=TJSJSON.parseObject(FXHR.responseText)
  155. else
  156. P:=Nil;
  157. if Assigned(FOnResponse) then
  158. FOnResponse(FXHR.Status,FXHR.StatusText,P);
  159. end;
  160. procedure TIDERequest.DoStateChange;
  161. begin
  162. case FXHR.readyState of
  163. TJSXMLHttpRequest.DONE :
  164. begin
  165. if Assigned(FOnResponse) then
  166. ProcessResponse;
  167. Free;
  168. end;
  169. end;
  170. end;
  171. constructor TIDERequest.Create(aMethod, aURl: String; aPayLoad: TJSObject; aOnResponse: TIDEResponseHandler);
  172. Var
  173. S : String;
  174. begin
  175. FOnResponse:=aOnResponse;
  176. FXHR:=TJSXMLHttpRequest.New;
  177. FXHR.open(aMethod,aURL);
  178. if assigned(aPayload) then
  179. S:=TJSJSON.Stringify(aPayload)
  180. else
  181. S:='';
  182. FXHR.setRequestHeader('Content-Type','application/json');
  183. FXHR.onreadystatechange:=@DoStateChange;
  184. FXHR.send(S);
  185. end;
  186. end.