今回の記事ではctrlXのInfluxDB APPを利用しInfluxDBを立ち上げ、Node-REDとTwinCAT3 TF6420から時系列データベースにQueryを送信し、またInfluxDBの中に簡単なDashboardを作成します。
さ、はじめよう!
InfluxDB?
InfluxDataTM*社のデータプラットフォームInfluxDBは、センサー、アプリケーション、ユーザー、システムからの大量のタイムスタンプデータを処理するために設計され、最適化されています。また、大量の時系列データを収集、保存、可視化することが容易になります。
ctrlX AUTOMATION – InfluxDB
InfluxDBはctrlX AUTOMATIONのアプリとして提供されております。InfluxDBは単なるデータベースではなく、MQTT、OPC UA、Modbusを含むほぼ全てのソースからデータを収集・分析するため、数多くのOpen source Telegraf Plug-inが提供されています。
Why use InfluxDB?
InfluxDBを使用すると、様々なメリットがあります。例えば、
- 時系列データの高速処理
- Data Explorerを利用しデータ分析
- データを直接見るための内蔵ダッシュボード
また、InfluxDBはグーグルのプログラミング言語Go(Golang)で書かれて、そしてInfluxDB2.0はFluxと呼ばれる新しい言語で書かれている。Fluxはデータベースの抽出、変換、ロード処理に最適化されている。
その文法は一般的な言語であるJavaScriptをベースにしています。Fluxの主な利点は、third-party APIなどを使って異なるデータソースを統合できることです。
Install APP
ctrlXのWeb serverを開き、”Install an app”をクリックしAPPをインストールします。
”Install from file”をクリックします。
InfluxDB Appを選び、App FileをOSにUploadしてください。
”Install”ボタンでInfluxDB Appをインストールします。
しばらく待ちます…
Done!
Web serverの左に”InfluxDB”という項目が増えます。
Configure Click screen?
次はctrlX OSにインストールされてるInfluxDB Appを構築するため、”GET STARTED”をクリックします、
初期Userの設定画面が表示されます。
User 名とBucket名を入力し、CONTINUEで進みます。
Done!API Tokenが表示され、外部デバイスからInfluxDB AppにアクセスするにはそのAPI Tokenが必要で、コビーしNotepadなどで貼り付けてください。
Done!こちらはInfluxDB App最初にの画面になります。
右のSlide Barから”Data Explorer”をクリックします。
こちらはData Explorer画面で、InfluxDB の中に溜まってた時系列データを可視化することできます。
Reference Video
こちらは今回記事の動画説明Verisonです。
Reference Link
Implementation From Node Red
Beckhoff TwinCAT3のTF6420と接続する前に、まずNode‐Redから通信テストを行います。
今回記事でNode-RedとctrlX InfluxDB Appを通信テストするために、使用したライブラリです。
npm install node-red-contrib-influxdb |
下記のLinkから該当するNodeの詳しい情報を確認できます。
https://flows.nodered.org/node/node-red-contrib-influxdb
Node-Red Side
InfluxDBのNodeをインストールしたら、Node-RedのEditor画面>Storge項目にInfluxDB関係のNodeがありました。Influx bathをFlowに追加します。
下図のようにTimeStampのTrigger Nodeを関数Nodeの入力に流し、Function Nodeの出力をInflux batchに繋がります。
Configure Database Configuration
次はInfluxDBの接続を行います。
Server
ServerはctrlX OSのIPアドレスになります。
Organization
Organizationは先程ctrlX InfluxDBで初期設定したOrganization名になり、今回は”mana”です。
Bucket
Bucket名は先程ctrlX InfluxDBで初期設定したBucket名になり、今回は”mainBucket”です。
Token
TokenはNode-RedがInfluxDBにアクセスするときに必要な認証キーです。
Fnction Code Node
msg.payload = [ { measurement: “weather_sensor”, fields: { temp: 5.5, light: 481, humidity: 51 }, tags:{ location:”garden” }, timestamp: new Date() }, { measurement: “alarm_sensor”, fields: { proximity: 1003, temp: 19.5 }, tags:{ location:”home” }, timestamp: new Date() } ]; return msg; |
Result
FlowをDeployし、timestampをクリックしDataをInfluxDBに送信してみましょう。
Data Explorer画面>mainBucketで先程Node-RedでPublishしたデータが見えました!可視化したデータを選択します。
右にあるSUBMITボタンをクリックします。
Done!
Implementation From beckhoff
Node-RedとctrlX InfluxDBの通信確認ができましたので、次はBeckhoff TwinCAT3でTF6420を使用しアクセスします。
Beckhoff Side
実際Tutorialを進める前にTF6420の仕様を簡単に紹介します。BeckhoffのTF6420ではInfluxDBの1.xと2.x Versionも対応しており、データベースの設定は”TwinCAT Database Server Configurator”から行います。
InfluxDB 2.xと接続する場合は、TwinCAT Database Server Configuratorに”InfluxDB2”を設定する必要があり、認証方法は”None”・”Username/password”・”Token”の3種類の対応ができます。
こちらはTwinCAT3 TF6420が対応する変数タイプになります。(注意するのはWSTRINGタイプが対応できません)
時系列データベースとして、InfluxDB2 にはいくつかの特別な機能があり、時系列の各測定値には、下記の項目が含まれています。
- Time Columns
- Tag Columns
- Field Columns
Time Columnsは、UNIX epochタイムとしてInfluxDBに格納されています。TF6420で用意されたFunction BlockではTwinCAT時間をUNIX epochタイムに自動変換するので、Programmerは自由のTimeStampを送信できます。
Activate License
TF6420でctrlXにインストールされたInfluxDB Appと接続テストするため、事前にTF6420のライセンスを有効にしましょう。
Add Database Configuration
TwinCATプロジェクトに新しいDatabase プロジェクトを追加するため、Add>New Projectをクリックします。
Empty TwinCAT Dataase Server Projectを選び、Next>進みます。
Data Server Project名を入力し、Createでプロジェクトを作成しましょう。
Done!
Add New Database Configuration
新しいデータベースを追加するため、Add New Databaseをクリックします。
Done!新しいDB Configurationが追加されました。
Configure DB
Database TypeをInfluxDB2に設定します。
InfluxDB2に関連する設定が表示されました。注意するのは接続設定をやってる最中に別のDatabase Typeを設定すると、元の設定が消えてしまいます。
Server
ServerはctrlX OSのIPアドレスになります。
Org
Organizationは先程ctrlX InfluxDBで初期設定したOrganization名になり、今回は”mana”です。
Bucket
Bucket名は先程ctrlX InfluxDBで初期設定したBucket名になり、今回は”mainBucket”です。
Authentication
Authenticationは”Token”に設定し、InfluxDBにアクセスするときに必要な認証キーを貼り付けます。
Check
最後はCheckボタンをクリックし通信テストを行います。
Done!TwinCAT3とctrlX InfluxDB Appと接続できます。
Check Sql Query Editor
実際プログラムを作成する前に、TwinCAT TF6420のSql Query Editorツールを使ってctrlX InfluxDB Appのデータベースの中身を覗いてみます。
こちらはTF6420のSql Query Editorツール画面です。
Reflesh ボタンをクリックします。
先程Node-Redで送信した時系列データがありました。
右クリック>QueryでctrlX InfluxDB AppにQueryを送信してみます。
DefaultではTF6420のSql Query EditorはQueryもすでに生成してくれます。
Queryの中身を確認し、FB_SQLCommandEvt.ExecuteDataRetrunをクリックします。
Done!!InfluxDB AppからデータがReturnしました。
DUT
T_QueryOptionTimeSeriesDB_Insert
こちらは時系列データベースにデータを書き込むための構造体であり、構造体の配列はシンボルで指定できます。 個々の配列要素は、データベース内で独自のTimeStampを持つRowとしてマッピングされ、開始タイムスタンプとデータセット間のタイムサイクルを指定して生成される。
TYPE T_QueryOptionTimeSeriesDB_Insert STRUCT pSymbol : PVOID; cbSymbol : UDINT; sDataType : STRING; nDataCount : UDINT := 1; sTableName : T_MaxString; nCycleTime : UDINT := 100000; nStartTimestamp : ULINT := 0; END_STRUCT END_TYPE |
Variable | Type | Descirption |
pSymbol | POINTER TO BYTE | データベースに書き込まれるSymbol Pointer |
cbSymbol | UDINT | 指定されたSymbol Pointerの長さ |
sDataType | STRING | 指定されたSymbol名 |
nDataCount | UDINT | 転送された配列のデータセット数 |
sTableName | T_MaxString | テーブルと同等の名称 |
nCycleTime | UDINT | データセットの時間間隔 |
nStartTimestamp | ULINT | TwinCAT時間での最初のデータセットのタイムスタンプ: 1601年1月1日からの100 ns間隔。 |
Function Block
FB_NoSQLQueryBuilder_TimeSeriesDB
こちらはTimeSeries データベースのQueryを定義するためのFunction Blockで、Queryは Function BlockFB_NoSQLQueryEvt 経由で送信します。
VAR_INPUT
Variable | Type | Descirption |
pQueryOption | POINTER TO BYTE | Query Optionsのアドレスを指定する |
cbQueryOptions | UDINT | Query Optionsの長さ |
Tc3_Eventlogger
TwinCAT3(4022.20)以後ではDatabase Server TF6420はTwinCAT3 Eventloggerに対応できるようになりました。これにより、インタフェースを介してFunction Blockの詳細を読み出すことができます。
RequestEventText
このMethodはイベントテキストを返します。
VAR_INPUT
Variable | Type | Descirption |
nLangId | DINT | イベントの言語を指定します、1033=英語です。 |
sResult | REFERENCE TO STRING | イベントテキストを格納先の変数サイズ(Bytes単位) |
VAR_OUTPUT
Variable | Type | Descirption |
bError | BOOL | TRUE=エラーある |
hrErrorCode | HRESULT | S_OK=Method実行OK |
Return
Variable | Type | Descirption |
RequestTextEvent | BOOL | TRUE=実行完了 |
Program
こちらは実際のプログラムです。
PROGRAM MAIN VAR State: E_DbLogState; bWriting: BOOL; dbid: UDINT := 1; //Queryparameter QueryOption_TSDB_Insert : T_QueryOptionTimeSeriesDB_Insert; //api fbNoSQLQueryBuilder_TimeSeriesDB : FB_NoSQLQueryBuilder_TimeSeriesDB; //execute queries fbNoSqlQueryEvt : FB_NoSQLQueryEvt(sNetID := ”, tTimeout := T#15S); // databuffer for 1 second with 10 ms time delta Data: ARRAY[1..100] OF DUT_Data; // error handling helper values TcResult: Tc3_Database.I_TcMessage; bError: BOOL; sErrorMessage: STRING(255); i: INT; rand : DRAND; nrand: LREAL; TON:TON; END_VAR |
FOR i := 1 TO 100 BY 1 DO rand(); nrand := rand.Num*5.0; Data[i].Direction := 240.328 + nrand; Data[i].Speed := 1200.3292 + nrand; Data[i].Power := 1500.1975 + nrand; Data[i].ID := ‘Unit13’; END_FOR TON( IN:=State = E_DbLogState.idle AND bWriting ,PT:=T#1S ); CASE State OF E_DbLogState.idle: IF TON.Q THEN //bWriting := FALSE; State := E_DbLogState.init; END_IF E_DbLogState.init: fbNoSQLQueryBuilder_TimeSeriesDB.pQueryOptions := ADR(QueryOption_TSDB_Insert); fbNoSQLQueryBuilder_TimeSeriesDB.cbQueryOptions := SIZEOF(QueryOption_TSDB_Insert); QueryOption_TSDB_Insert.sTableName := ‘ServoMeasurement’; QueryOption_TSDB_Insert.sDataType := ‘DUT_DATA’; QueryOption_TSDB_Insert.pSymbol := ADR(Data); QueryOption_TSDB_Insert.cbSymbol := SIZEOF(Data); QueryOption_TSDB_Insert.nDataCount := 100; QueryOption_TSDB_Insert.nStartTimestamp := F_GetSystemTime(); QueryOption_TSDB_Insert.nCycleTime := 10000; // (in 100 ns) State := E_DbLogState.writing; E_DbLogState.writing: IF fbNoSqlQueryEvt.Execute( hDBID:=dbid ,iNoSQLQueryBuilder:=fbNoSQLQueryBuilder_TimeSeriesDB ) THEN IF fbNoSqlQueryEvt.bError THEN TcResult := fbNoSqlQueryEvt.ipTcResult; State := E_DbLogState.error; ELSE State := E_DbLogState.idle; END_IF END_IF E_DbLogState.error: IF TcResult.RequestEventText( nLangId:=1033 ,sResult:=sErrorMessage ,nResultSize:=SIZEOF(sErrorMessage) ) THEN TcResult.Send(nTimeStamp:=F_GetSystemTime()); State := E_DbLogState.idle; bError := TRUE; END_IF END_CASE |
E_DbLogState.init:
こちらはTwinCATが時系列データベースにQueryを送信するときのOptionsになります。
sTableNameはInfluxDBの_Measurementであり、sDataTypeはTwinCATがプロジェクトの構造体と一致する必要があります。pSymbolはInfluxDBに送信するデータです。
E_DbLogState.init: fbNoSQLQueryBuilder_TimeSeriesDB.pQueryOptions := ADR(QueryOption_TSDB_Insert); fbNoSQLQueryBuilder_TimeSeriesDB.cbQueryOptions := SIZEOF(QueryOption_TSDB_Insert); QueryOption_TSDB_Insert.sTableName := ‘ServoMeasurement’; QueryOption_TSDB_Insert.sDataType := ‘DUT_DATA’; QueryOption_TSDB_Insert.pSymbol := ADR(Data); QueryOption_TSDB_Insert.cbSymbol := SIZEOF(Data); QueryOption_TSDB_Insert.nDataCount := 100; QueryOption_TSDB_Insert.nStartTimestamp := F_GetSystemTime(); QueryOption_TSDB_Insert.nCycleTime := 10000; // (in 100 ns) State := E_DbLogState.writing; |
E_DbLogState.writing
こちらはInfluxDBにQueryを送信するプログラムです。
E_DbLogState.writing: IF fbNoSqlQueryEvt.Execute( hDBID:=dbid ,iNoSQLQueryBuilder:=fbNoSQLQueryBuilder_TimeSeriesDB ) THEN IF fbNoSqlQueryEvt.bError THEN TcResult := fbNoSqlQueryEvt.ipTcResult; State := E_DbLogState.error; ELSE State := E_DbLogState.idle; END_IF END_IF |
Result
ctlXのInfluxDB APPを開くと、TwinCAT3のデータが見えました!
Dashboard
最後はctrlX InfluxDB APPの中にDashboardを作成します。
CREATE DASHBOARDをクリックし新しいDashboardを作成します。
New Dashboardをクリックします。
Done!ADD CELLをクリックし新しい画面を追加します。
Data Exploer画面が表示されました。
CELLで表示したいデータを選び>Check markをクリックし確定します。
Done!
このように自分のアプリケーションに合わせて様々なDashboardを作れます。
また、SET AUTO REFRESHでCellの更新時間を変更できます。
Reresh Intervalをアプリケーションに合わせて入れましょう。