25 #include <sys/socket.h>
27 #include <netinet/in.h>
34 # include <sys/statvfs.h>
35 # include <sys/sysinfo.h>
37 # include <sys/param.h>
38 # include <sys/mount.h>
40 # include <sys/statfs.h>
41 # else // if !__CYGWIN__
42 # include <sys/sysctl.h>
43 # endif // !__CYGWIN__
47 static constexpr
int MSG_NOSIGNAL { 0 };
55 static inline void ADD_STR(std::string& list,
const std::string& s)
56 { list += s; list +=
"[]:[]"; };
57 static inline void ADD_INT(std::string& list,
int n)
58 { list += std::to_string(n); list +=
"[]:[]"; };
111 std::cout <<
"loading zm config from " << configfile << std::endl;
113 std::ifstream ifs(configfile);
116 fprintf(
stderr,
"Can't open %s\n", configfile.c_str());
120 while ( std::getline(ifs, line) )
123 constexpr
const char *whitespace =
" \t\r\n";
124 auto begin = line.find_first_not_of(whitespace);
125 if (begin == std::string::npos)
127 auto end = line.find_last_not_of(whitespace);
128 if (end != std::string::npos)
130 line = line.substr(begin, end);
133 if ( line.empty() || line[0] ==
'#' )
137 auto index = line.find(
'=');
138 if (index == std::string::npos)
140 fprintf(
stderr,
"Invalid data in %s: '%s'\n", configfile.c_str(), line.c_str() );
145 std::string name = line.substr(0,index);
146 std::string val = line.substr(index+1);
149 end = name.find_last_not_of(whitespace);
150 if (end != std::string::npos)
152 name = name.substr(0, end);
155 begin = val.find_first_not_of(whitespace);
156 if (begin != std::string::npos)
157 val = val.substr(begin);
160 std::transform(name.cbegin(), name.cend(), name.begin(), ::toupper);
162 if ( name ==
"ZM_DB_HOST" )
g_server = val;
163 else if ( name ==
"ZM_DB_NAME" )
g_database = val;
164 else if ( name ==
"ZM_DB_USER" )
g_user = val;
165 else if ( name ==
"ZM_DB_PASS" )
g_password = val;
166 else if ( name ==
"ZM_PATH_WEB" )
g_webPath = val;
167 else if ( name ==
"ZM_PATH_BIN" )
g_binPath = val;
168 else if ( name ==
"ZM_WEB_USER" )
g_webUser = val;
169 else if ( name ==
"ZM_VERSION" )
g_zmversion = val;
170 else if ( name ==
"ZM_PATH_MAP" )
g_mmapPath = val;
175 #if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
185 std::cout <<
"Error: Can't initialise structure: " << mysql_error(&
g_dbConn) << std::endl;
186 exit(
static_cast<int>(mysql_errno(&
g_dbConn)));
190 mysql_options(&
g_dbConn, MYSQL_OPT_RECONNECT, &reconnect);
195 std::cout <<
"Error: Can't connect to server: " << mysql_error(&
g_dbConn) << std::endl;
196 exit(
static_cast<int>(mysql_errno( &
g_dbConn)));
201 std::cout <<
"Error: Can't select database: " << mysql_error(&
g_dbConn) << std::endl;
202 exit(
static_cast<int>(mysql_errno(&
g_dbConn)));
212 std::cout <<
"Kicking database connection" << std::endl;
216 if (mysql_query(&
g_dbConn,
"SELECT NULL;") == 0)
218 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
220 mysql_free_result(res);
224 std::cout <<
"Lost connection to DB - trying to reconnect" << std::endl;
235 size_t shared_data_size = 0;
270 #if _POSIX_MAPPED_FILES > 0L
275 std::stringstream mmap_filename;
276 mmap_filename << mmapPath <<
"/zm.mmap." <<
m_monId;
278 m_mapFile = open(mmap_filename.str().c_str(), O_RDONLY, 0
x0);
282 std::cout <<
"Opened mmap file: " << mmap_filename.str() << std::endl;
284 m_shmPtr = mmap(
nullptr, shared_data_size, PROT_READ,
288 std::cout <<
"Failed to map shared memory from file ["
289 << mmap_filename.str() <<
"] " <<
"for monitor: "
294 std::cout <<
"Failed to close mmap file" << std::endl;
308 std::cout <<
"Failed to open mmap file [" << mmap_filename.str() <<
"] "
310 <<
" : " << strerror(errno) << std::endl;
311 std::cout <<
"Falling back to the legacy shared memory method" << std::endl;
319 int shmid = shmget((shmKey & 0xffff0000) |
m_monId,
320 shared_data_size, SHM_R);
323 std::cout <<
"Failed to shmget for monitor: " <<
m_monId << std::endl;
327 case EACCES: std::cout <<
"EACCES - no rights to access segment\n";
break;
328 case EEXIST: std::cout <<
"EEXIST - segment already exists\n";
break;
329 case EINVAL: std::cout <<
"EINVAL - size < SHMMIN or size > SHMMAX\n";
break;
330 case ENFILE: std::cout <<
"ENFILE - limit on open files has been reached\n";
break;
331 case ENOENT: std::cout <<
"ENOENT - no segment exists for the given key\n";
break;
332 case ENOMEM: std::cout <<
"ENOMEM - couldn't reserve memory for segment\n";
break;
333 case ENOSPC: std::cout <<
"ENOSPC - shmmni or shmall limit reached\n";
break;
339 m_shmPtr = shmat(shmid,
nullptr, SHM_RDONLY);
344 std::cout <<
"Failed to shmat for monitor: " <<
m_monId << std::endl;
434 std::stringstream out;
527 if (!setting.empty())
530 sscanf(setting.c_str(),
"%20llx", &
tmp);
536 std::cout <<
"Shared memory key is: 0x"
537 << std::hex << (
unsigned int)
m_shmKey
538 << std::dec << std::endl;
549 std::cout <<
"Memory path directory is: " <<
m_mmapPath << std::endl;
554 int eventDigits = atoi(setting.c_str());
555 std::string eventDigitsFmt =
"%0" + std::to_string(eventDigits) +
"d";
570 std::cout <<
"using deep storage directory structure" << std::endl;
572 std::cout <<
"using flat directory structure" << std::endl;
580 std::cout <<
"using analysis images" << std::endl;
582 std::cout <<
"not using analysis images" << std::endl;
592 if (mon->m_mapFile != -1)
594 if (
close(mon->m_mapFile) == -1)
595 std::cout <<
"Failed to close mapFile" << std::endl;
598 std::cout <<
"Closed mapFile for monitor: " << mon->m_name << std::endl;
608 std::cout <<
"ZMServer destroyed\n";
615 std::string::size_type startPos = 0;
616 std::string::size_type endPos = 0;
618 while((endPos = command.find(
"[]:[]", startPos)) != std::string::npos)
620 token = command.substr(startPos, endPos - startPos);
621 tokens.push_back(token);
622 startPos = endPos + 5;
626 if (endPos != command.length())
628 token = command.substr(startPos);
629 tokens.push_back(token);
641 int dataLen = atoi(len);
645 std::string s(buf+8);
646 std::vector<std::string> tokens;
653 std::cout <<
"Processing: '" << tokens[0] <<
"'" << std::endl;
655 if (tokens[0] ==
"HELLO")
657 else if (tokens[0] ==
"QUIT")
659 else if (tokens[0] ==
"GET_SERVER_STATUS")
661 else if (tokens[0] ==
"GET_MONITOR_STATUS")
663 else if (tokens[0] ==
"GET_ALARM_STATES")
665 else if (tokens[0] ==
"GET_EVENT_LIST")
667 else if (tokens[0] ==
"GET_EVENT_DATES")
669 else if (tokens[0] ==
"GET_EVENT_FRAME")
671 else if (tokens[0] ==
"GET_ANALYSE_FRAME")
673 else if (tokens[0] ==
"GET_LIVE_FRAME")
675 else if (tokens[0] ==
"GET_FRAME_LIST")
677 else if (tokens[0] ==
"GET_CAMERA_LIST")
679 else if (tokens[0] ==
"GET_MONITOR_LIST")
681 else if (tokens[0] ==
"DELETE_EVENT")
683 else if (tokens[0] ==
"DELETE_EVENT_LIST")
685 else if (tokens[0] ==
"RUN_ZMAUDIT")
687 else if (tokens[0] ==
"SET_MONITOR_FUNCTION")
690 send(
"UNKNOWN_COMMAND");
698 std::string str =
"0000000" + std::to_string(s.size());
699 str.erase(0, str.size()-8);
700 int status =
::send(
m_sock, str.data(), 8, MSG_NOSIGNAL);
705 status =
::send(
m_sock, s.c_str(), s.size(), MSG_NOSIGNAL);
709 bool ZMServer::send(
const std::string &s,
const unsigned char *buffer,
int dataLen)
const
712 std::string str =
"0000000" + std::to_string(s.size());
713 str.erase(0, str.size()-8);
714 int status =
::send(
m_sock, str.data(), 8, MSG_NOSIGNAL);
719 status =
::send(
m_sock, s.c_str(), s.size(), MSG_NOSIGNAL);
748 long long freespace = -1;
766 freespace = freespace >> 10;
768 used = total - freespace;
784 std::array<double,3> loads {};
792 std::string buf = std::to_string(loads[0]);
793 buf.resize(buf.size() - 4);
800 std::string eventsDir =
g_webPath +
"/events/";
802 std::string buf = std::to_string(
static_cast<int>((used * 100) / total)) +
"%";
819 ADD_INT(outStr, monitor->m_monId);
822 ADD_INT(outStr, monitor->getState());
832 if (tokens.size() != 5)
838 std::string monitor = tokens[1];
839 bool oldestFirst = (tokens[2] ==
"1");
840 std::string date = tokens[3];
841 bool includeContinuous = (tokens[4] ==
"1");
844 std::cout <<
"Loading events for monitor: " << monitor <<
", date: " << date << std::endl;
848 std::string sql(
"SELECT E.Id, E.Name, M.Id AS MonitorID, M.Name AS MonitorName, E.StartTime, "
849 "E.Length, M.Width, M.Height, M.DefaultRate, M.DefaultScale "
850 "from Events as E inner join Monitors as M on E.MonitorId = M.Id ");
852 if (monitor !=
"<ANY>")
854 sql +=
"WHERE M.Name = '" + monitor +
"' ";
857 sql +=
"AND DATE(E.StartTime) = DATE('" + date +
"') ";
863 sql +=
"WHERE DATE(E.StartTime) = DATE('" + date +
"') ";
865 if (!includeContinuous)
866 sql +=
"AND Cause != 'Continuous' ";
869 if (!includeContinuous)
870 sql +=
"WHERE Cause != 'Continuous' ";
874 sql +=
"ORDER BY E.StartTime ASC";
876 sql +=
"ORDER BY E.StartTime DESC";
878 if (mysql_query(&
g_dbConn, sql.c_str()))
885 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
886 int eventCount = mysql_num_rows(res);
889 std::cout <<
"Got " << eventCount <<
" events" << std::endl;
893 for (
int x = 0; x < eventCount; x++)
895 MYSQL_ROW row = mysql_fetch_row(res);
908 std::cout <<
"Failed to get mysql row" << std::endl;
914 mysql_free_result(res);
923 if (tokens.size() != 3)
929 std::string monitor = tokens[1];
930 bool oldestFirst = (tokens[2] ==
"1");
933 std::cout <<
"Loading event dates for monitor: " << monitor << std::endl;
937 std::string sql(
"SELECT DISTINCT DATE(E.StartTime) "
938 "from Events as E inner join Monitors as M on E.MonitorId = M.Id ");
940 if (monitor !=
"<ANY>")
941 sql +=
"WHERE M.Name = '" + monitor +
"' ";
944 sql +=
"ORDER BY E.StartTime ASC";
946 sql +=
"ORDER BY E.StartTime DESC";
948 if (mysql_query(&
g_dbConn, sql.c_str()))
955 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
956 int dateCount = mysql_num_rows(res);
959 std::cout <<
"Got " << dateCount <<
" dates" << std::endl;
963 for (
int x = 0; x < dateCount; x++)
965 MYSQL_ROW row = mysql_fetch_row(res);
972 std::cout <<
"Failed to get mysql row" << std::endl;
978 mysql_free_result(res);
990 std::string sql(
"SELECT Id, Name, Type, Device, Host, Channel, `Function`, Enabled "
992 if (mysql_query(&
g_dbConn, sql.c_str()))
999 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1002 int monitorCount = mysql_num_rows(res);
1005 std::cout <<
"Got " << monitorCount <<
" monitors" << std::endl;
1007 ADD_INT(outStr, monitorCount);
1009 for (
int x = 0; x < monitorCount; x++)
1011 MYSQL_ROW row = mysql_fetch_row(res);
1014 std::string
id = row[0];
1015 std::string
type = row[2];
1016 std::string device = row[3];
1017 std::string host = row[4] ? row[4] :
"";
1018 std::string channel = row[5];
1019 std::string
function = row[6];
1020 std::string enabled = row[7];
1021 std::string name = row[1];
1023 std::string zmcStatus;
1024 std::string zmaStatus;
1026 zmcStatus, zmaStatus, enabled);
1028 std::string sql2(
"SELECT count(if(Archived=0,1,NULL)) AS EventCount "
1030 "WHERE MonitorId = " +
id);
1032 if (mysql_query(&
g_dbConn, sql2.c_str()))
1039 MYSQL_RES *res2 = mysql_store_result(&
g_dbConn);
1040 if (mysql_num_rows(res2) > 0)
1042 MYSQL_ROW row2 = mysql_fetch_row(res2);
1047 std::cout <<
"Failed to get mysql row" << std::endl;
1061 mysql_free_result(res2);
1065 std::cout <<
"Failed to get mysql row" << std::endl;
1071 mysql_free_result(res);
1079 FILE *fd = popen(command.c_str(),
"r");
1080 std::array<char,100> buffer {};
1082 while (fgets(buffer.data(), buffer.size(), fd) !=
nullptr)
1084 outStr += buffer.data();
1091 const std::string &device,
const std::string &host,
1092 const std::string &channel,
const std::string &
function,
1093 std::string &zmcStatus, std::string &zmaStatus,
1094 const std::string &enabled)
1099 std::string command(
g_binPath +
"/zmdc.pl status");
1102 if (
type ==
"Local")
1105 zmaStatus = device +
"(" + channel +
") [-]";
1106 else if (status.find(
"'zma -m " +
id +
"' running") != std::string::npos)
1107 zmaStatus = device +
"(" + channel +
") [R]";
1109 zmaStatus = device +
"(" + channel +
") [S]";
1114 zmaStatus = host +
" [-]";
1115 else if (status.find(
"'zma -m " +
id +
"' running") != std::string::npos)
1116 zmaStatus = host +
" [R]";
1118 zmaStatus = host +
" [S]";
1121 if (
type ==
"Local")
1124 zmcStatus =
function +
" [-]";
1125 else if (status.find(
"'zmc -d "+ device +
"' running") != std::string::npos)
1126 zmcStatus =
function +
" [R]";
1128 zmcStatus =
function +
" [S]";
1133 zmcStatus =
function +
" [-]";
1134 else if (status.find(
"'zmc -m " +
id +
"' running") != std::string::npos)
1135 zmcStatus =
function +
" [R]";
1137 zmcStatus =
function +
" [S]";
1145 if (tokens.size() != 5)
1151 std::string monitorID(tokens[1]);
1152 std::string eventID(tokens[2]);
1153 int frameNo = atoi(tokens[3].c_str());
1154 std::string eventTime(tokens[4]);
1158 std::cout <<
"Getting frame " << frameNo <<
" for event " << eventID
1159 <<
" on monitor " << monitorID <<
" event time is " << eventTime
1168 std::string filepath;
1169 std::string str (100,
'\0');
1177 sscanf(eventTime.data(),
"%2d/%2d/%2d", &year, &month, &day);
1178 sprintf(str.data(),
"20%02d-%02d-%02d", year, month, day);
1180 filepath =
g_eventsPath +
"/" + monitorID +
"/" + str +
"/" + eventID +
"/";
1188 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventTime +
"/";
1194 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventID +
"/";
1201 FILE *fd = fopen(filepath.c_str(),
"r" );
1204 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1209 std::cout <<
"Can't open " << filepath <<
": " << strerror(errno) << std::endl;
1215 std::cout <<
"Frame size: " << fileSize << std::endl;
1221 send(outStr, s_buffer.data(), fileSize);
1227 std::array<char,100> str {};
1229 if (tokens.size() != 5)
1235 std::string monitorID(tokens[1]);
1236 std::string eventID(tokens[2]);
1237 int frameNo = atoi(tokens[3].c_str());
1238 std::string eventTime(tokens[4]);
1244 std::cout <<
"Getting analysis frame " << frameNo <<
" for event " << eventID
1245 <<
" on monitor " << monitorID <<
" event time is " << eventTime
1251 sql +=
"SELECT FrameId FROM Frames ";
1252 sql +=
"WHERE EventID = " + eventID +
" ";
1253 sql +=
"AND Type = 'Alarm' ";
1254 sql +=
"ORDER BY FrameID";
1256 if (mysql_query(&
g_dbConn, sql.c_str()))
1263 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1264 frameCount = mysql_num_rows(res);
1267 if (frameCount == 0)
1269 mysql_free_result(res);
1271 sql =
"SELECT FrameId FROM Frames ";
1272 sql +=
"WHERE EventID = " + eventID +
" ";
1273 sql +=
"ORDER BY FrameID";
1275 if (mysql_query(&
g_dbConn, sql.c_str()))
1282 res = mysql_store_result(&
g_dbConn);
1283 frameCount = mysql_num_rows(res);
1287 if (frameCount == 0)
1289 std::cout <<
"handleGetAnalyseFrame: Failed to find any frames" << std::endl;
1295 if (frameNo == 0 || frameNo < 0 || frameNo > frameCount)
1296 frameNo = (frameCount / 2) + 1;
1299 MYSQL_ROW row =
nullptr;
1300 for (
int x = 0; x < frameNo; x++)
1302 row = mysql_fetch_row(res);
1307 frameID = atoi(row[0]);
1311 std::cout <<
"handleGetAnalyseFrame: Failed to get mysql row for frameNo " << frameNo << std::endl;
1316 mysql_free_result(res);
1319 std::string filepath;
1320 std::string frameFile;
1328 sscanf(eventTime.c_str(),
"%2d/%2d/%2d", &year, &month, &day);
1329 sprintf(str.data(),
"20%02d-%02d-%02d", year, month, day);
1330 filepath =
g_eventsPath +
"/" + monitorID +
"/" + str.data() +
"/" + eventID +
"/";
1335 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventTime +
"/";
1337 filepath =
g_webPath +
"/events/" + monitorID +
"/" + eventID +
"/";
1349 frameFile = filepath + str.data();
1351 if ((fd = fopen(frameFile.c_str(),
"r" )))
1353 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1357 std::cout <<
"Frame size: " << fileSize << std::endl;
1363 send(outStr, s_buffer.data(), fileSize);
1370 frameFile = filepath + str.data();
1372 if ((fd = fopen(frameFile.c_str(),
"r" )))
1374 fileSize = fread(s_buffer.data(), 1, s_buffer.size(), fd);
1379 std::cout <<
"Can't open " << frameFile <<
": " << strerror(errno) << std::endl;
1385 std::cout <<
"Frame size: " << fileSize << std::endl;
1391 send(outStr, s_buffer.data(), fileSize);
1404 if (tokens.size() != 2)
1410 int monitorID = atoi(tokens[1].c_str());
1413 std::cout <<
"Getting live frame from monitor: " << monitorID << std::endl;
1438 int dataSize =
getFrame(s_buffer, monitor);
1441 std::cout <<
"Frame size: " << dataSize << std::endl;
1447 ADD_STR(outStr,
"WARNING - No new frame available");
1459 send(outStr, s_buffer.data(), dataSize);
1464 std::string eventID;
1467 if (tokens.size() != 2)
1473 eventID = tokens[1];
1476 std::cout <<
"Loading frames for event: " << eventID << std::endl;
1481 std::string sql =
"SELECT Cause, Length, Frames FROM Events ";
1482 sql +=
"WHERE Id = " + eventID +
" ";
1484 if (mysql_query(&
g_dbConn, sql.c_str()))
1491 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1492 MYSQL_ROW row = mysql_fetch_row(res);
1495 if (row[1] ==
nullptr || row[2] ==
nullptr)
1501 std::string cause = row[0];
1502 double length = atof(row[1]);
1503 int frameCount = atoi(row[2]);
1505 mysql_free_result(res);
1507 if (cause ==
"Continuous")
1512 std::cout <<
"Got " << frameCount <<
" frames (continuous event)" << std::endl;
1518 double delta = length / frameCount;
1520 for (
int x = 0; x < frameCount; x++)
1523 ADD_STR(outStr, std::to_string(delta));
1529 sql =
"SELECT Type, Delta FROM Frames ";
1530 sql +=
"WHERE EventID = " + eventID +
" ";
1531 sql +=
"ORDER BY FrameID";
1533 if (mysql_query(&
g_dbConn, sql.c_str()))
1540 res = mysql_store_result(&
g_dbConn);
1541 frameCount = mysql_num_rows(res);
1544 std::cout <<
"Got " << frameCount <<
" frames" << std::endl;
1548 for (
int x = 0; x < frameCount; x++)
1550 row = mysql_fetch_row(res);
1558 std::cout <<
"handleGetFrameList: Failed to get mysql row " << x << std::endl;
1564 mysql_free_result(res);
1580 ADD_STR(outStr, monitor->m_name);
1593 std::cout <<
"We have " <<
m_monitors.size() <<
" monitors" << std::endl;
1599 ADD_INT(outStr, mon->m_monId);
1601 ADD_INT(outStr, mon->m_width);
1602 ADD_INT(outStr, mon->m_height);
1603 ADD_INT(outStr, mon->m_bytesPerPixel);
1607 std::cout <<
"id: " << mon->m_monId << std::endl;
1608 std::cout <<
"name: " << mon->m_name << std::endl;
1609 std::cout <<
"width: " << mon->m_width << std::endl;
1610 std::cout <<
"height: " << mon->m_height << std::endl;
1611 std::cout <<
"palette: " << mon->m_palette << std::endl;
1612 std::cout <<
"byte per pixel: " << mon->m_bytesPerPixel << std::endl;
1613 std::cout <<
"sub pixel order:" << mon->getSubpixelOrder() << std::endl;
1614 std::cout <<
"-------------------" << std::endl;
1623 std::string eventID;
1626 if (tokens.size() != 2)
1632 eventID = tokens[1];
1635 std::cout <<
"Deleting event: " << eventID << std::endl;
1640 sql +=
"DELETE FROM Events WHERE Id = " + eventID;
1642 if (mysql_query(&
g_dbConn, sql.c_str()))
1650 std::string command(
g_binPath +
"/zmaudit.pl &");
1652 if (system(command.c_str()) < 0 && errno)
1653 std::cerr <<
"Failed to run '" << command <<
"'" << std::endl;
1660 std::string eventList;
1663 auto it = tokens.begin();
1664 if (it != tokens.end())
1666 while (it != tokens.end())
1668 if (eventList.empty())
1671 eventList +=
"," + (*it);
1677 std::cout <<
"Deleting events: " << eventList << std::endl;
1680 sql +=
"DELETE FROM Events WHERE Id IN (" + eventList +
")";
1682 if (mysql_query(&
g_dbConn, sql.c_str()))
1698 std::string command(
g_binPath +
"/zmaudit.pl &");
1701 std::cout <<
"Running command: " << command << std::endl;
1704 if (system(command.c_str()) < 0 && errno)
1705 std::cerr <<
"Failed to run '" << command <<
"'" << std::endl;
1717 std::string sql(
"SELECT Id, Name, Width, Height, ImageBufferCount, MaxFPS, Palette, ");
1718 sql +=
" Type, `Function`, Enabled, Device, Host, Controllable, TrackMotion";
1723 sql +=
" FROM Monitors";
1724 sql +=
" ORDER BY Sequence";
1726 if (mysql_query(&
g_dbConn, sql.c_str()))
1732 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1733 int monitorCount = mysql_num_rows(res);
1736 std::cout <<
"Got " << monitorCount <<
" monitors" << std::endl;
1738 for (
int x = 0; x < monitorCount; x++)
1740 MYSQL_ROW row = mysql_fetch_row(res);
1746 m->m_width = atoi(row[2]);
1747 m->m_height = atoi(row[3]);
1748 m->m_imageBufferCount = atoi(row[4]);
1749 m->m_palette = atoi(row[6]);
1751 m->m_function = row[8];
1752 m->m_enabled = atoi(row[9]);
1753 m->m_device = row[10];
1754 m->m_host = row[11] ? row[11] :
"";
1755 m->m_controllable = atoi(row[12]);
1756 m->m_trackMotion = atoi(row[13]);
1761 m->m_bytesPerPixel = atoi(row[14]);
1763 if (m->m_palette == 1)
1764 m->m_bytesPerPixel = 1;
1766 m->m_bytesPerPixel = 3;
1775 std::cout <<
"Failed to get mysql row" << std::endl;
1780 mysql_free_result(res);
1824 unsigned int rpos = 0;
1825 unsigned int wpos = 0;
1831 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 1)
1833 buffer[wpos + 0] = data[rpos + 0];
1834 buffer[wpos + 1] = data[rpos + 0];
1835 buffer[wpos + 2] = data[rpos + 0];
1843 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 3)
1845 buffer[wpos + 0] = data[rpos + 0];
1846 buffer[wpos + 1] = data[rpos + 1];
1847 buffer[wpos + 2] = data[rpos + 2];
1855 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 3)
1857 buffer[wpos + 0] = data[rpos + 2];
1858 buffer[wpos + 1] = data[rpos + 1];
1859 buffer[wpos + 2] = data[rpos + 0];
1866 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1868 buffer[wpos + 0] = data[rpos + 2];
1869 buffer[wpos + 1] = data[rpos + 1];
1870 buffer[wpos + 2] = data[rpos + 0];
1878 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3 ); wpos += 3, rpos += 4)
1880 buffer[wpos + 0] = data[rpos + 0];
1881 buffer[wpos + 1] = data[rpos + 1];
1882 buffer[wpos + 2] = data[rpos + 2];
1890 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1892 buffer[wpos + 0] = data[rpos + 3];
1893 buffer[wpos + 1] = data[rpos + 2];
1894 buffer[wpos + 2] = data[rpos + 1];
1902 for (wpos = 0, rpos = 0; wpos < (
unsigned int) (monitor->
m_width * monitor->
m_height * 3); wpos += 3, rpos += 4)
1904 buffer[wpos + 0] = data[rpos + 1];
1905 buffer[wpos + 1] = data[rpos + 2];
1906 buffer[wpos + 2] = data[rpos + 3];
1919 std::string sql(
"SELECT Name, Value FROM Config ");
1920 sql +=
"WHERE Name = '" + setting +
"'";
1922 if (mysql_query(&
g_dbConn, sql.c_str()))
1928 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
1929 MYSQL_ROW row = mysql_fetch_row(res);
1936 std::cout <<
"Failed to get mysql row" << std::endl;
1941 std::cout <<
"getZMSetting: " << setting <<
" Result: " << result << std::endl;
1943 mysql_free_result(res);
1952 if (tokens.size() != 4)
1958 std::string monitorID(tokens[1]);
1959 std::string
function(tokens[2]);
1960 std::string enabled(tokens[3]);
1977 if (enabled !=
"0" && enabled !=
"1")
1984 std::cout <<
"User input validated OK" << std::endl;
1989 std::string oldFunction = monitor->
m_function;
1990 const std::string& newFunction =
function;
1992 int newEnabled = atoi(enabled.c_str());
1998 std::cout <<
"SetMonitorFunction MonitorId: " << monitorID << std::endl
1999 <<
" oldEnabled: " << oldEnabled << std::endl
2000 <<
" newEnabled: " << newEnabled << std::endl
2001 <<
" oldFunction: " << oldFunction << std::endl
2002 <<
" newFunction: " << newFunction << std::endl;
2005 if ( newFunction != oldFunction || newEnabled != oldEnabled)
2007 std::string sql(
"UPDATE Monitors ");
2008 sql +=
"SET Function = '" +
function +
"', ";
2009 sql +=
"Enabled = '" + enabled +
"' ";
2010 sql +=
"WHERE Id = '" + monitorID +
"'";
2012 if (mysql_query(&
g_dbConn, sql.c_str()))
2020 std::cout <<
"Monitor function SQL update OK" << std::endl;
2028 std::cout <<
"Monitor function Refreshing daemons" << std::endl;
2032 (newEnabled != oldEnabled);
2042 std::cout <<
"zm daemons are not running" << std::endl;
2045 std::cout <<
"Not updating monitor function as identical to existing configuration" << std::endl;
2053 std::string zmcArgs;
2055 sql +=
"SELECT count(if(Function!='None',1,NULL)) as ActiveCount ";
2056 sql +=
"FROM Monitors ";
2058 if (monitor->
m_type ==
"Local" )
2060 sql +=
"WHERE Device = '" + monitor->
m_device +
"'";
2061 zmcArgs =
"-d " + monitor->
m_device;
2065 sql +=
"WHERE Id = '" + monitor->
getIdStr() +
"'";
2066 zmcArgs =
"-m " + monitor->
getIdStr();
2069 if (mysql_query(&
g_dbConn, sql.c_str()))
2076 MYSQL_RES *res = mysql_store_result(&
g_dbConn);
2077 MYSQL_ROW row = mysql_fetch_row(res);
2083 int activeCount = atoi(row[0]);
2098 int zmOptControl = atoi(
getZMSetting(
"ZM_OPT_CONTROL").c_str());
2099 int zmOptFrameServer = atoi(
getZMSetting(
"ZM_OPT_FRAME_SERVER").c_str());
2113 if (zmOptFrameServer)
2117 if (zmOptFrameServer)
2136 if (zmOptFrameServer)