#include <opencv2/opencv.hpp>
#include <beyond/beyond.h>
#include <beyond/plugin/peer_nn_plugin.h>
+#include <beyond/plugin/discovery_dns_sd_plugin.h>
#include "task_runner.h"
#include "task_options.h"
+#define DEBUG false
+
static enum beyond_handler_return stdin_handler(beyond_object_h object, int type, void *data)
{
if ((type & BEYOND_EVENT_TYPE_ERROR) == BEYOND_EVENT_TYPE_ERROR) {
// command line options
constexpr char RunAsOpt[] = "run";
constexpr char UseConfigOpt[] = "use_config";
+
+// for edge
+constexpr char EdgeNameOpt[]= "service_name";
constexpr char EdgeStorageOpt[] = "storage";
constexpr char EdgePortOpt[] = "port";
+
+// for device
constexpr char DeviceModelFileOpt[] = "model_file";
constexpr char DeviceImagePathOpt[] = "image_path";
constexpr char DeviceOutputLabelsOpt[] = "output_labels";
const int IMG_HEIGHT = 100;
const int IMG_WIDTH = 100;
-enum class Mode {
+enum class TargetMode {
UNKNOWN,
DEVICE,
- EDGE
+ EDGE,
+ EDGELIST,
};
class ImageClassification : public TaskRunner {
, rep_port_(3001)
, service_port_(3000)
, use_config_(0)
- , mode_(Mode::UNKNOWN)
+ , discovered_(0)
+ , target_(TargetMode::UNKNOWN)
, session_h_(nullptr)
, evt_h_(nullptr)
, inference_h_(nullptr)
, peer_h_(nullptr)
+ , discovery_h_(nullptr)
{
}
~ImageClassification() override
{
+ if (discovery_h_ != nullptr) {
+ beyond_discovery_deactivate(discovery_h_);
+ beyond_discovery_destroy(discovery_h_);
+ }
+
if (peer_h_ != nullptr) {
if (inference_h_ != nullptr) {
beyond_inference_remove_peer(inference_h_, peer_h_);
private:
bool ReadytoRun();
bool CheckCmdline();
- bool CheckDevice();
- bool LoadLabels(std::vector<std::string> *labels);
- bool CheckEdge();
+ bool CheckDevice_InferencePeer();
+ bool CheckDevice_Discovery();
+ bool LoadLabels();
+ bool CheckEdge_Peer();
+ bool CheckEdge_Discovery();
bool Run();
bool RunMobilenet();
bool RunEdge();
+ bool PrintResult();
+
+ static int DeviceDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data);
+ static int EdgeDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data);
- std::string target_mode_;
+ std::string run_as_;
+ std::string service_name_;
std::string storage_;
std::string model_file_path_;
std::string input_image_path_;
unsigned short rep_port_;
unsigned short service_port_;
int use_config_;
+ int discovered_;
- Mode mode_;
+ TargetMode target_;
+ std::vector<std::string> image_labels_;
beyond_session_h session_h_;
beyond_event_handler_h evt_h_;
beyond_inference_h inference_h_;
beyond_peer_h peer_h_;
+ beyond_discovery_h discovery_h_;
};
std::vector<Option> ImageClassification::GetOptions()
{
std::vector<Option> opt_list = {
- Option::CreateOption(RunAsOpt, &target_mode_,
- "Target to run as ('device' or 'edge')"),
+ Option::CreateOption(RunAsOpt, &run_as_,
+ "Target to run as ('device', 'edge' or 'edgelist')"),
Option::CreateOption(UseConfigOpt, &use_config_,
- "Peer configuration On:1, Off:0 (default: 0)"),
+ "Peer configuration On:1, Off:0 (default: 0)\n"),
Option::CreateOption(DeviceModelFileOpt, &model_file_path_,
"Path to tflite model file"),
Option::CreateOption(DeviceImagePathOpt, &input_image_path_,
"Request Port (default: 3000)"),
Option::CreateOption(DeviceRepPortOpt, &rep_port_,
"Response Port (default: 3001)\n"),
+ Option::CreateOption(EdgeNameOpt, &service_name_,
+ "Service name to be registered"),
Option::CreateOption(EdgeStorageOpt, &storage_,
"Path to storage for edge service"),
Option::CreateOption(EdgePortOpt, &service_port_,
bool result = CheckCmdline();
if (result == true) {
- switch (mode_) {
- case Mode::DEVICE:
- result = CheckDevice();
+ switch (target_) {
+ case TargetMode::DEVICE:
+ result = CheckDevice_InferencePeer();
break;
- case Mode::EDGE:
- result = CheckEdge();
+ case TargetMode::EDGE:
+ result = (CheckEdge_Peer() & CheckEdge_Discovery());
break;
- case Mode::UNKNOWN:
+ case TargetMode::EDGELIST:
+ result = CheckDevice_Discovery();
+ break;
+ case TargetMode::UNKNOWN:
default:
result = false;
break;
{
bool result = true;
- if (target_mode_.compare("device") == 0) {
- mode_ = Mode::DEVICE;
- } else if (target_mode_.compare("edge") == 0) {
- mode_ = Mode::EDGE;
+ if (run_as_.compare("device") == 0) {
+ target_ = TargetMode::DEVICE;
+ } else if (run_as_.compare("edge") == 0) {
+ target_ = TargetMode::EDGE;
+ } else if (run_as_.compare("edgelist") == 0) {
+ target_ = TargetMode::EDGELIST;
} else {
printf("Target is incorrect\n");
result = false;
}
- if (mode_ == Mode::DEVICE) {
+ if (target_ == TargetMode::DEVICE) {
std::ifstream model_check(model_file_path_);
if (model_check.good() == false) {
printf("Incorrect Model file\n");
result = false;
}
+ model_check.close();
+
std::ifstream input_check(input_image_path_);
if (input_check.good() == false) {
printf("Incorrect Input Image file\n");
result = false;
}
+ input_check.close();
+
std::ifstream output_check(output_label_path_);
if (output_check.good() == false) {
printf("Incorrect Output Label file\n");
result = false;
}
+ output_check.close();
+ if (LoadLabels() == false) {
+ printf("Failed to load labels\n");
+ }
if (result == true) {
printf("------------------------------\n");
- printf("Target : %s \n", target_mode_.c_str());
+ printf("Target : %s \n", run_as_.c_str());
printf("Model File : %s \n", model_file_path_.c_str());
printf("Input Image File : %s \n", input_image_path_.c_str());
printf("Output Label File : %s \n", output_label_path_.c_str());
printf("Peer name : %s (configuration: %d) \n", peer_name_.c_str(), use_config_);
printf("------------------------------\n");
}
- } else if (mode_ == Mode::EDGE) {
+ } else if (target_ == TargetMode::EDGE) {
std::ifstream storage_check(storage_);
if (storage_check.good() == false) {
printf("Incorrect storage path %s\n", storage_.c_str());
if (result == true) {
printf("------------------------------\n");
- printf("Target : %s \n", target_mode_.c_str());
+ printf("Target : %s \n", run_as_.c_str());
+ printf("Service Name : %s \n", service_name_.c_str());
printf("Storage Path : %s \n", storage_.c_str());
printf("Service Port : %d \n", service_port_);
printf("Peer name : %s (configuration: %d) \n", peer_name_.c_str(), use_config_);
return result;
}
-bool ImageClassification::CheckDevice()
+bool ImageClassification::CheckDevice_InferencePeer()
{
- bool result = true;
-
session_h_ = beyond_session_create(0, 0);
if (session_h_ == nullptr) {
printf("Failed to create session handle\n");
int ret = beyond_peer_set_event_callback(
peer_h_, [](beyond_peer_h peer, struct beyond_event_info *event, void *data) -> int {
- printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+ if (DEBUG == true) {
+ printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+ }
return BEYOND_HANDLER_RETURN_RENEW;
},
nullptr);
return false;
}
- return result;
+ return true;
}
-bool ImageClassification::LoadLabels(std::vector<std::string> *labels)
+bool ImageClassification::CheckDevice_Discovery()
{
- if (labels == nullptr) {
+ int ret;
+ const char *s_device_argv = BEYOND_PLUGIN_DISCOVERY_DNS_SD_NAME;
+ beyond_argument discovery_option = {
+ .argc = 1,
+ .argv = (char **)&s_device_argv,
+ };
+
+ discovery_h_ = beyond_discovery_create(session_h_, &discovery_option);
+
+ ret = beyond_discovery_set_event_callback(discovery_h_, DeviceDiscoveryCallback, static_cast<void *>(this));
+ if (ret < 0) {
+ printf("Failed beyond_discovery_set_event_callback : %d\n", ret);
+ return false;
+ }
+
+ ret = beyond_discovery_activate(discovery_h_);
+ if (ret < 0) {
+ printf("Failed beyond_discovery_activate : %d\n", ret);
return false;
}
+
+ return true;
+}
+
+bool ImageClassification::LoadLabels()
+{
std::ifstream stream(output_label_path_.c_str());
if (!stream) {
return false;
}
+
+ image_labels_.clear();
+
std::string line;
while (std::getline(stream, line)) {
- labels->push_back(line);
+ image_labels_.push_back(line);
}
return true;
}
-bool ImageClassification::CheckEdge()
+bool ImageClassification::CheckEdge_Peer()
{
- bool result = true;
+ int ret;
session_h_ = beyond_session_create(0, 0);
if (session_h_ == nullptr) {
if (use_config_ == 1) {
// NO implementation yet for service config
struct beyond_config config = { 's', nullptr };
- if (beyond_peer_configure(peer_h_, &config) < 0) {
- printf("Failed to config input\n");
- result = false;
+ ret = beyond_peer_configure(peer_h_, &config);
+ if (ret < 0) {
+ printf("Failed to config input : %d\n", ret);
+ return false;
}
}
.free_memory = 0llu,
.free_storage = 0llu,
};
- if (beyond_peer_set_info(peer_h_, &info) < 0) {
- printf("Failed to set peer info\n");
+ ret = beyond_peer_set_info(peer_h_, &info);
+ if (ret < 0) {
+ printf("Failed to set peer info : %d\n", ret);
return false;
}
- int ret = beyond_peer_set_event_callback(
+ ret = beyond_peer_set_event_callback(
peer_h_, [](beyond_peer_h peer, struct beyond_event_info *event, void *data) -> int {
- printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+ if (DEBUG == true) {
+ printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+ }
return BEYOND_HANDLER_RETURN_RENEW;
},
nullptr);
if (ret < 0) {
- printf("peer_set_event_callback : %d", ret);
+ printf("Failed peer_set_event_callback : %d\n", ret);
+ return false;
}
// create connection & prepare communication channel
ret = beyond_peer_activate(peer_h_);
if (ret < 0) {
- printf("beyond_peer_activate : %d\n", ret);
- result = false;
+ printf("Failed beyond_peer_activate : %d\n", ret);
+ return false;
}
- return result;
+ return true;
}
+bool ImageClassification::CheckEdge_Discovery()
+{
+ int ret;
+
+ const char *service = service_name_.c_str();
+ const char *s_edge_argv[] = {
+ BEYOND_PLUGIN_DISCOVERY_DNS_SD_NAME,
+ BEYOND_PLUGIN_DISCOVERY_DNS_SD_ARGUMENT_SERVER,
+ BEYOND_PLUGIN_DISCOVERY_DNS_SD_ARGUMENT_NAME,
+ const_cast<char *>(service)
+ };
+ beyond_argument discovery_option = {
+ .argc = sizeof(s_edge_argv) / sizeof(char *),
+ .argv = const_cast<char **>(s_edge_argv)
+ };
+
+ discovery_h_ = beyond_discovery_create(session_h_, &discovery_option);
+ if (discovery_h_ == nullptr) {
+ printf("Failed beyond_discovery_create\n");
+ return false;
+ }
+
+ // TODO. key,val should be passed by cmdline
+ ret = beyond_discovery_set_item(discovery_h_, "uuid", "1234", 4);
+ if (ret < 0) {
+ printf("Failed beyond_discovery_set_item : %d\n", ret);
+ return false;
+ }
+
+ ret = beyond_discovery_set_event_callback(discovery_h_, EdgeDiscoveryCallback, nullptr);
+ if (ret < 0) {
+ printf("Failed beyond_discovery_set_event_callback : %d\n", ret);
+ return false;
+ }
+
+ ret = beyond_discovery_activate(discovery_h_);
+ if (ret < 0) {
+ printf("Failed beyond_discovery_activate : %d\n", ret);
+ return false;
+ }
+
+ return true;
+}
bool ImageClassification::Run()
{
bool result = true;
- switch (mode_) {
- case Mode::DEVICE:
- result = RunMobilenet();
+ switch (target_) {
+ case TargetMode::DEVICE:
break;
- case Mode::EDGE:
- result = RunEdge();
+ case TargetMode::EDGE:
+ case TargetMode::EDGELIST:
break;
- case Mode::UNKNOWN:
+ case TargetMode::UNKNOWN:
default:
result = false;
break;
cv::Mat inputImage = cv::imread(input_image_path_, cv::IMREAD_COLOR);
if (inputImage.empty()) {
- printf("Failed to read image");
+ printf("Failed to read image\n");
return false;
}
cv::Mat resizedImage;
// print label if invoke success
if (result == true) {
- beyond_tensor_h out_tensor_h;
- int count; // dummy: Could not get count in this api beyond_inference_get_output
- if (beyond_inference_get_output(inference_h_, &out_tensor_h, &count) < 0) {
- printf("Failed beyond_inference_get_output\n");
- return false;
- }
+ result = PrintResult();
+ }
- beyond_tensor *tensors = BEYOND_TENSOR(out_tensor_h);
- if ((tensors[0].type != BEYOND_TENSOR_TYPE_UINT8) ||
- (tensors[0].size != OUTPUT_LABELS_NUM)) {
- printf("incorrect output( type : %d, size : %d)\n", tensors[0].type, tensors[0].size);
- printf("expected result( type : %d, size : %d)\n", BEYOND_TENSOR_TYPE_UINT8, OUTPUT_LABELS_NUM);
- }
+ return result;
+}
- uint8_t max_score = 0;
- uint8_t scores[OUTPUT_LABELS_NUM];
- int index = -1;
+bool ImageClassification::PrintResult()
+{
+ beyond_tensor_h out_tensor_h;
+ int count; // dummy: Could not get count in this api beyond_inference_get_output
+ if (beyond_inference_get_output(inference_h_, &out_tensor_h, &count) < 0) {
+ printf("Failed beyond_inference_get_output\n");
+ return false;
+ }
- memcpy(&scores, tensors[0].data, tensors[0].size);
+ beyond_tensor *tensors = BEYOND_TENSOR(out_tensor_h);
+ if ((tensors[0].type != BEYOND_TENSOR_TYPE_UINT8) ||
+ (tensors[0].size != OUTPUT_LABELS_NUM)) {
+ printf("incorrect output( type : %d, size : %d)\n", tensors[0].type, tensors[0].size);
+ printf("expected result( type : %d, size : %d)\n", BEYOND_TENSOR_TYPE_UINT8, OUTPUT_LABELS_NUM);
+ }
- for (int i = 0; i < tensors[0].size; i++) {
- if (scores[i] > 0 && scores[i] > max_score) {
- index = i;
- max_score = scores[i];
- }
- }
+ uint8_t max_score = 0;
+ uint8_t scores[OUTPUT_LABELS_NUM];
+ int index = -1;
+ int loaded = image_labels_.size();
- if (index == -1) {
- printf("Failed to get label from output\n");
- }
+ memcpy(&scores, tensors[0].data, tensors[0].size);
- std::vector<std::string> image_labels;
- if (LoadLabels(&image_labels) == false) {
- printf("Failed to load labels\n");
+ for (int i = 0; i < tensors[0].size; i++) {
+ if (scores[i] > 0 && scores[i] > max_score) {
+ index = i;
+ max_score = scores[i];
}
+ }
- printf("\n%s\n", image_labels[index].c_str());
+ beyond_inference_unref_tensor(out_tensor_h);
- beyond_inference_unref_tensor(out_tensor_h);
+ if ((index == -1) ||
+ (loaded < index)) {
+ printf("Failed to get label from output\n");
+ return false;
}
- beyond_session_run(session_h_, 10, -1, -1);
+ printf("\n%s\n", image_labels_[index].c_str());
- return result;
+ return true;
}
bool ImageClassification::RunEdge()
return result;
}
+int ImageClassification::DeviceDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data)
+{
+ if ((event->type & BEYOND_EVENT_TYPE_ERROR) == BEYOND_EVENT_TYPE_ERROR) {
+ return BEYOND_HANDLER_RETURN_CANCEL;
+ }
+
+ if (DEBUG == true) {
+ printf("Discovery event callback for 0x%.8X (%p)\n", event->type, event->data);
+ }
+
+ auto info = static_cast<beyond_peer_info *>(event->data);
+ if (info == nullptr) {
+ return BEYOND_HANDLER_RETURN_CANCEL;
+ }
+
+ if (data == nullptr) {
+ return BEYOND_HANDLER_RETURN_CANCEL;
+ }
+ auto _this = static_cast<ImageClassification *>(data);
+
+ switch (event->type) {
+ case BEYOND_EVENT_TYPE_DISCOVERY_DISCOVERED:
+ _this->discovered_++;
+ printf("[%d] ", _this->discovered_);
+
+ printf("name: %s , ", info->name);
+ printf("host: %s , ", info->host);
+ printf("port: %d , ", info->port[0]);
+ printf("uuid: %s\n", info->uuid);
+ break;
+ case BEYOND_EVENT_TYPE_DISCOVERY_REMOVED:
+ printf("service %s is removed\n", info->name ? info->name : "unknown");
+ break;
+ default:
+ break;
+ }
+
+ return BEYOND_HANDLER_RETURN_RENEW;
+}
+
+int ImageClassification::EdgeDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data)
+{
+ if ((event->type & BEYOND_EVENT_TYPE_ERROR) == BEYOND_EVENT_TYPE_ERROR) {
+ return BEYOND_HANDLER_RETURN_CANCEL;
+ }
+
+ if (DEBUG == true) {
+ printf("Discovery event callback for 0x%.8X (%p)\n", event->type, event->data);
+ }
+
+ auto info = static_cast<char *>(event->data);
+ if (info == nullptr) {
+ return BEYOND_HANDLER_RETURN_CANCEL;
+ }
+
+ if (event->type == BEYOND_EVENT_TYPE_DISCOVERY_REGISTERED) {
+ printf("service %s is registered\n", info);
+ }
+
+ return BEYOND_HANDLER_RETURN_RENEW;
+}
+
std::unique_ptr<TaskRunner> CreateTaskRunner()
{
return std::unique_ptr<TaskRunner>(new ImageClassification());