Contents
- 1. 排他的操作
- 1-1.機能概要
- 1-2.フローの概要説明
- 2. ユーザー制限
- 2-1. ユーザー制限の方法
- 2-2. socketid記録簿の実装
- 2-3. Node-REDのフロー
- 3. ユーザー制限(2): 個別ユーザー名対応と操作ログの保存
- 3-1. 動作の概要
- 3-1-1. 個別ユーザー名とパスワードの認証
- 3-1-2. ログデータの記録
- 3-1-3. ログデータの参照
- 3-2. Node-REDのフロー
- 3-2-1. 個別ユーザー名とパスワードの認証
- 3-2-2. ログデータの記録
- 3-2-3. ログデータの参照
- Appendix. Node-REDのフローファイル
- 1) 排他的操作のみ
- 2) 排他制御+ユーザー制限
- 3) 排他制御+ユーザー制限(2):複数ユーザー名とログファイル記録
1. 排他的操作
排他的操作とは、現在操作しているユーザーに操作する権限を占有させ、他のユーザーと競合しないように、他のユーザーからの操作を制限する機能を言います。R-CPSではNode-REDのダッシュボードを使ってデータの表示や操作を行いますので、複数のユーザーが同時に操作してしまう競合が発生し易くなります。Node-REDのダッシュボードを使った、排他的操作の事例をを解説します。
1-1.機能概要
ダッシュボードを表示すると、接続元個別の識別子:msg.scokectidがサーバーであるNode-REDから付与されます。そして、ダッシュボードのスイッチやスライダーを操作すると、操作値(msg.payload)と共に、誰が操作したのかを知らせるために、msg.socketidがノードから出力されます。この機能を使い、ユーザー端末を識別し、特定の端末からの操作だけを許可するようにフローを記述します。
具体的には、グローバル変数:global.socketidを、識別のために使用します。これに設定されている値で未接続と接続中を判断します。
未接続の場合には、初めに接続ボタンを押した端末のmsg.socketidが設定されて、接続中に移行します。
接続中の場合には、global.socketidと等しいmsg.socketidを持つ端末しか切断ボタンを含めて操作することはできません。
以下、もう少し詳しく動作を説明します。
global.socketidの初期値には、ダミーのsocketidである”demae0000000000“を設定します。このダミーのsocketidが、global.socketidに設定されているときは、未接続状態を意味します。状態の表示は、未接続です。
そして、ダッシュボードの「接続」ボタンが押されると、その端末のmsg.socketidを取得し、global.socketidが初期値”demae0000000000“ならば、未接続と判断し上書きます。そして、状態が、接続中に移ります。
接続中にスライダーやスイッチを押された場合、その端末のmsg.socketidとglobal.socketidを比較し、同じ場合のみ操作を反映します。異なるmsg.socketidの端末から操作しても、出力には反映されず、2秒後に事前の状態に戻ります。
接続中に他の端末から「接続」ボタンが押されると、接続要求が出されたことが表示されますが、接続中はglobal.socketidは変わりません。
同様に、接続中に他の端末から「切断」ボタンが押されても、無視され、global.socketidは変わりません。
global.socketidと同じmsg.socketidを持つ端末から、「切断」ボタンが押されるまでは接続中が維持されます。そして、「切断」ボタンが押されると、global.socketidは初期値と同じ”demae0000000000“に戻され、未接続の状態になります。
もし、 global.socketidと同じmsg.socketidを持つ端末が「切断」を押さずにダッシュボードから抜けた場合には、抜けたことを検出して、 global.socketidを初期値と同じ”demae0000000000“に戻し、未接続の状態に初期化します。
1-2.フローの概要説明
以下にフローを示します。フローのJSONファイルは、Appendixに載せています。
フローの肝としては、2つあります。
1) global変数
以下の3つのglobal変数を使用しています。global.switchとglobal.sliderは、許可されていない端末からの操作を2秒後に元に戻すために使用されます。
global変数に関しては、こちら(ノード間のデータの受け渡し(Context))を参照ください。
global.socketid : ダミーid “demae0000000000”か、未接続状態で最初に「接続」ボタンを押した端末のmsg.scoketidを保持
global.switch : global.socketidと同じmsg.socketidを持つ端末が設定したswicthの状態 “true” or “false”
global.slider : global.socketidと同じmsg.socketidを持つ端末が設定したsliderの操作値 0~10の整数
2) ui-controlノード
ui-controlノードは、ダッシュボードのタブやグループなどの表示切替などの制御に使用されるノードですので、ダッシュボードへの接続(connect)、切断(lost)、タブの移動(change)などの情報を出力してくれます。これを、「切断」ボタンを押さないまま、ダッシュボードから抜けていった端末を検出するのに使用します。
ダッシュボードを抜けた端末があった場合のui-controlノードの出力を以下に示します。payload: “lost”, scoketid: “NOVvHuLWieGVWT-MAAAB”のように表示されます。これを利用して、msg.payload:”lost”の場合のmsg.socketid:が、global.socketidと同じだったら、「切断」し忘れと判断して、global.socket.idを初期化します。
2. ユーザー制限
ユーザー制限とは、ユーザーIDとパスワードでの認証により、限られたユーザーだけに操作することを可能にする機能です。
ここでは、上記の排他制御にユーザー制限を追加します。
2-1. ユーザー制限の方法
ダッシュボードの閲覧にはユーザー制限を設けず、操作を行うことにのみユーザー制限をかけることから、socketidの認証記録簿方式の以下の様なユーザー制限の方法を行います。
①「接続」ボタンを押した際に、socketidの認証記録簿にscoketidが登録されているかどうかをまず確認します。
②登録されている場合には、socketidによる排他制御に移ります。
③登録されていない場合には、ユーザー認証画面に移動し、ユーザーIDとパスワードを入力してもらいます。ユーザー認証OKの場合(ユーザーIDとパスワードが正しい)は、認証が出来た旨を表示し、socketidを記録します。その後、 socketidによる排他制御に移ります。
④認証記録簿からのsocketidの削除は、利用者がダッシュボードから抜けた際に行います。ですので、一度認証すると、抜けるまで「接続」ボタンを押しても、認証画面に移ることはありません。
⑤認証記録簿は、10人の利用者までのsocketidを記録できます。11人目の利用者が認証OKしても、「参加者が10名を超えました」と表示して、認証できません。誰か利用者がダッシュボードから抜けると、socketid記録簿に空きができますので、認証できるようになります。
2-2. socketid記録簿の実装
socketid記録簿の実装に関して説明します。global変数の配列global.mem_id[]を使用します。11個の配列を使用します。
利用者が登録されていない配列には、すべて”non”を入れておきます。そのため、”non”が入っている配列は、socketidが登録されていないことを意味します。
そして、初めの人が認証OKになると、global.mem_id[0]にsocketidを保存します。2人目のsocketidは、global.mem_id[1]に保存されます。5人目の人はglobal.mem_id[4]に、10人目の人はglobal_mem_id[9]にsocketidが保存されます。
具体的な動作を説明します。
a)global.mem_id[]の初期化
Node-REDの起動直後に、global.mem_id=[“non”, “non”, “non”, “non”, “non”, “non”, “non”, “non”, “non”, “non”, “non”];のようにすべて”non”を代入します。
b)global.mem_id[]への追加
global.mem_id[]をgetし、global.mem_id[0]から順に、”non”かどうかを調べていきます。初めに”non”が出た場所に、socketidを追加します。追加後、global.mem_id[]にsetします。
c) mem_id[]にsocketidが登録されているかの確認global.mem_id[]をgetし、global.mem_id[0]から順に、sockteidが一致するかどうか“non”がでるまで調べていきます。”non”がでてきたら登録されていません。
d) mem_id[]からのsocktidの削除
i) mem_id[]をgetし、global.mem_id[0]から順に調べて、何番目に”non”がでるかを確認します。例えば、global.mem_id[5]に”non”があれば、5人の利用者のsocketidが登録されています。global.mem_id[10]に”non”があれば、10人の利用者のsocktidが登録されています(定員一杯です)。
ii) 次に、mem_id[]の何番目に削除するsocktidが登録されているかを調べます。
iii) 削除するsocktidが登録されていた番号の次の番号から最初の”non”までのデータを登録されていた番号以降に上書きします。これで、削除が完了します。
以下に、sockeidの削除の例を示します。
2-3. Node-REDのフロー
次にNode-REDのフローを説明します。下の図の左側は上記で説明した排他的操作のみのフローです。右側はそれに、ユーザー認証を追加したフローです。
追加した部分のポイントを説明します。
①のfunctionノードは、Node-RED起動時に、mem_id[]の初期化とusernameとpasswordの設定を行っています。
usenameとpasswordは、必要に応じて、変更してください。
var id = ["non", "non", "non", "non", "non", "non", "non", "non", "non", "non", "non"];
global.set("mem_id", id);
global.set("username","r-cps-member");
global.set("password","r-msm-pdh");
return msg;
②のfunctionノードとswitchノードは、「接続」ボタンを押した利用者のsocketidが、 socketidの認証記録簿に存在するかどうかを調べています。存在すれば、
排他制御のcheck idのノードへ移動し、存在しなければ、登録者の人数が10名に達しているかどうかのチェックを経て、③の認証画面への移行へ移ります。②のfunctionノードでは、上のsocktid記録簿の実装の「c) mem_id[]にsocketidが登録されているかの確認」で述べた内容を実装しています。
存在していれば、is_member=“true”、存在しなければ、is_member=“false”を返します。次段のswitchノードで行先を振り分けます。
もう一つの機能は、記録簿の中の”non”の位置をmsg.numで返します。次の満席のswitchノードで使用します。msg.num=10であれば、定員一杯であるので、「参加者が10名に達しました」と表示して認証画面に移行できません。
var mem_id = global.get("mem_id");
var max = 10;
var num = 10;
var i;
var is_member = false;
// confirm current number of member
for (i=0; i<max; i++){
if (mem_id[i] == "non"){
num = i;
break;
}
}
// check socketid registered or not
for (i=0; i<num; i++){
if (msg.socketid == mem_id[i]){
is_member = true;
break;
}
}
msg.num = num;
msg.is_member = is_member;
return msg;
③のchangeノードとui-controlノードで、認証画面を表示させます。
changeノードで、msg.payloadに、移動先のタブ名を、JSONフォーマット{“tab”:”認証画面”}で記載します。それを、ui-controlノードに渡すことで、タブの移動を実現します。ui-controlノードは、出力を「タブ変更もしくはグループイベントのみ」とします。
④のformノードで、認証画面を作成します。
・formノードを配置するタブとグループを新規に作成します。
・フォームの要素にユーザーIDとパスワードの欄を作成します。この時、必須にチェックを入れてください。
これで、認証画面が出来上がりました。
ユーザーidとパスワードが、①の初期化ノードで設定したglobal.username, global.passwordと一致するかswitchノードで確認して一致すれば、
⑤のfunctionノードで、socketid記録簿に追加します。ここでは、上のsocketid記録簿の実装の「b) global.mem_id[]への追加」で述べた内容を実装しています。
var mem_id = global.get("mem_id");
var max = 10;
var num = 10;
var i;
// confirm current number of member
for (i=0; i<max; i++){
if (mem_id[i] == "non"){
num = i;
break;
}
}
// store socket id
mem_id[i] = msg.socketid;
// socketid registered
global.set("mem_id", mem_id);
msg.mem_id = mem_id;
return msg;
ユーザーidとパスワードが、①の初期化ノードで設定したglobal.username, global.passwordと一致しなかった場合と、一致した後にsocketid記録簿への追加が終わったら、それぞれ、「認証できませんでした」と「認証できました」の表示をnotificationノードで出してから、⑥のchangeノードとui-controlノードで、”認証画面“から、”操作テスト”の画面に戻ります。
changeノードで、msg.payloadに、移動先のタブ名を、JSONフォーマット{“tab”:”操作テスト”}で記載します。ui-controlノードの設定は上と同じです。
最後に、利用者が抜けた場合のsocketid記録簿からの削除の処理です。
⑦のfunctionノードで実装しています。上のsocktid記録簿の実装の「d) mem_id[]からのsocktidの削除」で説明した内容を実装しています。
赤枠で囲った部分で、抜けた利用者のsocketidの記録簿内位置を探して、見つかったら、一つずつ、大きい位置のsocktidをずらして上書きしていきます。最後は、“non”が上書きされ、一つsocketidが減ります。
var mem_id = global.get("mem_id");
var max = 10;
var num = 10;
var own = 0;
var i, j;
// confirm current number of member
for (i=0; i<max; i++){
if (mem_id[i] == "non"){
num = i;
break;
}
}
// check socketid registered or not
for (i=0; i<num; i++){
if (msg.socketid == mem_id[i]){
own = i;
// shift socketid
for (j = own; j < num; j++) {
mem_id[j] = mem_id[j + 1];
}
break;
}
}
global.set("mem_id", mem_id);
msg.mem_id = mem_id;
return msg;
3. ユーザー制限(2): 個別ユーザー名対応と操作ログの保存
2章のユーザー制限では、一つのユーザーIDとパスワードを知っている人だけが操作できるというユーザー制限を実現しました。
ここでは、一人一人のユーザーに個別のユーザー名とパスワードを付与し、それを使って、誰がいつダッシュボードを操作したかと最終設定値をログに保存してみます。
3-1. 動作の概要
2章のユーザー制限のフローに、個別ユーザー名対応と操作ログの記録対応を追加する方針で進めます。追加する機能の概要を以下に説明します。
2章のユーザー制限のフローの仕様には、以下の様な特徴があります。
1) 一度ユーザー認証を済ませると、ダッシュボードを抜けるまで認証が有効。「接続」ボタンを押すたびに認証を要求されることは無い。
2) その代わりに、認証を済ませた待機者は最大10名
3-1-1. 個別ユーザー名とパスワードの認証
ユーザー名とパスワードが複数あることから、それらをあらかじめファイルに記載しておき、起動時に読み込む方式にします。Node-RED起動直後に、ファイルを読み込み、グローバル変数userに2次元配列で保存します。そして、接続ボタンが押されたら、認証画面に移行しユーザー名とパスワードを入力してもらい、グローバル変数userの中に両方共に一致するものがあるかどうかを調べます。一致すれば、socketid記録簿にsocktidを保存します。そして、この時にユーザー名記録簿の同じ番号にユーザー名も保存します。ユーザー名とsocketidの対応をとるのは、操作ログの作成のためです。ユーザー名とsocketidは認証時にしか対応が取れないので、配列の添え字で対応させて保存します。
【使用するglobal変数】
1) global.user_name:ユーザ名とパスワードが記載されたファイル名(パスを含む)
2) global.user[][2]: ユーザー名とパスワードを保管しておく2次元配列 配列のlengthは、ファイルを読み込んだ時点で決まります。global.user[i][0]が、i番目のユーザー名、global.user[i][1]が、i番目のパスワード
3) global.mem_id[11]:認証できたユーザーのsocketidを保存する配列(認証済みの人のsocketidの管理用。最大10名)
4) global.info[11]:認証できたユーザーのユーザー名を保存する配列。配列の添え字が同じglobal.mem_id[j]とglobal.info[j]は、同じユーザーのsocketidとユーザー名を示します(これも最大10名分)
3-1-2. ログデータの記録
ログデータとして記録するのは、以下の5つです。
1) ユーザー名
2) socketid
3) 操作開始時刻(操作が可能になった時刻)
4) 操作終了時刻(「切断」ボタンを押した時刻もしくは、ダッシュボードを抜けた時)
5) 操作データ:switchノードのデータ(true or false)とsliderノードのデータ(0~10の整数)
・操作開始時:他の人が接続していない状態で「接続」ボタンを押して操作が可能になった時に、ユーザー名とsocketidと現在の時刻を操作開始時刻として、global変数に保存します。
・操作終了時:「切断」ボタンを押したとき、もしくは「切断」せずにダッシュボードを抜けた時に、現在の時刻を操作終了時刻として、global変数に保存します。
そして、操作開始時に保存したユーザー名、socketid、操作開始時刻と今回の操作終了時刻、そして現在の操作データをcsv形式に変換してglobal変数log_nameで指定されたファイルに保存します。
【使用するglobal変数】
1)login_user
2)login_time
3)switch:switchノードのデータ(true or false)
4)slider:sliderノードのデータ(0~10の整数)
5)log_name:logファイル名
3-1-3. ログデータの参照
ログデータとしてグローバル変数log_nameで指定したファイルに保存したデータを、読み込みデバッグ画面に表示させる機能です。
csvファイルを読み込み、オブジェクトの配列に保存して、最後にdebugノードで出力します。
【使用するglobal変数】
1)log_name:logファイル名
2)log_data:読み出したデータを保管するオブジェクトの配列
3-2. Node-REDのフロー
次に、「動作の概要」で説明した内容を実装したNode-REDのフローの説明を行います。下に、フローの全体像を示します。右側の青い一点鎖線で括った部分が今回追加したフローのメイン部分です。Link inノードとLink outノードを使って、左側と右側を繋いでいます。左側の図の赤い番号を付けたLink outから、右側の図の同じ番号に接続しています。
「3-1-1. 個別ユーザー名とパスワードの認証」で動作概要を説明した機能を、④と⑤の部分で実現しています。
「3-1-2. ログデータの記録」で動作概要を説明した機能を、⑥の部分で実現しています。
「3-1-3. ログデータの参照」で動作概要を説明した機能を、⑦の部分で実現しています。
以下、それぞれのフローのポイントを説明していきます。
3-2-1. 個別ユーザー名とパスワードの認証
④の部分では、大きく2つの機能を実現しています。global変数の初期化と、global変数user_nameで指定されたファイルからユーザ名とパスワードを読み出しglobal変数userに保管することです。
1) global変数の初期化
初期化のfunctionノードの記述を次に示します。各種global変数の初期化を行っています。最初の2つのファイル名に関しては、環境に合わせて変更する必要があります。また、ユーザー名とパスワードを記載したファイルのファイル名user_nameは、msg.filenameとして、次段のread fileノードに渡します。
// file for username and password
var user_name = "/home/pi/Documents/userkanri.txt";
// log file name with full path
var log_name = "/home/pi/Documents/user_log.csv";
// initialize routine # Don't touch!!
var id = ["non", "non", "non", "non", "non", "non", "non", "non", "non", "non", "non"];
var user = new Array();
global.set("user", user);
global.set("mem_id", id);
var info = new Array();
for(var i=0; i<10; i++){
info[i] = "username";
}
global.set("info",info);
global.set("login_time","19991231125959");
global.set("login_user","username");
global.set("log_name",log_name);
msg.filename = user_name;
global.set("log_data",new Array());
return msg;
2) ユーザー名とパスワードの保管
ユーザー名とパスワードの保管は、read fileノードとcsvファイルノードとswitchノードとfunctionノードの4つで実現しています。
read fileノードで、初期化のノードからmsg.filenameにセットされたファイルを開いて1行毎読み出します。csvノードで読み込んだデータをオブジェクトに変換します。switchノードでは、usernameがキーとして含まれているかをチェックします。その後、functionノードで、global変数userにmsg.payload.usernameとmsg.payload.passwordを保管します。
ユーザー名とパスワードを記載したファイルは、以下の例のように1行目にusername,passwordというヘッダーを記載し、2行目から実際のユーザー名とパスワードを“、”で区切り、1行毎に記載するフォーマットで書く必要があります。
username,password
r-cps-user01,r-cps-pass01
r-cps-user02,r-cps-pass02
r-cps-user03,r-cps-pass03
r-cps-user04,r-cps-pass04
以下の様に、2次元配列として保存されます。参照は、user[0][0]=“r-cps-user01”, user[1][1]=“r-cps-pass02”のように行います。
下の段のcompleteノードとchangeノードとdebugノードは、読み込みがうまく行ったかを確認するためのデバッグ用ノードです。
⑤の部分では、ユーザー認証が終わった時点で、ユーザー名をglobal変数infoに保管します。前段のfunctionノードで、soketidをglobal変数mem_idに保存しています。その時に保存に使用した配列の添え字を、msg.mem_numとして送ってもらっており、その値を使って同じ配列番号に保管します。
これによって、socketidとユーザ名が1対1で対応して保管できます。デバッグ用に、msg.payloadにsockettidとユーザー名を代入しています。
var info = global.get("info");
var num = msg.mem_num;
// save login name
info[num] = msg.payload.username;
global.set("info",info);
msg.payload = {"socketid":msg.mem_id[num], "username":info[num]};
return msg;
3-2-2. ログデータの記録
⑥の部分では、ログとして保存するのに必要なデータを取得し、「切断」ボタンが押された際に、global変数log_nameで指定されたファイルに保存します。
1)操作開始時
link inノードが2つあります。上側(②)が、未接続状態時に「接続」ボタンが押され、操作が開始されたときのパスです。
まず、Date/Time formatterノードで現在の時刻を取得し、msg.datetimeに乗せます。次段のlog in functionノードでは、global変数mem_idの中からsocketidを見つけます。その時の添え字を使って、ユーザー名をglobal変数infoから取得して、global変数login_userにセットします。合わせてmsg.datetimeをglobal変数login_timeにセットします。以上が操作開始時のフローです。
var mem_id = global.get("mem_id");
var info = global.get("info");
var max = 10;
var num = 10;
var i;
// confirm current number of member
for (i=0; i<max; i++){
if (mem_id[i] == "non"){
num = i;
break;
}
}
// check socketid registered or not
for (i=0; i<num; i++){
if (msg.socketid == mem_id[i]){
global.set("login_user", info[i]);
break;
}
}
global.set("login_time", msg.datetime);
msg.payload ={"login_user":info[i], "socket_id":msg.socketid, "login_time":msg.datetime};
return msg;
2)操作終了時
下側(③)のlink inノードが、接続中に「切断」ボタンが押された、もしくは、ダッシュボードから抜けた(ui-controlで”lost”検出された)ときのパスです。
まず、Date/Time formatterノードで現在の時刻を取得し、msg.datetimeに乗せます。これは操作開始時と同じです。次段のlog outのfunctionノードでは、ログファイルに保存するためのデータを集めて、msg.payloadオブジェクトに乗せます。
“login_user”:global.login_user
“socket_id”:socketid
“login_time”:global.login_time
“logout_time”:msg.datetime
“switch”:global.switch
“slider”:global.slider
次のcsvノードでオブジェクトをcsv形式に変換します。その次のchangeノードで、ログファイル名を指定したglobal変数log_nameをmsg.filenameにセットします。
そして、write fileノードで、ファイルに書き込みます。
var login_user = global.get("login_user");
var login_time = global.get("login_time");
var socketid = msg.socketid;
var _switch = global.get("switch");
var _slider = global.get("slider");
msg.payload ={"login_user":login_user, "socket_id":socketid, "login_time":login_time, "logout_time":msg.datetime, "switch":_switch, "slider":_slider};
return msg;
3-2-3. ログデータの参照
⑦の部分では、injectノードを押すとログファイルを開いて、csvデータを読み込んで、配列にセットします。csvファイルのデータを配列に読み込むフローに関しては、こちら(csvファイルのデータを配列に読込む)を参照してください。
ポイントとしては、以下の3つになります。
1)read fileにログファイル名として、global変数log_nameをmsg.filenameとして渡しています。
2)ログデータをファイルに記録するところで、1行目にヘッダを付けています。デプロイのたびにヘッダが1行記録されるので、読み込んだ時に、ヘッダを読み飛ばすためのswitchノードを付けています。
3)また、completeノードを使っているのは、配列functionをそのまま出力するとcsvファイルの行数分データが出力されるので、ファイルを読み終わったことを検出して、1秒待って、安定した時点で、global変数log_dataを読み出しています。
Appendix. Node-REDのフローファイル
1) 排他的操作のみ
[
{
"id": "9624ddaf8e7b3698",
"type": "tab",
"label": "排他制御",
"disabled": false,
"info": "",
"env": []
},
{
"id": "ad5b1d37877d52ee",
"type": "ui_switch",
"z": "9624ddaf8e7b3698",
"name": "",
"label": "switch",
"tooltip": "",
"group": "c56c2f84eee38f59",
"order": 7,
"width": 0,
"height": 0,
"passthru": true,
"decouple": "false",
"topic": "topic",
"topicType": "msg",
"style": "",
"onvalue": "true",
"onvalueType": "bool",
"onicon": "",
"oncolor": "",
"offvalue": "false",
"offvalueType": "bool",
"officon": "",
"offcolor": "",
"animate": false,
"x": 110,
"y": 440,
"wires": [
[
"d3dd68a84bd2ee59"
]
]
},
{
"id": "066ef102062a6dc8",
"type": "ui_button",
"z": "9624ddaf8e7b3698",
"name": "",
"group": "c56c2f84eee38f59",
"order": 5,
"width": 0,
"height": 0,
"passthru": false,
"label": "接続",
"tooltip": "",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 110,
"y": 280,
"wires": [
[
"a364df582bdb65bd",
"5e001c2f7435054a"
]
]
},
{
"id": "6580298aa247f490",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "排他制御",
"info": "",
"x": 80,
"y": 40,
"wires": []
},
{
"id": "59b75511d3bb0aaa",
"type": "ui_text",
"z": "9624ddaf8e7b3698",
"group": "c56c2f84eee38f59",
"order": 3,
"width": 0,
"height": 0,
"name": "",
"label": "接続要求",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 720,
"y": 240,
"wires": []
},
{
"id": "f3d968583e2847bd",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "read id",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "socketid",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 560,
"y": 160,
"wires": [
[
"c5e54309c7f7bce3"
]
]
},
{
"id": "c97ff4710e0ffbfb",
"type": "ui_button",
"z": "9624ddaf8e7b3698",
"name": "",
"group": "c56c2f84eee38f59",
"order": 6,
"width": 0,
"height": 0,
"passthru": false,
"label": "切断",
"tooltip": "",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 110,
"y": 180,
"wires": [
[
"2d29b5872f72f234"
]
]
},
{
"id": "2967777faab35bab",
"type": "inject",
"z": "9624ddaf8e7b3698",
"name": "初期化",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "str",
"x": 240,
"y": 220,
"wires": [
[
"90e66fce09272b50"
]
]
},
{
"id": "c5e54309c7f7bce3",
"type": "ui_text",
"z": "9624ddaf8e7b3698",
"group": "c56c2f84eee38f59",
"order": 2,
"width": 0,
"height": 0,
"name": "",
"label": "操作可能",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 720,
"y": 160,
"wires": []
},
{
"id": "a364df582bdb65bd",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "check id",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "demae0000000000",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 240,
"y": 260,
"wires": [
[
"d68a8951689519d6",
"8d17f7f04fa27519"
]
]
},
{
"id": "d3dd68a84bd2ee59",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "Judge",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
},
{
"t": "neq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 230,
"y": 440,
"wires": [
[
"729bd4a3291ee25d"
],
[
"4e20b95c94917b94"
]
]
},
{
"id": "5e001c2f7435054a",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "display id",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "socketid",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 560,
"y": 280,
"wires": [
[
"59b75511d3bb0aaa"
]
]
},
{
"id": "8b589828c0b36b10",
"type": "ui_text",
"z": "9624ddaf8e7b3698",
"group": "c56c2f84eee38f59",
"order": 4,
"width": 0,
"height": 0,
"name": "",
"label": "状態",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 710,
"y": 340,
"wires": []
},
{
"id": "a0208d9f0c132d2c",
"type": "ui_slider",
"z": "9624ddaf8e7b3698",
"name": "",
"label": "slider",
"tooltip": "",
"group": "c56c2f84eee38f59",
"order": 8,
"width": 0,
"height": 0,
"passthru": true,
"outs": "all",
"topic": "topic",
"topicType": "msg",
"min": 0,
"max": 10,
"step": 1,
"x": 110,
"y": 620,
"wires": [
[
"6b54522fd8bd7754"
]
]
},
{
"id": "504973adb30b1a56",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "未接続",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "未接続",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 320,
"wires": [
[
"8b589828c0b36b10"
]
]
},
{
"id": "d68a8951689519d6",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "接続中",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "接続中",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 360,
"wires": [
[
"8b589828c0b36b10"
]
]
},
{
"id": "19e298710e52f945",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 31",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 560,
"y": 560,
"wires": []
},
{
"id": "eeee16370fe62739",
"type": "ui_gauge",
"z": "9624ddaf8e7b3698",
"name": "",
"group": "68a74b5e3cb81569",
"order": 2,
"width": 0,
"height": 0,
"gtype": "gage",
"title": "gauge",
"label": "units",
"format": "{{value}}",
"min": 0,
"max": 10,
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"x": 570,
"y": 600,
"wires": []
},
{
"id": "6b54522fd8bd7754",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "Judge",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
},
{
"t": "neq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 230,
"y": 620,
"wires": [
[
"c6dbb33518226fb1"
],
[
"e1027b676fc5ea9e"
]
]
},
{
"id": "b2a18a8c82a7f1cb",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 32",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 560,
"y": 420,
"wires": []
},
{
"id": "d6ca2d5a9b099f4f",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "read slider",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "slider",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 250,
"y": 680,
"wires": [
[
"a0208d9f0c132d2c"
]
]
},
{
"id": "c6a37e9657b90baf",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "read switch",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "switch",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 250,
"y": 500,
"wires": [
[
"ad5b1d37877d52ee"
]
]
},
{
"id": "4e20b95c94917b94",
"type": "delay",
"z": "9624ddaf8e7b3698",
"name": "",
"pauseType": "delay",
"timeout": "2",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 100,
"y": 500,
"wires": [
[
"c6a37e9657b90baf"
]
]
},
{
"id": "e1027b676fc5ea9e",
"type": "delay",
"z": "9624ddaf8e7b3698",
"name": "",
"pauseType": "delay",
"timeout": "2",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 100,
"y": 680,
"wires": [
[
"d6ca2d5a9b099f4f"
]
]
},
{
"id": "a2a31d783183bcbd",
"type": "inject",
"z": "9624ddaf8e7b3698",
"name": "20秒毎",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "20",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "str",
"x": 640,
"y": 200,
"wires": [
[
"59b75511d3bb0aaa"
]
]
},
{
"id": "e58f52290cef7435",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 36",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 240,
"y": 80,
"wires": []
},
{
"id": "287b49bdf06d04da",
"type": "ui_ui_control",
"z": "9624ddaf8e7b3698",
"name": "",
"events": "all",
"x": 100,
"y": 100,
"wires": [
[
"13fdcb314bdb2b29",
"e58f52290cef7435"
]
]
},
{
"id": "90e66fce09272b50",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "id初期化",
"rules": [
{
"t": "set",
"p": "socketid",
"pt": "global",
"to": "demae0000000000",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 400,
"y": 160,
"wires": [
[
"f3d968583e2847bd",
"504973adb30b1a56",
"0865d69acac9245b"
]
]
},
{
"id": "8d17f7f04fa27519",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "set id",
"rules": [
{
"t": "set",
"p": "socketid",
"pt": "global",
"to": "socketid",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 410,
"y": 260,
"wires": [
[
"f3d968583e2847bd"
]
]
},
{
"id": "729bd4a3291ee25d",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "set switch",
"rules": [
{
"t": "set",
"p": "switch",
"pt": "global",
"to": "payload",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 400,
"y": 420,
"wires": [
[
"b2a18a8c82a7f1cb"
]
]
},
{
"id": "c6dbb33518226fb1",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "set slider",
"rules": [
{
"t": "set",
"p": "slider",
"pt": "global",
"to": "payload",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 400,
"y": 600,
"wires": [
[
"eeee16370fe62739",
"19e298710e52f945"
]
]
},
{
"id": "da7b75a16f43986c",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "Switch制御",
"info": "",
"x": 100,
"y": 380,
"wires": []
},
{
"id": "bd0d0849d1eef2f5",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "Slider制御",
"info": "",
"x": 100,
"y": 580,
"wires": []
},
{
"id": "13fdcb314bdb2b29",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "lost検出",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "lost",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 240,
"y": 120,
"wires": [
[
"8778866f5540b29e"
]
]
},
{
"id": "8778866f5540b29e",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "切断忘れ",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 380,
"y": 120,
"wires": [
[
"90e66fce09272b50"
]
]
},
{
"id": "2d29b5872f72f234",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "check id",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
},
{
"t": "neq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 240,
"y": 180,
"wires": [
[
"90e66fce09272b50"
],
[
"0865d69acac9245b"
]
]
},
{
"id": "0865d69acac9245b",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "clear",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 410,
"y": 220,
"wires": [
[
"59b75511d3bb0aaa"
]
]
},
{
"id": "c56c2f84eee38f59",
"type": "ui_group",
"name": "排他制御",
"tab": "b5de217d24b3769b",
"order": 2,
"disp": true,
"width": "6",
"collapse": false
},
{
"id": "68a74b5e3cb81569",
"type": "ui_group",
"name": "ファイル保存",
"tab": "b5de217d24b3769b",
"order": 1,
"disp": true,
"width": "6",
"collapse": false
},
{
"id": "b5de217d24b3769b",
"type": "ui_tab",
"name": "操作テスト",
"icon": "dashboard",
"order": 6,
"disabled": false,
"hidden": false
}
]
2) 排他制御+ユーザー制限
[{"id":"9624ddaf8e7b3698","type":"tab","label":"排他制御+ユーザ認証","disabled":false,"info":"","env":[]},{"id":"ad5b1d37877d52ee","type":"ui_switch","z":"9624ddaf8e7b3698","name":"","label":"switch","tooltip":"","group":"c56c2f84eee38f59","order":7,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"x":110,"y":560,"wires":[["d3dd68a84bd2ee59"]]},{"id":"066ef102062a6dc8","type":"ui_button","z":"9624ddaf8e7b3698","name":"","group":"c56c2f84eee38f59","order":5,"width":0,"height":0,"passthru":false,"label":"接続","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":110,"y":400,"wires":[["4dee3c0539dc31f5"]]},{"id":"6580298aa247f490","type":"comment","z":"9624ddaf8e7b3698","name":"排他制御","info":"","x":80,"y":40,"wires":[]},{"id":"59b75511d3bb0aaa","type":"ui_text","z":"9624ddaf8e7b3698","group":"c56c2f84eee38f59","order":3,"width":0,"height":0,"name":"","label":"接続要求","format":"{{msg.payload}}","layout":"row-spread","x":720,"y":280,"wires":[]},{"id":"f3d968583e2847bd","type":"change","z":"9624ddaf8e7b3698","name":"read id","rules":[{"t":"set","p":"payload","pt":"msg","to":"socketid","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":200,"wires":[["c5e54309c7f7bce3"]]},{"id":"c97ff4710e0ffbfb","type":"ui_button","z":"9624ddaf8e7b3698","name":"","group":"c56c2f84eee38f59","order":6,"width":0,"height":0,"passthru":false,"label":"切断","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":110,"y":220,"wires":[["2d29b5872f72f234"]]},{"id":"2967777faab35bab","type":"inject","z":"9624ddaf8e7b3698","name":"初期化","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":100,"y":180,"wires":[["90e66fce09272b50","3979fd3c78aa9a41"]]},{"id":"c5e54309c7f7bce3","type":"ui_text","z":"9624ddaf8e7b3698","group":"c56c2f84eee38f59","order":2,"width":0,"height":0,"name":"","label":"操作可能","format":"{{msg.payload}}","layout":"row-spread","className":"","x":720,"y":200,"wires":[]},{"id":"a364df582bdb65bd","type":"switch","z":"9624ddaf8e7b3698","name":"check id","property":"socketid","propertyType":"global","rules":[{"t":"eq","v":"demae0000000000","vt":"str"},{"t":"neq","v":"demae0000000000","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":240,"y":300,"wires":[["d68a8951689519d6","8d17f7f04fa27519"],["36adac1a0492a813"]]},{"id":"d3dd68a84bd2ee59","type":"switch","z":"9624ddaf8e7b3698","name":"Judge","property":"socketid","propertyType":"global","rules":[{"t":"eq","v":"socketid","vt":"msg"},{"t":"neq","v":"socketid","vt":"msg"}],"checkall":"true","repair":false,"outputs":2,"x":230,"y":560,"wires":[["729bd4a3291ee25d"],["4e20b95c94917b94"]]},{"id":"5e001c2f7435054a","type":"change","z":"9624ddaf8e7b3698","name":"display id","rules":[{"t":"set","p":"payload","pt":"msg","to":"socketid","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":320,"wires":[["59b75511d3bb0aaa"]]},{"id":"8b589828c0b36b10","type":"ui_text","z":"9624ddaf8e7b3698","group":"c56c2f84eee38f59","order":4,"width":0,"height":0,"name":"","label":"状態","format":"{{msg.payload}}","layout":"row-spread","x":710,"y":380,"wires":[]},{"id":"a0208d9f0c132d2c","type":"ui_slider","z":"9624ddaf8e7b3698","name":"","label":"slider","tooltip":"","group":"c56c2f84eee38f59","order":8,"width":0,"height":0,"passthru":true,"outs":"all","topic":"topic","topicType":"msg","min":0,"max":10,"step":1,"x":110,"y":740,"wires":[["6b54522fd8bd7754"]]},{"id":"504973adb30b1a56","type":"change","z":"9624ddaf8e7b3698","name":"未接続","rules":[{"t":"set","p":"payload","pt":"msg","to":"未接続","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":360,"wires":[["8b589828c0b36b10"]]},{"id":"d68a8951689519d6","type":"change","z":"9624ddaf8e7b3698","name":"接続中","rules":[{"t":"set","p":"payload","pt":"msg","to":"接続中","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":400,"wires":[["8b589828c0b36b10"]]},{"id":"19e298710e52f945","type":"debug","z":"9624ddaf8e7b3698","name":"debug 31","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":560,"y":680,"wires":[]},{"id":"eeee16370fe62739","type":"ui_gauge","z":"9624ddaf8e7b3698","name":"","group":"68a74b5e3cb81569","order":2,"width":0,"height":0,"gtype":"gage","title":"gauge","label":"units","format":"{{value}}","min":0,"max":10,"colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":570,"y":720,"wires":[]},{"id":"6b54522fd8bd7754","type":"switch","z":"9624ddaf8e7b3698","name":"Judge","property":"socketid","propertyType":"global","rules":[{"t":"eq","v":"socketid","vt":"msg"},{"t":"neq","v":"socketid","vt":"msg"}],"checkall":"true","repair":false,"outputs":2,"x":230,"y":740,"wires":[["c6dbb33518226fb1"],["e1027b676fc5ea9e"]]},{"id":"b2a18a8c82a7f1cb","type":"debug","z":"9624ddaf8e7b3698","name":"debug 32","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":560,"y":540,"wires":[]},{"id":"d6ca2d5a9b099f4f","type":"change","z":"9624ddaf8e7b3698","name":"read slider","rules":[{"t":"set","p":"payload","pt":"msg","to":"slider","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":800,"wires":[["a0208d9f0c132d2c"]]},{"id":"c6a37e9657b90baf","type":"change","z":"9624ddaf8e7b3698","name":"read switch","rules":[{"t":"set","p":"payload","pt":"msg","to":"switch","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":620,"wires":[["ad5b1d37877d52ee"]]},{"id":"4e20b95c94917b94","type":"delay","z":"9624ddaf8e7b3698","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":100,"y":620,"wires":[["c6a37e9657b90baf"]]},{"id":"e1027b676fc5ea9e","type":"delay","z":"9624ddaf8e7b3698","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":100,"y":800,"wires":[["d6ca2d5a9b099f4f"]]},{"id":"a2a31d783183bcbd","type":"inject","z":"9624ddaf8e7b3698","name":"20秒毎","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"20","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":640,"y":240,"wires":[["59b75511d3bb0aaa"]]},{"id":"e58f52290cef7435","type":"debug","z":"9624ddaf8e7b3698","name":"debug 36","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":240,"y":80,"wires":[]},{"id":"287b49bdf06d04da","type":"ui_ui_control","z":"9624ddaf8e7b3698","name":"","events":"all","x":100,"y":100,"wires":[["13fdcb314bdb2b29","e58f52290cef7435"]]},{"id":"90e66fce09272b50","type":"change","z":"9624ddaf8e7b3698","name":"id初期化","rules":[{"t":"set","p":"socketid","pt":"global","to":"demae0000000000","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":200,"wires":[["f3d968583e2847bd","504973adb30b1a56","0865d69acac9245b"]]},{"id":"8d17f7f04fa27519","type":"change","z":"9624ddaf8e7b3698","name":"set id","rules":[{"t":"set","p":"socketid","pt":"global","to":"socketid","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":300,"wires":[["f3d968583e2847bd"]]},{"id":"729bd4a3291ee25d","type":"change","z":"9624ddaf8e7b3698","name":"set switch","rules":[{"t":"set","p":"switch","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":540,"wires":[["b2a18a8c82a7f1cb"]]},{"id":"c6dbb33518226fb1","type":"change","z":"9624ddaf8e7b3698","name":"set slider","rules":[{"t":"set","p":"slider","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":720,"wires":[["eeee16370fe62739","19e298710e52f945"]]},{"id":"da7b75a16f43986c","type":"comment","z":"9624ddaf8e7b3698","name":"Switch制御","info":"","x":100,"y":500,"wires":[]},{"id":"bd0d0849d1eef2f5","type":"comment","z":"9624ddaf8e7b3698","name":"Slider制御","info":"","x":100,"y":700,"wires":[]},{"id":"13fdcb314bdb2b29","type":"switch","z":"9624ddaf8e7b3698","name":"lost検出","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"lost","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":240,"y":120,"wires":[["8778866f5540b29e","278ec74755d2d931"]]},{"id":"8778866f5540b29e","type":"switch","z":"9624ddaf8e7b3698","name":"切断忘れ","property":"socketid","propertyType":"global","rules":[{"t":"eq","v":"socketid","vt":"msg"}],"checkall":"true","repair":false,"outputs":1,"x":400,"y":140,"wires":[["90e66fce09272b50"]]},{"id":"2d29b5872f72f234","type":"switch","z":"9624ddaf8e7b3698","name":"check id","property":"socketid","propertyType":"global","rules":[{"t":"eq","v":"socketid","vt":"msg"},{"t":"neq","v":"socketid","vt":"msg"}],"checkall":"true","repair":false,"outputs":2,"x":240,"y":220,"wires":[["90e66fce09272b50"],["0865d69acac9245b"]]},{"id":"0865d69acac9245b","type":"change","z":"9624ddaf8e7b3698","name":"clear","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":260,"wires":[["59b75511d3bb0aaa"]]},{"id":"3979fd3c78aa9a41","type":"function","z":"9624ddaf8e7b3698","name":"初期化","func":"var id = [\"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\"];\nglobal.set(\"mem_id\", id);\nglobal.set(\"username\",\"test-user\");\nglobal.set(\"password\",\"test-password\");\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":230,"y":160,"wires":[[]]},{"id":"4dee3c0539dc31f5","type":"function","z":"9624ddaf8e7b3698","name":"check id","func":"var mem_id = global.get(\"mem_id\");\nvar max = 10;\nvar num = 10;\nvar i;\nvar is_member = false;\n\n// confirm current number of member\nfor (i=0; i<max; i++){\n if (mem_id[i] == \"non\"){\n num = i;\n break;\n }\n}\n\n\n// check socketid registered or not\nfor (i=0; i<num; i++){\n if (msg.socketid == mem_id[i]){\n is_member = true;\n break;\n }\n}\n\nmsg.num = num;\nmsg.is_member = is_member;\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":400,"wires":[["b43c421a968ba039"]]},{"id":"b43c421a968ba039","type":"switch","z":"9624ddaf8e7b3698","name":"member?","property":"is_member","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":380,"y":400,"wires":[["5e001c2f7435054a","a364df582bdb65bd"],["133470df1e98dc54"]]},{"id":"a5e3f4f6352e8f7c","type":"ui_ui_control","z":"9624ddaf8e7b3698","name":"認証へ","events":"change","x":570,"y":460,"wires":[[]]},{"id":"21d1e93119832dc8","type":"change","z":"9624ddaf8e7b3698","name":"認証へ","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"tab\":\"認証画面\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":460,"wires":[["a5e3f4f6352e8f7c"]]},{"id":"5816be9c07043ada","type":"function","z":"9624ddaf8e7b3698","name":"store id","func":"var mem_id = global.get(\"mem_id\");\nvar max = 10;\nvar num = 10;\nvar i;\n\n// confirm current number of member\nfor (i=0; i<max; i++){\n if (mem_id[i] == \"non\"){\n num = i;\n break;\n }\n}\n\n// store socket id\nmem_id[i] = msg.socketid;\n\n// socketid registered\nglobal.set(\"mem_id\", mem_id);\n\nmsg.mem_id = mem_id;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":900,"wires":[["8018ae89832c410c","f5fcc419c1256484","81d42cd238d23df4"]]},{"id":"0d6c188b5829f4a9","type":"switch","z":"9624ddaf8e7b3698","name":"pass","property":"payload.password","propertyType":"msg","rules":[{"t":"eq","v":"password","vt":"global"},{"t":"neq","v":"password","vt":"global"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":920,"wires":[["5816be9c07043ada","79a6c1643e7416cf"],["a6edc64ef1ff368d","79a6c1643e7416cf"]]},{"id":"2172f9310d3398fc","type":"switch","z":"9624ddaf8e7b3698","name":"user","property":"payload.username","propertyType":"msg","rules":[{"t":"eq","v":"username","vt":"global"},{"t":"neq","v":"username","vt":"global"}],"checkall":"true","repair":false,"outputs":2,"x":210,"y":940,"wires":[["0d6c188b5829f4a9"],["a6edc64ef1ff368d","79a6c1643e7416cf"]]},{"id":"59f8caa3b319d315","type":"ui_ui_control","z":"9624ddaf8e7b3698","name":"操作へ","events":"change","x":590,"y":980,"wires":[[]]},{"id":"a6edc64ef1ff368d","type":"change","z":"9624ddaf8e7b3698","name":"残念","rules":[{"t":"set","p":"payload","pt":"msg","to":"認証できませんでした","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":940,"wires":[["2caa54e89853cf80"]]},{"id":"bd25dcdf6fac48c5","type":"ui_form","z":"9624ddaf8e7b3698","name":"","label":"","group":"9258a40ced27eba1","order":0,"width":"6","height":"3","options":[{"label":"ユーザID","value":"username","type":"text","required":true,"rows":null},{"label":"パスワード","value":"password","type":"text","required":true,"rows":null}],"formValue":{"username":"","password":""},"payload":"","submit":"submit","cancel":"cancel","topic":"topic","topicType":"msg","splitLayout":"","className":"","x":90,"y":940,"wires":[["2172f9310d3398fc"]]},{"id":"2caa54e89853cf80","type":"ui_toast","z":"9624ddaf8e7b3698","position":"top left","displayTime":"3","highlight":"","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"className":"","topic":"","name":"通知","x":730,"y":940,"wires":[]},{"id":"c0f9d30a34e2a0d9","type":"comment","z":"9624ddaf8e7b3698","name":"認証","info":"","x":90,"y":900,"wires":[]},{"id":"8018ae89832c410c","type":"change","z":"9624ddaf8e7b3698","name":"OK","rules":[{"t":"set","p":"payload","pt":"msg","to":"認証できました","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":900,"wires":[["2caa54e89853cf80"]]},{"id":"278ec74755d2d931","type":"function","z":"9624ddaf8e7b3698","name":"check id","func":"var mem_id = global.get(\"mem_id\");\nvar max = 10;\nvar num = 10;\nvar own = 0;\nvar i, j;\n\n// confirm current number of member\nfor (i=0; i<max; i++){\n if (mem_id[i] == \"non\"){\n num = i;\n break;\n }\n}\n\n// check socketid registered or not\nfor (i=0; i<num; i++){\n if (msg.socketid == mem_id[i]){\n own = i;\n // shift socketid \n for (j = own; j < num; j++) {\n mem_id[j] = mem_id[j + 1];\n }\n break;\n }\n}\n\nglobal.set(\"mem_id\", mem_id);\n\nmsg.mem_id = mem_id;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":100,"wires":[["062f012abfb1cb7e"]]},{"id":"062f012abfb1cb7e","type":"debug","z":"9624ddaf8e7b3698","name":"debug 37","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":100,"wires":[]},{"id":"f5fcc419c1256484","type":"debug","z":"9624ddaf8e7b3698","name":"debug 38","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":600,"y":820,"wires":[]},{"id":"79a6c1643e7416cf","type":"change","z":"9624ddaf8e7b3698","name":"操作へ","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"tab\":\"操作テスト\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":980,"wires":[["59f8caa3b319d315"]]},{"id":"133470df1e98dc54","type":"switch","z":"9624ddaf8e7b3698","name":"満席","property":"num","propertyType":"msg","rules":[{"t":"neq","v":"10","vt":"num"},{"t":"eq","v":"10","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":480,"wires":[["21d1e93119832dc8"],["362480522c9df186"]]},{"id":"6fe7d9d5b8edae46","type":"ui_toast","z":"9624ddaf8e7b3698","position":"top left","displayTime":"3","highlight":"","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"className":"","topic":"","name":"満席","x":570,"y":500,"wires":[]},{"id":"362480522c9df186","type":"change","z":"9624ddaf8e7b3698","name":"満席","rules":[{"t":"set","p":"payload","pt":"msg","to":"参加者が10名に達しました","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":500,"wires":[["6fe7d9d5b8edae46"]]},{"id":"81d42cd238d23df4","type":"link out","z":"9624ddaf8e7b3698","name":"OK","mode":"link","links":["ede040597906f361"],"x":565,"y":860,"wires":[]},{"id":"ede040597906f361","type":"link in","z":"9624ddaf8e7b3698","name":"link in 1","links":["81d42cd238d23df4"],"x":135,"y":280,"wires":[["a364df582bdb65bd"]]},{"id":"36adac1a0492a813","type":"change","z":"9624ddaf8e7b3698","name":"接続中","rules":[{"t":"set","p":"payload","pt":"msg","to":"他の方が接続中です。しばらくお待ちください。","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":360,"wires":[["ffd6107f94293144"]]},{"id":"ffd6107f94293144","type":"ui_toast","z":"9624ddaf8e7b3698","position":"top right","displayTime":"3","highlight":"","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"className":"","topic":"","name":"接続中","x":310,"y":360,"wires":[]},{"id":"c56c2f84eee38f59","type":"ui_group","name":"排他制御","tab":"b5de217d24b3769b","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"68a74b5e3cb81569","type":"ui_group","name":"ファイル保存","tab":"b5de217d24b3769b","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"9258a40ced27eba1","type":"ui_group","name":"認証","tab":"7be2d49e0eb0264b","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"b5de217d24b3769b","type":"ui_tab","name":"操作テスト","icon":"dashboard","order":6,"disabled":false,"hidden":false},{"id":"7be2d49e0eb0264b","type":"ui_tab","name":"認証画面","icon":"dashboard","disabled":false,"hidden":false}]
3) 排他制御+ユーザー制限(2):複数ユーザー名とログファイル記録
[
{
"id": "9624ddaf8e7b3698",
"type": "tab",
"label": "排他制御+ユーザ認証+log",
"disabled": false,
"info": "",
"env": []
},
{
"id": "ad5b1d37877d52ee",
"type": "ui_switch",
"z": "9624ddaf8e7b3698",
"name": "",
"label": "switch",
"tooltip": "",
"group": "c56c2f84eee38f59",
"order": 7,
"width": 0,
"height": 0,
"passthru": true,
"decouple": "false",
"topic": "topic",
"topicType": "msg",
"style": "",
"onvalue": "true",
"onvalueType": "bool",
"onicon": "",
"oncolor": "",
"offvalue": "false",
"offvalueType": "bool",
"officon": "",
"offcolor": "",
"animate": false,
"x": 110,
"y": 560,
"wires": [
[
"d3dd68a84bd2ee59"
]
]
},
{
"id": "066ef102062a6dc8",
"type": "ui_button",
"z": "9624ddaf8e7b3698",
"name": "",
"group": "c56c2f84eee38f59",
"order": 5,
"width": 0,
"height": 0,
"passthru": false,
"label": "接続",
"tooltip": "",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 110,
"y": 400,
"wires": [
[
"4dee3c0539dc31f5"
]
]
},
{
"id": "6580298aa247f490",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "排他制御",
"info": "",
"x": 80,
"y": 40,
"wires": []
},
{
"id": "59b75511d3bb0aaa",
"type": "ui_text",
"z": "9624ddaf8e7b3698",
"group": "c56c2f84eee38f59",
"order": 3,
"width": 0,
"height": 0,
"name": "",
"label": "接続要求",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 720,
"y": 280,
"wires": []
},
{
"id": "f3d968583e2847bd",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "read id",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "socketid",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 560,
"y": 200,
"wires": [
[
"c5e54309c7f7bce3"
]
]
},
{
"id": "c97ff4710e0ffbfb",
"type": "ui_button",
"z": "9624ddaf8e7b3698",
"name": "",
"group": "c56c2f84eee38f59",
"order": 6,
"width": 0,
"height": 0,
"passthru": false,
"label": "切断",
"tooltip": "",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 110,
"y": 220,
"wires": [
[
"2d29b5872f72f234"
]
]
},
{
"id": "2967777faab35bab",
"type": "inject",
"z": "9624ddaf8e7b3698",
"name": "初期化",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "str",
"x": 100,
"y": 180,
"wires": [
[
"90e66fce09272b50",
"ced2afe73aa72f86"
]
]
},
{
"id": "c5e54309c7f7bce3",
"type": "ui_text",
"z": "9624ddaf8e7b3698",
"group": "c56c2f84eee38f59",
"order": 2,
"width": 0,
"height": 0,
"name": "",
"label": "操作可能",
"format": "{{msg.payload}}",
"layout": "row-spread",
"className": "",
"x": 720,
"y": 200,
"wires": []
},
{
"id": "a364df582bdb65bd",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "check id",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "demae0000000000",
"vt": "str"
},
{
"t": "neq",
"v": "demae0000000000",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 240,
"y": 300,
"wires": [
[
"d68a8951689519d6",
"8d17f7f04fa27519"
],
[
"36adac1a0492a813"
]
]
},
{
"id": "d3dd68a84bd2ee59",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "Judge",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
},
{
"t": "neq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 230,
"y": 560,
"wires": [
[
"729bd4a3291ee25d"
],
[
"4e20b95c94917b94"
]
]
},
{
"id": "5e001c2f7435054a",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "display id",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "socketid",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 560,
"y": 320,
"wires": [
[
"59b75511d3bb0aaa"
]
]
},
{
"id": "8b589828c0b36b10",
"type": "ui_text",
"z": "9624ddaf8e7b3698",
"group": "c56c2f84eee38f59",
"order": 4,
"width": 0,
"height": 0,
"name": "",
"label": "状態",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 710,
"y": 380,
"wires": []
},
{
"id": "a0208d9f0c132d2c",
"type": "ui_slider",
"z": "9624ddaf8e7b3698",
"name": "",
"label": "slider",
"tooltip": "",
"group": "c56c2f84eee38f59",
"order": 8,
"width": 0,
"height": 0,
"passthru": true,
"outs": "all",
"topic": "topic",
"topicType": "msg",
"min": 0,
"max": 10,
"step": 1,
"x": 110,
"y": 740,
"wires": [
[
"6b54522fd8bd7754"
]
]
},
{
"id": "504973adb30b1a56",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "未接続",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "未接続",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 360,
"wires": [
[
"8b589828c0b36b10"
]
]
},
{
"id": "d68a8951689519d6",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "接続中",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "接続中",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 400,
"wires": [
[
"8b589828c0b36b10"
]
]
},
{
"id": "19e298710e52f945",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 31",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 560,
"y": 680,
"wires": []
},
{
"id": "eeee16370fe62739",
"type": "ui_gauge",
"z": "9624ddaf8e7b3698",
"name": "",
"group": "68a74b5e3cb81569",
"order": 2,
"width": 0,
"height": 0,
"gtype": "gage",
"title": "gauge",
"label": "units",
"format": "{{value}}",
"min": 0,
"max": 10,
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"diff": false,
"className": "",
"x": 570,
"y": 720,
"wires": []
},
{
"id": "6b54522fd8bd7754",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "Judge",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
},
{
"t": "neq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 230,
"y": 740,
"wires": [
[
"c6dbb33518226fb1"
],
[
"e1027b676fc5ea9e"
]
]
},
{
"id": "b2a18a8c82a7f1cb",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 32",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 560,
"y": 540,
"wires": []
},
{
"id": "d6ca2d5a9b099f4f",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "read slider",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "slider",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 250,
"y": 800,
"wires": [
[
"a0208d9f0c132d2c"
]
]
},
{
"id": "c6a37e9657b90baf",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "read switch",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "switch",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 250,
"y": 620,
"wires": [
[
"ad5b1d37877d52ee"
]
]
},
{
"id": "4e20b95c94917b94",
"type": "delay",
"z": "9624ddaf8e7b3698",
"name": "",
"pauseType": "delay",
"timeout": "2",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 100,
"y": 620,
"wires": [
[
"c6a37e9657b90baf"
]
]
},
{
"id": "e1027b676fc5ea9e",
"type": "delay",
"z": "9624ddaf8e7b3698",
"name": "",
"pauseType": "delay",
"timeout": "2",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 100,
"y": 800,
"wires": [
[
"d6ca2d5a9b099f4f"
]
]
},
{
"id": "a2a31d783183bcbd",
"type": "inject",
"z": "9624ddaf8e7b3698",
"name": "20秒毎",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "20",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "str",
"x": 640,
"y": 240,
"wires": [
[
"59b75511d3bb0aaa"
]
]
},
{
"id": "e58f52290cef7435",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 36",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 240,
"y": 80,
"wires": []
},
{
"id": "287b49bdf06d04da",
"type": "ui_ui_control",
"z": "9624ddaf8e7b3698",
"name": "",
"events": "all",
"x": 100,
"y": 100,
"wires": [
[
"13fdcb314bdb2b29",
"e58f52290cef7435"
]
]
},
{
"id": "90e66fce09272b50",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "id初期化",
"rules": [
{
"t": "set",
"p": "socketid",
"pt": "global",
"to": "demae0000000000",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 400,
"y": 200,
"wires": [
[
"f3d968583e2847bd",
"504973adb30b1a56",
"0865d69acac9245b"
]
]
},
{
"id": "8d17f7f04fa27519",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "set id",
"rules": [
{
"t": "set",
"p": "socketid",
"pt": "global",
"to": "socketid",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 410,
"y": 300,
"wires": [
[
"f3d968583e2847bd",
"139943774e4cd120"
]
]
},
{
"id": "729bd4a3291ee25d",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "set switch",
"rules": [
{
"t": "set",
"p": "switch",
"pt": "global",
"to": "payload",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 400,
"y": 540,
"wires": [
[
"b2a18a8c82a7f1cb"
]
]
},
{
"id": "c6dbb33518226fb1",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "set slider",
"rules": [
{
"t": "set",
"p": "slider",
"pt": "global",
"to": "payload",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 400,
"y": 720,
"wires": [
[
"eeee16370fe62739",
"19e298710e52f945"
]
]
},
{
"id": "da7b75a16f43986c",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "Switch制御",
"info": "",
"x": 100,
"y": 500,
"wires": []
},
{
"id": "bd0d0849d1eef2f5",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "Slider制御",
"info": "",
"x": 100,
"y": 700,
"wires": []
},
{
"id": "13fdcb314bdb2b29",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "lost検出",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "lost",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 240,
"y": 120,
"wires": [
[
"8778866f5540b29e",
"278ec74755d2d931"
]
]
},
{
"id": "8778866f5540b29e",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "切断忘れ",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 400,
"y": 140,
"wires": [
[
"90e66fce09272b50",
"8de94317fcf035e7"
]
]
},
{
"id": "2d29b5872f72f234",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "check id",
"property": "socketid",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "socketid",
"vt": "msg"
},
{
"t": "neq",
"v": "socketid",
"vt": "msg"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 240,
"y": 220,
"wires": [
[
"90e66fce09272b50",
"8de94317fcf035e7"
],
[
"0865d69acac9245b",
"711c442e587074ee"
]
]
},
{
"id": "0865d69acac9245b",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "clear",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 410,
"y": 260,
"wires": [
[
"59b75511d3bb0aaa"
]
]
},
{
"id": "4dee3c0539dc31f5",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "check id",
"func": "var mem_id = global.get(\"mem_id\");\nvar max = 10;\nvar num = 10;\nvar i;\nvar is_member = false;\n\n// confirm current number of member\nfor (i=0; i<max; i++){\n if (mem_id[i] == \"non\"){\n num = i;\n break;\n }\n}\n\n\n// check socketid registered or not\nfor (i=0; i<num; i++){\n if (msg.socketid == mem_id[i]){\n is_member = true;\n break;\n }\n}\n\nmsg.num = num;\nmsg.is_member = is_member;\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 240,
"y": 400,
"wires": [
[
"b43c421a968ba039"
]
]
},
{
"id": "b43c421a968ba039",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "member?",
"property": "is_member",
"propertyType": "msg",
"rules": [
{
"t": "true"
},
{
"t": "false"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 380,
"y": 400,
"wires": [
[
"5e001c2f7435054a",
"a364df582bdb65bd"
],
[
"133470df1e98dc54"
]
]
},
{
"id": "a5e3f4f6352e8f7c",
"type": "ui_ui_control",
"z": "9624ddaf8e7b3698",
"name": "認証へ",
"events": "change",
"x": 570,
"y": 460,
"wires": [
[]
]
},
{
"id": "21d1e93119832dc8",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "認証へ",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"tab\":\"認証画面\"}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 450,
"y": 460,
"wires": [
[
"a5e3f4f6352e8f7c"
]
]
},
{
"id": "5816be9c07043ada",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "store id",
"func": "var mem_id = global.get(\"mem_id\");\nvar max = 10;\nvar num = 10;\nvar i;\n\n// confirm current number of member\nfor (i=0; i<max; i++){\n if (mem_id[i] == \"non\"){\n num = i;\n break;\n }\n}\n\n// store socket id\nmem_id[num] = msg.socketid;\n\n// socketid registered\nglobal.set(\"mem_id\", mem_id);\n\nmsg.mem_num = num;\nmsg.mem_id = mem_id;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 500,
"y": 880,
"wires": [
[
"81d42cd238d23df4",
"1355945a196cd2ca"
]
]
},
{
"id": "59f8caa3b319d315",
"type": "ui_ui_control",
"z": "9624ddaf8e7b3698",
"name": "操作へ",
"events": "change",
"x": 630,
"y": 1000,
"wires": [
[]
]
},
{
"id": "a6edc64ef1ff368d",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "残念",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "認証できません",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 510,
"y": 960,
"wires": [
[
"2caa54e89853cf80",
"6a9c802414f3a28d"
]
]
},
{
"id": "bd25dcdf6fac48c5",
"type": "ui_form",
"z": "9624ddaf8e7b3698",
"name": "",
"label": "",
"group": "9258a40ced27eba1",
"order": 0,
"width": "6",
"height": "3",
"options": [
{
"label": "ユーザID",
"value": "username",
"type": "text",
"required": true,
"rows": null
},
{
"label": "パスワード",
"value": "password",
"type": "text",
"required": true,
"rows": null
}
],
"formValue": {
"username": "",
"password": ""
},
"payload": "",
"submit": "submit",
"cancel": "cancel",
"topic": "topic",
"topicType": "msg",
"splitLayout": "",
"className": "",
"x": 90,
"y": 940,
"wires": [
[
"41995ab37fecc948"
]
]
},
{
"id": "2caa54e89853cf80",
"type": "ui_toast",
"z": "9624ddaf8e7b3698",
"position": "top left",
"displayTime": "3",
"highlight": "",
"sendall": false,
"outputs": 0,
"ok": "OK",
"cancel": "",
"raw": false,
"className": "",
"topic": "",
"name": "通知",
"x": 630,
"y": 940,
"wires": []
},
{
"id": "c0f9d30a34e2a0d9",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "認証",
"info": "",
"x": 90,
"y": 900,
"wires": []
},
{
"id": "8018ae89832c410c",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "OK",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "認証できました",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 510,
"y": 920,
"wires": [
[
"2caa54e89853cf80",
"6a9c802414f3a28d"
]
]
},
{
"id": "278ec74755d2d931",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "check id",
"func": "var mem_id = global.get(\"mem_id\");\nvar max = 10;\nvar num = 10;\nvar own = 0;\nvar i, j;\n\n// confirm current number of member\nfor (i=0; i<max; i++){\n if (mem_id[i] == \"non\"){\n num = i;\n break;\n }\n}\n\n// check socketid registered or not\nfor (i=0; i<num; i++){\n if (msg.socketid == mem_id[i]){\n own = i;\n // shift socketid \n for (j = own; j < num; j++) {\n mem_id[j] = mem_id[j + 1];\n }\n break;\n }\n}\n\nglobal.set(\"mem_id\", mem_id);\n\nmsg.mem_id = mem_id;\nmsg.mem_num = own;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 400,
"y": 100,
"wires": [
[
"062f012abfb1cb7e"
]
]
},
{
"id": "062f012abfb1cb7e",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 37",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 540,
"y": 100,
"wires": []
},
{
"id": "f5fcc419c1256484",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 38",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 760,
"y": 880,
"wires": []
},
{
"id": "79a6c1643e7416cf",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "操作へ",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"tab\":\"操作テスト\"}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 510,
"y": 1000,
"wires": [
[
"59f8caa3b319d315"
]
]
},
{
"id": "133470df1e98dc54",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "満席",
"property": "num",
"propertyType": "msg",
"rules": [
{
"t": "neq",
"v": "10",
"vt": "num"
},
{
"t": "eq",
"v": "10",
"vt": "num"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 330,
"y": 480,
"wires": [
[
"21d1e93119832dc8"
],
[
"362480522c9df186"
]
]
},
{
"id": "6fe7d9d5b8edae46",
"type": "ui_toast",
"z": "9624ddaf8e7b3698",
"position": "top left",
"displayTime": "3",
"highlight": "",
"sendall": false,
"outputs": 0,
"ok": "OK",
"cancel": "",
"raw": false,
"className": "",
"topic": "",
"name": "満席",
"x": 570,
"y": 500,
"wires": []
},
{
"id": "362480522c9df186",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "満席",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "参加者が10名に達しました",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 450,
"y": 500,
"wires": [
[
"6fe7d9d5b8edae46"
]
]
},
{
"id": "81d42cd238d23df4",
"type": "link out",
"z": "9624ddaf8e7b3698",
"name": "OK",
"mode": "link",
"links": [
"ede040597906f361"
],
"x": 595,
"y": 820,
"wires": []
},
{
"id": "ede040597906f361",
"type": "link in",
"z": "9624ddaf8e7b3698",
"name": "link in 1",
"links": [
"81d42cd238d23df4"
],
"x": 115,
"y": 300,
"wires": [
[
"a364df582bdb65bd"
]
]
},
{
"id": "36adac1a0492a813",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "接続中",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "他の方が接続中です。しばらくお待ちください。",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 190,
"y": 360,
"wires": [
[
"ffd6107f94293144"
]
]
},
{
"id": "ffd6107f94293144",
"type": "ui_toast",
"z": "9624ddaf8e7b3698",
"position": "top right",
"displayTime": "3",
"highlight": "",
"sendall": false,
"outputs": 0,
"ok": "OK",
"cancel": "",
"raw": false,
"className": "",
"topic": "",
"name": "接続中",
"x": 310,
"y": 360,
"wires": []
},
{
"id": "3979fd3c78aa9a41",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "初期化",
"func": "// file for username and password\nvar user_name = \"/home/pi/Documents/userkanri.txt\";\n\n// log file name with full path\nvar log_name = \"/home/pi/Documents/user_log.csv\";\n\n// initialize routine # Don't touch!!\nvar id = [\"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\", \"non\"];\nvar user = new Array();\nglobal.set(\"user\", user);\nglobal.set(\"mem_id\", id);\nvar info = new Array();\nfor(var i=0; i<10; i++){\n info[i] = \"username\";\n}\nglobal.set(\"info\",info);\nglobal.set(\"login_time\",\"19991231125959\");\nglobal.set(\"login_user\",\"username\");\nglobal.set(\"log_name\",log_name);\nmsg.filename = user_name;\nglobal.set(\"log_data\",new Array());\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 210,
"y": 1100,
"wires": [
[
"f9c35b3fa0a4eb93"
]
]
},
{
"id": "ced2afe73aa72f86",
"type": "link out",
"z": "9624ddaf8e7b3698",
"name": "Initialize",
"mode": "link",
"links": [
"a9ffebea6e68125e"
],
"x": 205,
"y": 160,
"wires": []
},
{
"id": "a9ffebea6e68125e",
"type": "link in",
"z": "9624ddaf8e7b3698",
"name": "link in 2",
"links": [
"ced2afe73aa72f86"
],
"x": 125,
"y": 1100,
"wires": [
[
"3979fd3c78aa9a41"
]
]
},
{
"id": "f9c35b3fa0a4eb93",
"type": "file in",
"z": "9624ddaf8e7b3698",
"name": "userkanri.txt",
"filename": "filename",
"filenameType": "msg",
"format": "lines",
"chunk": false,
"sendError": false,
"encoding": "none",
"allProps": false,
"x": 350,
"y": 1100,
"wires": [
[
"cacc80e023a74043"
]
]
},
{
"id": "cacc80e023a74043",
"type": "csv",
"z": "9624ddaf8e7b3698",
"name": "",
"sep": ",",
"hdrin": true,
"hdrout": "none",
"multi": "one",
"ret": "\\n",
"temp": "",
"skip": "0",
"strings": true,
"include_empty_strings": "",
"include_null_values": "",
"x": 490,
"y": 1100,
"wires": [
[
"d9c0baa861008737"
]
]
},
{
"id": "d9c0baa861008737",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "username",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "hask",
"v": "username",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 260,
"y": 1140,
"wires": [
[
"9249c6f3cca45e5e"
]
]
},
{
"id": "9249c6f3cca45e5e",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "append",
"func": "var user = global.get(\"user\");\nvar len = user.length;\nuser[len] = new Array(msg.payload.username, msg.payload.password);\nglobal.set(\"user\",user);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 400,
"y": 1140,
"wires": [
[]
]
},
{
"id": "41995ab37fecc948",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "認証",
"func": "var user = global.get(\"user\");\nvar max = user.length;\nvar is_member = false;\n\n// check username & password\nfor (var i=0; i<max; i++){\n if (msg.payload.username == user[i][0] && msg.payload.password == user[i][1]){\n is_member = true;\n break;\n }\n}\nmsg.payload.is_member = is_member;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 210,
"y": 940,
"wires": [
[
"b11d379a01770491",
"b93eb0dc3d794cb5"
]
]
},
{
"id": "b11d379a01770491",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "",
"property": "payload.is_member",
"propertyType": "msg",
"rules": [
{
"t": "true"
},
{
"t": "false"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 330,
"y": 940,
"wires": [
[
"5816be9c07043ada",
"79a6c1643e7416cf",
"8018ae89832c410c"
],
[
"79a6c1643e7416cf",
"a6edc64ef1ff368d"
]
]
},
{
"id": "1355945a196cd2ca",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "記録",
"func": "var info = global.get(\"info\");\n\nvar num = msg.mem_num;\n\n// save login name\ninfo[num] = msg.payload.username;\n\nglobal.set(\"info\",info);\n\nmsg.payload = {\"socketid\":msg.mem_id[num], \"username\":info[num]};\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 630,
"y": 880,
"wires": [
[
"f5fcc419c1256484"
]
]
},
{
"id": "b8f656d397bc6038",
"type": "moment",
"z": "9624ddaf8e7b3698",
"name": "日時",
"topic": "",
"input": "",
"inputType": "date",
"inTz": "Asia/Tokyo",
"adjAmount": 0,
"adjType": "days",
"adjDir": "add",
"format": "YYYYMMDDHHmmss",
"locale": "ja-JP",
"output": "datetime",
"outputType": "msg",
"outTz": "Asia/Tokyo",
"x": 210,
"y": 1280,
"wires": [
[
"f065fb14d8154c01"
]
]
},
{
"id": "139943774e4cd120",
"type": "link out",
"z": "9624ddaf8e7b3698",
"name": "log in",
"mode": "link",
"links": [
"34c6bb2031b1235c"
],
"x": 535,
"y": 280,
"wires": []
},
{
"id": "34c6bb2031b1235c",
"type": "link in",
"z": "9624ddaf8e7b3698",
"name": "link in 3",
"links": [
"139943774e4cd120"
],
"x": 125,
"y": 1280,
"wires": [
[
"b8f656d397bc6038"
]
]
},
{
"id": "f065fb14d8154c01",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "log in",
"func": "var mem_id = global.get(\"mem_id\");\nvar info = global.get(\"info\");\nvar max = 10;\nvar num = 10;\nvar i;\n\n// confirm current number of member\nfor (i=0; i<max; i++){\n if (mem_id[i] == \"non\"){\n num = i;\n break;\n }\n}\n\n\n// check socketid registered or not\nfor (i=0; i<num; i++){\n if (msg.socketid == mem_id[i]){\n global.set(\"login_user\", info[i]);\n break;\n }\n}\n\nglobal.set(\"login_time\", msg.datetime);\n\nmsg.payload ={\"login_user\":info[i], \"socket_id\":msg.socketid, \"login_time\":msg.datetime};\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 330,
"y": 1280,
"wires": [
[
"9412d1f46ea1ed1d"
]
]
},
{
"id": "9412d1f46ea1ed1d",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 40",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 460,
"y": 1300,
"wires": []
},
{
"id": "8de94317fcf035e7",
"type": "link out",
"z": "9624ddaf8e7b3698",
"name": "log out",
"mode": "link",
"links": [
"8ef2970ce8b1474d"
],
"x": 555,
"y": 160,
"wires": []
},
{
"id": "8ef2970ce8b1474d",
"type": "link in",
"z": "9624ddaf8e7b3698",
"name": "link in 4",
"links": [
"8de94317fcf035e7"
],
"x": 125,
"y": 1340,
"wires": [
[
"e757ef1c674e0c60"
]
]
},
{
"id": "e757ef1c674e0c60",
"type": "moment",
"z": "9624ddaf8e7b3698",
"name": "日時",
"topic": "",
"input": "",
"inputType": "date",
"inTz": "Asia/Tokyo",
"adjAmount": 0,
"adjType": "days",
"adjDir": "add",
"format": "YYYYMMDDHHmmss",
"locale": "ja-JP",
"output": "datetime",
"outputType": "msg",
"outTz": "Asia/Tokyo",
"x": 210,
"y": 1340,
"wires": [
[
"35d86ceafebdd112"
]
]
},
{
"id": "35d86ceafebdd112",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "log out",
"func": "var login_user = global.get(\"login_user\");\nvar login_time = global.get(\"login_time\");\nvar socketid = msg.socketid;\nvar _switch = global.get(\"switch\");\nvar _slider = global.get(\"slider\");\n\nmsg.payload ={\"login_user\":login_user, \"socket_id\":socketid, \"login_time\":login_time, \"logout_time\":msg.datetime, \"switch\":_switch, \"slider\":_slider};\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 330,
"y": 1340,
"wires": [
[
"9412d1f46ea1ed1d",
"c08af49593b3018c"
]
]
},
{
"id": "6a9c802414f3a28d",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 41",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 760,
"y": 940,
"wires": []
},
{
"id": "b93eb0dc3d794cb5",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 42",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 320,
"y": 1000,
"wires": []
},
{
"id": "fa7be12cd3b493bf",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "初期化",
"info": "",
"x": 90,
"y": 1060,
"wires": []
},
{
"id": "2cf86b2057dff257",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "user",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "user",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 370,
"y": 1180,
"wires": [
[
"6abf84fad253dda2",
"f9e7153c0be5dd6d"
]
]
},
{
"id": "7642ea3289f4172b",
"type": "complete",
"z": "9624ddaf8e7b3698",
"name": "",
"scope": [
"f9c35b3fa0a4eb93"
],
"uncaught": false,
"x": 230,
"y": 1180,
"wires": [
[
"2cf86b2057dff257"
]
]
},
{
"id": "6abf84fad253dda2",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 39",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 620,
"y": 1140,
"wires": []
},
{
"id": "f9e7153c0be5dd6d",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "info",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "info",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 490,
"y": 1180,
"wires": [
[
"6abf84fad253dda2"
]
]
},
{
"id": "9ea3d49792f87d4c",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "ログデータ記録",
"info": "",
"x": 120,
"y": 1240,
"wires": []
},
{
"id": "bc5d36ccc92dfd92",
"type": "file",
"z": "9624ddaf8e7b3698",
"name": "write file",
"filename": "filename",
"filenameType": "msg",
"appendNewline": true,
"createDir": true,
"overwriteFile": "false",
"encoding": "none",
"x": 720,
"y": 1340,
"wires": [
[]
]
},
{
"id": "e41161d94530a0c7",
"type": "comment",
"z": "9624ddaf8e7b3698",
"name": "ログデータ参照",
"info": "",
"x": 120,
"y": 1400,
"wires": []
},
{
"id": "1d4fd9a53b236dd3",
"type": "inject",
"z": "9624ddaf8e7b3698",
"name": "ログ参照",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 100,
"y": 1440,
"wires": [
[
"a6dc347bdf54e1bf"
]
]
},
{
"id": "9ee76930aadc0625",
"type": "file in",
"z": "9624ddaf8e7b3698",
"name": "log read",
"filename": "filename",
"filenameType": "msg",
"format": "utf8",
"chunk": false,
"sendError": false,
"encoding": "none",
"allProps": false,
"x": 380,
"y": 1440,
"wires": [
[
"41f0e463dfea64ad"
]
]
},
{
"id": "537cfcf432aae7a2",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "file_name",
"rules": [
{
"t": "set",
"p": "filename",
"pt": "msg",
"to": "log_name",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 580,
"y": 1340,
"wires": [
[
"bc5d36ccc92dfd92",
"da4c8088816dab48"
]
]
},
{
"id": "a6dc347bdf54e1bf",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "file_name",
"rules": [
{
"t": "set",
"p": "filename",
"pt": "msg",
"to": "log_name",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 240,
"y": 1440,
"wires": [
[
"9ee76930aadc0625"
]
]
},
{
"id": "00ec3f7d482dbea8",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 43",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 660,
"y": 1520,
"wires": []
},
{
"id": "da4c8088816dab48",
"type": "debug",
"z": "9624ddaf8e7b3698",
"name": "debug 44",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 720,
"y": 1300,
"wires": []
},
{
"id": "c08af49593b3018c",
"type": "csv",
"z": "9624ddaf8e7b3698",
"name": "csv",
"sep": ",",
"hdrin": "",
"hdrout": "once",
"multi": "one",
"ret": "\\n",
"temp": "login_user,socket_id,login_time,logout_time,switch,slider",
"skip": "0",
"strings": true,
"include_empty_strings": "",
"include_null_values": "",
"x": 450,
"y": 1340,
"wires": [
[
"537cfcf432aae7a2"
]
]
},
{
"id": "41f0e463dfea64ad",
"type": "csv",
"z": "9624ddaf8e7b3698",
"name": "csv",
"sep": ",",
"hdrin": "",
"hdrout": "once",
"multi": "one",
"ret": "\\n",
"temp": "login_user,socket_id,login_time,logout_time,switch,slider",
"skip": "0",
"strings": true,
"include_empty_strings": "",
"include_null_values": "",
"x": 510,
"y": 1440,
"wires": [
[
"b5fc2f5a95f0e59f"
]
]
},
{
"id": "6d3de56e13dec0b1",
"type": "function",
"z": "9624ddaf8e7b3698",
"name": "配列",
"func": "var data = global.get(\"log_data\");\ndata.push(msg.payload);\nglobal.set(\"log_data\", data);\nmsg.payload = data;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 510,
"y": 1480,
"wires": [
[]
]
},
{
"id": "b5fc2f5a95f0e59f",
"type": "switch",
"z": "9624ddaf8e7b3698",
"name": "del",
"property": "payload.login_user",
"propertyType": "msg",
"rules": [
{
"t": "neq",
"v": "login_user",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 390,
"y": 1480,
"wires": [
[
"6d3de56e13dec0b1"
]
]
},
{
"id": "711c442e587074ee",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "使用中",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "他の方が使用中です。切断はできません。",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 150,
"y": 260,
"wires": [
[
"14146fd4a816d51b"
]
]
},
{
"id": "14146fd4a816d51b",
"type": "ui_toast",
"z": "9624ddaf8e7b3698",
"position": "top right",
"displayTime": "3",
"highlight": "",
"sendall": false,
"outputs": 0,
"ok": "OK",
"cancel": "",
"raw": false,
"className": "",
"topic": "",
"name": "使用中",
"x": 270,
"y": 260,
"wires": []
},
{
"id": "a739c7a734dfac5e",
"type": "complete",
"z": "9624ddaf8e7b3698",
"name": "",
"scope": [
"9ee76930aadc0625"
],
"uncaught": false,
"x": 270,
"y": 1520,
"wires": [
[
"570a1ffa2b23a7f1"
]
]
},
{
"id": "2beac260907d827c",
"type": "change",
"z": "9624ddaf8e7b3698",
"name": "出力",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "log_data",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 530,
"y": 1520,
"wires": [
[
"00ec3f7d482dbea8"
]
]
},
{
"id": "570a1ffa2b23a7f1",
"type": "delay",
"z": "9624ddaf8e7b3698",
"name": "1秒",
"pauseType": "delay",
"timeout": "1",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 410,
"y": 1520,
"wires": [
[
"2beac260907d827c"
]
]
},
{
"id": "c56c2f84eee38f59",
"type": "ui_group",
"name": "排他制御",
"tab": "b5de217d24b3769b",
"order": 2,
"disp": true,
"width": "6",
"collapse": false,
"className": ""
},
{
"id": "68a74b5e3cb81569",
"type": "ui_group",
"name": "ファイル保存",
"tab": "b5de217d24b3769b",
"order": 1,
"disp": true,
"width": "6",
"collapse": false,
"className": ""
},
{
"id": "9258a40ced27eba1",
"type": "ui_group",
"name": "認証",
"tab": "7be2d49e0eb0264b",
"order": 1,
"disp": true,
"width": "6",
"collapse": false,
"className": ""
},
{
"id": "b5de217d24b3769b",
"type": "ui_tab",
"name": "操作テスト",
"icon": "dashboard",
"order": 6,
"disabled": false,
"hidden": false
},
{
"id": "7be2d49e0eb0264b",
"type": "ui_tab",
"name": "認証画面",
"icon": "dashboard",
"disabled": false,
"hidden": false
}
]