Gtk3アプリ NodeRedで仮想通貨を表示する その２

###Gtk3アプリ NodeRedで仮想通貨を表示する その２

####仮想通貨の価格をチャートに表示する

<img width="300" alt="Screenshot from 2021-10-29 13-39-34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/df2a8883-9fac-e7d8-89e2-56ec67e56cf5.png">

node-red-dashboardをインストールします。

https://flows.nodered.org/node/node-red-dashboard

```
node-red-dashboard
```

####学習動画

https://www.youtube.com/watch?v=eCGtI6IaskI

https://www.youtube.com/watch?v=Z48Niaqa93Y

https://www.youtube.com/watch?v=Lv6SZ2mV5kg

####パラメーター設定


topicとpayloadを追加します。

```
{topic:"temperature", payload:22}
```

https://github.com/node-red/node-red-dashboard/blob/master/Charts.md

####全体図
<img width="600" alt="Screenshot from 2021-10-29 13-50-03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/1afe42b8-bdb9-bc5b-777e-eac26ea724c5.png">
####Flow図

```
[{"id":"5fb94a5f12d9b343","type":"tab","label":"フロー 3","disabled":false,"info":"","env":[]},{"id":"c51cb05a05f0bbd0","type":"ui_chart","z":"5fb94a5f12d9b343","name":"","group":"bbc543c8094bb4ea","order":1,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"2","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":590,"y":180,"wires":[[]]},{"id":"d41012e0b93c34ec","type":"binance-get-price","z":"5fb94a5f12d9b343","name":"","ticker":"BNBBTC","x":180,"y":100,"wires":[["fbb0fe65d9a45fad"]]},{"id":"60a6820af7cee079","type":"debug","z":"5fb94a5f12d9b343","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":590,"y":100,"wires":[]},{"id":"e63a8a5503a5a6e7","type":"inject","z":"5fb94a5f12d9b343","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"1","topic":"","payloadType":"date","x":130,"y":40,"wires":[["d41012e0b93c34ec"]]},{"id":"fbb0fe65d9a45fad","type":"function","z":"5fb94a5f12d9b343","name":"","func":"msg.topic = \"temperature\";\n\nvar obj = {\n  \"topic\":msg.topic,  \n  \"payload\":msg.payload,     \n  \"_msgid\":msg._msgid       \n};\n\nmsg.tmp = JSON.stringify(obj); \n\nmsg.tmp = encodeURI(msg.tmp);\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":180,"wires":[["c51cb05a05f0bbd0","60a6820af7cee079","56dbaafa99bbf7bd","019b328ad992a833"]]},{"id":"56dbaafa99bbf7bd","type":"exec","z":"5fb94a5f12d9b343","command":"nodeSqlApp","addpay":"tmp","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"exe","x":130,"y":280,"wires":[["8d821d5df7a19461"],["fce4cb380b7057d8"],["47ffb0fb6b305d87"]]},{"id":"8d821d5df7a19461","type":"debug","z":"5fb94a5f12d9b343","name":"標準出力","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":310,"y":280,"wires":[]},{"id":"fce4cb380b7057d8","type":"debug","z":"5fb94a5f12d9b343","name":"標準エラー出力","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":330,"y":340,"wires":[]},{"id":"47ffb0fb6b305d87","type":"debug","z":"5fb94a5f12d9b343","name":"返却コード","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":310,"y":400,"wires":[]},{"id":"019b328ad992a833","type":"func-exec","z":"5fb94a5f12d9b343","name":"","func":"var command = 'nodeSqlApp ' + msg.tmp;\n\nvar exec = child_process.exec(command, (error, stdout, stderr) => { \n    if (error) { \n    node.error(`exec error: ${error}`); \n    return; \n    } \n    node.error(`stdout: ${stdout}`); \n    node.error(`stderr: ${stderr}`); \n    msg.payload = stdout;\n    callback(msg);\n}); \nreturn msg;","outputs":1,"noerr":0,"x":570,"y":280,"wires":[["3da616399aedc082"]]},{"id":"3da616399aedc082","type":"debug","z":"5fb94a5f12d9b343","name":"標準出力","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":720,"y":280,"wires":[]},{"id":"bbc543c8094bb4ea","type":"ui_group","name":"デフォルト","tab":"af105c0b8ff4ec1a","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"af105c0b8ff4ec1a","type":"ui_tab","name":"ホーム","icon":"dashboard","disabled":false,"hidden":false}]
```

####取得したデータをC#側で保存する
execノードを使ってC#コンソールアプリを実行します。Jsonを引数に渡します。
Sqliteに保存します。

<img width="500" alt="Screenshot from 2021-10-29 15-00-54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/af91b497-100b-b87f-16b2-84416bfce53a.png">

引き渡すJsonは必ず**URLエンコード**します。

####functionノード

```js
msg.topic = "temperature";

var obj = {
  "topic":msg.topic,  
  "payload":msg.payload,     
  "_msgid":msg._msgid       
};

msg.tmp = JSON.stringify(obj); 
//エンコードする
msg.tmp = encodeURI(msg.tmp);

return msg;
```

#####func-execで実行する場合

```js
var command = '/nodeSqlApp ' + msg.tmp;

var exec = child_process.exec(command, (error, stdout, stderr) => { 
    if (error) { 
    node.error(`exec error: ${error}`); 
    return; 
    } 
    node.error(`stdout: ${stdout}`); 
    node.error(`stderr: ${stderr}`); 
    msg.payload = stdout;
    callback(msg);
}); 
return msg;
```

####C#コンソールアプリ側　プログラムの解説

引数で受けたJsonデーターは**必ずエンコード、デコード**します。

```cs
static void Main(string[] args)
{
    //必ずデーコードする
    var jesonStr = System.Web.HttpUtility.UrlDecode(args[0]);
}
```

Jsonをモデルに変換します。DepperExtensionを使いModelのままInsertします。

```test.cs
BinancePriceModel BinancePriceModel1 = JsonSerializer.Deserialize<BinancePriceModel>(jsonStr);

con.Insert<BinancePriceModel>(BinancePriceModel1);
```

レコード数を表示します。

```cs
string sql = "select * from BinancePriceTable;";
var testResult = con.QueryAsync<BinancePriceModel>(sql);
Console.WriteLine("書き込み数" + testResult.Result.Count());
```

Dapperが生成するSQLのテーブル名を変更するため、ClassMapperを使います。

```cs
public class BinancePriceModelMap : ClassMapper<BinancePriceModel>
{
    public BinancePriceModelMap()
    {
        base.Table("BinancePriceTable");
        base.AutoMap();
    }
}
```


C#とFlowデータをGitに上げました。

https://github.com/iotagtk1/nodeRedApp

####参考
https://qiita.com/kuraoka/items/2e14bc2fefb9b0183cc7
https://qiita.com/HiroyasuNishiyama/items/2433d275c667bc75ed8c
https://qiita.com/takeyan/items/fff5e8d64da25220a0c0
https://qiita.com/youtoy/items/61e4a6c9061d68f09e3b

####バイナンスとは
世界最大の仮想通貨取引所です。
バイナンスノードを利用するにはユーザー登録する必要があります。

[バイナンスへ](https://www.binance.com/ja?ref=TK4QGRCX)
<a href="https://www.binance.com/ja?ref=TK4QGRCX" target="_blank"><img width="350" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/8960c90e-e297-5fe8-5896-ee00dad5b151.png" src="https://www.binance.com/ja?ref=TK4QGRCX"></a>
[C#から仮想通貨サイトのAPI(Node.js)を呼ぶ](https://qiita.com/iota_11/items/24ab2db7f2ee758f715c)に続く