Figure ウィンドウでのストリームデータの表示
この例では、HTTP StringConsumer
クラス PricesStreamer
をカスタマイズして、架空の Web サイトからのストリームデータを MATLAB® Figure ウィンドウに表示する方法を説明します。実際に動作する例を作成するには、次を行います。
次のような URL を識別する
url = matlab.net.URI('<URL>','accountId',<YOUR_ACCOUNT_ID>,'<NAME>','<VALUE>');
PricesStreamer.putData
を変更して、Web サービス固有のデータを読み取る
このトピックでは、次のタスクについて説明しています。Figure ウィンドウで table データを表示する方法の詳細については、uitable
を参照してください。
PricesStreamer
クラス
PricesStreamer.m
は StringConsumer
クラスのサブクラスで、StringConsumer は ContentConsumer
のサブクラスです。PricesStreamer
は、特定の Web サービスによって提供されるデータ用にカスタマイズされたストリームデータを受信します。この例では、データの構造は次のとおりです。
% Data contains one or more CRLF-separated JSON structures. % Each structure is one of the format: % {"heartbeat"="timestamp"} % {"tick"="timestamp", "bid"=bid, "ask"=ask} % where timestamp is a GMT time and bid and ask are numbers.
MATLAB は、サーバーから受信する各データ チャンクに対して関数 PricesStreamer.putData
を呼び出します。この関数は、まず StringConsumer
を使用して生の uint8
バイトを JSON 文字列に変換します。次に、jsondecode
を使用して JSON 文字列から MATLAB 構造体を取得し、そのデータを Figure 内の table として表示します。その際、データをインクリメントするごとに table の上部に 1 行追加されます。関数 putData
に変更を加えて、データに他の操作を行うこともできます。たとえば、リアルタイム グラフをプロットする、価格の差を表示するなどです。PricesStreamer
は戻り値 stop
を設定して、ユーザーが Figure を閉じたときに操作が停止するようにします。詳細については、putData
を参照してください。
classdef PricesStreamer < matlab.net.http.io.StringConsumer % PricesStreamer accepts streamed JSON % and displays the result in a uitable in a figure window. % Copyright 2016-2017 The MathWorks, Inc. properties Figure Table Endit logical HaveTick logical end methods (Access=protected) function length = start(obj) if obj.Response.StatusCode ~= matlab.net.http.StatusCode.OK length = 0; else length = obj.start@matlab.net.http.io.StringConsumer; obj.Figure = figure('CloseRequestFcn',@obj.endit); obj.Figure.Position(4) = 550; obj.Figure.Position(2) = 50; obj.Table = uitable(obj.Figure,... 'ColumnName',{'Time','Bid','Ask'},... 'ColumnWidth',{130,'auto','auto'}); obj.Table.Position(4) = 500; obj.Table.Data = cell(0,3); obj.Endit = false; obj.HaveTick = false; end end end methods function [len,stop] = putData(obj, data) % Data contains one or more CRLF-separated JSON structures. % Each structure is one of the format: % {"heartbeat"="timestamp"} % {"tick"="timestamp", "bid"=bid, "ask"=ask} % where timestamp is a GMT time and bid and ask are numbers. if obj.Endit data = []; delete(obj.Figure); end first = obj.CurrentLength + 1; [len,stop] = obj.putData@matlab.net.http.io.StringConsumer(data); if isempty(data) || stop if ischar(data) % data == '' means user ctrl/c'ed, so set to obj.Endit = true; % delete figure on next close end stop = true; else stop = false; last = obj.CurrentLength; newData = obj.Response.Body.Data.extractBetween(first,last); % split at CRLFs strings = strsplit(newData, '\r\n'); try cellfun(@obj.displayJSON, strings); catch e fprintf('Error on JSON:\n%s<EOF>\n',data); obj.Endit = true; rethrow(e); end end end function displayJSON(obj, str) if ~isempty(str) try val = jsondecode(str); catch e fprintf('Error "%s" on JSON:\n%s<EOF>\n',e.message,str); rethrow(e); end if isfield(val,'tick') tick = val.tick; newdata = {cvtime(val.tick.time),tick.bid,tick.ask}; setExtent = ~obj.HaveTick; obj.HaveTick = true; elseif isfield(val, 'heartbeat') newdata = {cvtime(val.heartbeat.time),'',''}; setExtent = false; end obj.Table.Data = [newdata;obj.Table.Data]; if setExtent || ~mod(log10(length(obj.Table.Data)),1) % set extent on first tick and every power of 10 % add 15 for width of scroll bar obj.Table.Position(3) = obj.Table.Extent(3) + 15; end drawnow end end function endit(obj,~,~) % endit callback from close(obj.Figure) if exist('obj','var') && isvalid(obj) if obj.Endit if isvalid(obj.Figure) delete(obj.Figure); end else obj.Endit = true; end end end function delete(obj) if ~isempty(obj.Figure) && isvalid(obj.Figure) delete(obj.Figure); end end end end function time = cvtime(time) % Format time data for display time = datetime(time,'InputFormat','yyyy-MM-dd''T''HH:mm:ss.S''Z''','TimeZone','GMT'); time.TimeZone = 'local'; time = char(time, 'dd-MMM-yyyy HH:mm:ss.S'); end
MATLAB uitable
オブジェクトへのデータのマッピング
Web サービスの API 情報を確認して、ユース ケースに合わせたデータ構造体を特定します。この例のデータには、CRLF で区切られた 1 つ以上の JSON 構造体が含まれます。構造体の形式は以下のいずれかです。ここで、timestamp
は GMT 時間、bid
と ask
は数値です。
{"heartbeat"="timestamp"}
{"tick"="timestamp", "bid"=bid, "ask"=ask}
この特定の形式を読み取るには、putData
メソッドをオーバーライドします。PricesStreamer
クラスの次のステートメントは、StringConsumer.putData
を使用して次のバッファーを読み取ってから、JSON 文字列を選択します。
first = obj.CurrentLength + 1; [len,stop] = obj.putData@matlab.net.http.io.StringConsumer(data); last = obj.CurrentLength; newData = obj.Response.Body.Data.extractBetween(first,last); % split at CRLFs strings = strsplit(newData, '\r\n');
JSON 形式によるデータの表示
関数 displayJSON
の次のステートメントは、JSON の tick
および heartbeat
構造体を個別に処理します。補助関数 cvtime
は、table で表示するために時刻データの形式を整えます。
function displayJSON(obj, str) ... val = jsondecode(str); if isfield(val,'tick') tick = val.tick; newdata = {cvtime(val.tick.time),tick.bid,tick.ask}; ... elseif isfield(val, 'heartbeat') newdata = {cvtime(val.heartbeat.time),'',''}; ... end obj.Table.Data = [newdata;obj.Table.Data]; ... end
データ ストリームの終了
この例では、MATLAB は Web サービスがアクティブである間データを受け取り続けます。ユーザーは Figure ウィンドウを閉じるか Ctrl+C を押して、ストリームを終了できます。ユーザーによる割り込みを MATLAB に通知するには、putData
の引数 stop
を false
に設定します。クリーンアップ タスクには、CloseRequestFcn
プロパティを使用して Figure を閉じることや、関数 PricesStreamer.delete
を使用してオブジェクトを削除することが含まれます。
PricesStreamer
の呼び出し
次のコードは、Web サービスからデータを取得するためのフレームワークを提供します。コードを実行するには、<>
文字に囲まれた内容の値を指定しなければなりません。Web サービスの URL には、ログイン情報やその他の情報を名前と値のペア引数で指定する追加パラメーターが含まれる場合があります。PricesStreamer
を活用するには、これを send
の呼び出しに追加します。要求メッセージ作成の詳細については、HTTP を使用した MATLAB からの Web サービスの呼び出しを参照してください。
url = matlab.net.URI('<URL>','accountId',<YOUR_ACCOUNT_ID>,'<NAME>','<VALUE>'); authInfo = matlab.net.http.AuthInfo(matlab.net.http.AuthenticationScheme.Bearer,... 'Encoded','<YOUR_CREDENTIALS>'); af = matlab.net.http.field.AuthorizationField('Authorization',authInfo); r = matlab.net.http.RequestMessage('get',af); consumer = PricesStreamer; % SavePayload set to retain all results - useful for debugging [resp,req,hist] = r.send(url,matlab.net.http.HTTPOptions('SavePayload',true),consumer); % Show the results for debugging show(resp)
以下は、MATLAB uitable オブジェクトへのデータのマッピングで説明されているデータを送信する Web サービスからのデータの例です。
HTTP/1.1 200 Ok Server: openresty/1.9.15.1 Date: Wed, 06 Sep 2017 19:26:56 GMT Content-Type: application/json Transfer-Encoding: chunked Connection: close Access-Control-Allow-Origin: * {"tick":{"instrument":"AUD_CAD","time":"2017-09-06T19:26:54.304054Z","bid":0.97679,"ask":0.97703}} {"heartbeat":{"time":"2017-09-06T19:26:56.253091Z"}} {"tick":{"instrument":"AUD_CAD","time":"2017-09-06T19:26:57.226918Z","bid":0.97678,"ask":0.97703}} {"tick":{"instrument":"AUD_CAD","time":"2017-09-06T19:26:58.226909Z","bid":0.97678,"ask":0.97705}} {"heartbeat":{"time":"2017-09-06T19:26:58.720409Z"}} {"tick":{"instrument":"AUD_CAD","time":"2017-09-06T19:27:00.733194Z","bid":0.97679,"ask":0.97704}} {"heartbeat":{"time":"2017-09-06T19:27:01.251202Z"}} {"tick":{"instrument":"AUD_CAD","time":"2017-09-06T19:27:01.757501Z","bid":0.9768,"ask":0.97706}} {"heartbeat":{"time":"2017-09-06T19:27:03.720469Z"}}