27 m_retryTimer(new QTimer(this))
29 setObjectName(
"ZMClient");
46 QString zmserver_host;
52 if (zmserver_host.isEmpty() || zmserver_port == -1)
54 LOG(VB_GENERAL, LOG_INFO,
"ZMClient: no valid IP or port found for mythzmserver");
74 LOG(VB_GENERAL, LOG_INFO,
75 QString(
"Connecting to zm server: %1:%2 (try %3 of 2)")
105 "Have you set the correct IP and port in the settings?"));
124 QStringList origStrList = strList;
132 LOG(VB_GENERAL, LOG_NOTICE,
"Connection to mythzmserver lost");
136 LOG(VB_GENERAL, LOG_ERR,
"Re-connection to mythzmserver failed");
141 strList = origStrList;
153 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
158 if (strList[0] ==
"UNKNOWN_COMMAND")
160 LOG(VB_GENERAL, LOG_ERR,
"Somethings is getting passed to the server "
161 "that it doesn't understand");
166 if (strList[0].startsWith(
"ERROR"))
168 LOG(VB_GENERAL, LOG_ERR,
169 QString(
"The server failed to process the command. "
170 "The error was:- \n\t\t\t%1").arg(strList[0]));
175 return strList[0] ==
"OK";
182 QStringList strList(
"HELLO");
185 LOG(VB_GENERAL, LOG_ERR, QString(
"Server didn't respond to 'HELLO'!!"));
187 ShowOkPopup(tr(
"The mythzmserver didn't respond to our request "
188 "to get the protocol version!!"));
193 if (strList.size() < 2)
195 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
201 LOG(VB_GENERAL, LOG_ERR,
202 QString(
"Protocol version mismatch (plugin=%1, mythzmserver=%2)")
205 ShowOkPopup(QString(
"The mythzmserver uses protocol version %1, "
206 "but this client only understands version %2. "
207 "Make sure you are running compatible versions of "
208 "both the server and plugin.")
213 LOG(VB_GENERAL, LOG_INFO,
259 QStringList strList(
"GET_SERVER_STATUS");
264 if (strList.size() < 4)
266 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
271 cpuStat = strList[2];
272 diskStat = strList[3];
279 QStringList strList(
"GET_MONITOR_STATUS");
284 if (strList.size() < 2)
286 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
291 int monitorCount = strList[1].toInt(&bOK);
294 LOG(VB_GENERAL, LOG_ERR,
295 "ZMClient received bad int in getMonitorStatus()");
301 for (
int x = 0; x < monitorCount; x++)
303 int monID = strList[(x * 7) + 2].toInt();
308 mon->
name = strList[(x * 7) + 3];
311 mon->
events = strList[(x * 7) + 6].toInt();
312 mon->
function = strList[(x * 7) + 7];
313 mon->
enabled = (strList[(x * 7) + 8].toInt() != 0);
320 QString result =
"UNKNOWN";
350 QStringList strList(
"GET_ALARM_STATES");
355 if (strList.size() < 2)
357 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
362 int monitorCount = strList[1].toInt(&bOK);
365 LOG(VB_GENERAL, LOG_ERR,
366 "ZMClient received bad int in getAlarmStates()");
372 bool changed =
false;
373 for (
int x = 0; x < monitorCount; x++)
375 int monID = strList[(x * 2) + 2].toInt();
376 auto state = (
State)strList[(x * 2) + 3].toInt();
381 if (mon->
state != state)
384 LOG(VB_GENERAL, LOG_DEBUG,
385 QString(
"ZMClient monitor %1 changed state from %2 to %3")
398 const QString &date,
bool includeContinuous,
399 std::vector<Event*> *eventList)
405 QStringList strList(
"GET_EVENT_LIST");
406 strList << monitorName << (oldestFirst ?
"1" :
"0") ;
408 strList << (includeContinuous ?
"1" :
"0") ;
414 if (strList.size() < 2)
416 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
421 int eventCount = strList[1].toInt(&bOK);
424 LOG(VB_GENERAL, LOG_ERR,
"ZMClient received bad int in getEventList()");
429 if ((strList.size() - 2) / 6 != eventCount)
431 LOG(VB_GENERAL, LOG_ERR,
432 "ZMClient got a mismatch between the number of events and "
433 "the expected number of stringlist items in getEventList()");
437 QStringList::Iterator it = strList.begin();
439 for (
int x = 0; x < eventCount; x++)
441 eventList->push_back(
453 QStringList &dateList)
459 QStringList strList(
"GET_EVENT_DATES");
460 strList << monitorName << (oldestFirst ?
"1" :
"0") ;
466 if (strList.size() < 2)
468 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
473 int dateCount = strList[1].toInt(&bOK);
476 LOG(VB_GENERAL, LOG_ERR,
477 "ZMClient received bad int in getEventDates()");
482 if ((strList.size() - 3) != dateCount)
484 LOG(VB_GENERAL, LOG_ERR,
485 "ZMClient got a mismatch between the number of dates and "
486 "the expected number of stringlist items in getEventDates()");
490 QStringList::Iterator it = strList.begin();
492 for (
int x = 0; x < dateCount; x++)
494 dateList.append(*it++);
504 QStringList strList(
"GET_FRAME_LIST");
505 strList << QString::number(eventID);
510 if (strList.size() < 2)
512 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
517 int frameCount = strList[1].toInt(&bOK);
520 LOG(VB_GENERAL, LOG_ERR,
"ZMClient received bad int in getFrameList()");
525 if ((strList.size() - 2) / 2 != frameCount)
527 LOG(VB_GENERAL, LOG_ERR,
528 "ZMClient got a mismatch between the number of frames and "
529 "the expected number of stringlist items in getFrameList()");
533 QStringList::Iterator it = strList.begin();
535 for (
int x = 0; x < frameCount; x++)
537 auto *item =
new Frame;
539 item->delta = (*it++).toDouble();
540 frameList->push_back(item);
548 QStringList strList(
"DELETE_EVENT");
549 strList << QString::number(eventID);
558 QStringList strList(
"DELETE_EVENT_LIST");
560 std::vector<Event*>::iterator it;
561 for (it = eventList->begin(); it != eventList->end(); ++it)
563 strList << QString::number((*it)->eventID());
568 strList = QStringList(
"DELETE_EVENT_LIST");
577 strList = QStringList(
"RUN_ZMAUDIT");
584 std::chrono::milliseconds errmsgtime { 0ms };
602 LOG(VB_GENERAL, LOG_ERR,
"readData: Error, readBlock");
608 LOG(VB_GENERAL, LOG_ERR,
609 "readData: Error, socket went unconnected");
615 std::chrono::milliseconds elapsed = timer.
elapsed();
618 if ((elapsed - errmsgtime) > 10s)
620 errmsgtime = elapsed;
621 LOG(VB_GENERAL, LOG_ERR,
622 QString(
"m_socket->: Waiting for data: %1 %2")
623 .arg(
read).arg(dataSize));
629 LOG(VB_GENERAL, LOG_ERR,
"Error, readData timeout (readBlock)");
648 QStringList strList(
"GET_EVENT_FRAME");
649 strList << QString::number(event->
monitorID());
650 strList << QString::number(event->
eventID());
651 strList << QString::number(frameNo);
652#if QT_VERSION < QT_VERSION_CHECK(6,5,0)
653 strList <<
event->startTime(Qt::LocalTime).toString(
"yy/MM/dd/hh/mm/ss");
655 static const QTimeZone localtime(QTimeZone::LocalTime);
656 strList <<
event->startTime(localtime).toString(
"yy/MM/dd/hh/mm/ss");
662 if (strList.size() < 2)
664 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
669 int imageSize = strList[1].toInt();
672 auto *data =
new unsigned char[imageSize];
675 LOG(VB_GENERAL, LOG_ERR,
676 "ZMClient::getEventFrame(): Failed to get image data");
685 if (!(*image)->loadFromData(data, imageSize,
"JPEG"))
687 LOG(VB_GENERAL, LOG_ERR,
688 "ZMClient::getEventFrame(): Failed to load image from data");
698 QStringList strList(
"GET_ANALYSE_FRAME");
699 strList << QString::number(event->
monitorID());
700 strList << QString::number(event->
eventID());
701 strList << QString::number(frameNo);
702#if QT_VERSION < QT_VERSION_CHECK(6,5,0)
703 strList <<
event->startTime(Qt::LocalTime).toString(
"yy/MM/dd/hh/mm/ss");
705 static const QTimeZone localtime(QTimeZone::LocalTime);
706 strList <<
event->startTime(localtime).toString(
"yy/MM/dd/hh/mm/ss");
715 if (strList.size() < 2)
717 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
722 int imageSize = strList[1].toInt();
725 auto *data =
new unsigned char[imageSize];
728 LOG(VB_GENERAL, LOG_ERR,
729 "ZMClient::getAnalyseFrame(): Failed to get image data");
735 if (!image.loadFromData(data, imageSize,
"JPEG"))
737 LOG(VB_GENERAL, LOG_ERR,
738 "ZMClient::getAnalyseFrame(): Failed to load image from data");
750 QStringList strList(
"GET_LIVE_FRAME");
751 strList << QString::number(monitorID);
756 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
762 if (strList[0].startsWith(
"WARNING"))
771 if (strList.size() < 4)
773 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
781 size_t imageSize = strList[3].toInt();
783 if (buffer.size() < imageSize)
785 LOG(VB_GENERAL, LOG_ERR,
786 "ZMClient::getLiveFrame(): Live frame buffer is too small!");
794 if (!
readData(buffer.data(), imageSize))
796 LOG(VB_GENERAL, LOG_ERR,
797 "ZMClient::getLiveFrame(): Failed to get image data");
810 QStringList strList(
"GET_CAMERA_LIST");
815 if (strList.size() < 2)
817 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
822 int cameraCount = strList[1].toInt(&bOK);
825 LOG(VB_GENERAL, LOG_ERR,
826 "ZMClient received bad int in getCameraList()");
831 if (strList.size() < cameraCount + 2)
833 LOG(VB_GENERAL, LOG_ERR, QString(
834 "ZMClient got a mismatch between the number of cameras (%1) and "
835 "the expected number of stringlist items (%2) in getCameraList()")
836 .arg(cameraCount).arg(strList.size()));
840 for (
int x = 0; x < cameraCount; x++)
842 cameraList.append(strList[x + 2]);
883 QStringList strList(
"GET_MONITOR_LIST");
888 if (strList.size() < 2)
890 LOG(VB_GENERAL, LOG_ERR,
"ZMClient response too short");
895 int monitorCount = strList[1].toInt(&bOK);
898 LOG(VB_GENERAL, LOG_ERR,
899 "ZMClient received bad int in getMonitorList()");
904 if ((strList.size() - 2) / 5 != monitorCount)
906 LOG(VB_GENERAL, LOG_ERR,
907 "ZMClient got a mismatch between the number of monitors and "
908 "the expected number of stringlist items in getMonitorList()");
914 QStringList notificationMonitors = s.split(
",");
916 for (
int x = 0; x < monitorCount; x++)
919 item->
id = strList[(x * 5) + 2].toInt();
920 item->name = strList[(x * 5) + 3];
921 item->width = strList[(x * 5) + 4].toInt();
922 item->height = strList[(x * 5) + 5].toInt();
923 item->bytes_per_pixel = strList[(x * 5) + 6].toInt();
924 item->zmcStatus =
"";
925 item->zmaStatus =
"";
928 item->showNotifications = notificationMonitors.contains(QString::number(item->id));
933 LOG(VB_GENERAL, LOG_NOTICE,
934 QString(
"Monitor: %1 (%2) is using %3 bytes per pixel")
935 .arg(item->name).arg(item->id).arg(item->bytes_per_pixel));
943 QStringList strList(
"SET_MONITOR_FUNCTION");
944 strList << QString::number(monitorID);
946 strList << QString::number(static_cast<int>(enabled));
962 s += QString(
",%1").arg(mon->
id);
964 s = QString(
"%1").arg(mon->
id);
975 auto *me =
dynamic_cast<MythEvent*
>(event);
979 if (me->Message().startsWith(
"ZONEMINDER_NOTIFICATION"))
981 QStringList list = me->
Message().simplified().split(
' ');
986 int monID = list[1].toInt();
991 QObject::customEvent(event);
1003 miniPlayer->setAlarmMonitor(monitorID);
1005 if (miniPlayer->Create())
int monitorID(void) const
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
int GetNumSetting(const QString &key, int defaultval=0)
This class is used as a container for messages.
const QString & Message() const
static const Type kMythEventMessage
MythPainter * GetPainter()
MythScreenStack * GetStack(const QString &Stackname)
void addListener(QObject *listener)
Add a listener to the observable.
void removeListener(QObject *listener)
Remove a listener to the observable.
MythImage * GetFormatImage()
Returns a blank reference counted image in the format required for the Draw functions for this painte...
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Class for communcating between myth backends and frontends.
bool SendReceiveStringList(QStringList &list, uint min_reply_length=0, std::chrono::milliseconds timeoutMS=kLongTimeout)
bool IsConnected(void) const
int Read(char *data, int size, std::chrono::milliseconds max_wait)
void DisconnectFromHost(void)
bool ConnectToHost(const QString &hostname, quint16 port)
connect to host
A QElapsedTimer based timer to replace use of QTime as a timer.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
void start(void)
starts measuring elapsed time.
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
void doGetMonitorList(void)
int getMonitorCount(void)
bool sendReceiveStringList(QStringList &strList)
bool isMiniPlayerEnabled(void) const
void getEventFrame(Event *event, int frameNo, MythImage **image)
QMap< int, Monitor * > m_monitorMap
void deleteEventList(std::vector< Event * > *eventList)
void updateMonitorStatus(void)
QRecursiveMutex m_listLock
void getAnalyseFrame(Event *event, int frameNo, QImage &image)
Monitor * getMonitorByID(int monID)
bool readData(unsigned char *data, int dataSize)
void deleteEvent(int eventID)
void customEvent(QEvent *event) override
QList< Monitor * > m_monitorList
Monitor * getMonitorAt(int pos)
void getServerStatus(QString &status, QString &cpuStat, QString &diskStat)
static ZMClient * get(void)
bool updateAlarmStates(void)
void getEventDates(const QString &monitorName, bool oldestFirst, QStringList &dateList)
void getCameraList(QStringList &cameraList)
void saveNotificationMonitors(void)
void getEventList(const QString &monitorName, bool oldestFirst, const QString &date, bool includeContinuous, std::vector< Event * > *eventList)
static bool setupZMClient(void)
void setMonitorFunction(int monitorID, const QString &function, bool enabled)
void getFrameList(int eventID, std::vector< Frame * > *frameList)
bool connectToHost(const QString &hostname, unsigned int port)
QRecursiveMutex m_commandLock
QRecursiveMutex m_socketLock
bool checkProtoVersion(void)
static ZMClient * m_zmclient
void restartConnection(void)
int getLiveFrame(int monitorID, QString &status, FrameData &buffer)
void showMiniPlayer(int monitorID) const
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MythNotificationCenter * GetNotificationCenter(void)
MythMainWindow * GetMythMainWindow(void)
void ShowNotificationError(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
convenience utility to display error message as notification
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
def read(device=None, features=[])
static QString stateToString(State state)
static constexpr const char * ZM_PROTOCOL_VERSION
std::array< uint8_t, MAX_IMAGE_SIZE > FrameData