blob: 794adda18765b9e566698c27e458b385e36e888a [file] [log] [blame]
// Copyright (C) 2024 Amlogic, Inc. All rights reserved.
//
// All information contained herein is Amlogic confidential.
//
// This software is provided to you pursuant to Software License
// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
// used only in accordance with the terms of this agreement.
//
// Redistribution and use in source and binary forms, with or without
// modification is strictly prohibited without prior written permission
// from Amlogic.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 COPYRIGHT
// OWNER OR CONTRIBUTORS 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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <semaphore.h>
#include <time.h>
#include <thread>
#include <string>
#include <iostream>
#include <chrono>
#include "alg_lib/include/iva/iva_wisense_ppd.hpp"
extern "C" {
#include "csi_lib/aml_csi.h"
}
static int cnt = 0;
static int motion_status = -1;
static WiSenseIn g_csi_buffer;
static WiSenseIn *g_csi_detail = &g_csi_buffer;
static aai_iva_wisense_ppd_handle_t iva_wisense_ppd_handle;
static aai_iva_wisense_ppd_output_t wi_out_ret;
static aai_iva_wisense_ppd_input_t wi_in;
static aai_iva_wisense_ppd_mlevel_t mlevel;
static aai_iva_wisense_ppd_param_t params;
static std::string g_ctimes = "";
static volatile bool keep_running = true;
static sem_t semaphore;
/*print different colors*/
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
/*
copy csi to WiSenseIn struct,when get csi about 20 packets, send them to algorithm api
*/
void csi_cb(unsigned char *csi_data, int csi_data_lean) {
csi_stream *c = (csi_stream *)csi_data;
if (keep_running) {
if (cnt < 20) {
g_csi_detail->time_stamp[cnt] = c->time_stamp;
g_csi_detail->rssi[cnt][0] = c->rssi[0];
g_csi_detail->rssi[cnt][1] = c->rssi[1];
g_csi_detail->bw[cnt] = static_cast<int>((unsigned char)c->bw);
g_csi_detail->ntx[cnt] = c->ntx;
g_csi_detail->channel[cnt] = c->channel;
g_csi_detail->protocol_mode[cnt] = c->protocol_mode;
memcpy(g_csi_detail->csi[cnt], c->csi, 4 * 1024);
cnt++;
if (cnt == 20) {
sem_post(&semaphore);
}
}
}
}
void csi_data_collection_start(void)
{
int interval = 50;
int period = 0;
csi_enable_debug(0);
ping_start(NULL, 50);
csi_register_data_recv_func(NULL, csi_cb);
csi_set_config(NULL, interval, 1);
csi_set_filter(0, 0, 0, 0, NULL, NULL,0, NULL);
csi_start(&period);
return;
}
void csi_data_collection_end(void)
{
csi_stop(NULL);
ping_stop();
}
/*
* @brief If you want to turn on the light when motion is wisense detected,
* you can define WISENSE_LED_ACTION macro and specify the gpio num on your board.
* */
void wisense_led_init(void)
{
#if WISENSE_LED_ACTION
system("echo 449 > /sys/class/gpio/export");
system("echo out > /sys/class/gpio/gpio449/direction");
#endif
}
/*
* @brief If you want to turn on the light when wisense motion is detected,
* you can define WISENSE_LED_ACTION macro and specify the gpio num on your board.
* */
void wisense_led_set(int value)
{
#if WISENSE_DEBUG
std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(
std::chrono::system_clock::now().time_since_epoch()
);
std::cout << ms.count()/100 << std::endl;
#endif
std::cout << "--->motion status is " << value << std::endl;
#if WISENSE_LED_ACTION
if (value) {
system("echo 1 > /sys/class/gpio/gpio449/value"); // Red led
else
system("echo 0 > /sys/class/gpio/gpio449/value"); // Green led
#endif
}
void update_current_time(void) {
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
std::time_t t = std::chrono::system_clock::to_time_t(now_ms);
std::tm *now_tm = std::localtime(&t);
char buffer[100];
std::strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", now_tm);
g_ctimes = buffer;
}
void* wisense_processing_thread(void* arg)
{
while (keep_running) {
sem_wait(&semaphore);
if (cnt >= 20) {
cnt = 0;
update_current_time();
wi_in.wisenseIn = g_csi_detail;
aai_iva_wisense_ppd_detect(iva_wisense_ppd_handle, wi_in, wi_out_ret, params);
motion_status = wi_out_ret.motion_status;
wisense_led_set(motion_status);
switch (wi_out_ret.motion_class) {
case 1:
std::cout << RED << "Motion class is 1. Large human activity in close range[TX/RX] at " << g_ctimes << "\033[0m\n";
break;
case 2:
std::cout << MAGENTA << "Motion class is 2. Human activity at " << g_ctimes << "\033[0m\n";
break;
case 3:
std::cout << GREEN << "Motion class is 3. Human activity at " << g_ctimes << "\033[0m\n";
break;
case 4:
std::cout << GREEN << "Motion class is 4. Lightweight motion. Human activity at " << g_ctimes << "\033[0m\n";
break;
case 5:
std::cout << GREEN << "Motion class is 5. Lightweight motion. Human activity at " << g_ctimes << "\033[0m\n";
break;
default:
std::cout << YELLOW << "Motion class is 0, No person activity detect at " << g_ctimes << "\033[0m\n";
break;
}
}
}
return NULL;
}
int main(int argc, char** argv)
{
int opt;
int mlevel = 4;
while ((opt = getopt(argc, argv, "l:")) != -1) {
switch (opt)
{
case 'l':
mlevel = atoi(optarg);
break;
default:
break;
}
}
sem_init(&semaphore, 0, 0);
wisense_led_init();
csi_data_collection_start();
iva_wisense_ppd_handle = aai_iva_wisense_ppd_init(params);
if (iva_wisense_ppd_handle != NULL) {
params.e_mlevel = static_cast<aai_iva_wisense_ppd_mlevel_t>(mlevel);
aai_iva_wisense_ppd_param_set(iva_wisense_ppd_handle, params);
std::thread wisense_thread(wisense_processing_thread, nullptr);
wisense_thread.join();
}
csi_data_collection_end();
if (iva_wisense_ppd_handle != NULL) {
aai_iva_wisense_ppd_deinit(iva_wisense_ppd_handle);
}
sem_destroy(&semaphore);
return 0;
}