- Since
-
- See also
-
数値データ、または1次元数値配列を送受信する型です。 double型で送受信されます。
コマンドライン
を実行し、数字を入力すると送信されます。(1つ入力するごとに改行してください)
オプションでclientやデータの名前を変更できます。 詳細は webcface-send のページを参照
送信
C++ Client::value からValueオブジェクトを作り、 Value::set() でデータを代入し、Client::sync()することで送信されます。
wcli.value("hoge").set(5);
wcli.value("fuga").set({1, 2, 3, 4, 5});
- Note
- 1.7 配列データは
std::vector<double>
だけでなく、std::arrayや生配列などstd::ranges::rangeに合うものならなんでも使えます。 要素の型はdoubleに変換可能ならなんでもokです。
set() の代わりに代入演算子(Value::operator=)でも同様のことができます。 また、 operator+= など、doubleやintの変数で使える各種演算子も使えます
1.11 valueに直接[]
(またはchild()
)で要素アクセスが可能です。 また、resize()で配列を初期化しpush_back()で追加する使い方もできます。
wcli.value("fuga").resize(5);
for(int i = 0; i < 5; i++){
wcli.value("fuga").push_back(i);
}
wcli.value("fuga")[3] = 100;
- C double型の単一の値は wcfValueSet, (2.0 wcfValueSetW)
wcfStatus wcfValueSet(wcfClient *wcli, const char *field, double value)
単一の値を送信する
Definition value.cc:111
配列データは wcfValueSetVecD, (2.0 wcfValueSetVecDW) double value[5] = {1, 2, 3, 4, 5};
wcfStatus wcfValueSetVecD(wcfClient *wcli, const char *field, const double *values, int size)
複数の値を送信する(doubleの配列)
Definition value.cc:117
で送信できます。
- JavaScript Client.value からValueオブジェクトを作り、 Value.set() でデータを代入し、Client.sync()することで送信されます。
wcli.value("hoge").set(5);
wcli.value("fuga").set([1, 2, 3, 4, 5]);
Python Client.value からValueオブジェクトを作り、 Value.set() でデータを代入し、Client.sync()することで送信されます。
wcli.value("hoge").set(5)
wcli.value("fuga").set([1, 2, 3, 4, 5])
2.0 数値型はfloatに変換可能なもの(SupportsFloat型)であればなんでもokです。(例えばnumpyの数値型なども使用可能です。)
- Note
- (serverが1.10以降の場合) データの名前を半角ピリオドから始めると、Entryが他クライアントに送信されなくなります。 (WebUI上に表示することなくデータを送ることができます)
半角ピリオド2つから始まる名前はwebcface内部の処理で利用する場合があるので使用しないでください。
Text、Funcなど他のデータ型についても同様です。
通信データについて
クライアントが送信したデータは、サーバーを経由して別のクライアントに送られます。 (Valueに限らず、これ以降説明する他のデータ型のfieldについても同様です。)
サーバー→クライアント間では、初期状態ではデータは送信されず、 クライアントがリクエストを送って初めてサーバーからデータが順次送られてくるようになります。
1.8 1.4.1 1.1.2 クライアント→サーバー間では、同じデータを繰り返しsetした場合は2回目以降はデータを送信しないことで通信量を削減しています。
基本的にクライアント→サーバーの方向にはすべてのデータが送信されるのに対し、サーバー→クライアントの方向には必要なデータのみを送信する設計になっていますが、これは前者はlocalhost(サーバーとクライアントが同じPC)のみで、後者はWi-FiやLANでも通信することを想定したものです。 (通信量は増えますがクライアント→サーバーのデータ送信をWi-FiやLAN経由で行うことも可能です)
- Note
- webcfaceのvalueは浮動小数型のみを扱いますが、値が整数だった場合シリアライズ時に自動的に整数型として送受信されるようなので、整数値やbool値を送りたい場合でも通信量を気にする必要はありません。(msgpack/msgpack-c#1017)
グループ化
Valueの名前を半角ピリオドで区切ると、WebUI上ではフォルダアイコンで表示されグループ化されて表示されます。
Valueに限らず他のデータ型 (View, Canvas2D, Image, Canvas3D, RobotModel) でも同様です。
- Note
- ROSのTopicではPointやTransformなど目的に応じてさまざまな型が用意されていますが、 WebCFaceではそういう場合はValueを複数用意して送信することを想定しています。
複数の値をまとめて送る
- Todo:
- Pythonの辞書型への対応は未実装
- JavaScript オブジェクトを渡すことができます。
wcli.value("a").set({
x: 1,
y: 2,
vec: [1, 2, 3],
a: {
a: 1,
b: 1,
},
});
/* 結果は以下のようになる
value("a.x") -> 1
value("a.y") -> 2
value("a.vec") -> {1, 2, 3}
value("a.a.a") -> 1
value("a.a.b") -> 1
*/
(ver1.11まで) C++でwebcface::Value::Dictを使った値のセット
webcface::Value::Dict オブジェクトを使うと複数の値をまとめて送ることができます。 これは構造体などのデータを送るときに使えます
struct A {
double x, y;
operator webcface::Value::Dict() const {
return {
{"x", x},
{"y", y},
{"vec", {1, 2, 3}},
{"a", {
{"a", 1},
{"b", 1},
}}
}
}
};
A a_instance;
wcli.value("a").set(a_instance);
受信
C++ Member::value() でValueクラスのオブジェクトが得られ、 Value::tryGet(), Value::tryGetVec() などで値のリクエストをするとともに受信した値を取得できます。
例えばfoo
というクライアントのhoge
という名前のデータを取得したい場合は次のようにします。
std::optional<double> hoge = wcli.member("foo").value("hoge").tryGet();
std::optional<std::vector<double>> hoge = wcli.member("foo").value("hoge").tryGetVec();
- 値をまだ受信していない場合 tryGet(), tryGetVec() はstd::nulloptを返し、そのデータのリクエストをサーバーに送ります。
- リクエストは
次にClient::sync()したときに 1.2自動的に別スレッドで送信されます。
- そのデータを受信した後(4-1. Clientを参照)、再度tryGet()することで値が得られます。
- Value::get(), Value::getVec() はstd::nulloptの代わりに0を返します。
- また、doubleやstd::vector<double> などの型にキャストすることでも同様に値が得られます。
1.7 Value::request() で明示的にリクエストを送信することもできます。
1.8 std::ostreamにValueを直接渡して表示することもできます。 まだ受信していない場合nullと表示されます。
std::cout << "hoge = " << wcli.member("foo").value("hoge") << std::endl;
グループ化したデータは送信時と同様child()を使っても要素を参照できます。
Value value(std::string_view field="") const
Definition field.cc:54
double get() const
値を返す
Definition value.h:196
Member member() const
Memberを返す
Definition field.cc:21
Field child(const SharedString &field) const
Definition field.cc:42
Member member() const
Memberを返す
Definition field.cc:21
1.11 送信時と同様、配列データはchild()または[]
を使ってもアクセスできます。 cpp double hoge = wcli.member("foo").value("hoge")[3].get();
- Warning
- 1.11 Valueオブジェクト同士を
==
, !=
で比較するとValueが参照するデータの名前が一致するかどうかで判定されます。 (Textなど他のデータ型でも同様です。)
- ver1.10まではdoubleにキャストされた上で値を比較していたので、異なる挙動になります。 値を比較したい場合は明示的にキャストするか
get()
などを呼んでください。
C wcfValueGetVecD, (2.0 wcfValueGetVecDW) で受信できます。
例えばfoo
というクライアントのhoge
という名前のデータを取得したい場合は次のようにします。
double value[5];
int size;
wcfStatus wcfValueGetVecD(wcfClient *wcli, const char *member, const char *field, double *values, int size, int *recv_size)
値を受信する
Definition value.cc:125
- sizeに受信した値の個数、valueに受信した値が入ります。
- 値をまだ受信していない場合
WCF_NOT_FOUND
2.0 WCF_NO_DATA
を返し、そのデータのリクエストをサーバーに送ります。
- そのデータを受信した後(4-1. Clientを参照)、再度wcfValueGetVecD()することで値が得られます。
1.7 1つの値のみを受信する場合は wcfValueGet, (2.0 wcfValueGetW) も使えます。 double型1つのみが受け取れる以外、動作はwcfValueGetVecDと同様です。
double value;
wcfStatus wcfValueGet(wcfClient *wcli, const char *member, const char *field, double *value)
値を受信する
Definition value.cc:135
- Note
- 1.7 member名に空文字列またはNULLを指定すると自分自身を指します。
JavaScript Member.value() でValueクラスのオブジェクトが得られ、 Value.tryGet(), Value.tryGetVec() などで値のリクエストをするとともに受信した値を取得できます。
例えばfoo
というクライアントのhoge
という名前のデータを取得したい場合は次のようにします。
const hoge: double | null = wcli.member("foo").value("hoge").tryGet();
const hoge: double[] | null = wcli.member("foo").value("hoge").tryGetVec();
- 値を受信していない場合 tryGet(), tryGetVec() はnullを返し、そのデータのリクエストをサーバーに送ります。
- リクエストは
次にClient.sync()したときに 1.1自動的に別スレッドで送信されます。
- そのデータを受信した後(4-1. Clientを参照)、再度tryGet()することで値が得られます。
- get(), getVec() はnullの代わりに0を返します。
1.1 Value.request()で明示的にリクエストを送信することもできます。
Python Member.value() でValueクラスのオブジェクトが得られ、 Value.try_get(), Value.try_get_vec() などで値のリクエストをするとともに受信した値を取得できます。
例えばfoo
というクライアントのhoge
という名前のデータを取得したい場合は次のようにします。
hoge = wcli.member("foo").value("hoge").try_get()
hoge = wcli.member("foo").value("hoge").try_get_vec()
- 値をまだ受信していない場合 try_get(), try_get_vec() はNoneを返し、そのデータのリクエストをサーバーに送ります。
- get(), getVec() はNoneの代わりに0を返します。
Value.request()で明示的にリクエストを送信することもできます。
グループ化したデータは送信時と同様child()を使っても要素を参照できます。
x = pos.
child(
"x").get();
y = pos.
child(
"y").get();
z = pos.
child(
"z").get();
時刻
- C++
Value::time() でその値が送信されたとき(そのMemberがsync()で送信したとき)の時刻が得られます。
1.7 Member::syncTime() に変更 (Textなど他のデータの送信時刻と共通です)
- C
- Since
- 2.0
wcfMemberSyncTime() でその値が送信されたとき(そのMemberがsync()で送信したとき)の時刻が得られます。 (Textなど他のデータの送信時刻と共通です)
- JavaScript
Value.time() でその値が送信されたとき(そのMemberがsync()で送信したとき)の時刻が得られます。
1.6 Member.syncTime() に変更 (Textなど他のデータの送信時刻と共通です)
- Python Member.sync_time() でその値が送信されたとき(そのMemberがsync()で送信したとき)の時刻が得られます。 (Textなど他のデータの送信時刻と共通です)
Entry
データ自体はすべて受信しなくても、データが存在するかどうか(他memberが送信しているかどうか)は取得することができます。
- Warning
- (serverが1.10以降の場合) 半角ピリオドから始まる名前のデータはEntryが送信されないため、 明示的に名前を指定して受信することはできても、以下の方法でデータが存在するかどうかを確認することはできません。
C++ Member::values() で そのMemberが送信しているvalueのリストが得られます
1.6 Member::valueEntries() に変更
Text, Func, View など他のデータ型に関しても同様に textEntries()
, funcEntries()
, viewEntries()
などで取得できます。
1.11 Field::valueEntries() でそのfield以下のvalueのみが得られます (Textなど他の型についても同様)
std::vector<webcface::Value> values = wcli.member("foo").field("pos").valueEntries();
2.1 Value::exists() でそのデータが送信されているかどうかを確認できます。 tryGet() と違い、データそのものを受信するリクエストは送られません。 他のデータ型に関しても同様に Text::exists()
, Func::exists()
, View::exists()
などが使えます。
C
- Since
- 2.0
wcfValueEntryList
, wcfValueEntryListW
にchar*の配列とサイズを渡すと、valueの一覧を取得できます。
const char *value_list[10];
int actual_value_num;
wcfStatus wcfValueEntryList(wcfClient *wcli, const char *member, const char **list, int size, int *field_num)
memberが公開しているValueのリストを得る
Definition member.cc:139
それぞれのvalue名の文字列は、 wcfClose() するまではfreeされません。
Text, Func, View など他のデータ型に関しても同様に wcfTextEntryList()
, wcfFuncEntryList()
, wcfViewEntryList()
などで取得できます。
JavaScript Member.values() でそのMemberが送信しているvalueのリストが得られます
for(const v of wcli.member("foo").values()){
// ...
}
Text, Func, View など他のデータ型に関しても同様に texts()
, funcs()
, views()
などで取得できます。
1.8 Value.exists() でそのデータが送信されているかどうかを確認できます。 tryGet() と違い、データそのものを受信するリクエストは送られません。 他のデータ型に関しても同様に Text.exists()
, Func.exists()
, View.exists()
などが使えます。
Python Member.values() で そのMemberが送信しているvalueのリストが得られます
1.1 Member.value_entries() に変更
for v in wcli.member("foo").value_entries():
Text, Func, View など他のデータ型に関しても同様に text_entries()
, func_entries()
, view_entries()
などで取得できます。
2.0 Value.exists() でそのデータが送信されているかどうかを確認できます。 try_get() と違い、データそのものを受信するリクエストは送られません。 他のデータ型に関しても同様に Text.exists()
, Func.exists()
, View.exists()
などが使えます。
ValueEntry イベント
他のメンバーが新しくデータを追加したときに呼び出されるコールバックを設定できます。
イベントの詳細な使い方はMemberEntryと同様です(Member のページを参照してください)。 このクライアントが接続する前から存在したデータについては start(), waitConnection() 時に一度に送られるので、 コールバックの設定はstart()より前に行うと良いです。
ValueEntryではデータの存在を知ることしかできません。 データの内容を取得するにはコールバックの中で改めてget()やrequest()を呼ぶか、 後述のValueChangeイベントを使ってください。
C++ 2.0 Member::onValueEntry() でコールバックを設定できます。 新しく追加されたValueの情報が引数に渡されます。
ver1.11以前では .onValueEntry().appendListener(...)
他のデータ型に関しても同様に onTextEntry()
, onFuncEntry()
, onViewEntry()
などが使えます。
- Note
- コールバックを設定する前から存在したデータについてはコールバックは呼び出されません。
- 2.0 Client::waitConnection()は接続時にサーバーに存在するデータすべてについてコールバックを呼んでからreturnします。
- すべてのデータに対してコールバックが呼ばれるようにしたい場合は、 Member名がわかっていれば
初回の Client::sync() Client::start() または waitConnection() 前に設定してください。
- すべてのメンバーのすべてのデータに対してコールバックが呼ばれるようにしたい場合は、 Client::onMemberEntry() イベントのコールバックの中で各種イベントを設定すればよいです。
C
- Since
- 2.0
wcfValueEntryEvent
, wcfValueEntryEventW
で引数に const char * 2つと void * をとる関数ポインタをコールバックとして設定できます。
新しく追加されたValueの名前が引数に渡されます。 void*引数には登録時に任意のデータのポインタを渡すことができます。(使用しない場合はNULLでよいです。)
void callback_value_entry(const char *member_name, const char *value_name, void *user_data_p) {
struct UserData *user_data = (struct UserData *)user_data_p;
}
struct UserData user_data = {...};
wcfStatus wcfValueEntryEvent(wcfClient *wcli, const char *member, wcfEventCallback2 callback, void *user_data)
Valueが追加された時のイベント
Definition member.cc:172
他のデータ型に関しても同様に wcfTextEntryEvent()
, wcfFuncEntryEvent()
, wcfViewEntryEvent()
などが使えます。
- Note
- コールバックを設定する前から存在したデータについてはコールバックは呼び出されません。
- wcfWaitConnection()は接続時にサーバーに存在するデータすべてについてコールバックを呼んでからreturnします。
- すべてのデータに対してコールバックが呼ばれるようにしたい場合は、 Member名がわかっていれば wcfStart() または wcfWaitConnection() 前に設定してください。
- すべてのメンバーのすべてのデータに対してコールバックが呼ばれるようにしたい場合は、 MemberEntryイベントのコールバックの中で各種イベントを設定すればよいです。
JavaScript Member.onValueEntry でコールバックを設定できます。 新しく追加されたValueの情報が引数に渡されます。
import { Value } from "webcface";
wcli.member("foo").onValueEntry.on((v: Value) => { /* ... */ });
他のデータ型に関しても同様に onTextEntry
, onFuncEntry
, onViewEntry
などが使えます。
- Note
- コールバックを設定する前から存在したデータについてはコールバックは呼び出されません。
- すべてのデータに対してコールバックが呼ばれるようにしたい場合は、 Member名がわかっていれば Client.start() 前に設定してください。
- すべてのメンバーのすべてのデータに対してコールバックが呼ばれるようにしたい場合は、 Client.onMemberEntry イベントのコールバックの中で各種イベントを設定すればよいです。
Python Member.on_value_entry() でコールバックを設定できます。 新しく追加されたValueの情報が引数に渡されます。
def value_entry(v: webcface.Value):
pass
wcli.member("foo").on_value_entry(value_entry)
- ver1.1以前では
on_value_entry.connect(...)
- 他のデータ型に関しても同様に
on_text_entry()
, on_func_entry()
, on_view_entry()
などが使えます。
- on_member_entryと同様、デコレータにすることもできます。
- Note
- コールバックを設定する前から存在したデータについてはコールバックは呼び出されません。
- 2.0 Client.wait_connection()は接続時にサーバーに存在するデータすべてについてコールバックを呼んでからreturnします。
- すべてのデータに対してコールバックが呼ばれるようにしたい場合は、 Member名がわかっていればClient.start() または wait_connection() 前に設定してください。
- すべてのメンバーのすべてのデータに対してコールバックが呼ばれるようにしたい場合は、 Client.on_member_entry() イベントのコールバックの中で各種イベントを設定すればよいです。
ValueChange イベント, onSync イベント
受信したデータが変化したときにコールバックを呼び出すことができます。 コールバックを設定するとget()やrequest()を呼ばなくても自動的にその値がリクエストされます。
また、データが変化したどうかに関わらずそのMemberがsync()したときにコールバックを呼び出したい場合は onSync が使えます。
イベントの詳細な使い方はonMemberEntryと同様です(Member のページを参照してください)。
C++ 2.0 Value::onChange(), Member::onSync() でコールバックを設定できます。
引数にはそれぞれそのValue自身,Member自身が渡されます。 (キャプチャでも同じことができるのでなくてもよい)
Memberを指すクラス
Definition member.h:22
- ver1.11以前は
value("hoge").appendListener(...)
, member("foo").onSync().appendListener(...)
です
- 1.7 引数を持たない関数もイベントのコールバックに設定可能です。
wcli.member("foo").value("hoge").onChange([](){ });
wcli.member("foo").onSync([](){ });
(ver1.11以前は appendListener())
すべてのデータを受信したい場合は ValueEntry イベントの中でonChangeを設定すると可能です。
});
});
});
const Member & onValueEntry(std::function< void(Value)> callback) const
valueが追加された時のイベント
Definition member.cc:18
const Value & onChange(std::function< void(Value)> callback) const
値が変化したときに呼び出されるコールバックを設定
Definition value.cc:57
- C
- Since
- 2.0
wcfValueChangeEvent
, wcfValueChangeEventW
で引数に const char * 2つと void * をとる関数ポインタをコールバックとして設定できます。 void*引数には登録時に任意のデータのポインタを渡すことができます。(使用しない場合はNULLでよいです。) void callback_value_change(const char *member_name, const char *value_name, void *user_data_p) {
double value[5];
int size;
}
struct UserData user_data = {...};
wcfStatus wcfValueChangeEvent(wcfClient *wcli, const char *member, const char *field, wcfEventCallback2 callback, void *user_data)
Valueが変化した時のイベント
Definition value.cc:143
JavaScript Value.on(), Member.onSync.on() などでコールバックを設定できます。
引数にはそれぞれそのValue自身,Member自身が渡されます。 (なくてもよい)
import { Member, Value } from "webcface";
wcli.member("foo").value("hoge").on((v: Value) => { /* ... */ });
wcli.member("foo").onSync.on((m: Member) => { /* ... */ });
例えば全Memberの全Valueデータを受信するには
wcli.onMemberEntry.on((m: Member) => {
m.onValueEntry.on((v: Value) => {
v.on((v: Value) => {
// ...
});
});
});
のようにすると可能です。
Python 2.0 Value.on_change(), Member.on_sync() でコールバックを設定できます。 引数にはそれぞれそのValue自身,Member自身が渡されます。
def value_change(v: webcface.Value):
pass
wcli.member("foo").value("hoge").on_change(value_change)
def synced(m: webcface.Member):
pass
wcli.member("foo").on_sync(synced)
すべてのデータを受信したい場合は ValueEntry イベントの中でonChangeを設定すると可能です。
@wcli.on_member_entry
def member_entry(m: Member):
@m.on_value_entry
def value_entry(v: Value):
@v.on_change
def on_change(v: Value):
pass
Python 〜ver1.1の仕様
pythonでは Value.signal プロパティがこのイベントのsignalを返します。
def value_change(v: webcface.Value):
pass
wcli.member("foo").value("hoge").signal.connect(value_change)
def synced(m: webcface.Member):
pass
wcli.member("foo").on_sync.connect(synced)