webideclient.pp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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 : nativeint; 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 : nativeint 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) and Assigned(aPayload) and Assigned(OnActionResponse) then
  65. begin
  66. aID:=NativeInt(aPayLoad['id']);
  67. aName:=String(aPayLoad['name']);
  68. aActionPayLoad:=TJSObject(aPayLoad['payload']);
  69. OnActionResponse(Self,aID,aName,aActionPayload);
  70. end;
  71. end;
  72. procedure TIDEClient.OnClientRegistered(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  73. begin
  74. if (aCode div 100)=2 then
  75. begin
  76. FClientID:=NativeInt(aPayload['id']);
  77. if FStartPolling then
  78. StartCommandPolling;
  79. end
  80. else
  81. FClientID:=0;
  82. end;
  83. procedure TIDEClient.OnCommandsReceived(aCode: Integer; aCodeText: String; aPayload: TJSObject);
  84. Var
  85. A: TJSArray;
  86. begin
  87. FLastPoll:=Nil;
  88. if (aCode div 100)<>2 then
  89. exit;
  90. if Assigned(aPayload) and isArray(aPayload['commands']) then
  91. begin
  92. A:=TJSArray(aPayload['commands']);
  93. if (A.Length>0) then
  94. OnCommands(Self,A);
  95. end;
  96. end;
  97. constructor TIDEClient.Create(aOwner: TComponent);
  98. begin
  99. Inherited;
  100. FLastPoll:=Nil;
  101. IDEURL:='http://'+Window.location.hostname+':'+Window.location.port+'/IDE/';
  102. end;
  103. procedure TIDEClient.RegisterClient;
  104. Var
  105. P : TJSObject;
  106. Req : TIDERequest;
  107. begin
  108. P:=New(['url',window.locationString]);
  109. req:=TIDERequest.Create('POST',IDEURL+'Client',P,@OnClientRegistered);
  110. end;
  111. procedure TIDEClient.UnRegisterClient;
  112. Var
  113. Req : TIDERequest;
  114. begin
  115. Req:=TIDERequest.Create('DELETE',IDEURL+'Client/'+IntToStr(ClientID),Nil,@OnClientRegistered);
  116. end;
  117. procedure TIDEClient.StartCommandPolling;
  118. begin
  119. if ClientID<>0 then
  120. FPollID:=Window.setInterval(@DoCommandPoll,FCommandPollInterval)
  121. else
  122. FStartPolling:=True;
  123. end;
  124. procedure TIDEClient.StopCommandPolling;
  125. begin
  126. FStartPolling:=False;
  127. if (FPollID>0) then
  128. Window.clearInterval(FPollID);
  129. end;
  130. function TIDEClient.GetNextID: NativeInt;
  131. begin
  132. Inc(FActionID);
  133. Result:=FActionID;
  134. end;
  135. procedure TIDEClient.SendAction(const aName: String; aPayLoad: TJSObject);
  136. Var
  137. aAction : TJSObject;
  138. aID : NativeInt;
  139. req: TIDERequest;
  140. begin
  141. aID:=GetNextID;
  142. aAction:=New(['id',aID,
  143. 'name',aName,
  144. 'payload',aPayLoad]);
  145. req:=TIDERequest.Create('POST',IDEURL+'Action/'+IntToStr(ClientID)+'/'+IntToStr(aID),aAction,@OnActionSent);
  146. end;
  147. { TIDERequest }
  148. procedure TIDERequest.ProcessResponse;
  149. var
  150. P : TJSObject;
  151. begin
  152. if ((FXHR.Status div 100)=2) and (FXHR.ResponseHeaders['Content-Type']='application/json') then
  153. P:=TJSJSON.parseObject(FXHR.responseText)
  154. else
  155. P:=Nil;
  156. if Assigned(FOnResponse) then
  157. FOnResponse(FXHR.Status,FXHR.StatusText,P);
  158. end;
  159. procedure TIDERequest.DoStateChange;
  160. begin
  161. case FXHR.readyState of
  162. TJSXMLHttpRequest.DONE :
  163. begin
  164. if Assigned(FOnResponse) then
  165. ProcessResponse;
  166. Free;
  167. end;
  168. end;
  169. end;
  170. constructor TIDERequest.Create(aMethod, aURl: String; aPayLoad: TJSObject; aOnResponse: TIDEResponseHandler);
  171. Var
  172. S : String;
  173. begin
  174. FOnResponse:=aOnResponse;
  175. FXHR:=TJSXMLHttpRequest.New;
  176. FXHR.open(aMethod,aURL);
  177. if assigned(aPayload) then
  178. S:=TJSJSON.Stringify(aPayload)
  179. else
  180. S:='';
  181. FXHR.setRequestHeader('Content-Type','application/json');
  182. FXHR.onreadystatechange:=@DoStateChange;
  183. FXHR.send(S);
  184. end;
  185. end.