PD Agent

デフォルトパス

PD agent に関連するファイルのデフォルトパスは次の通りです。

PD agentに関連するファイルのデフォルトパス

パス名説明
/usr/sbin/pd_agent常駐実行オブジェクト(デーモン)
/lib/systemd/system/pd_agent.serviceSystemd Service ファイル
/etc/init.d/pd_agentRC ファイル
/var/webui/config/pd_agent.conf設定ファイル
/var/run/pd_agent.pidPID ファイル

設定ファイルの書式

構文

{
"agents": [
{
"enable": <bool値>,
"localname": "<デバイス番号>",
"bind": "<受信ソケット名>",
"push_to": "<送信先ソケット名>",
"buffer_size": <バッファサイズ>,
"channels": [
{
<channelsオブジェクト>
},
{
<channelsオブジェクト>
}
]
},
{
"enable": <bool値>,
"localname": "<デバイス番号>",
"bind": "<受信ソケット名>",
"push_to": "<送信先ソケット名>",
"buffer_size": <バッファサイズ>,
"channels": [
{
<channelsオブジェクト>
}
]
}
]
}

agents オブジェクト

キーデータ型説明
enable論理値デフォルト値は false.
localname文字列デバイスのローカル名(デバイス番号). (32byte)
bind文字列制御メッセージを受け取るソケット名. 文字列の先頭が '@' の場合は abstract namespace と解釈する. 空の場合は、デフォルト値 '@/pd_handler/<localname>.sock' が設定される. (MAXPATHLEN)
push_to文字列応答メッセージの送り先ソケット名. 文字列の先頭が '@' の場合は abstract namespace と解釈する. 空の場合は、デフォルト値 '@/pd_repeater/<localname>.sock' が設定される. (MAXPATHLEN)
buffer_size整数値データのバッファサイズ(byte). デフォルト値は 4096.
channelsJSON配列channels オブジェクト. 最大32 個まで設定可能.

channels オブジェクト

キーデータ型説明
name文字列チャンネルの名称. (32byte)
reply論理値'push to' キーに設定されるソケットに応答を返すか否かの設定. デフォルト値は true.
index文字列'exec' キーに指定される実行オブェクトの起動条件として評価される、JSON文字列データのキー. (32byte)
value文字列'exec' キーに指定される実行オブェクトの起動条件として評価される、JSON 文字列データの値. (32byte)
exec文字列'index' キーに設定されるキーと'value' キーに設定されるその値が、JSON文字列データに含まれている場合に実行される実行オブェクトもしくは Dynamic Link モジュール又は Lua 言語スクリプトのパス名のパス名. ファイル記述子が .so の場合は Dinamic Link モジュール、.lua の場合は Lua言語スクリプト、それ以外の場合は実行オブジェクトと見なされる. (MAXPATHLEN)
args文字列'exec' キーに設定される実行オブェクトに与える引数. 'exec' に指定されるパス名が Dynamic Link モジュールまたは Lua言語スクリプトの場合は無視されます. (1024byte)
lua_func文字列実行される Lua 言語スクリプト内の関数名. (64bye)

実行オブジェクトに継承される環境変数

受信データの JSON 文字列の内、起動条件の評価に用いたキーと値を含め、値が文字列か数値の場合は、これを環境変数に設定し実行オブジェクトに継承します。
また、 下流方向メッセージに記載される Cloud ID、受信データ(ペイロード) の MD5 ハッシュ値、受信データのヘッダ情報と PD Agent に設定されているデバイスのローカル名も合わせて環境変数に継承します。

実行オブジェクトに環境変数として継承されるパラメータ

環境変数名データ型説明
request_cloud_id整数値PD Repeater が便宜上割り当てている番号
request_sub_id整数値同一クラウドの複数サーバを利用している場合の識別子
request_header文字列PD Repeater から渡される受信データのヘッダ情報
request_payload文字列PD Repeater から渡される受信データ(ペイロード)
request_md5文字列PD Repeater から渡される受信データ(ペイロード) の MD5 ハッシュ値
agent_localname文字列'localname' キーに設定されているデバイスのローカル名(デバイス番号).
agent_bind文字列'bind' キーに設定されているデータを受け取ったソケット名.
agent_push_to文字列'push_to' キーに設定されている応答先ソケット名.
agent_buffer_size整数値'buffer_size' キーに設定されているデータのバッファサイズ.(byte)

Dynamic Link モジュール

Dynamic Link モジュールのサンプルコードを示します。
Dynamic Link モジュールは、dlopen()によって PD Agent に取り込まれます。dl_exec() が、execv() によって実行される外部の実行オブジェクトの代わりに呼び出される関数です。
dl_exec() の引数には、実行オブジェクトを実行する際に環境変数として継承される全てのパラメータを含みます。 JSONオブジェクトポインタ result が NULL の場合、応答メッセージの 'result' キーの値は 'done'となります。 dl_init() は PD Agent の起動時に、dl_fini() は停止時に一度だけ呼ばれる関数であり、必要が無ければサンプルコードのままとして下さい。
本サンプルコードは、/usr/share/pdhms/agent/dl_module.c としてインストールされています。

dl_module.c
/*
* Copyright (c) 2018 - 2020
* Plat'Home CO., LTD. <support@plathome.co.jp>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Plat'Home CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <jansson.h>
#ifdef __linux__
#include <lua5.3/lua.h>
#else
#include <lua.h>
#endif
#define N_CHANNEL 32
struct channel_t {
unsigned char reply; /* Enable replay or not. */
unsigned char objtype; /* 1 for dynamic link module. */
char name[32]; /* Name of chaanel */
char index[32]; /* Index of JSON string to be driven. */
char value[32]; /* Value of JSON string to be driven. */
char exec[MAXPATHLEN]; /* Pathname of dynamic link module. */
char lua_func[64]; /* Not use in dynamic link module. */
int argc; /* Not use in dynamic link module. */
char *argv[16]; /* Not use in dynamic link module. */
void *dl_handle; /* Handle on the global symbol object. */
lua_State *lua_state; /* Not use in dynamic link module. */
};
struct agent_t {
int num_ch; /* Total number of channels in device. */
unsigned char enable;
char localname[32]; /* Local Device name (number). */
char bind[MAXPATHLEN]; /* Pathname of UNIX domain socket to listen. */
size_t buffer_size; /* Buffer size of UNIX domain socket. */
char push_to[MAXPATHLEN]; /* Pathname of UNIX domain socket to send. */
struct channel_t *ch[N_CHANNEL]; /* Pointer to each channel. */
char *buf; /* message buffer for down stream. */
};
// Your own functions
/*
Your own initialize function : void dl_init()
It is called only once at startup.
Return value : none.
*/
void dl_init()
{
return;
}
/*
Your own finalize function : void dl_fini()
It is called only once at termination.
Return value : none.
*/
void dl_fini()
{
return;
}
/*
Your own exec function : int dl_exec()
JSON *result : Reply value for 'result' key of JSON.
struct agent_t *agent : See above structure declaration.
int ch_number : Channel number where Index and Value match.
json_t *json_obj : It stores all indexes and values contained in the payload of
the downstream message as Jansson C objects.
unsigned char cloud_id : Cloud Id.
unsigned char sub_id : Sub Cloud Id.
These are the indications from which cloud they have been sent.
char *rcv_header : Contain the header information of the down stream message.
char *rcv_payload : Contain the paylod of the down stream message.
char *hash : Hash value (MD5) of paylod of the down stream message.
Return value : must be 0 for normal, -1 for error.
*/
int dl_exec(json_t *result, struct agent_t *agent, int ch_number, json_t *json_obj,
unsigned char cloud_id, unsigned char sub_id,
char *rcv_header, char *rcv_payload, char *hash)
{
int rc;
char *tx_payload;
struct channel_t *ch;
ch = (struct channel_t *)agent->ch[ch_number];
pid_t pid;
// The method to obtain Index and value from json_obj is shown below.
/*
json_t *val;
const char *key;
val = json_object();
json_object_foreach(json_obj, key, val) {
if(json_is_string(val)) {
printf("%s", json_string_value(val));
}
else if(json_is_integer(val)) {
printf("%ld", json_integer_value(val));
}
else if(json_is_real(val)) {
printf("%lf", json_real_value(val));
}
}
*/
// Write your own process here.
// Set any value for 'result' key
json_object_set(result, "done", json_true());
json_object_set(result, "localname", json_string(agent->localname));
return(0);
}

Lua 言語スクリプト

Lua 言語スクリプトのサンプルコードを示します。
Lua 言語スクリプトは、luaL_dofile()によって PD Agent に取り込まれ、同スクリプトに含まれる関数の内、'lua_func' キーに指定された関数が実行されます。
指定された関数には、実行オブジェクトを実行する場合に環境変数として継承される全てのパラメータが継承(push)されます。
関数の戻り値 Stack1 は、正常終了であれば 0, 異常終了であれば -1 を返して下さい。
戻り値の Stack2 は、応答メッセージの 'result'キーに与えられる JSON 文字列を返して下さい。
本サンプルコードは、/usr/share/pdhms/agent/example.lua としてインストールされています。

example.lua
--
-- Copyright (c) 2018, 2019
-- Plat'Home CO., LTD. <support@plathome.co.jp>. All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
-- 3. Neither the name of the Plat'Home CO., LTD. nor the names of
-- its contributors may be used to endorse or promote products derived
-- from this software without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
-- Argument for lua function
-- string localname : Local Device name (number).
-- string bind : Pathname of UNIX domain socket to listen.
-- string push_to : Pathname of UNIX domain socket to send.
-- number buffer_size : Buffer size of UNIX domain socket.
-- number ch_number : Channel number where Index and Value match.
-- boolean reply : Enable replay or not.
-- string name : Name of chaanel.
-- string index : Index of JSON string to be driven.
-- string value : Value of JSON string to be driven.
-- number cloud_id : Cloud Id.
-- number sub_id : Sub Cloud Id.
-- These are the indications from which cloud they have been sent.
-- string rcv_header : Contain the header information of the down stream message.
-- string rcv_payload : Contain the paylod of the down stream message.
-- string hash : Hash value (MD5) of paylod of the down stream message.
-- Return value of lua function
-- Stack 1 : must be 0 for normal, -1 for error, will be get by lua_tointeger().
-- Stack 2 : any string for results, will be get by lua_tolstring().
function my_lua_func1(localname, bind, push_to, buffer_size, ch_number, reply,
name, index, value, cloud_id, sub_id, rcv_header, rcv_payload, hash)
fp = io.open("/tmp/my_lua_func1.txt", "w")
s = string.format("localname : %s\n", localname)
fp:write(s)
s = string.format("bind : %s\n", bind)
fp:write(s)
s = string.format("push_to : %s\n", push_to)
fp:write(s)
s = string.format("buffer_size : %d\n", buffer_size)
fp:write(s)
s = string.format("ch_number : %d\n", ch_number)
fp:write(s)
if (reply) then
_replay = "true"
else
_replay = "false"
end
s = string.format("reply : %s\n", _reply)
fp:write(s)
s = string.format("name : %s\n", name)
fp:write(s)
s = string.format("index : %s\n", index)
fp:write(s)
s = string.format("value : %s\n", value)
fp:write(s)
s = string.format("cloud_id : %d\n", cloud_id)
fp:write(s)
s = string.format("sub_id : %d\n", sub_id)
fp:write(s)
s = string.format("rcv_header : %s\n", rcv_header)
fp:write(s)
s = string.format("rcv_payload : %s\n", rcv_payload)
fp:write(s)
s = string.format("hash : %s\n", hash)
fp:write(s)
fp:close()
-- reply message in "result" keys.
result = string.format("{\"done\": true, \"localname\":\"%s\"}", localname)
return 0, result
end

応答メッセージ

'reply' キーがtrue の場合、PD Agent は'push to' に設定されるソケットに実行ステータスを JSON 文字列で返します。

実行コマンドを起動した :
{
"time": "timestamp", "reply_to": "md5", "result": "queuing",
"reason": "matched", "matched": {"key": "value"}
}
実行コマンドの実行に失敗した :
{
"time": "timestamp", "reply_to": "md5", "result": "faild",
"reason": "matched", "matched": {"key": "value"}
}
実行コマンドの実行を終了した :
{
"time": "timestamp", "reply_to": "md5", "result": "done",
"reason": "matched", "matched": {"key": "value"}
}
一致するキーと値が存在しない :
{
"time": "timestamp", "reply_to": "md5", "result": "not queuing",
"reason": "key and value not matched"
}
制御メッセージがJSON文字列でない :
{
"time": "timestamp", "reply_to": "md5", "result": "not queuing",
"reason": "not JSON form"
}

ここで、md5は、 下流方向メッセージに記載される制御メッセージのハッシュ値、{"key": "value"} は、一致した「判断キー」と「処理判断値」です。
実行ステータスは、実行オブジェクトもしくはシェルスクリプトを呼び出す execv() の戻り値であり、実行オブジェクトもしくはシェルスクリプトの処理結果を示すものではありません。 処理の完全性を求めるのであれば応答メッセージは実行オブジェクトもしくはシェルスクリプトから agent_push_to 環境変数で継承されるUNIXドメインソケットに返すようにして下さい。

Dynamic Link モジュール使用時で、dl_exec() の JSON 文字列ポインタ引数 result が NULL で無い場合、 実行終了時の 'result'キーの値は JSON 文字列ポインタ引数 result の値(JSON文字列)に置き換えられます。

Lua言語スクリプト使用時で、戻り値 Stack2 が NULL で無い場合、実行終了時の 'result'キーの値は、戻り値 Stack2 の値(JSON文字列)に置き換えられます。