26#include <sys/socket.h>
28#include <netinet/in.h>
43static inline void ADD_STR(std::string& list,
const std::string& s)
44{ list += s; list +=
"[]:[]"; };
45static inline void ADD_INT(std::string& list,
int n)
46{ list += std::to_string(n); list +=
"[]:[]"; };
99 std::cout <<
"loading zm config from " << configfile <<
'\n';
101 std::ifstream ifs(configfile);
104 fprintf(
stderr,
"Can't open %s\n", configfile.c_str());
108 while ( std::getline(ifs, line) )
111 constexpr const char *whitespace =
" \t\r\n";
112 auto begin = line.find_first_not_of(whitespace);
113 if (begin == std::string::npos)
115 auto end = line.find_last_not_of(whitespace);
116 if (end != std::string::npos)
118 line = line.substr(begin, end);
121 if ( line.empty() || line[0] ==
'#' )
125 auto index = line.find(
'=');
126 if (index == std::string::npos)
128 fprintf(
stderr,
"Invalid data in %s: '%s'\n", configfile.c_str(), line.c_str() );
133 std::string name = line.substr(0,index);
134 std::string val = line.substr(index+1);
137 end = name.find_last_not_of(whitespace);
138 if (end != std::string::npos)
140 name = name.substr(0, end);
143 begin = val.find_first_not_of(whitespace);
144 if (begin != std::string::npos)
145 val = val.substr(begin);
148 std::ranges::transform(name, name.begin(), ::toupper);
150 if ( name ==
"ZM_DB_HOST" )
g_server = val;
151 else if ( name ==
"ZM_DB_NAME" )
g_database = val;
152 else if ( name ==
"ZM_DB_USER" )
g_user = val;
153 else if ( name ==
"ZM_DB_PASS" )
g_password = val;
154 else if ( name ==
"ZM_PATH_WEB" )
g_webPath = val;
155 else if ( name ==
"ZM_PATH_BIN" )
g_binPath = val;
156 else if ( name ==
"ZM_WEB_USER" )
g_webUser = val;
157 else if ( name ==
"ZM_VERSION" )
g_zmversion = val;
158 else if ( name ==
"ZM_PATH_MAP" )
g_mmapPath = val;
163#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
173 std::cout <<
"Error: Can't initialise structure: " << mysql_error(&
g_dbConn) <<
'\n';
174 exit(
static_cast<int>(mysql_errno(&
g_dbConn)));
178 mysql_options(&
g_dbConn, MYSQL_OPT_RECONNECT, &reconnect);
183 std::cout <<
"Error: Can't connect to server: " << mysql_error(&
g_dbConn) <<
'\n';
184 exit(
static_cast<int>(mysql_errno( &
g_dbConn)));
189 std::cout <<
"Error: Can't select database: " << mysql_error(&
g_dbConn) <<
'\n';
190 exit(
static_cast<int>(mysql_errno(&
g_dbConn)));
200 std::cout <<
"Kicking database connection\n";
204 if (mysql_query(&
g_dbConn,
"SELECT NULL;") == 0)
206 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
208 mysql_free_result(res);
212 std::cout <<
"Lost connection to DB - trying to reconnect\n";
223 size_t shared_data_size = 0;
258#if _POSIX_MAPPED_FILES > 0L
263 std::stringstream mmap_filename;
264 mmap_filename << mmapPath <<
"/zm.mmap." <<
m_monId;
266 m_mapFile = open(mmap_filename.str().c_str(), O_RDONLY, 0x0);
270 std::cout <<
"Opened mmap file: " << mmap_filename.str() <<
'\n';
272 m_shmPtr = mmap(
nullptr, shared_data_size, PROT_READ,
276 std::cout <<
"Failed to map shared memory from file ["
277 << mmap_filename.str() <<
"] " <<
"for monitor: "
282 std::cout <<
"Failed to close mmap file\n";
296 std::cout <<
"Failed to open mmap file [" << mmap_filename.str() <<
"] "
298 <<
" : " << strerror(errno) <<
'\n';
299 std::cout <<
"Falling back to the legacy shared memory method\n";
307 int shmid = shmget((shmKey & 0xffff0000) |
m_monId,
308 shared_data_size, SHM_R);
311 std::cout <<
"Failed to shmget for monitor: " <<
m_monId <<
'\n';
315 case EACCES: std::cout <<
"EACCES - no rights to access segment\n";
break;
316 case EEXIST: std::cout <<
"EEXIST - segment already exists\n";
break;
317 case EINVAL: std::cout <<
"EINVAL - size < SHMMIN or size > SHMMAX\n";
break;
318 case ENFILE: std::cout <<
"ENFILE - limit on open files has been reached\n";
break;
319 case ENOENT: std::cout <<
"ENOENT - no segment exists for the given key\n";
break;
320 case ENOMEM: std::cout <<
"ENOMEM - couldn't reserve memory for segment\n";
break;
321 case ENOSPC: std::cout <<
"ENOSPC - shmmni or shmall limit reached\n";
break;
327 m_shmPtr = shmat(shmid,
nullptr, SHM_RDONLY);
332 std::cout <<
"Failed to shmat for monitor: " <<
m_monId <<
'\n';
422 std::stringstream out;
515 if (!setting.empty())
518 sscanf(setting.c_str(),
"%20llx", &tmp);
524 std::cout <<
"Shared memory key is: 0x"
525 << std::hex << (
unsigned int)
m_shmKey
537 std::cout <<
"Memory path directory is: " <<
m_mmapPath <<
'\n';
542 int eventDigits = atoi(setting.c_str());
543 std::string eventDigitsFmt =
"%0" + std::to_string(eventDigits) +
"d";
558 std::cout <<
"using deep storage directory structure\n";
560 std::cout <<
"using flat directory structure\n";
568 std::cout <<
"using analysis images\n";
570 std::cout <<
"not using analysis images\n";
580 if (mon->m_mapFile != -1)
582 if (
close(mon->m_mapFile) == -1)
583 std::cout <<
"Failed to close mapFile\n";
586 std::cout <<
"Closed mapFile for monitor: " << mon->m_name <<
'\n';
596 std::cout <<
"ZMServer destroyed\n";
603 std::string::size_type startPos = 0;
604 std::string::size_type endPos = 0;
606 while((endPos = command.find(
"[]:[]", startPos)) != std::string::npos)
608 token = command.substr(startPos, endPos - startPos);
609 tokens.push_back(token);
610 startPos = endPos + 5;
614 if (endPos != command.length())
616 token = command.substr(startPos);
617 tokens.push_back(token);
629 int dataLen = atoi(len);
633 std::string s(buf+8);
634 std::vector<std::string> tokens;
641 std::cout <<
"Processing: '" << tokens[0] <<
"'\n";
643 if (tokens[0] ==
"HELLO")
645 else if (tokens[0] ==
"QUIT")
647 else if (tokens[0] ==
"GET_SERVER_STATUS")
649 else if (tokens[0] ==
"GET_MONITOR_STATUS")
651 else if (tokens[0] ==
"GET_ALARM_STATES")
653 else if (tokens[0] ==
"GET_EVENT_LIST")
655 else if (tokens[0] ==
"GET_EVENT_DATES")
657 else if (tokens[0] ==
"GET_EVENT_FRAME")
659 else if (tokens[0] ==
"GET_ANALYSE_FRAME")
661 else if (tokens[0] ==
"GET_LIVE_FRAME")
663 else if (tokens[0] ==
"GET_FRAME_LIST")
665 else if (tokens[0] ==
"GET_CAMERA_LIST")
667 else if (tokens[0] ==
"GET_MONITOR_LIST")
669 else if (tokens[0] ==
"DELETE_EVENT")
671 else if (tokens[0] ==
"DELETE_EVENT_LIST")
673 else if (tokens[0] ==
"RUN_ZMAUDIT")
675 else if (tokens[0] ==
"SET_MONITOR_FUNCTION")
678 send(
"UNKNOWN_COMMAND");
686 std::string str =
"0000000" + std::to_string(s.size());
687 str.erase(0, str.size()-8);
697bool ZMServer::send(
const std::string &s,
const unsigned char *buffer,
int dataLen)
const
700 std::string str =
"0000000" + std::to_string(s.size());
701 str.erase(0, str.size()-8);
735 constexpr uintmax_t k_unknown_size {
static_cast<std::uintmax_t
>(-1)};
737 (space_info.capacity == 0
738 || space_info.free == 0
739 || space_info.available == 0
741 (space_info.capacity == k_unknown_size
742 || space_info.free == k_unknown_size
743 || space_info.available == k_unknown_size
749 return (100 * (space_info.capacity - space_info.available)) / space_info.capacity;
762 std::array<double,3> loads {};
770 std::string buf = std::to_string(loads[0]);
771 buf.resize(buf.size() - 4);
775 std::string eventsDir =
g_webPath +
"/events/";
794 ADD_INT(outStr, monitor->m_monId);
797 ADD_INT(outStr, monitor->getState());
807 if (tokens.size() != 5)
813 const std::string& monitor = tokens[1];
814 bool oldestFirst = (tokens[2] ==
"1");
815 const std::string& date = tokens[3];
816 bool includeContinuous = (tokens[4] ==
"1");
819 std::cout <<
"Loading events for monitor: " << monitor <<
", date: " << date <<
'\n';
823 std::string sql(
"SELECT E.Id, E.Name, M.Id AS MonitorID, M.Name AS MonitorName, E.StartTime, "
824 "E.Length, M.Width, M.Height, M.DefaultRate, M.DefaultScale "
825 "from Events as E inner join Monitors as M on E.MonitorId = M.Id ");
827 if (monitor !=
"<ANY>")
829 sql +=
"WHERE M.Name = '" + monitor +
"' ";
832 sql +=
"AND DATE(E.StartTime) = DATE('" + date +
"') ";
838 sql +=
"WHERE DATE(E.StartTime) = DATE('" + date +
"') ";
840 if (!includeContinuous)
841 sql +=
"AND Cause != 'Continuous' ";
844 if (!includeContinuous)
846 sql +=
"WHERE Cause != 'Continuous' ";
851 sql +=
"ORDER BY E.StartTime ASC";
853 sql +=
"ORDER BY E.StartTime DESC";
855 if (mysql_query(&
g_dbConn, sql.c_str()))
862 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
863 int eventCount = mysql_num_rows(res);
866 std::cout <<
"Got " << eventCount <<
" events\n";
870 for (
int x = 0; x < eventCount; x++)
872 MYSQL_ROW row = mysql_fetch_row(res);
885 std::cout <<
"Failed to get mysql row\n";
891 mysql_free_result(res);
900 if (tokens.size() != 3)
906 const std::string& monitor = tokens[1];
907 bool oldestFirst = (tokens[2] ==
"1");
910 std::cout <<
"Loading event dates for monitor: " << monitor <<
'\n';
914 std::string sql(
"SELECT DISTINCT DATE(E.StartTime) "
915 "from Events as E inner join Monitors as M on E.MonitorId = M.Id ");
917 if (monitor !=
"<ANY>")
918 sql +=
"WHERE M.Name = '" + monitor +
"' ";
921 sql +=
"ORDER BY E.StartTime ASC";
923 sql +=
"ORDER BY E.StartTime DESC";
925 if (mysql_query(&
g_dbConn, sql.c_str()))
932 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
933 int dateCount = mysql_num_rows(res);
936 std::cout <<
"Got " << dateCount <<
" dates\n";
940 for (
int x = 0; x < dateCount; x++)
942 MYSQL_ROW row = mysql_fetch_row(res);
949 std::cout <<
"Failed to get mysql row\n";
955 mysql_free_result(res);
967 std::string sql(
"SELECT Id, Name, Type, Device, Host, Channel, `Function`, Enabled "
969 if (mysql_query(&
g_dbConn, sql.c_str()))
976 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
979 int monitorCount = mysql_num_rows(res);
982 std::cout <<
"Got " << monitorCount <<
" monitors\n";
986 for (
int x = 0; x < monitorCount; x++)
988 MYSQL_ROW row = mysql_fetch_row(res);
991 std::string
id = row[0];
992 std::string
type = row[2];
993 std::string device = row[3];
994 std::string host = row[4] ? row[4] :
"";
995 std::string channel = row[5];
996 std::string function = row[6];
997 std::string enabled = row[7];
998 std::string name = row[1];
1000 std::string zmcStatus;
1001 std::string zmaStatus;
1003 zmcStatus, zmaStatus, enabled);
1005 std::string sql2(
"SELECT count(if(Archived=0,1,NULL)) AS EventCount "
1007 "WHERE MonitorId = " +
id);
1009 if (mysql_query(&
g_dbConn, sql2.c_str()))
1016 MYSQL_RES *res2 = mysql_store_result(&
g_dbConn);
1017 if (mysql_num_rows(res2) > 0)
1019 MYSQL_ROW row2 = mysql_fetch_row(res2);
1026 std::cout <<
"Failed to get mysql row\n";
1040 mysql_free_result(res2);
1044 std::cout <<
"Failed to get mysql row\n";
1050 mysql_free_result(res);
1058 FILE *fd = popen(command.c_str(),
"r");
1061 std::cout <<
"Call to popen() failed.\n";
1065 std::array<char,100> buffer {};
1066 while (fgets(buffer.data(), buffer.size(), fd) !=
nullptr)
1068 outStr += buffer.data();
1075 const std::string &device,
const std::string &host,
1076 const std::string &channel,
const std::string &function,
1077 std::string &zmcStatus, std::string &zmaStatus,
1078 const std::string &enabled)
1083 std::string command(
g_binPath +
"/zmdc.pl status");
1086 if (
type ==
"Local")
1089 zmaStatus = device +
"(" + channel +
") [-]";
1090 else if (status.find(
"'zma -m " +
id +
"' running") != std::string::npos)
1091 zmaStatus = device +
"(" + channel +
") [R]";
1093 zmaStatus = device +
"(" + channel +
") [S]";
1098 zmaStatus = host +
" [-]";
1099 else if (status.find(
"'zma -m " +
id +
"' running") != std::string::npos)
1100 zmaStatus = host +
" [R]";
1102 zmaStatus = host +
" [S]";
1105 if (
type ==
"Local")
1108 zmcStatus = function +
" [-]";
1109 else if (status.find(
"'zmc -d "+ device +
"' running") != std::string::npos)
1110 zmcStatus = function +
" [R]";
1112 zmcStatus = function +
" [S]";
1117 zmcStatus = function +
" [-]";
1118 else if (status.find(
"'zmc -m " +
id +
"' running") != std::string::npos)
1119 zmcStatus = function +
" [R]";
1121 zmcStatus = function +
" [S]";
1129 if (tokens.size() != 5)
1135 const std::string& monitorID(tokens[1]);
1136 const std::string& eventID(tokens[2]);
1137 int frameNo = atoi(tokens[3].c_str());
1138 const std::string& eventTime(tokens[4]);
1142 std::cout <<
"Getting frame " << frameNo <<
" for event " << eventID
1143 <<
" on monitor " << monitorID <<
" event time is " << eventTime
1152 std::string filepath;
1153 std::string str (100,
'\0');
1161 sscanf(eventTime.data(),
"%2d/%2d/%2d", &year, &month, &day);
1162 sprintf(str.data(),
"20%02d-%02d-%02d", year, month, day);
1164 filepath =
g_eventsPath +
"/" + monitorID +
"/" + str +
"/" + eventID +
"/";
1172 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventTime +
"/";
1178 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventID +
"/";
1185 FILE *fd = fopen(filepath.c_str(),
"r" );
1188 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1193 std::cout <<
"Can't open " << filepath <<
": " << strerror(errno) <<
'\n';
1199 std::cout <<
"Frame size: " << fileSize <<
'\n';
1205 send(outStr, s_buffer.data(), fileSize);
1211 std::array<char,100> str {};
1213 if (tokens.size() != 5)
1219 const std::string& monitorID(tokens[1]);
1220 const std::string& eventID(tokens[2]);
1221 int frameNo = atoi(tokens[3].c_str());
1222 const std::string& eventTime(tokens[4]);
1228 std::cout <<
"Getting analysis frame " << frameNo <<
" for event " << eventID
1229 <<
" on monitor " << monitorID <<
" event time is " << eventTime
1235 sql +=
"SELECT FrameId FROM Frames ";
1236 sql +=
"WHERE EventID = " + eventID +
" ";
1237 sql +=
"AND Type = 'Alarm' ";
1238 sql +=
"ORDER BY FrameID";
1240 if (mysql_query(&
g_dbConn, sql.c_str()))
1247 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1248 frameCount = mysql_num_rows(res);
1251 if (frameCount == 0)
1253 mysql_free_result(res);
1255 sql =
"SELECT FrameId FROM Frames ";
1256 sql +=
"WHERE EventID = " + eventID +
" ";
1257 sql +=
"ORDER BY FrameID";
1259 if (mysql_query(&
g_dbConn, sql.c_str()))
1266 res = mysql_store_result(&
g_dbConn);
1267 frameCount = mysql_num_rows(res);
1271 if (frameCount == 0)
1273 std::cout <<
"handleGetAnalyseFrame: Failed to find any frames\n";
1279 if (frameNo == 0 || frameNo < 0 || frameNo > frameCount)
1280 frameNo = (frameCount / 2) + 1;
1283 MYSQL_ROW row =
nullptr;
1284 for (
int x = 0; x < frameNo; x++)
1286 row = mysql_fetch_row(res);
1291 frameID = atoi(row[0]);
1295 std::cout <<
"handleGetAnalyseFrame: Failed to get mysql row for frameNo " << frameNo <<
'\n';
1300 mysql_free_result(res);
1303 std::string filepath;
1304 std::string frameFile;
1312 sscanf(eventTime.c_str(),
"%2d/%2d/%2d", &year, &month, &day);
1313 sprintf(str.data(),
"20%02d-%02d-%02d", year, month, day);
1314 filepath =
g_eventsPath +
"/" + monitorID +
"/" + str.data() +
"/" + eventID +
"/";
1319 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventTime +
"/";
1321 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventID +
"/";
1333 frameFile = filepath + str.data();
1335 fd = fopen(frameFile.c_str(),
"r" );
1338 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1342 std::cout <<
"Frame size: " << fileSize <<
'\n';
1348 send(outStr, s_buffer.data(), fileSize);
1355 frameFile = filepath + str.data();
1357 fd = fopen(frameFile.c_str(),
"r" );
1360 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1365 std::cout <<
"Can't open " << frameFile <<
": " << strerror(errno) <<
'\n';
1371 std::cout <<
"Frame size: " << fileSize <<
'\n';
1377 send(outStr, s_buffer.data(), fileSize);
1390 if (tokens.size() != 2)
1396 int monitorID = atoi(tokens[1].c_str());
1399 std::cout <<
"Getting live frame from monitor: " << monitorID <<
'\n';
1424 int dataSize =
getFrame(s_buffer, monitor);
1427 std::cout <<
"Frame size: " << dataSize <<
'\n';
1433 ADD_STR(outStr,
"WARNING - No new frame available");
1445 send(outStr, s_buffer.data(), dataSize);
1450 std::string eventID;
1453 if (tokens.size() != 2)
1459 eventID = tokens[1];
1462 std::cout <<
"Loading frames for event: " << eventID <<
'\n';
1467 std::string sql =
"SELECT Cause, Length, Frames FROM Events ";
1468 sql +=
"WHERE Id = " + eventID +
" ";
1470 if (mysql_query(&
g_dbConn, sql.c_str()))
1477 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1478 MYSQL_ROW row = mysql_fetch_row(res);
1481 if (row[1] ==
nullptr || row[2] ==
nullptr)
1487 std::string cause = row[0];
1488 double length = atof(row[1]);
1489 int frameCount = atoi(row[2]);
1491 mysql_free_result(res);
1493 if (cause ==
"Continuous")
1498 std::cout <<
"Got " << frameCount <<
" frames (continuous event)\n";
1504 double delta = length / frameCount;
1506 for (
int x = 0; x < frameCount; x++)
1509 ADD_STR(outStr, std::to_string(delta));
1515 sql =
"SELECT Type, Delta FROM Frames ";
1516 sql +=
"WHERE EventID = " + eventID +
" ";
1517 sql +=
"ORDER BY FrameID";
1519 if (mysql_query(&
g_dbConn, sql.c_str()))
1526 res = mysql_store_result(&
g_dbConn);
1527 frameCount = mysql_num_rows(res);
1530 std::cout <<
"Got " << frameCount <<
" frames\n";
1534 for (
int x = 0; x < frameCount; x++)
1536 row = mysql_fetch_row(res);
1544 std::cout <<
"handleGetFrameList: Failed to get mysql row " << x <<
'\n';
1550 mysql_free_result(res);
1566 ADD_STR(outStr, monitor->m_name);
1579 std::cout <<
"We have " <<
m_monitors.size() <<
" monitors\n";
1585 ADD_INT(outStr, mon->m_monId);
1587 ADD_INT(outStr, mon->m_width);
1588 ADD_INT(outStr, mon->m_height);
1589 ADD_INT(outStr, mon->m_bytesPerPixel);
1593 std::cout <<
"id: " << mon->m_monId <<
'\n';
1594 std::cout <<
"name: " << mon->m_name <<
'\n';
1595 std::cout <<
"width: " << mon->m_width <<
'\n';
1596 std::cout <<
"height: " << mon->m_height <<
'\n';
1597 std::cout <<
"palette: " << mon->m_palette <<
'\n';
1598 std::cout <<
"byte per pixel: " << mon->m_bytesPerPixel <<
'\n';
1599 std::cout <<
"sub pixel order:" << mon->getSubpixelOrder() <<
'\n';
1600 std::cout <<
"-------------------\n";
1609 std::string eventID;
1612 if (tokens.size() != 2)
1618 eventID = tokens[1];
1621 std::cout <<
"Deleting event: " << eventID <<
'\n';
1626 sql +=
"DELETE FROM Events WHERE Id = " + eventID;
1628 if (mysql_query(&
g_dbConn, sql.c_str()))
1636 std::string command(
g_binPath +
"/zmaudit.pl &");
1638 if (system(command.c_str()) < 0 && errno)
1639 std::cerr <<
"Failed to run '" << command <<
"'\n";
1646 std::string eventList;
1649 auto it = tokens.begin();
1650 if (it != tokens.end())
1652 while (it != tokens.end())
1654 if (eventList.empty())
1657 eventList +=
"," + (*it);
1663 std::cout <<
"Deleting events: " << eventList <<
'\n';
1666 sql +=
"DELETE FROM Events WHERE Id IN (" + eventList +
")";
1668 if (mysql_query(&
g_dbConn, sql.c_str()))
1684 std::string command(
g_binPath +
"/zmaudit.pl &");
1687 std::cout <<
"Running command: " << command <<
'\n';
1690 if (system(command.c_str()) < 0 && errno)
1691 std::cerr <<
"Failed to run '" << command <<
"'\n";
1703 std::string sql(
"SELECT Id, Name, Width, Height, ImageBufferCount, MaxFPS, Palette, ");
1704 sql +=
" Type, `Function`, Enabled, Device, Host, Controllable, TrackMotion";
1709 sql +=
" FROM Monitors";
1710 sql +=
" ORDER BY Sequence";
1712 if (mysql_query(&
g_dbConn, sql.c_str()))
1718 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1719 int monitorCount = mysql_num_rows(res);
1722 std::cout <<
"Got " << monitorCount <<
" monitors\n";
1724 for (
int x = 0; x < monitorCount; x++)
1726 MYSQL_ROW row = mysql_fetch_row(res);
1732 m->m_width = atoi(row[2]);
1733 m->m_height = atoi(row[3]);
1734 m->m_imageBufferCount = atoi(row[4]);
1735 m->m_palette = atoi(row[6]);
1737 m->m_function = row[8];
1738 m->m_enabled = atoi(row[9]);
1739 m->m_device = row[10];
1740 m->m_host = row[11] ? row[11] :
"";
1741 m->m_controllable = atoi(row[12]);
1742 m->m_trackMotion = atoi(row[13]);
1747 m->m_bytesPerPixel = atoi(row[14]);
1749 if (m->m_palette == 1)
1750 m->m_bytesPerPixel = 1;
1752 m->m_bytesPerPixel = 3;
1761 std::cout <<
"Failed to get mysql row\n";
1766 mysql_free_result(res);
1810 unsigned int rpos = 0;
1811 unsigned int wpos = 0;
1817 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 1)
1819 buffer[wpos + 0] = data[rpos + 0];
1820 buffer[wpos + 1] = data[rpos + 0];
1821 buffer[wpos + 2] = data[rpos + 0];
1829 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 3)
1831 buffer[wpos + 0] = data[rpos + 0];
1832 buffer[wpos + 1] = data[rpos + 1];
1833 buffer[wpos + 2] = data[rpos + 2];
1841 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 3)
1843 buffer[wpos + 0] = data[rpos + 2];
1844 buffer[wpos + 1] = data[rpos + 1];
1845 buffer[wpos + 2] = data[rpos + 0];
1852 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1854 buffer[wpos + 0] = data[rpos + 2];
1855 buffer[wpos + 1] = data[rpos + 1];
1856 buffer[wpos + 2] = data[rpos + 0];
1864 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3 ); wpos += 3, rpos += 4)
1866 buffer[wpos + 0] = data[rpos + 0];
1867 buffer[wpos + 1] = data[rpos + 1];
1868 buffer[wpos + 2] = data[rpos + 2];
1876 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1878 buffer[wpos + 0] = data[rpos + 3];
1879 buffer[wpos + 1] = data[rpos + 2];
1880 buffer[wpos + 2] = data[rpos + 1];
1888 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1890 buffer[wpos + 0] = data[rpos + 1];
1891 buffer[wpos + 1] = data[rpos + 2];
1892 buffer[wpos + 2] = data[rpos + 3];
1905 std::string sql(
"SELECT Name, Value FROM Config ");
1906 sql +=
"WHERE Name = '" + setting +
"'";
1908 if (mysql_query(&
g_dbConn, sql.c_str()))
1914 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1915 MYSQL_ROW row = mysql_fetch_row(res);
1922 std::cout <<
"Failed to get mysql row\n";
1927 std::cout <<
"getZMSetting: " << setting <<
" Result: " << result <<
'\n';
1929 mysql_free_result(res);
1938 if (tokens.size() != 4)
1944 const std::string& monitorID(tokens[1]);
1945 const std::string& function(tokens[2]);
1946 const std::string& enabled(tokens[3]);
1963 if (enabled !=
"0" && enabled !=
"1")
1970 std::cout <<
"User input validated OK\n";
1975 std::string oldFunction = monitor->
m_function;
1976 const std::string& newFunction = function;
1978 int newEnabled = atoi(enabled.c_str());
1984 std::cout <<
"SetMonitorFunction MonitorId: " << monitorID <<
'\n'
1985 <<
" oldEnabled: " << oldEnabled <<
'\n'
1986 <<
" newEnabled: " << newEnabled <<
'\n'
1987 <<
" oldFunction: " << oldFunction <<
'\n'
1988 <<
" newFunction: " << newFunction <<
'\n';
1991 if ( newFunction != oldFunction || newEnabled != oldEnabled)
1993 std::string sql(
"UPDATE Monitors ");
1994 sql +=
"SET Function = '" + function +
"', ";
1995 sql +=
"Enabled = '" + enabled +
"' ";
1996 sql +=
"WHERE Id = '" + monitorID +
"'";
1998 if (mysql_query(&
g_dbConn, sql.c_str()))
2006 std::cout <<
"Monitor function SQL update OK\n";
2014 std::cout <<
"Monitor function Refreshing daemons\n";
2018 (newEnabled != oldEnabled);
2029 std::cout <<
"zm daemons are not running\n";
2034 std::cout <<
"Not updating monitor function as identical to existing configuration\n";
2043 std::string zmcArgs;
2045 sql +=
"SELECT count(if(Function!='None',1,NULL)) as ActiveCount ";
2046 sql +=
"FROM Monitors ";
2048 if (monitor->
m_type ==
"Local" )
2050 sql +=
"WHERE Device = '" + monitor->
m_device +
"'";
2051 zmcArgs =
"-d " + monitor->
m_device;
2055 sql +=
"WHERE Id = '" + monitor->
getIdStr() +
"'";
2056 zmcArgs =
"-m " + monitor->
getIdStr();
2059 if (mysql_query(&
g_dbConn, sql.c_str()))
2066 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
2067 MYSQL_ROW row = mysql_fetch_row(res);
2073 int activeCount = atoi(row[0]);
2090 int zmOptControl = atoi(
getZMSetting(
"ZM_OPT_CONTROL").c_str());
2091 int zmOptFrameServer = atoi(
getZMSetting(
"ZM_OPT_FRAME_SERVER").c_str());
2105 if (zmOptFrameServer)
2109 if (zmOptFrameServer)
2128 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