websocketКак проанализировать json из websocket для отображения данных в реальном времени? (How to parse json from websocket to display realtime data?)
Привет, Я пытаюсь создать клиент для повторного получения данных в реальном времени из "twelvedata.com " это возвращается с сервера websocket. Вот строка JSON
Я написал клиентский код Delphi, как показано ниже, чтобы получить объект Json, но он вернул статическое значение, и программа зависла.
Спойлер
unit UnitWebsocket;
interface
uses
System.SysUtils,System.Types,System.UITypes,System.Classes,System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Layouts, FMX.Objects, FMX.Memo.Types,Skia.FMX,
FMX.ScrollBox, FMX.Memo,System.IOUtils,Ics.Fmx.OverbyteIcsWndControl,Ics.Fmx.OverbyteIcsWSocket,Bird.Socket.Client, FMX.WebBrowser;const// API = 'wss://ws.twelvedata.com/v1/quotes/price?apikey=key';
API ='';
type
TMainUnit=class(TForm)Rectangle1:TRectangle;GridPanelLayout1:TGridPanelLayout;GridPanelLayout2:TGridPanelLayout;GridPanelLayout3:TGridPanelLayout;Connection:TLabel;OpenConnection:TCornerButton;CloseConnection:TCornerButton;Messages:TLabel;Subscribe:TCornerButton;Unsubscribe:TCornerButton;Reset:TCornerButton;Layout1:TLayout;Memo1:TMemo;Send:TCornerButton;Timer1:TTimer;GridPanelLayout4:TGridPanelLayout;GridPanelLayout5:TGridPanelLayout;Price:TLabel;Beautify:TCornerButton;Layout2:TLayout;DisplayMemo:TMemo;WebBrowser1:TWebBrowser;Splitter1:TSplitter;
procedure SubscribeClick(Sender:TObject);
procedure UnsubscribeClick(Sender:TObject);
procedure ResetClick(Sender:TObject);
procedure SendClick(Sender:TObject);
procedure CloseConnectionClick(Sender:TObject);
procedure FormCreate(Sender:TObject);
procedure OpenConnectionClick(Sender:TObject);// procedure BeautifyClick(Sender: TObject);// procedure LoadCode(const ACode, AType: string; Wrapped: Boolean = False);// procedure LoadError(const Msg: string);private{ D�clarations priv�es }FBirdSocket:TBirdSocketClient;
procedure StartCources;
procedure Display(Msg:String);
procedure SocketText(Sender:TObject;const iText:String);
procedure FCources(const rowCount, colCount, srowCount, scolCount: integer);
procedure Timer1Timer(Sender:TObject);public{ D�clarations publiques }
end;
var
MainUnit:TMainUnit;
implementation
{$R *.fmx}
uses
System.NetEncoding,System.Rtti,System.Math,System.JSON.Types,System.JSON.Builders,System.JSON.Readers,Common,Converters;
procedure TMainUnit.CloseConnectionClick(Sender:TObject);
begin
tryif not Assigned(FBirdSocket) then
Exit;ifFBirdSocket.Connected then
FBirdSocket.Disconnect;FreeAndNil(FBirdSocket);DisplayMemo.Lines.Add('Websocket connection closed!');// Timer1.Enabled := False;CloseConnection.Enabled:=False;Send.Enabled:=False;OpenConnection.Enabled:=True;
except
on E:ExceptiondoDisplay(E.Message);
end
end;{**************************************}{Display a message in our display memo.Delete lines to be sure to not }{ overflow the memo which may have a limited capacity.}
procedure TMainUnit.Display(Msg:String);
var
I :Integer;
begin
DisplayMemo.Lines.BeginUpdate;tryifDisplayMemo.Lines.Count>200 then begin
for I :=1 to 50doDisplayMemo.Lines.Delete(0);
end;DisplayMemo.Lines.Add(Format('%s <== %s',[FormatDateTime('dd/mm/yyyy hh:mm:ss',Now),Msg]));
finally
DisplayMemo.Lines.EndUpdate;DisplayMemo.GoToTextEnd;
end;
end;
procedure TMainUnit.FCources(const rowCount, colCount, srowCount, scolCount: integer);
var
i,j: integer;
trend:TSkSvg;
aRect:TRectangle;
bRect:TRectangle;
aGridP:TGridPanelLayout;
fLabel:TLabel;
aControl, bControl, cControl, dControl :TControl;
begin
GridPanelLayout5.RowCollection.BeginUpdate;GridPanelLayout5.ColumnCollection.BeginUpdate;GridPanelLayout5.ControlCollection.Clear;GridPanelLayout5.RowCollection.Clear;GridPanelLayout5.ColumnCollection.Clear;for i :=0 to -1+GridPanelLayout5.ControlsCountdoGridPanelLayout5.Controls[0].Free;for i :=1 to rowCount do
with GridPanelLayout5.RowCollection.Adddo
begin
SizeStyle:=TGridPanelLayout.TSizeStyle.Percent;Value:=100/ rowCount;//have cells evenly distributed
end;for i :=1 to colCount do
with GridPanelLayout5.ColumnCollection.Adddo
begin
SizeStyle:=TGridPanelLayout.TSizeStyle.Percent;Value:=100/ colCount;//have cells evenly distributed
end;for i :=0 to -1+ rowCount * colCount do
begin
aRect :=TRectangle.Create(self);
aRect.Parent:=GridPanelLayout5;//magic: place in the next empty cell
aRect.Align:=TAlignLayout.Client;
aRect.Visible:=true;
aRect.Name:='FCource'+IntToStr(i);
aRect.Fill.Color:=TAlphaColorRec.White;
aRect.Margins.Rect:=TRectF.Create(1,1,1,1);
aRect.Stroke.Color:= $FFE5E4E3;
aRect.Stroke.Thickness:=0.7;
aRect.XRadius:=7;
aRect.YRadius:=7;
bRect :=TRectangle.Create(self);
bRect.Parent:= aRect;
bRect.Align:=TAlignLayout.left;
bRect.Name:='FTrend'+IntToStr(i);
bRect.Fill.Color:= $FFE6F4EA;
bRect.Margins.Rect:=TRectF.Create(3,3,3,3);
bRect.Stroke.Kind:=TBrushKind.None;
bRect.Height:=30;
bRect.Width:=30;
bRect.XRadius:=7;
bRect.YRadius:=7;
trend :=TSkSvg.Create(Self);
trend.Svg.Source:=TFile.ReadAllText('Assets\Trendup.svg');// throws error, so put the file inside bin folder
trend.Parent:= bRect;
trend.Align:=TAlignLayout.Center;
trend.Svg.OverrideColor:= $FF137333;
trend.Height:=21;
trend.Width:=21;
aGridP :=TGridPanelLayout.Create(Self);
with aGridP do
begin
aGridP.Parent:= aRect;
aGridP.Align:=TAlignLayout.Client;
aGridP.Margins.Left:=3;
aGridP.RowCollection.BeginUpdate;
aGridP.ColumnCollection.BeginUpdate;
aGridP.ControlCollection.Clear;
aGridP.RowCollection.Clear;
aGridP.ColumnCollection.Clear;try// Make a loop in the columns using Avisoff and this seems to work in all platformsfor j :=0 to -1+ aGridP.ControlsCountdo
aGridP.ControlCollection.Controls[j,0].DisposeOf;for j :=1 to srowCount do
with aGridP.RowCollection.Adddo
begin
SizeStyle:=TGridPanelLayout.TSizeStyle.Percent;Value:=100/ srowCount;//have cells evenly distributed
end;for j :=1 to colCount do
with aGridP.ColumnCollection.Adddo
begin
SizeStyle:=TGridPanelLayout.TSizeStyle.Percent;
end;// have specified cells values
aGridP.ColumnCollection[0].Value:=60;
aGridP.ColumnCollection[1].Value:=40;{$REGION 'Region loop'}for j :=0 to -1+ srowCount * scolCount do
begin
fLabel :=TLabel.Create(Self);
fLabel.Parent:= aGridP;
fLabel.Align:=TAlignLayout.Client;// fLabel.AutoSize := true;
fLabel.Margins.Right:=3;
fLabel.Margins.Left:=3;
fLabel.Margins.Top:=3;
fLabel.Margins.Bottom:=3;
aControl := aGridP.ControlCollection.Controls[0,0];ifAssigned(aControl) AND (aControl IS TLabel) then
begin
TLabel(aControl).StyledSettings:=TLabel(aControl).StyledSettings-[TStyledSetting.Style];TLabel(aControl).TextSettings.Font.Style:=TLabel(aControl).TextSettings.Font.Style+[TFontStyle.fsBold];TLabel(aControl).Text:='FTicker'+IntToStr(aGridP.ControlCollection.IndexOf(aControl));
end;
bControl := aGridP.ControlCollection.Controls[0,1];ifAssigned(bControl) AND (bControl IS TLabel) then
begin
TLabel(bControl).Text:='FxValue'+IntToStr(aGridP.ControlCollection.IndexOf(bControl));
end;
cControl := aGridP.ControlCollection.Controls[1,0];ifAssigned(cControl) AND (cControl IS TLabel) then
begin
TLabel(cControl).Text:='Percantage'+IntToStr(aGridP.ControlCollection.IndexOf(cControl));TLabel(cControl).TextAlign:=TTextAlign.Trailing
end;
dControl := aGridP.ControlCollection.Controls[1,1];ifAssigned(dControl) AND (dControl IS TLabel) then
begin
TLabel(dControl).Text:='Change'+IntToStr(aGridP.ControlCollection.IndexOf(dControl));TLabel(dControl).TextAlign:=TTextAlign.Trailing
end;
end;{$ENDREGION 'Region loop'}{$REGION 'Region JSONIterator'}{$ENDREGION 'Region JSONIterator'}
finally
aGridP.RowCollection.EndUpdate;
aGridP.ColumnCollection.EndUpdate;
end;
end;
end;GridPanelLayout5.RowCollection.EndUpdate;GridPanelLayout5.ColumnCollection.EndUpdate;
end;
procedure TMainUnit.StartCources;
begin
//
end;
procedure TMainUnit.FormCreate(Sender:TObject);
begin
{$IFDEF MSWINDOWS}ReportMemoryLeaksOnShutdown:=(DebugHook<>0);{$ENDIF}// FBirdSocket.HeartBeatInterval := 17;Timer1:=TTimer.Create(Self);Timer1.Interval:=10000;Timer1.OnTimer:=Timer1Timer;Timer1.Enabled:=False;CloseConnection.Enabled:=False;Send.Enabled:=False;
end;
procedure TMainUnit.OpenConnectionClick(Sender:TObject);
begin
tryif API=EmptyWideStr then
begin
ShowMessage('Register to TwelveDate and paste API key');Exit;
end
elseFBirdSocket:=TBirdSocketClient.New(API);FBirdSocket.AddEventListener(TEventType.MESSAGE,
procedure(constAText: string)
begin
Display(AText);SocketText(FBirdSocket,AText);
end);FBirdSocket.Connect;FBirdSocket.AutoCreateHandler:=True;DisplayMemo.Lines.Add('Websocket connection opened!');OpenConnection.Enabled:=False;CloseConnection.Enabled:=True;// FBirdSocket.HeartBeatInterval := 70;Timer1.Enabled:=True;FCources(3,2,2,2);
except
on E:Exceptiondo
begin
FBirdSocket.Disconnect;FreeAndNil(FBirdSocket);Display(E.Message);
end;
end
end;
procedure TMainUnit.ResetClick(Sender:TObject);
begin
Memo1.Lines.Clear;Memo1.Lines.Text:=' {'+ sLineBreak +' "action": "reset"'+ sLineBreak +' }'+'';Send.Enabled:=True;
end;
procedure TMainUnit.SubscribeClick(Sender:TObject);
begin
Memo1.Lines.Clear;Memo1.Lines.Text:=' {'+ sLineBreak +' "action": "subscribe",'+ sLineBreak +' "params": {'+ sLineBreak +' "symbols": "EUR/USD,BTC/USD"'+ sLineBreak +' }'+ sLineBreak +' }'+'';Send.Enabled:=True;
end;
procedure TMainUnit.UnsubscribeClick(Sender:TObject);
begin
Memo1.Lines.Clear;Memo1.Lines.Text:=' {'+ sLineBreak +' "action": "unsubscribe",'+ sLineBreak +' "params": {'+ sLineBreak +' "symbols": "EUR/USD"'+ sLineBreak +' }'+ sLineBreak +' }'+'';Send.Enabled:=True;
end;
procedure TMainUnit.SendClick(Sender:TObject);
begin
FBirdSocket.Send(Memo1.lines.Text);StartCources;
end;
procedure TMainUnit.SocketText(Sender:TObject;const iText:String);
begin
var StringReader:=TStringReader.Create(iText);
var TextReader:=TJsonTextReader.Create(StringReader);
var Iterator:=TJSONIterator.Create(TextReader);tryIterator.Recurse;whileIterator.Nextdo
begin
var cIterator :=Iterator;if cIterator.Find('price') then
begin
Price.Text:= cIterator.AsDouble.ToString;
end;
end;
finally
StringReader.DisposeOf;TextReader.DisposeOf;Iterator.DisposeOf;
end;
end;
procedure TMainUnit.Timer1Timer(Sender:TObject);
begin
FBirdSocket.Send('{"action": "heartbeat"}');
end;
end.
ПРИМЕЧАНИЕ: Я использую эту бесплатную библиотеку websocket bird-socket-client
я хочу, чтобы данные отображались следующим образом:
Вопрос
Legit Coder
Привет, Я пытаюсь создать клиент для повторного получения данных в реальном времени из "twelvedata.com " это возвращается с сервера websocket. Вот строка JSON
Я написал клиентский код Delphi, как показано ниже, чтобы получить объект Json, но он вернул статическое значение, и программа зависла.
ПРИМЕЧАНИЕ: Я использую эту бесплатную библиотеку websocket bird-socket-client
я хочу, чтобы данные отображались следующим образом:
12dataClient.zip
Ссылка на комментарий
3 ответа на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.