前回はTwinCATとTF6420を使用しMongoDBの接続設定を行いました。今回はTF6420のLibraryを使用しMongoDBのデータにアクセスします。
さ、はじめよう!
Reference Link
Function Block
今回の記事で使用するFunction Blockを紹介します。
FB_NoSQLQueryBuilder_DocumentDB
DateBaseにクエリを定義するためのFunction Blockです。Queryは FB_NoSQLQueryEvt で送信されるので、Build Methodを直接呼び出す必要はありません。
VAR_INPUT
Name | Type | Descirption |
eQueryType | E_DocumentDbQueryType | データベースに送信されるクエリのタイプ。 |
sCollectionName | T_ MAXSTRING | Queryの対象となるCollectionsの名前 |
pQueryOptions | POINTER TO BYTE | QueryOptionsのPointerアドレスを指定します。 |
cbQueryOptionsr | UDINT | QueryOptionsのサイズ |
E_DocumentDBQueryType
{attribute ‘qualified_only’} TYPE E_DocumentDbQueryType : ( InsertOne := 1, InsertMany := 2, UpdateOne := 3, UpdateMany := 4 , Find := 5, Aggregation := 6, Delete := 7, DeleteMany := 8, CreateCollection := 9, DropCollection := 10 ); END_TYPE |
T_QueryOptionDocumentDB_Insert
TYPE T_QueryOptionDocumentDB_Insert STRUCT pDocuments: POINTER TO BYTE; cbDocuments: UDINT; END_STRUCT END_TYPE |
Name | Type | pDocuments |
pDocuments | POINTER TO BYTE | Collectionsに追加するDocumetns変数のアドレスを指定します。 |
cbDocuments | UDINT | Documetns変数のデータサイズ |
FB_NoSQLQueryEvt
NoSQL DatabaseのQueryを実行するためのFunction Blockです。QueryBuilder Function BlockのMethodに入力して使用します。
VAR_INPUT
Name | Type | Descirption |
sNetID | T_AmsNetID | AMS Network ID、Localなら空きにしてください |
tTimeout | TIME | FBが実行キャンセルされるまでの時間設定 |
VAR_OUTPUTS
Name | Type | Descirption |
bBusy | BOOL | 1=FBが実行中 |
bError | BOOL | 1=FBがエラーあり |
ipTcResult | Tc3_EventLogger.I_TcMessage | FB実行結果をMessageに表示するためのTwinCAT 3 EventLogger Interface |
Properties:eTraceLevel
Name | Type | Access | Descirption |
eTraceLevel | TcEventSeverity | Get, Set | 1=FBが実行中イベントの重み付けを指定します。この値より高い重み付けのイベントのみがTwinCATシステムに送信されます。Eventの重要度を指定します。この値より高いイベントのみをTwinCAT Systemに送信します。 |
METHODS:Execute
QueryBuilderFBで作成したQueryをData Baseに送信します。
METHOD Execute : BOOL VAR_INPUT hDBID: UDINT; iNoSQLQueryBuilder: I_NoSQLQueryBuilder; END_VAR |
VAR_INPUT
Name | Type | Descirption |
hDBID | UDINT | 設定されたデータベース設定のID |
iNoSSQLQueryBuilder | I_NoSQLQueryBuilder | QueryBuilder FBになります |
Return Value
Name | Type | Descirption |
Execute | BOOL | Methodの実行結果になります。True=Method実行成功 |
METHODS:ExecuteDataReturn
QueryBuilderFBで作成したQueryをData Baseに送信します。FB_NoSqlResultEvtは、Databaseから戻したData Recordを読むために渡します。
METHOD ExecuteDataReturn : BOOL VAR_INPUT hDBID : UDINT; iNoSSQLQueryBuilder: I_NoSQLQueryBuilder; pNoSQLResult: POINTER TO FB_NoSQLResultEvt; END_VAR |
VAR_INPUT
Name | Type | Descirption |
hDBID | UDINT | 設定されたデータベース設定のID |
iNoSSQLQueryBuilder | I_NoSQLQueryBuilder | QueryBuilder FBになります |
pNoSQLResult | POINTER TO FB_NoSSQLResultEvt | FB_NoSQLResultEvt のInstance Pointerで、Methods結果を読むために使われています |
Return Value
Name | Type | Descirption |
ExecuteDataReturn | BOOL | Methodの実行結果になります。True=Method実行成功 |
nDataCount | UDINT | 返されたレコード数 |
FB_NoSQLResultEvt
バッファされたレコードを読み込むためのFBで、ExecuteDataReturn Mehtodが呼び出されたら、まず FB_NoSQLQueryEvt を使用してData BaseからData Recordを取得する必要があります。FB_NoSQLResultEvtを一旦初期化したら、PLC 構造体または文字列として読み出すことができます。
VAR_INPUTS
Name | Type | Descirption |
sNetID | T_AmsNetID | AMS Network ID、Localなら空きにしてください |
tTimeout | TIME | FBが実行キャンセルされるまでの時間設定 |
VAR_OUTPUTS
Name | Type | Descirption |
bBusy | BOOL | 1=FBが実行中 |
bError | BOOL | 1=FBがエラーあり |
ipTcResult | Tc3_EventLogger.I_TcMessage | FB実行結果をMessageに表示するためのTwinCAT 3 EventLogger Interface |
Properties:eTraceLevel
Name | Type | Descirption |
eTraceLevel | TcEventSeverity | 1=FBが実行中イベントの重み付けを指定します。この値より高い重み付けのイベントのみがTwinCATシステムに送信されます。Eventの重要度を指定します。この値より高いイベントのみをTwinCAT Systemに送信します。 |
Properties:nDataCount
Name | Type | Descirption |
nDataCount | UDINT | Databaseから取得したData Record数 |
Methods:ReadAsString
このメソッドは、TwinCAT Database Serverにキャッシュされたデータから、指定した数のRecordを読み込み、このデータをJSONとしてコピーする文字列の配列を指定します。
VAR_INPUTS
Name | Type | Descirption |
nStartIndex | UDINT | 最初に読み込まれるRecordのIndex |
nRecordCount | UDINT | 読み込むRecordの数 |
pData | POINTER TO BYTE | Recordを書き込むTwinCAT Runtime文字列配列のアドレス Offset |
cbData | UDINT | Recordを書き込むTwinCAT Runtime文字列配列のサイズ |
nMaxDocumentSize | UDINT | pDataから取られたJSONドキュメントの最大サイズ。 |
bDataRelease | BOOL | キャッシュされたデータを削除する |
Return Value
Name | Type | Descirption |
ReadAsString | BOOL | Methodの実行結果になります。True=Method実行成功 |
Method:ReadAsStruct
このメソッドは、バッファされた結果データから指定された数のレコードを読み込み、TwinCAT Runtimeの構造体または構造体の配列に格納できます。Function BlockのValidation機能はデータの逸脱を検出して対応することができます。
VAR_INPUTS
Name | Type | Descirption |
nStartIndex | UDINT | 最初に読み込まれるRecordのIndex |
nRecordCount | UDINT | 読み込むRecordの数 |
pData | POINTER TO BYTE | Recordを書き込むTwinCAT Runtime文字列配列のアドレス Offset |
cbData | UDINT | Recordを書き込むTwinCAT Runtime文字列配列のサイズ |
bValidate | BOOL | 返されたデータはpData構造体配列と比較するか、そして必要に応じて調整します。 |
pNoSQLValidation | POINTER TO FB_NoSQLValidationEvt | 検証するための情報を提供するFunction Block FB_NoSQLValidationEvt のアドレス。 |
nMaxDocumentSize | UDINT | pDataから取られたJSONドキュメントの最大サイズ。 |
bDataRelease | BOOL | キャッシュされたデータを削除する |
Return Value
Name | Type | Descirption |
ReadAsStruct | BOOL | Methodの実行結果になります。True=Method実行成功 |
METHOD:Release
このメソッドは、TwinCAT Database Serverがキャッシュしたデータを解放するために使用できます。
Return Value
Name | Type | Descirption |
Release | BOOL | Methodの実行結果になります。True=Method実行成功 |
FB_NoSQLValidationEvt
FB_NoSQLResultEvt でデータを読み込む際に発生した検証イベントと結果を読み込むためのFunction Blockです。このFunction Blockは NoSQLResult の CreateValidation メソッドで初期化され、最後はReadAsStruct メソッドの呼び出しを参照します。
VAR_INPUTS
Name | Type | Descirption |
sNetID | T_AmsNetID | AMS Network ID、Localなら空きにしてください |
tTimeout | TIME | FBが実行キャンセルされるまでの時間設定 |
VAR_OUTPUTS
Name | Type | Descirption |
bBusy | BOOL | 1=FBが実行中 |
bError | BOOL | 1=FBがエラーあり |
ipTcResult | Tc3_EventLogger.I_TcMessage | FB実行結果をMessageに表示するためのTwinCAT 3 EventLogger Interface |
Properties:eTraceLevel
Name | Type | Access | Descirption |
eTraceLevel | TcEventSeverity | Get, Set | 1=FBが実行中イベントの重み付けを指定します。この値より高い重み付けのイベントのみがTwinCATシステムに送信されます。Eventの重要度を指定します。この値より高いイベントのみをTwinCAT Systemに送信します。 |
Methods:GetIssues
Function Blockが発生した検証イベントを T_MAXSTRING 型の配列に読み込みます。
VAR_INPUTS
Name | Type | Descirption |
pData | POINTER TO BYTE | Recordを書き込むTwinCAT Runtime文字列配列のアドレス Offset |
cbData | UDINT | Recordを書き込むTwinCAT Runtime文字列配列のサイズ |
bDataRelease | BOOL | キャッシュされたデータを削除する |
Return Value
Name | Type | Descirption |
GetIssues | BOOL | Methodの実行結果になります。True=Method実行成功 |
Methods:GetRemainingData
このメソッドを使用して、検証後の残りのデータを JSON 形式で読み取ることができます。
VAR_INPUTS
Name | Type | Descirption |
pData | POINTER TO BYTE | Recordを書き込むTwinCAT Runtime文字列配列のアドレス Offset |
cbData | UDINT | Recordを書き込むTwinCAT Runtime文字列配列のサイズ |
cbDocument | UDINT | Document配列のサイズ |
bDataRelease | BOOL | キャッシュされたデータを削除する |
Return Value
Name | Type | Descirption |
GetRemainingData | BOOL | Methodの実行結果になります。True=Method実行成功 |
METHOD:Release
このメソッドは、TwinCAT Database Serverがキャッシュしたデータを解放するために使用できます。
Return Value
Name | Type | Descirption |
Release | BOOL | Methodの実行結果になります。True=Method実行成功 |
Implementation
これからTwinCATのTF6420Libraryを使用しMongoDBのデータにアクセスしてみます。
Flow
こちらはプログラムの動作Flowです。
DUT
こちらはプログラムの中でMongoDBに送信するQueryデータの構造体です。
ST_SubStrucure
TYPE ST_SubStrucure : STRUCT Speed:LREAL; Position:LREAL; ErrorCode:LINT; END_STRUCT END_TYPE |
ST_MainStructure
TYPE ST_MainStructure : STRUCT Sensor1:LREAL; r32Array:ARRAY[0..2]OF LREAL; iArray:ARRAY[0..8]OF DINT; MotorData:ST_SubStrucure; END_STRUCT END_TYPE |
Program
こちらはプログラムです。
PROGRAM MAIN VAR fbJson : FB_JsonSaxWriter; jsonDoc :SJsonValue; sJsonDoc :STRING(2000); sDocument : STRING(2000); END_VAR VAR nDBID: INT := 1; sNetID : STRING := ”; tTimer4SendQuery :TIME:=T#1S; TONReflesh :TON; r32SensorData :LREAL:=0.0; bError:BOOL; iStep:INT:=0; iCount:INT:=0; ArrayStuctureData : ARRAY [0..999] OF ST_MainStructure; END_VAR VAR //NoSQLFunctionBlock fbNoSQLQueryBuilder_DocumentDB: FB_NoSQLQueryBuilder_DocumentDB; fbNoSQLQuery: FB_NoSQLQueryEvt(sNetID := sNetID, tTimeout := TIME#15S0MS); fbNoSQLResult: FB_NoSQLResultEvt(sNetID := sNetID, tTimeout := TIME#15S0MS); fbNoSqlValidation : FB_NoSQLValidationEvt(sNetID := sNetID, tTimeout := TIME#15S0MS); //Optiotns InsertQueryOptions: T_QueryOptionDocumentDB_Insert; AggregationQueryOptions: T_QueryOptionDocumentDB_Aggregate; //Others InfoResult: I_TcMessage; sPipeStages : STRING(1000); END_VAR CASE iStep OF 0: InsertQueryOptions.pDocuments:= ADR(sDocument); InsertQueryOptions.cbDocuments:= SIZEOF(sDocument); fbNoSQLQueryBuilder_DocumentDB.eQueryType := E_DocumentDbQueryType.InsertOne; fbNoSQLQueryBuilder_DocumentDB.sCollectionName := ‘myCollection22’; fbNoSQLQueryBuilder_DocumentDB.pQueryOptions := ADR(InsertQueryOptions); fbNoSQLQueryBuilder_DocumentDB.cbQueryOptions := SIZEOF(InsertQueryOptions); iStep:=10; bError:=FALSE; 10: // fbJson.StartObject(); r32SensorData:=r32SensorData+0.01; IF r32SensorData > 99999.9 THEN r32SensorData:=0.0; END_IF fbJson.AddKeyLreal(key:=’Sensor1′,value:=r32SensorData); fbJson.AddKey(‘r32Array’); fbJson.StartArray(); fbJson.AddRawArray(‘123.1,444.5,512.3’); fbJson.EndArray(); fbJson.AddKey(‘iArray’); fbJson.StartArray(); fbJson.AddRawArray(‘123,1,5,6,7,8,9,0,111’); fbJson.EndArray(); fbJson.AddKey(‘MotorData’); fbJson.StartObject(); fbJson.AddKeyLreal(key:=’Speed’,value:=567.12334); fbJson.AddKeyLreal(key:=’Position’,value:=450.42); fbJson.AddKeyNumber(key:=’ErrorCode’,value:=9872); fbJson.EndObject(); fbJson.EndObject(); sJsonDoc := fbJson.GetDocument(); fbJson.ResetDocument(); iStep:=20; 20: sDocument:=sJsonDoc; IF fbNoSQLQuery.Execute(nDBID, fbNoSQLQueryBuilder_DocumentDB) THEN IF fbNoSQLQuery.bError THEN InfoResult := fbNoSQLQuery.ipTcResult; bError:=TRUE; iStep:=998; ELSE IF NOT fbNoSQLQuery.bBusy THEN iStep:=30; END_IF; END_IF END_IF 30: AggregationQueryOptions.pPipeStages := ADR(sPipeStages); AggregationQueryOptions.cbPipeStages := SIZEOF(sPipeStages); fbNoSQLQueryBuilder_DocumentDB.eQueryType := E_DocumentDbQueryType.Aggregation; fbNoSQLQueryBuilder_DocumentDB.sCollectionName := ‘myCollection22’; fbNoSQLQueryBuilder_DocumentDB.pQueryOptions := ADR(AggregationQueryOptions); fbNoSQLQueryBuilder_DocumentDB.cbQueryOptions := SIZEOF(AggregationQueryOptions); sPipeStages :='{$$match :{}}’; IF fbNoSQLQuery.ExecuteDataReturn(nDBID, fbNoSQLQueryBuilder_DocumentDB, pNoSqlResult:= ADR(fbNoSQLResult)) THEN IF fbNoSQLQuery.bError THEN InfoResult := fbNoSQLQuery.ipTcResult; bError:=TRUE; iStep:=997; ELSE iStep:=40; END_IF END_IF 40: IF fbNoSQLResult.ReadAsStruct(1, 10, ADR(ArrayStuctureData), SIZEOF(ArrayStuctureData), bValidate := TRUE, ADR(fbNoSqlValidation), bDataRelease:= TRUE) THEN IF fbNoSQLResult.bError THEN InfoResult := fbNoSQLResult.ipTcResult; bError:=TRUE; ELSE iStep:=50; END_IF END_IF 50: TONReflesh(IN:=TRUE,pt:=tTimer4SendQuery); IF TONReflesh.Q THEN TONReflesh(IN:=FALSE); iCount:=iCount+1; iStep:=0; END_IF END_CASE |
Result
Done!MyCollections22という新しいCollectionsが作成されました。
From Mongo
こちらのコマンドでMongoDBのShellから最新のデータを取得できます。
db.myCollection22.find().sort({$natural:-1}).limit(10) |
Done!TwinCATからの発行したデータが見えましたね。
> db.myCollection22.find().sort({$natural:-1}).limit(10) { “_id” : ObjectId(“64aa662bbfe68217dc626f99”), “Sensor1” : 14.549999999999734, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6629bfe68217dc626f98”), “Sensor1” : 14.539999999999734, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6628bfe68217dc626f97”), “Sensor1” : 14.529999999999735, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6627bfe68217dc626f96”), “Sensor1” : 14.519999999999735, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6625bfe68217dc626f95”), “Sensor1” : 14.509999999999735, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6624bfe68217dc626f94”), “Sensor1” : 14.499999999999735, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6623bfe68217dc626f93”), “Sensor1” : 14.489999999999736, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6622bfe68217dc626f92”), “Sensor1” : 14.479999999999736, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa6620bfe68217dc626f91”), “Sensor1” : 14.469999999999736, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } { “_id” : ObjectId(“64aa661fbfe68217dc626f90”), “Sensor1” : 14.459999999999736, “r32Array” : [ 123.1, 444.5, 512.3 ], “iArray” : [ 123, 1, 5, 6, 7, 8, 9, 0, 111 ], “MotorData” : { “Speed” : 567.12334, “Position” : 450.42, “ErrorCode” : 9872 } } |
From TwinCAT
TwinCATからMongoDBにデータを取りました。
Download Project
こちらのLinkからプロジェクトをDownloadしてください。
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT_TF6420_ConnectWithMongoDB.tnzip