#!/usr/bin/php -q $callback, "ttype" => $ttype, "msgtype" => $msgtype, "dtype" => $dtype]; $this->__Callbacks[] = $cb; } function execute($can, $msg) { $unhandled = true; foreach ($this->__Callbacks as $cb) { if ($msg['msgtype'] == $cb['msgtype'] && $msg['ttype'] == $cb['ttype'] && $msg['dtype'] == $cb['dtype']) { call_user_func($cb['callback'], $can, $msg); $unhandled = false; } } if ($unhandled) { echo "Unhandled msg" . PHP_EOL; } return $unhandled; } } function raw_dinet_time($can, $msg) { $time = $msg['msg']; echo __FUNCTION__ . " (" . strval($time) .") ". date("M d Y H:i:s", $time / 1000) . PHP_EOL; } function raw_device_uid($can, $msg) { global $deviceUID; echo __FUNCTION__ . PHP_EOL; $len = strlen($deviceUID); echo "device:uid: $deviceUID (len: $len)" . PHP_EOL; $rep = [ 'dst_id' => $msg['src_id'], 'msgtype' => DI_CAN_MSGTYPE_RAW, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dtype' => DI_CAN_RAW_DTYPE_DEVICE_UID, 'ptype' => DI_CAN_PTYPE_STRING, 'msg' => $deviceUID ]; di_can_send($can, $rep); } function raw_project_id($can, $msg) { global $projectID; echo __FUNCTION__ . PHP_EOL; echo "project:id: $projectID" . PHP_EOL; $rep = [ 'dst_id' => $msg['src_id'], 'msgtype' => DI_CAN_MSGTYPE_RAW, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dtype' => DI_CAN_RAW_DTYPE_PROJECT_ID, 'ptype' => DI_CAN_PTYPE_U32, 'msg' => intval($projectID) ]; di_can_send($can, $rep); } function raw_connection_state($can, $msg) { echo __FUNCTION__ . " " . strval($msg['msg']). PHP_EOL; } function net_heartbeat($can, $msg) { echo __FUNCTION__ . " " . bin2hex($msg['msg']) . PHP_EOL; } function net_node_uid($can, $msg) { echo __FUNCTION__ . " " . $msg['msg'] . PHP_EOL; } function net_heartbeat_publish($can, $msg) { $msg = [ 'msgtype' => DI_CAN_MSGTYPE_NET, 'ttype' => DI_CAN_TRANSFERTYPE_PUBLISH, 'dst_id' => DI_CAN_NODEID_BROADCAST, 'dtype' => DI_CAN_NET_DTYPE_HEARTBEAT, 'ptype' => DI_CAN_PTYPE_STRUCT, 'msg' => hex3bin("0201") // DEVICE, PASSIVE ]; di_can_send($can, $msg); } function rpc_sensor_publish($can, $uid, $value) { $msgpack = msgpack_pack([[ "uid" => $uid, "value" => $value, "time" => mstime() ]]); $msg = [ 'msgtype' => DI_CAN_MSGTYPE_RPC, 'ttype' => DI_CAN_TRANSFERTYPE_PUBLISH, 'dst_id' => DI_CAN_NODEID_BROADCAST, 'dtype' => DI_RPC_TYPE_SENSOR_DATA, 'ptype' => DI_CAN_PTYPE_MSGPACK, 'msg' => $msgpack ]; di_can_send($can, $msg); } function net_discover($can, $msg) { echo __FUNCTION__ . " " . strval($msg['msg']). PHP_EOL; $rep = [ 'msgtype' => DI_CAN_MSGTYPE_NET, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dst_id' => $msg['src_id'], 'dtype' => DI_CAN_NET_DTYPE_DISCOVER, 'ptype' => DI_CAN_PTYPE_STRUCT, 'msg' => hex2bin("0201") // DEVICE, PASSIVE ]; di_can_send($can, $rep); } function rpc_device_ping($can, $msg) { echo __FUNCTION__ . PHP_EOL; $rep = [ 'dst_id' => $msg['src_id'], 'msgtype' => DI_CAN_MSGTYPE_RPC, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dtype' => DI_RPC_TYPE_DEVICE_PING ]; di_can_send($can, $rep); } function rpc_device_info($can, $msg) { echo __FUNCTION__ . PHP_EOL; $rep = [ 'dst_id' => $msg['src_id'], 'msgtype' => DI_CAN_MSGTYPE_RPC, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dtype' => DI_RPC_TYPE_DEVICE_INFO, 'ptype' => DI_CAN_PTYPE_MSGPACK, 'msg' => msgpack_pack([[ "type" => "tws-3000-dum", "version" => "0.1.2-fakedevice", "revision" => 1337]] ) ]; di_can_send($can, $rep); } function rpc_config_info($can, $msg) { echo __FUNCTION__ . PHP_EOL; $rep = [ 'dst_id' => $msg['src_id'], 'msgtype' => DI_CAN_MSGTYPE_RPC, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dtype' => DI_RPC_TYPE_CONFIG_INFO, 'ptype' => DI_CAN_PTYPE_MSGPACK, 'msg' => msgpack_pack([]) ]; di_can_send($can, $rep); } function rpc_sensor_info($can, $msg) { echo __FUNCTION__ . PHP_EOL; $rep = [ 'dst_id' => $msg['src_id'], 'msgtype' => DI_CAN_MSGTYPE_RPC, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dtype' => DI_RPC_TYPE_SENSOR_INFO, 'ptype' => DI_CAN_PTYPE_MSGPACK, 'msg' => msgpack_pack([]) ]; di_can_send($can, $rep); } function rpc_notify_info($can, $msg) { echo __FUNCTION__ . PHP_EOL; $rep = [ 'dst_id' => $msg['src_id'], 'msgtype' => DI_CAN_MSGTYPE_RPC, 'ttype' => DI_CAN_TRANSFERTYPE_REPLY, 'dtype' => DI_RPC_TYPE_NOTIFY_INFO, 'ptype' => DI_CAN_PTYPE_MSGPACK, 'msg' => msgpack_pack([]) ]; di_can_send($can, $rep); } $registry = new CANMsgRegistry(); /** RAW */ $registry->register("raw_dinet_time", DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_MSGTYPE_RAW, DI_CAN_RAW_DTYPE_DINET_TIME); $registry->register("raw_device_uid", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_RAW, DI_CAN_RAW_DTYPE_DEVICE_UID); $registry->register("raw_project_id", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_RAW, DI_CAN_RAW_DTYPE_PROJECT_ID); $registry->register("raw_connection_state", DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_MSGTYPE_RAW, DI_CAN_RAW_DTYPE_CONNECTION_STATE); /** NET */ $registry->register("net_heartbeat", DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_MSGTYPE_NET, DI_CAN_NET_DTYPE_HEARTBEAT); $registry->register("net_discover", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_NET, DI_CAN_NET_DTYPE_DISCOVER); $registry->register("net_node_uid", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_NET, DI_CAN_NET_DTYPE_NODE_UID); $registry->register("net_node_uid", DI_CAN_TRANSFERTYPE_REPLY, DI_CAN_MSGTYPE_NET, DI_CAN_NET_DTYPE_NODE_UID); /** RPC */ $registry->register("rpc_device_ping", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_RPC, DI_RPC_TYPE_DEVICE_PING); $registry->register("rpc_device_info", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_RPC, DI_RPC_TYPE_DEVICE_INFO); $registry->register("rpc_config_info", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_RPC, DI_RPC_TYPE_CONFIG_INFO); $registry->register("rpc_sensor_info", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_RPC, DI_RPC_TYPE_SENSOR_INFO); $registry->register("rpc_notify_info", DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_MSGTYPE_RPC, DI_RPC_TYPE_NOTIFY_INFO); if (!isset($argv[1])) { echo "argument expected" . PHP_EOL; echo "usage: di-candump " . PHP_EOL; exit(1); } $fd = di_can_open($argv[1]); if ($fd === null) { echo "error opening: '".$argv[1]."'" . PHP_EOL; echo "usage: di-can-fakedevice " . PHP_EOL; exit(1); } di_can_set_nodeid($fd, $deviceUID); function mstime() { return round(microtime(true) * 1000); } /** * Sensor 666 triangle */ $next = 0; $value = 0; $up = true; function publish_sensor_uid_666_triangle($fd) { global $next; global $value; global $up; if (mstime() >= $next) { rpc_sensor_publish($fd, 666, $value); $next = mstime() + 500; if ($up) $value += 1; else $value -= 1; if ($value == 4) $up = false; else if ($value == -4) $up = true; } } declare(ticks=1); // php magic to make signal handler work... function sig_handler($signo) { echo "Got signal $signo...\n"; di_can_close($GLOBALS['fd']); unset($GLOBALS['fd']); switch ($signo) { case SIGINT: exit; break; case SIGTERM: exit; break; case SIGHUP: break; default: } } pcntl_signal(SIGTERM, "sig_handler"); pcntl_signal(SIGHUP, "sig_handler"); pcntl_signal(SIGINT, "sig_handler"); while(true) { $msg = di_can_recv($fd); if ($msg === null) continue; $t = microtime(true); $micro = sprintf("%06d",($t - floor($t)) * 1000000); $d = new DateTime( date('Y-m-d H:i:s.'.$micro, $t) ); $timestr = $d->format("Y-m-d H:i:s.u"); // Convert src and dst node id to hex $src_id = dechex($msg['src_id']); $src_id = '0x' . str_pad($src_id, 8, "0", STR_PAD_LEFT); $dst_id = dechex($msg['dst_id']); $dst_id = '0x' . str_pad($dst_id, 8, "0", STR_PAD_LEFT); echo "[" . $timestr . "] ($src_id -> $dst_id) "; $registry->execute($fd, $msg); }