26#include <sys/socket.h>
28#include <netinet/in.h>
42static inline void ADD_STR(std::string& list,
const std::string& s)
43{ list += s; list +=
"[]:[]"; };
44static inline void ADD_INT(std::string& list,
int n)
45{ list += std::to_string(n); list +=
"[]:[]"; };
98 std::cout <<
"loading zm config from " << configfile << std::endl;
100 std::ifstream ifs(configfile);
103 fprintf(
stderr,
"Can't open %s\n", configfile.c_str());
107 while ( std::getline(ifs, line) )
110 constexpr const char *whitespace =
" \t\r\n";
111 auto begin = line.find_first_not_of(whitespace);
112 if (begin == std::string::npos)
114 auto end = line.find_last_not_of(whitespace);
115 if (end != std::string::npos)
117 line = line.substr(begin, end);
120 if ( line.empty() || line[0] ==
'#' )
124 auto index = line.find(
'=');
125 if (index == std::string::npos)
127 fprintf(
stderr,
"Invalid data in %s: '%s'\n", configfile.c_str(), line.c_str() );
132 std::string name = line.substr(0,index);
133 std::string val = line.substr(index+1);
136 end = name.find_last_not_of(whitespace);
137 if (end != std::string::npos)
139 name = name.substr(0, end);
142 begin = val.find_first_not_of(whitespace);
143 if (begin != std::string::npos)
144 val = val.substr(begin);
147 std::transform(name.cbegin(), name.cend(), name.begin(), ::toupper);
149 if ( name ==
"ZM_DB_HOST" )
g_server = val;
150 else if ( name ==
"ZM_DB_NAME" )
g_database = val;
151 else if ( name ==
"ZM_DB_USER" )
g_user = val;
152 else if ( name ==
"ZM_DB_PASS" )
g_password = val;
153 else if ( name ==
"ZM_PATH_WEB" )
g_webPath = val;
154 else if ( name ==
"ZM_PATH_BIN" )
g_binPath = val;
155 else if ( name ==
"ZM_WEB_USER" )
g_webUser = val;
156 else if ( name ==
"ZM_VERSION" )
g_zmversion = val;
157 else if ( name ==
"ZM_PATH_MAP" )
g_mmapPath = val;
162#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
172 std::cout <<
"Error: Can't initialise structure: " << mysql_error(&
g_dbConn) << std::endl;
173 exit(
static_cast<int>(mysql_errno(&
g_dbConn)));
177 mysql_options(&
g_dbConn, MYSQL_OPT_RECONNECT, &reconnect);
182 std::cout <<
"Error: Can't connect to server: " << mysql_error(&
g_dbConn) << std::endl;
183 exit(
static_cast<int>(mysql_errno( &
g_dbConn)));
188 std::cout <<
"Error: Can't select database: " << mysql_error(&
g_dbConn) << std::endl;
189 exit(
static_cast<int>(mysql_errno(&
g_dbConn)));
199 std::cout <<
"Kicking database connection" << std::endl;
203 if (mysql_query(&
g_dbConn,
"SELECT NULL;") == 0)
205 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
207 mysql_free_result(res);
211 std::cout <<
"Lost connection to DB - trying to reconnect" << std::endl;
222 size_t shared_data_size = 0;
257#if _POSIX_MAPPED_FILES > 0L
262 std::stringstream mmap_filename;
263 mmap_filename << mmapPath <<
"/zm.mmap." <<
m_monId;
265 m_mapFile = open(mmap_filename.str().c_str(), O_RDONLY, 0x0);
269 std::cout <<
"Opened mmap file: " << mmap_filename.str() << std::endl;
271 m_shmPtr = mmap(
nullptr, shared_data_size, PROT_READ,
275 std::cout <<
"Failed to map shared memory from file ["
276 << mmap_filename.str() <<
"] " <<
"for monitor: "
281 std::cout <<
"Failed to close mmap file" << std::endl;
295 std::cout <<
"Failed to open mmap file [" << mmap_filename.str() <<
"] "
297 <<
" : " << strerror(errno) << std::endl;
298 std::cout <<
"Falling back to the legacy shared memory method" << std::endl;
306 int shmid = shmget((shmKey & 0xffff0000) |
m_monId,
307 shared_data_size, SHM_R);
310 std::cout <<
"Failed to shmget for monitor: " <<
m_monId << std::endl;
314 case EACCES: std::cout <<
"EACCES - no rights to access segment\n";
break;
315 case EEXIST: std::cout <<
"EEXIST - segment already exists\n";
break;
316 case EINVAL: std::cout <<
"EINVAL - size < SHMMIN or size > SHMMAX\n";
break;
317 case ENFILE: std::cout <<
"ENFILE - limit on open files has been reached\n";
break;
318 case ENOENT: std::cout <<
"ENOENT - no segment exists for the given key\n";
break;
319 case ENOMEM: std::cout <<
"ENOMEM - couldn't reserve memory for segment\n";
break;
320 case ENOSPC: std::cout <<
"ENOSPC - shmmni or shmall limit reached\n";
break;
326 m_shmPtr = shmat(shmid,
nullptr, SHM_RDONLY);
331 std::cout <<
"Failed to shmat for monitor: " <<
m_monId << std::endl;
421 std::stringstream out;
514 if (!setting.empty())
517 sscanf(setting.c_str(),
"%20llx", &
tmp);
523 std::cout <<
"Shared memory key is: 0x"
524 << std::hex << (
unsigned int)
m_shmKey
525 << std::dec << std::endl;
536 std::cout <<
"Memory path directory is: " <<
m_mmapPath << std::endl;
541 int eventDigits = atoi(setting.c_str());
542 std::string eventDigitsFmt =
"%0" + std::to_string(eventDigits) +
"d";
557 std::cout <<
"using deep storage directory structure" << std::endl;
559 std::cout <<
"using flat directory structure" << std::endl;
567 std::cout <<
"using analysis images" << std::endl;
569 std::cout <<
"not using analysis images" << std::endl;
579 if (mon->m_mapFile != -1)
581 if (
close(mon->m_mapFile) == -1)
582 std::cout <<
"Failed to close mapFile" << std::endl;
585 std::cout <<
"Closed mapFile for monitor: " << mon->m_name << std::endl;
595 std::cout <<
"ZMServer destroyed\n";
602 std::string::size_type startPos = 0;
603 std::string::size_type endPos = 0;
605 while((endPos = command.find(
"[]:[]", startPos)) != std::string::npos)
607 token = command.substr(startPos, endPos - startPos);
608 tokens.push_back(token);
609 startPos = endPos + 5;
613 if (endPos != command.length())
615 token = command.substr(startPos);
616 tokens.push_back(token);
628 int dataLen = atoi(len);
632 std::string s(buf+8);
633 std::vector<std::string> tokens;
640 std::cout <<
"Processing: '" << tokens[0] <<
"'" << std::endl;
642 if (tokens[0] ==
"HELLO")
644 else if (tokens[0] ==
"QUIT")
646 else if (tokens[0] ==
"GET_SERVER_STATUS")
648 else if (tokens[0] ==
"GET_MONITOR_STATUS")
650 else if (tokens[0] ==
"GET_ALARM_STATES")
652 else if (tokens[0] ==
"GET_EVENT_LIST")
654 else if (tokens[0] ==
"GET_EVENT_DATES")
656 else if (tokens[0] ==
"GET_EVENT_FRAME")
658 else if (tokens[0] ==
"GET_ANALYSE_FRAME")
660 else if (tokens[0] ==
"GET_LIVE_FRAME")
662 else if (tokens[0] ==
"GET_FRAME_LIST")
664 else if (tokens[0] ==
"GET_CAMERA_LIST")
666 else if (tokens[0] ==
"GET_MONITOR_LIST")
668 else if (tokens[0] ==
"DELETE_EVENT")
670 else if (tokens[0] ==
"DELETE_EVENT_LIST")
672 else if (tokens[0] ==
"RUN_ZMAUDIT")
674 else if (tokens[0] ==
"SET_MONITOR_FUNCTION")
677 send(
"UNKNOWN_COMMAND");
685 std::string str =
"0000000" + std::to_string(s.size());
686 str.erase(0, str.size()-8);
696bool ZMServer::send(
const std::string &s,
const unsigned char *buffer,
int dataLen)
const
699 std::string str =
"0000000" + std::to_string(s.size());
700 str.erase(0, str.size()-8);
734 constexpr uintmax_t k_unknown_size {
static_cast<std::uintmax_t
>(-1)};
736 (space_info.capacity == 0
737 || space_info.free == 0
738 || space_info.available == 0
740 (space_info.capacity == k_unknown_size
741 || space_info.free == k_unknown_size
742 || space_info.available == k_unknown_size
748 return (100 * (space_info.capacity - space_info.available)) / space_info.capacity;
761 std::array<double,3> loads {};
769 std::string buf = std::to_string(loads[0]);
770 buf.resize(buf.size() - 4);
774 std::string eventsDir =
g_webPath +
"/events/";
793 ADD_INT(outStr, monitor->m_monId);
796 ADD_INT(outStr, monitor->getState());
806 if (tokens.size() != 5)
812 const std::string& monitor = tokens[1];
813 bool oldestFirst = (tokens[2] ==
"1");
814 const std::string& date = tokens[3];
815 bool includeContinuous = (tokens[4] ==
"1");
818 std::cout <<
"Loading events for monitor: " << monitor <<
", date: " << date << std::endl;
822 std::string sql(
"SELECT E.Id, E.Name, M.Id AS MonitorID, M.Name AS MonitorName, E.StartTime, "
823 "E.Length, M.Width, M.Height, M.DefaultRate, M.DefaultScale "
824 "from Events as E inner join Monitors as M on E.MonitorId = M.Id ");
826 if (monitor !=
"<ANY>")
828 sql +=
"WHERE M.Name = '" + monitor +
"' ";
831 sql +=
"AND DATE(E.StartTime) = DATE('" + date +
"') ";
837 sql +=
"WHERE DATE(E.StartTime) = DATE('" + date +
"') ";
839 if (!includeContinuous)
840 sql +=
"AND Cause != 'Continuous' ";
843 if (!includeContinuous)
845 sql +=
"WHERE Cause != 'Continuous' ";
850 sql +=
"ORDER BY E.StartTime ASC";
852 sql +=
"ORDER BY E.StartTime DESC";
854 if (mysql_query(&
g_dbConn, sql.c_str()))
861 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
862 int eventCount = mysql_num_rows(res);
865 std::cout <<
"Got " << eventCount <<
" events" << std::endl;
869 for (
int x = 0; x < eventCount; x++)
871 MYSQL_ROW row = mysql_fetch_row(res);
884 std::cout <<
"Failed to get mysql row" << std::endl;
890 mysql_free_result(res);
899 if (tokens.size() != 3)
905 const std::string& monitor = tokens[1];
906 bool oldestFirst = (tokens[2] ==
"1");
909 std::cout <<
"Loading event dates for monitor: " << monitor << std::endl;
913 std::string sql(
"SELECT DISTINCT DATE(E.StartTime) "
914 "from Events as E inner join Monitors as M on E.MonitorId = M.Id ");
916 if (monitor !=
"<ANY>")
917 sql +=
"WHERE M.Name = '" + monitor +
"' ";
920 sql +=
"ORDER BY E.StartTime ASC";
922 sql +=
"ORDER BY E.StartTime DESC";
924 if (mysql_query(&
g_dbConn, sql.c_str()))
931 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
932 int dateCount = mysql_num_rows(res);
935 std::cout <<
"Got " << dateCount <<
" dates" << std::endl;
939 for (
int x = 0; x < dateCount; x++)
941 MYSQL_ROW row = mysql_fetch_row(res);
948 std::cout <<
"Failed to get mysql row" << std::endl;
954 mysql_free_result(res);
966 std::string sql(
"SELECT Id, Name, Type, Device, Host, Channel, `Function`, Enabled "
968 if (mysql_query(&
g_dbConn, sql.c_str()))
975 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
978 int monitorCount = mysql_num_rows(res);
981 std::cout <<
"Got " << monitorCount <<
" monitors" << std::endl;
985 for (
int x = 0; x < monitorCount; x++)
987 MYSQL_ROW row = mysql_fetch_row(res);
990 std::string
id = row[0];
991 std::string
type = row[2];
992 std::string device = row[3];
993 std::string host = row[4] ? row[4] :
"";
994 std::string channel = row[5];
995 std::string function = row[6];
996 std::string enabled = row[7];
997 std::string name = row[1];
999 std::string zmcStatus;
1000 std::string zmaStatus;
1002 zmcStatus, zmaStatus, enabled);
1004 std::string sql2(
"SELECT count(if(Archived=0,1,NULL)) AS EventCount "
1006 "WHERE MonitorId = " +
id);
1008 if (mysql_query(&
g_dbConn, sql2.c_str()))
1015 MYSQL_RES *res2 = mysql_store_result(&
g_dbConn);
1016 if (mysql_num_rows(res2) > 0)
1018 MYSQL_ROW row2 = mysql_fetch_row(res2);
1023 std::cout <<
"Failed to get mysql row" << std::endl;
1037 mysql_free_result(res2);
1041 std::cout <<
"Failed to get mysql row" << std::endl;
1047 mysql_free_result(res);
1055 FILE *fd = popen(command.c_str(),
"r");
1056 std::array<char,100> buffer {};
1058 while (fgets(buffer.data(), buffer.size(), fd) !=
nullptr)
1060 outStr += buffer.data();
1067 const std::string &device,
const std::string &host,
1068 const std::string &channel,
const std::string &function,
1069 std::string &zmcStatus, std::string &zmaStatus,
1070 const std::string &enabled)
1075 std::string command(
g_binPath +
"/zmdc.pl status");
1078 if (
type ==
"Local")
1081 zmaStatus = device +
"(" + channel +
") [-]";
1082 else if (status.find(
"'zma -m " +
id +
"' running") != std::string::npos)
1083 zmaStatus = device +
"(" + channel +
") [R]";
1085 zmaStatus = device +
"(" + channel +
") [S]";
1090 zmaStatus = host +
" [-]";
1091 else if (status.find(
"'zma -m " +
id +
"' running") != std::string::npos)
1092 zmaStatus = host +
" [R]";
1094 zmaStatus = host +
" [S]";
1097 if (
type ==
"Local")
1100 zmcStatus = function +
" [-]";
1101 else if (status.find(
"'zmc -d "+ device +
"' running") != std::string::npos)
1102 zmcStatus = function +
" [R]";
1104 zmcStatus = function +
" [S]";
1109 zmcStatus = function +
" [-]";
1110 else if (status.find(
"'zmc -m " +
id +
"' running") != std::string::npos)
1111 zmcStatus = function +
" [R]";
1113 zmcStatus = function +
" [S]";
1121 if (tokens.size() != 5)
1127 const std::string& monitorID(tokens[1]);
1128 const std::string& eventID(tokens[2]);
1129 int frameNo = atoi(tokens[3].c_str());
1130 const std::string& eventTime(tokens[4]);
1134 std::cout <<
"Getting frame " << frameNo <<
" for event " << eventID
1135 <<
" on monitor " << monitorID <<
" event time is " << eventTime
1144 std::string filepath;
1145 std::string str (100,
'\0');
1153 sscanf(eventTime.data(),
"%2d/%2d/%2d", &year, &month, &day);
1154 sprintf(str.data(),
"20%02d-%02d-%02d", year, month, day);
1156 filepath =
g_eventsPath +
"/" + monitorID +
"/" + str +
"/" + eventID +
"/";
1164 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventTime +
"/";
1170 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventID +
"/";
1177 FILE *fd = fopen(filepath.c_str(),
"r" );
1180 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1185 std::cout <<
"Can't open " << filepath <<
": " << strerror(errno) << std::endl;
1191 std::cout <<
"Frame size: " << fileSize << std::endl;
1197 send(outStr, s_buffer.data(), fileSize);
1203 std::array<char,100> str {};
1205 if (tokens.size() != 5)
1211 const std::string& monitorID(tokens[1]);
1212 const std::string& eventID(tokens[2]);
1213 int frameNo = atoi(tokens[3].c_str());
1214 const std::string& eventTime(tokens[4]);
1220 std::cout <<
"Getting analysis frame " << frameNo <<
" for event " << eventID
1221 <<
" on monitor " << monitorID <<
" event time is " << eventTime
1227 sql +=
"SELECT FrameId FROM Frames ";
1228 sql +=
"WHERE EventID = " + eventID +
" ";
1229 sql +=
"AND Type = 'Alarm' ";
1230 sql +=
"ORDER BY FrameID";
1232 if (mysql_query(&
g_dbConn, sql.c_str()))
1239 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1240 frameCount = mysql_num_rows(res);
1243 if (frameCount == 0)
1245 mysql_free_result(res);
1247 sql =
"SELECT FrameId FROM Frames ";
1248 sql +=
"WHERE EventID = " + eventID +
" ";
1249 sql +=
"ORDER BY FrameID";
1251 if (mysql_query(&
g_dbConn, sql.c_str()))
1258 res = mysql_store_result(&
g_dbConn);
1259 frameCount = mysql_num_rows(res);
1263 if (frameCount == 0)
1265 std::cout <<
"handleGetAnalyseFrame: Failed to find any frames" << std::endl;
1271 if (frameNo == 0 || frameNo < 0 || frameNo > frameCount)
1272 frameNo = (frameCount / 2) + 1;
1275 MYSQL_ROW row =
nullptr;
1276 for (
int x = 0; x < frameNo; x++)
1278 row = mysql_fetch_row(res);
1283 frameID = atoi(row[0]);
1287 std::cout <<
"handleGetAnalyseFrame: Failed to get mysql row for frameNo " << frameNo << std::endl;
1292 mysql_free_result(res);
1295 std::string filepath;
1296 std::string frameFile;
1304 sscanf(eventTime.c_str(),
"%2d/%2d/%2d", &year, &month, &day);
1305 sprintf(str.data(),
"20%02d-%02d-%02d", year, month, day);
1306 filepath =
g_eventsPath +
"/" + monitorID +
"/" + str.data() +
"/" + eventID +
"/";
1311 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventTime +
"/";
1313 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventID +
"/";
1325 frameFile = filepath + str.data();
1327 fd = fopen(frameFile.c_str(),
"r" );
1330 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1334 std::cout <<
"Frame size: " << fileSize << std::endl;
1340 send(outStr, s_buffer.data(), fileSize);
1347 frameFile = filepath + str.data();
1349 fd = fopen(frameFile.c_str(),
"r" );
1352 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1357 std::cout <<
"Can't open " << frameFile <<
": " << strerror(errno) << std::endl;
1363 std::cout <<
"Frame size: " << fileSize << std::endl;
1369 send(outStr, s_buffer.data(), fileSize);
1382 if (tokens.size() != 2)
1388 int monitorID = atoi(tokens[1].c_str());
1391 std::cout <<
"Getting live frame from monitor: " << monitorID << std::endl;
1416 int dataSize =
getFrame(s_buffer, monitor);
1419 std::cout <<
"Frame size: " << dataSize << std::endl;
1425 ADD_STR(outStr,
"WARNING - No new frame available");
1437 send(outStr, s_buffer.data(), dataSize);
1442 std::string eventID;
1445 if (tokens.size() != 2)
1451 eventID = tokens[1];
1454 std::cout <<
"Loading frames for event: " << eventID << std::endl;
1459 std::string sql =
"SELECT Cause, Length, Frames FROM Events ";
1460 sql +=
"WHERE Id = " + eventID +
" ";
1462 if (mysql_query(&
g_dbConn, sql.c_str()))
1469 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1470 MYSQL_ROW row = mysql_fetch_row(res);
1473 if (row[1] ==
nullptr || row[2] ==
nullptr)
1479 std::string cause = row[0];
1480 double length = atof(row[1]);
1481 int frameCount = atoi(row[2]);
1483 mysql_free_result(res);
1485 if (cause ==
"Continuous")
1490 std::cout <<
"Got " << frameCount <<
" frames (continuous event)" << std::endl;
1496 double delta = length / frameCount;
1498 for (
int x = 0; x < frameCount; x++)
1501 ADD_STR(outStr, std::to_string(delta));
1507 sql =
"SELECT Type, Delta FROM Frames ";
1508 sql +=
"WHERE EventID = " + eventID +
" ";
1509 sql +=
"ORDER BY FrameID";
1511 if (mysql_query(&
g_dbConn, sql.c_str()))
1518 res = mysql_store_result(&
g_dbConn);
1519 frameCount = mysql_num_rows(res);
1522 std::cout <<
"Got " << frameCount <<
" frames" << std::endl;
1526 for (
int x = 0; x < frameCount; x++)
1528 row = mysql_fetch_row(res);
1536 std::cout <<
"handleGetFrameList: Failed to get mysql row " << x << std::endl;
1542 mysql_free_result(res);
1558 ADD_STR(outStr, monitor->m_name);
1571 std::cout <<
"We have " <<
m_monitors.size() <<
" monitors" << std::endl;
1577 ADD_INT(outStr, mon->m_monId);
1579 ADD_INT(outStr, mon->m_width);
1580 ADD_INT(outStr, mon->m_height);
1581 ADD_INT(outStr, mon->m_bytesPerPixel);
1585 std::cout <<
"id: " << mon->m_monId << std::endl;
1586 std::cout <<
"name: " << mon->m_name << std::endl;
1587 std::cout <<
"width: " << mon->m_width << std::endl;
1588 std::cout <<
"height: " << mon->m_height << std::endl;
1589 std::cout <<
"palette: " << mon->m_palette << std::endl;
1590 std::cout <<
"byte per pixel: " << mon->m_bytesPerPixel << std::endl;
1591 std::cout <<
"sub pixel order:" << mon->getSubpixelOrder() << std::endl;
1592 std::cout <<
"-------------------" << std::endl;
1601 std::string eventID;
1604 if (tokens.size() != 2)
1610 eventID = tokens[1];
1613 std::cout <<
"Deleting event: " << eventID << std::endl;
1618 sql +=
"DELETE FROM Events WHERE Id = " + eventID;
1620 if (mysql_query(&
g_dbConn, sql.c_str()))
1628 std::string command(
g_binPath +
"/zmaudit.pl &");
1630 if (system(command.c_str()) < 0 && errno)
1631 std::cerr <<
"Failed to run '" << command <<
"'" << std::endl;
1638 std::string eventList;
1641 auto it = tokens.begin();
1642 if (it != tokens.end())
1644 while (it != tokens.end())
1646 if (eventList.empty())
1649 eventList +=
"," + (*it);
1655 std::cout <<
"Deleting events: " << eventList << std::endl;
1658 sql +=
"DELETE FROM Events WHERE Id IN (" + eventList +
")";
1660 if (mysql_query(&
g_dbConn, sql.c_str()))
1676 std::string command(
g_binPath +
"/zmaudit.pl &");
1679 std::cout <<
"Running command: " << command << std::endl;
1682 if (system(command.c_str()) < 0 && errno)
1683 std::cerr <<
"Failed to run '" << command <<
"'" << std::endl;
1695 std::string sql(
"SELECT Id, Name, Width, Height, ImageBufferCount, MaxFPS, Palette, ");
1696 sql +=
" Type, `Function`, Enabled, Device, Host, Controllable, TrackMotion";
1701 sql +=
" FROM Monitors";
1702 sql +=
" ORDER BY Sequence";
1704 if (mysql_query(&
g_dbConn, sql.c_str()))
1710 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1711 int monitorCount = mysql_num_rows(res);
1714 std::cout <<
"Got " << monitorCount <<
" monitors" << std::endl;
1716 for (
int x = 0; x < monitorCount; x++)
1718 MYSQL_ROW row = mysql_fetch_row(res);
1724 m->m_width = atoi(row[2]);
1725 m->m_height = atoi(row[3]);
1726 m->m_imageBufferCount = atoi(row[4]);
1727 m->m_palette = atoi(row[6]);
1729 m->m_function = row[8];
1730 m->m_enabled = atoi(row[9]);
1731 m->m_device = row[10];
1732 m->m_host = row[11] ? row[11] :
"";
1733 m->m_controllable = atoi(row[12]);
1734 m->m_trackMotion = atoi(row[13]);
1739 m->m_bytesPerPixel = atoi(row[14]);
1741 if (m->m_palette == 1)
1742 m->m_bytesPerPixel = 1;
1744 m->m_bytesPerPixel = 3;
1753 std::cout <<
"Failed to get mysql row" << std::endl;
1758 mysql_free_result(res);
1802 unsigned int rpos = 0;
1803 unsigned int wpos = 0;
1809 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 1)
1811 buffer[wpos + 0] = data[rpos + 0];
1812 buffer[wpos + 1] = data[rpos + 0];
1813 buffer[wpos + 2] = data[rpos + 0];
1821 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 3)
1823 buffer[wpos + 0] = data[rpos + 0];
1824 buffer[wpos + 1] = data[rpos + 1];
1825 buffer[wpos + 2] = data[rpos + 2];
1833 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 3)
1835 buffer[wpos + 0] = data[rpos + 2];
1836 buffer[wpos + 1] = data[rpos + 1];
1837 buffer[wpos + 2] = data[rpos + 0];
1844 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1846 buffer[wpos + 0] = data[rpos + 2];
1847 buffer[wpos + 1] = data[rpos + 1];
1848 buffer[wpos + 2] = data[rpos + 0];
1856 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3 ); wpos += 3, rpos += 4)
1858 buffer[wpos + 0] = data[rpos + 0];
1859 buffer[wpos + 1] = data[rpos + 1];
1860 buffer[wpos + 2] = data[rpos + 2];
1868 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1870 buffer[wpos + 0] = data[rpos + 3];
1871 buffer[wpos + 1] = data[rpos + 2];
1872 buffer[wpos + 2] = data[rpos + 1];
1880 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1882 buffer[wpos + 0] = data[rpos + 1];
1883 buffer[wpos + 1] = data[rpos + 2];
1884 buffer[wpos + 2] = data[rpos + 3];
1897 std::string sql(
"SELECT Name, Value FROM Config ");
1898 sql +=
"WHERE Name = '" + setting +
"'";
1900 if (mysql_query(&
g_dbConn, sql.c_str()))
1906 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1907 MYSQL_ROW row = mysql_fetch_row(res);
1914 std::cout <<
"Failed to get mysql row" << std::endl;
1919 std::cout <<
"getZMSetting: " << setting <<
" Result: " << result << std::endl;
1921 mysql_free_result(res);
1930 if (tokens.size() != 4)
1936 const std::string& monitorID(tokens[1]);
1937 const std::string& function(tokens[2]);
1938 const std::string& enabled(tokens[3]);
1955 if (enabled !=
"0" && enabled !=
"1")
1962 std::cout <<
"User input validated OK" << std::endl;
1967 std::string oldFunction = monitor->
m_function;
1968 const std::string& newFunction = function;
1970 int newEnabled = atoi(enabled.c_str());
1976 std::cout <<
"SetMonitorFunction MonitorId: " << monitorID << std::endl
1977 <<
" oldEnabled: " << oldEnabled << std::endl
1978 <<
" newEnabled: " << newEnabled << std::endl
1979 <<
" oldFunction: " << oldFunction << std::endl
1980 <<
" newFunction: " << newFunction << std::endl;
1983 if ( newFunction != oldFunction || newEnabled != oldEnabled)
1985 std::string sql(
"UPDATE Monitors ");
1986 sql +=
"SET Function = '" + function +
"', ";
1987 sql +=
"Enabled = '" + enabled +
"' ";
1988 sql +=
"WHERE Id = '" + monitorID +
"'";
1990 if (mysql_query(&
g_dbConn, sql.c_str()))
1998 std::cout <<
"Monitor function SQL update OK" << std::endl;
2006 std::cout <<
"Monitor function Refreshing daemons" << std::endl;
2010 (newEnabled != oldEnabled);
2021 std::cout <<
"zm daemons are not running" << std::endl;
2026 std::cout <<
"Not updating monitor function as identical to existing configuration" << std::endl;
2035 std::string zmcArgs;
2037 sql +=
"SELECT count(if(Function!='None',1,NULL)) as ActiveCount ";
2038 sql +=
"FROM Monitors ";
2040 if (monitor->
m_type ==
"Local" )
2042 sql +=
"WHERE Device = '" + monitor->
m_device +
"'";
2043 zmcArgs =
"-d " + monitor->
m_device;
2047 sql +=
"WHERE Id = '" + monitor->
getIdStr() +
"'";
2048 zmcArgs =
"-m " + monitor->
getIdStr();
2051 if (mysql_query(&
g_dbConn, sql.c_str()))
2058 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
2059 MYSQL_ROW row = mysql_fetch_row(res);
2065 int activeCount = atoi(row[0]);
2080 int zmOptControl = atoi(
getZMSetting(
"ZM_OPT_CONTROL").c_str());
2081 int zmOptFrameServer = atoi(
getZMSetting(
"ZM_OPT_FRAME_SERVER").c_str());
2095 if (zmOptFrameServer)
2099 if (zmOptFrameServer)
2118 if (zmOptFrameServer)
int getSubpixelOrder(void)
SharedData * m_sharedData
void initMonitor(bool debug, const std::string &mmapPath, int shmKey)
std::string getIdStr(void)
SharedData32 * m_sharedData32
SharedData26 * m_sharedData26
int getLastWriteIndex(void)
SharedData34 * m_sharedData34
unsigned char * m_sharedImages
std::vector< MONITOR * > m_monitors
static std::string runCommand(const std::string &command)
void zmaControl(MONITOR *monitor, const std::string &mode)
void handleGetAlarmStates(void)
void zmcControl(MONITOR *monitor, const std::string &mode)
void handleGetMonitorStatus(void)
std::string getZMSetting(const std::string &setting) const
void handleGetEventDates(std::vector< std::string > tokens)
std::string m_eventFileFormat
void handleGetEventList(std::vector< std::string > tokens)
static void tokenize(const std::string &command, std::vector< std::string > &tokens)
void handleSetMonitorFunction(std::vector< std::string > tokens)
void handleGetServerStatus(void)
void handleGetMonitorList(void)
bool processRequest(char *buf, int nbytes)
static int getFrame(FrameData &buffer, MONITOR *monitor)
void getMonitorList(void)
std::map< int, MONITOR * > m_monitorMap
void handleGetAnalysisFrame(std::vector< std::string > tokens)
void handleGetEventFrame(std::vector< std::string > tokens)
void handleGetLiveFrame(std::vector< std::string > tokens)
void handleDeleteEvent(std::vector< std::string > tokens)
bool send(const std::string &s) const
void handleRunZMAudit(void)
void sendError(const std::string &error)
ZMServer(int sock, bool debug)
void handleGetFrameList(std::vector< std::string > tokens)
void handleDeleteEventList(std::vector< std::string > tokens)
static void getMonitorStatus(const std::string &id, const std::string &type, const std::string &device, const std::string &host, const std::string &channel, const std::string &function, std::string &zmcStatus, std::string &zmaStatus, const std::string &enabled)
std::string m_analysisFileFormat
void handleGetCameraList(void)
uint32_t last_write_index
uint32_t last_write_index
uint32_t last_write_index
VERBOSE_PREAMBLE Most debug(nodatabase, notimestamp, noextra)") VERBOSE_MAP(VB_GENERAL
void loadZMConfig(const std::string &configfile)
static uintmax_t disk_usage_percent(const std::filesystem::space_info &space_info)
static constexpr const char * ERROR_NO_FRAMES
static constexpr const char * ERROR_MYSQL_QUERY
static constexpr const char * ERROR_INVALID_MONITOR_FUNCTION
static constexpr const char * ERROR_INVALID_MONITOR
static constexpr const char * ERROR_FILE_OPEN
bool checkVersion(int major, int minor, int revision)
static constexpr const char * ERROR_INVALID_MONITOR_ENABLE_VALUE
static constexpr int MSG_NOSIGNAL
static void ADD_INT(std::string &list, int n)
static constexpr const char * ZM_PROTOCOL_VERSION
void kickDatabase(bool debug)
static constexpr const char * ERROR_TOKEN_COUNT
static constexpr const char * ERROR_INVALID_POINTERS
static void ADD_STR(std::string &list, const std::string &s)
static constexpr const char * ERROR_MYSQL_ROW
void connectToDatabase(void)
const std::string FUNCTION_NODECT
std::array< uint8_t, MAX_IMAGE_SIZE > FrameData
const std::string RUNNING
const std::string FUNCTION_MONITOR
const std::string FUNCTION_MODECT
const std::string FUNCTION_RECORD
std::chrono::time_point< Clock > TimePoint
const std::string FUNCTION_MOCORD
const std::string FUNCTION_NONE
const std::string RESTART
static constexpr std::chrono::seconds DB_CHECK_TIME