Add inference snapshot notify client
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
#include "snapshot_notify.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int g_snapshot_fd = -1;
|
||||
static struct sockaddr_in g_snapshot_addr;
|
||||
static unsigned long g_notify_seq = 0;
|
||||
|
||||
static void set_reason(char *reason, int reason_size, const char *text)
|
||||
{
|
||||
if (reason && reason_size > 0) {
|
||||
snprintf(reason, reason_size, "%s", text ? text : "unknown");
|
||||
}
|
||||
}
|
||||
|
||||
static int json_escape(char *out, int out_size, const char *in)
|
||||
{
|
||||
if (!out || out_size <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int used = 0;
|
||||
const char *src = in ? in : "";
|
||||
for (const char *p = src; *p; ++p) {
|
||||
const char *rep = NULL;
|
||||
char tmp[7];
|
||||
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
rep = "\\\\";
|
||||
break;
|
||||
case '"':
|
||||
rep = "\\\"";
|
||||
break;
|
||||
case '\b':
|
||||
rep = "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
rep = "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
rep = "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
rep = "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
rep = "\\t";
|
||||
break;
|
||||
default:
|
||||
if ((unsigned char)*p < 0x20) {
|
||||
snprintf(tmp, sizeof(tmp), "\\u%04x", (unsigned char)*p);
|
||||
rep = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (rep) {
|
||||
int len = strlen(rep);
|
||||
if (used + len >= out_size) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(out + used, rep, len);
|
||||
used += len;
|
||||
} else {
|
||||
if (used + 1 >= out_size) {
|
||||
return -1;
|
||||
}
|
||||
out[used++] = *p;
|
||||
}
|
||||
}
|
||||
out[used] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snapshot_notify_init(void)
|
||||
{
|
||||
if (g_snapshot_fd >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_snapshot_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (g_snapshot_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 20000;
|
||||
setsockopt(g_snapshot_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
|
||||
memset(&g_snapshot_addr, 0, sizeof(g_snapshot_addr));
|
||||
g_snapshot_addr.sin_family = AF_INET;
|
||||
g_snapshot_addr.sin_port = htons(SNAPSHOT_NOTIFY_DEFAULT_PORT);
|
||||
if (inet_pton(AF_INET, SNAPSHOT_NOTIFY_DEFAULT_HOST, &g_snapshot_addr.sin_addr) != 1) {
|
||||
close(g_snapshot_fd);
|
||||
g_snapshot_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void snapshot_notify_close(void)
|
||||
{
|
||||
if (g_snapshot_fd >= 0) {
|
||||
close(g_snapshot_fd);
|
||||
g_snapshot_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int snapshot_notify_send(const snapshot_notify_event_t *event, char *reason, int reason_size)
|
||||
{
|
||||
if (!event) {
|
||||
set_reason(reason, reason_size, "invalid_event");
|
||||
return -1;
|
||||
}
|
||||
if (snapshot_notify_init() != 0) {
|
||||
set_reason(reason, reason_size, "socket_init_failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char camera_id[256];
|
||||
char rtsp[1024];
|
||||
char label[256];
|
||||
if (json_escape(camera_id, sizeof(camera_id), event->camera_id) != 0 ||
|
||||
json_escape(rtsp, sizeof(rtsp), event->rtsp) != 0 ||
|
||||
json_escape(label, sizeof(label), event->label) != 0) {
|
||||
set_reason(reason, reason_size, "json_escape_failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long notify_id = ++g_notify_seq;
|
||||
char notify_id_text[32];
|
||||
snprintf(notify_id_text, sizeof(notify_id_text), "%lu", notify_id);
|
||||
|
||||
char payload[2048];
|
||||
int n = snprintf(payload, sizeof(payload),
|
||||
"{\"notify_id\":\"%s\",\"camera_id\":\"%s\",\"rtsp\":\"%s\",\"ts\":%ld,\"frame\":%lld,"
|
||||
"\"ccid\":%d,\"label\":\"%s\",\"confidence\":%.3f,"
|
||||
"\"box\":[%d,%d,%d,%d]}",
|
||||
notify_id_text,
|
||||
camera_id,
|
||||
rtsp,
|
||||
event->ts,
|
||||
event->frame,
|
||||
event->ccid,
|
||||
label,
|
||||
event->confidence,
|
||||
event->box_left,
|
||||
event->box_top,
|
||||
event->box_right,
|
||||
event->box_bottom);
|
||||
if (n <= 0 || n >= (int)sizeof(payload)) {
|
||||
set_reason(reason, reason_size, "payload_too_large");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t sent = sendto(g_snapshot_fd, payload, n, 0,
|
||||
(struct sockaddr *)&g_snapshot_addr,
|
||||
sizeof(g_snapshot_addr));
|
||||
if (sent != n) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "send_failed_%d", errno);
|
||||
set_reason(reason, reason_size, buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char ack[128];
|
||||
ssize_t got = recv(g_snapshot_fd, ack, sizeof(ack) - 1, 0);
|
||||
if (got <= 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
set_reason(reason, reason_size, "ack_timeout");
|
||||
} else {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "ack_failed_%d", errno);
|
||||
set_reason(reason, reason_size, buf);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ack[got] = '\0';
|
||||
char expected_ack[64];
|
||||
snprintf(expected_ack, sizeof(expected_ack), "OK %s", notify_id_text);
|
||||
if (strncmp(ack, expected_ack, strlen(expected_ack)) == 0) {
|
||||
set_reason(reason, reason_size, "ok");
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_reason(reason, reason_size, ack);
|
||||
return -1;
|
||||
}
|
||||
Reference in New Issue
Block a user