/*
* This file is part of MotionPlus.
*
* MotionPlus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MotionPlus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MotionPlus. If not, see .
*
*/
#include "motionplus.hpp"
#include "conf.hpp"
#include "logger.hpp"
#include "util.hpp"
#include "webu.hpp"
#include "webu_ans.hpp"
#include "webu_common.hpp"
#include "webu_json.hpp"
#include "dbse.hpp"
void cls_webu_json::parms_item(cls_config *conf, int indx_parm)
{
size_t indx;
std::string parm_orig, parm_val, parm_list, parm_enable;
parm_orig = "";
parm_val = "";
parm_list = "";
if (app->conf->webcontrol_parms < WEBUI_LEVEL_LIMITED) {
parm_enable = "false";
} else {
parm_enable = "true";
}
conf->edit_get(config_parms[indx_parm].parm_name
, parm_orig, config_parms[indx_parm].parm_cat);
for (indx = 0; indx < parm_orig.length(); indx++) {
if ((parm_orig[indx] == '"') ||
(parm_orig[indx] == '\\')) {
parm_val += '\\';
}
parm_val += parm_orig[indx];
}
if (config_parms[indx_parm].parm_type == PARM_TYP_INT) {
webua->resp_page +=
"\"" + config_parms[indx_parm].parm_name + "\"" +
":{" +
" \"value\":" + parm_val +
",\"enabled\":" + parm_enable +
",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) +
",\"type\":\"" + conf->type_desc(config_parms[indx_parm].parm_type) + "\"" +
"}";
} else if (config_parms[indx_parm].parm_type == PARM_TYP_BOOL) {
if (parm_val == "on") {
webua->resp_page +=
"\"" + config_parms[indx_parm].parm_name + "\"" +
":{" +
" \"value\":true" +
",\"enabled\":" + parm_enable +
",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) +
",\"type\":\"" + conf->type_desc(config_parms[indx_parm].parm_type) + "\""+
"}";
} else {
webua->resp_page +=
"\"" + config_parms[indx_parm].parm_name + "\"" +
":{" +
" \"value\":false" +
",\"enabled\":" + parm_enable +
",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) +
",\"type\":\"" + conf->type_desc(config_parms[indx_parm].parm_type) + "\"" +
"}";
}
} else if (config_parms[indx_parm].parm_type == PARM_TYP_LIST) {
conf->edit_list(config_parms[indx_parm].parm_name
, parm_list, config_parms[indx_parm].parm_cat);
webua->resp_page +=
"\"" + config_parms[indx_parm].parm_name + "\"" +
":{" +
" \"value\": \"" + parm_val + "\"" +
",\"enabled\":" + parm_enable +
",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) +
",\"type\":\"" + conf->type_desc(config_parms[indx_parm].parm_type) + "\"" +
",\"list\":" + parm_list +
"}";
} else {
webua->resp_page +=
"\"" + config_parms[indx_parm].parm_name + "\"" +
":{" +
" \"value\":\"" + parm_val + "\"" +
",\"enabled\":" + parm_enable +
",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) +
",\"type\":\""+ conf->type_desc(config_parms[indx_parm].parm_type) + "\"" +
"}";
}
}
void cls_webu_json::parms_one(cls_config *conf)
{
int indx_parm;
bool first;
std::string response;
indx_parm = 0;
first = true;
while ((config_parms[indx_parm].parm_name != "") ) {
if (config_parms[indx_parm].webui_level == WEBUI_LEVEL_NEVER) {
indx_parm++;
continue;
}
if (first) {
first = false;
webua->resp_page += "{";
} else {
webua->resp_page += ",";
}
/* Allow limited parameters to be read only to the web page */
if ((config_parms[indx_parm].webui_level >
app->conf->webcontrol_parms) &&
(config_parms[indx_parm].webui_level > WEBUI_LEVEL_LIMITED)) {
webua->resp_page +=
"\""+config_parms[indx_parm].parm_name+"\"" +
":{" +
" \"value\":\"\"" +
",\"enabled\":false" +
",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) +
",\"type\":\""+ conf->type_desc(config_parms[indx_parm].parm_type) + "\"";
if (config_parms[indx_parm].parm_type == PARM_TYP_LIST) {
webua->resp_page += ",\"list\":[\"na\"]";
}
webua->resp_page +="}";
} else {
parms_item(conf, indx_parm);
}
indx_parm++;
}
webua->resp_page += "}";
}
void cls_webu_json::parms_all()
{
int indx_cam;
webua->resp_page += "{";
webua->resp_page += "\"default\": ";
parms_one(app->conf);
for (indx_cam=0; indx_camcam_cnt; indx_cam++) {
webua->resp_page += ",\"cam" +
std::to_string(app->cam_list[indx_cam]->device_id) + "\": ";
parms_one(app->cam_list[indx_cam]->conf);
}
webua->resp_page += "}";
}
void cls_webu_json::cameras_list()
{
int indx_cam;
std::string response;
std::string strid;
ctx_dev *cam;
webua->resp_page += "{\"count\" : " + std::to_string(app->cam_cnt);
for (indx_cam=0; indx_camcam_cnt; indx_cam++) {
cam = app->cam_list[indx_cam];
strid =std::to_string(cam->device_id);
webua->resp_page += ",\"" + std::to_string(indx_cam) + "\":";
if (cam->conf->device_name == "") {
webua->resp_page += "{\"name\": \"camera " + strid + "\"";
} else {
webua->resp_page += "{\"name\": \"" + cam->conf->device_name + "\"";
}
webua->resp_page += ",\"id\": " + strid;
webua->resp_page += ",\"url\": \"" + webua->hostfull + "/" + strid + "/\"} ";
}
webua->resp_page += "}";
}
void cls_webu_json::categories_list()
{
int indx_cat;
std::string catnm_short, catnm_long;
webua->resp_page += "{";
indx_cat = 0;
while (indx_cat != PARM_CAT_MAX) {
if (indx_cat != 0) {
webua->resp_page += ",";
}
webua->resp_page += "\"" + std::to_string(indx_cat) + "\": ";
catnm_long = webua->app->conf->cat_desc((enum PARM_CAT)indx_cat, false);
catnm_short = webua->app->conf->cat_desc((enum PARM_CAT)indx_cat, true);
webua->resp_page += "{\"name\":\"" + catnm_short + "\",\"display\":\"" + catnm_long + "\"}";
indx_cat++;
}
webua->resp_page += "}";
}
void cls_webu_json::config()
{
webua->resp_type = WEBUI_RESP_JSON;
webua->resp_page += "{\"version\" : \"" VERSION "\"";
webua->resp_page += ",\"cameras\" : ";
cameras_list();
webua->resp_page += ",\"configuration\" : ";
parms_all();
webua->resp_page += ",\"categories\" : ";
categories_list();
webua->resp_page += "}";
}
void cls_webu_json::movies_list()
{
int indx;
std::string response;
char fmt[PATH_MAX];
lst_movies movielist;
it_movies m_it;
p_lst *lst = &webu->wb_actions->params_array;
p_it it;
for (it = lst->begin(); it != lst->end(); it++) {
if (it->param_name == "movies") {
if (it->param_value == "off") {
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, "Movies via webcontrol disabled");
webua->resp_page += "{\"count\" : 0} ";
webua->resp_page += ",\"device_id\" : ";
webua->resp_page += std::to_string(webua->cam->device_id);
webua->resp_page += "}";
return;
} else {
break;
}
}
}
app->dbse->movielist_get(webua->cam->device_id, &movielist);
webua->resp_page += "{";
indx = 0;
for (m_it = movielist.begin(); m_it != movielist.end(); m_it++){
if (m_it->found == true) {
if ((m_it->movie_sz/1000) < 1000) {
snprintf(fmt,PATH_MAX,"%.1fKB"
,((double)m_it->movie_sz/1000));
} else if ((m_it->movie_sz/1000000) < 1000) {
snprintf(fmt,PATH_MAX,"%.1fMB"
,((double)m_it->movie_sz/1000000));
} else {
snprintf(fmt,PATH_MAX,"%.1fGB"
,((double)m_it->movie_sz/1000000000));
}
webua->resp_page += "\""+ std::to_string(indx) + "\":";
webua->resp_page += "{\"name\": \"";
webua->resp_page += m_it->movie_nm + "\"";
webua->resp_page += ",\"size\": \"";
webua->resp_page += std::string(fmt) + "\"";
webua->resp_page += ",\"date\": \"";
webua->resp_page += std::to_string(m_it->movie_dtl) + "\"";
webua->resp_page += ",\"time\": \"";
webua->resp_page += m_it->movie_tmc + "\"";
webua->resp_page += ",\"diff_avg\": \"";
webua->resp_page += std::to_string(m_it->diff_avg) + "\"";
webua->resp_page += ",\"sdev_min\": \"";
webua->resp_page += std::to_string(m_it->sdev_min) + "\"";
webua->resp_page += ",\"sdev_max\": \"";
webua->resp_page += std::to_string(m_it->sdev_max) + "\"";
webua->resp_page += ",\"sdev_avg\": \"";
webua->resp_page += std::to_string(m_it->sdev_avg) + "\"";
webua->resp_page += "}";
webua->resp_page += ",";
indx++;
}
}
webua->resp_page += "\"count\" : " + std::to_string(indx);
webua->resp_page += ",\"device_id\" : ";
webua->resp_page += std::to_string(webua->cam->device_id);
webua->resp_page += "}";
}
void cls_webu_json::movies()
{
int indx_cam, indx_req;
webua->resp_type = WEBUI_RESP_JSON;
webua->resp_page += "{\"movies\" : ";
if (webua->cam == NULL) {
webua->resp_page += "{\"count\" :" + std::to_string(app->cam_cnt);
for (indx_cam=0; indx_camcam_cnt; indx_cam++) {
webua->cam = app->cam_list[indx_cam];
webua->resp_page += ",\""+ std::to_string(indx_cam) + "\":";
movies_list();
}
webua->resp_page += "}";
webua->cam = NULL;
} else {
indx_req = -1;
for (indx_cam=0; indx_camcam_cnt; indx_cam++) {
if (webua->cam->device_id == app->cam_list[indx_cam]->device_id){
indx_req = indx_cam;
}
}
webua->resp_page += "{\"count\" : 1";
webua->resp_page += ",\""+ std::to_string(indx_req) + "\":";
movies_list();
webua->resp_page += "}";
}
webua->resp_page += "}";
}
void cls_webu_json::status_vars(int indx_cam)
{
char buf[32];
struct tm timestamp_tm;
struct timespec curr_ts;
ctx_dev *cam;
cam = app->cam_list[indx_cam];
webua->resp_page += "{";
webua->resp_page += "\"name\":\"" + cam->conf->device_name+"\"";
webua->resp_page += ",\"id\":" + std::to_string(cam->device_id);
webua->resp_page += ",\"width\":" + std::to_string(cam->imgs.width);
webua->resp_page += ",\"height\":" + std::to_string(cam->imgs.height);
webua->resp_page += ",\"fps\":" + std::to_string(cam->lastrate);
clock_gettime(CLOCK_REALTIME, &curr_ts);
localtime_r(&curr_ts.tv_sec, ×tamp_tm);
strftime(buf, sizeof(buf), "%FT%T", ×tamp_tm);
webua->resp_page += ",\"current_time\":\"" + std::string(buf)+"\"";
webua->resp_page += ",\"missing_frame_counter\":" +
std::to_string(cam->missing_frame_counter);
if (cam->lost_connection) {
webua->resp_page += ",\"lost_connection\":true";
} else {
webua->resp_page += ",\"lost_connection\":false";
}
if (cam->connectionlosttime.tv_sec != 0) {
localtime_r(&cam->connectionlosttime.tv_sec, ×tamp_tm);
strftime(buf, sizeof(buf), "%FT%T", ×tamp_tm);
webua->resp_page += ",\"connection_lost_time\":\"" + std::string(buf)+"\"";
} else {
webua->resp_page += ",\"connection_lost_time\":\"\"" ;
}
if (cam->detecting_motion) {
webua->resp_page += ",\"detecting\":true";
} else {
webua->resp_page += ",\"detecting\":false";
}
if (cam->pause) {
webua->resp_page += ",\"pause\":true";
} else {
webua->resp_page += ",\"pause\":false";
}
webua->resp_page += "}";
}
void cls_webu_json::status()
{
int indx_cam;
webua->resp_type = WEBUI_RESP_JSON;
webua->resp_page += "{\"version\" : \"" VERSION "\"";
webua->resp_page += ",\"status\" : ";
webua->resp_page += "{\"count\" : " + std::to_string(app->cam_cnt);
for (indx_cam=0; indx_camcam_cnt; indx_cam++) {
webua->resp_page += ",\"cam" +
std::to_string(app->cam_list[indx_cam]->device_id) + "\": ";
status_vars(indx_cam);
}
webua->resp_page += "}";
webua->resp_page += "}";
}
void cls_webu_json::main()
{
pthread_mutex_lock(&app->mutex_post);
if (webua->uri_cmd1 == "config.json") {
config();
} else if (webua->uri_cmd1 == "movies.json") {
movies();
} else if (webua->uri_cmd1 == "status.json") {
status();
} else {
webua->bad_request();
pthread_mutex_unlock(&app->mutex_post);
return;
}
pthread_mutex_unlock(&app->mutex_post);
webua->mhd_send();
}
cls_webu_json::cls_webu_json(cls_webu_ans *p_webua)
{
app = p_webua->app;
webu = p_webua->webu;
webua = p_webua;
}
cls_webu_json::~cls_webu_json()
{
app = nullptr;
webu = nullptr;
webua = nullptr;
}