Link to home
Start Free TrialLog in
Avatar of VirtueTech
VirtueTech

asked on

Help with my Timer Function

Hello everyone,

In an old question "krbatge" helped me with a timer function. Here is that thread:
https://www.experts-exchange.com/questions/21666588/How-to-start-a-file-on-the-TENS.html

My program is creating clips every ten minutes. So basically I want the clips to all start on the TENS. Meaning 10:00:00, 10:10:00, 10:20:00, 10:30:00, etc.

So if the program started at 12:35:29 the first timer would figure out the time until the next TENS (12:40:00) and make the time for that...which is this example is 00:04:31. Then the secondary timer that would keep everything running on the TENS would be in the timer function.

Everything seems to work well....except after running for a couple of days it starts to get out of wack. It starts slowly like so. 12:00:01, 12:00:02, 12:00:03,  until eventually my clip files no longer start on the TENS.

So I need a way of testing to make sure that everything is still running on the TENS.

The first timer that checks the current time and makes a timer to get to the first TENS:
-----------------------------------------------------
time_t ltime;
struct tm now;
time(&ltime);
now = *localtime(&ltime);
int nMinsTillTen = (10 - (now.tm_min % 10));
int nSecsTillTen = nMinsTillTen*60 - now.tm_sec;
OnStartTimerOne = SetTimer(15, nSecsTillTen*1000, NULL);


Here is the timer in the OnTimer function to run every ten minutes:
-------------------------------------------------------
OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);


Can someone please help me figure a way out to keep it sync'd and always running on the TENS. I was thinking maybe a way to check the time and if its not on the TENS restart the first timer to put us back in place. I tried but couldn't get it to work. Any tips, pushes in the right direction, or code is greatly appreciated.

- James
Avatar of krbatge
krbatge

Can you post the full code you have in OnTimer?
Avatar of VirtueTech

ASKER

My OnTimer looks like this:
else if (nIDEvent == 15) // JLM
{      
// ************* This timer runs every 10 Minutes to create clips *********************************
// After 10 minutes time
// Stop Capture
      if (UseOnStartTimerOne == 0) {
            UseOnStartTimerOne = 1;
            KillTimer(OnStartTimerOne);
      }
      OnStop();
      OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);
      OnStart();
}


=======================================================
Now my "OnStop" functon:
=======================================================
void CHKVisionDlg::OnStop()
{
      CString msg;

      // The following creates a temp variable so its not lost for the thread
      TEMPtimeFileDBStart = timeFileDBStart;
      ULONG endCode = END_CODE;
      for(int i = 0; i < GetTotalDSPs(); i++){            
            _write(gFileHandle[i], &endCode, sizeof(ULONG));
            _close(gFileHandle[i]);
      }
      THREADlpszDateDirectory = lpszDateDirectory;
      THREADlpszTimeFile = lpszTimeFile;
      timeFileDBEnd = CTime::GetCurrentTime();

      // ************************ Removing for the OnStop Thread *************
      DWORD dw;
      if (m_hOnStopThread == NULL)
      {
            m_hOnStopThread = CreateThread(NULL,0, LPTHREAD_START_ROUTINE (OnStopThread),this,0,&dw);
            
            if(!(m_hOnStopThread))
            {
                  return;
            }
      }
      else
      {
            //debug only - MessageBox("OnStopThread - Previous thread never got set to NULL");
      }
      // **************** END - Removing for Onstop Thread ********************

      capimageX = 0;
}


========================================================
Now my "OnStart" function
========================================================
void CHKVisionDlg::OnStart()
{
      // make sure we have the directory for today's clips
      CString formatStr= _T("%Y%m%d");
      lpszDateDirectory = CTime:: GetCurrentTime().Format(formatStr);
            
      // Format the current time for string
      formatStr= _T("%H%M%S");
      lpszTimeFile = CTime::GetCurrentTime().Format(formatStr);

            
      if (bWorking = finder.FindFile(DriveLetter + ":\\clips\\" + lpszDateDirectory  ))
      {
            bWorking = finder.FindNextFile();
            if (!finder.IsDirectory())
                  if (!CreateDirectory(DriveLetter + ":\\clips\\" + lpszDateDirectory ,NULL))
                        MessageBox("Unable to Create Clips Directory");
      }
      else
            if (!CreateDirectory(DriveLetter + ":\\clips\\" + lpszDateDirectory ,NULL))
                        MessageBox("Unable to Create Day Directory");
            
            
      for(int i = 0; i < GetTotalDSPs(); i++)
      {
            streamX[i] = 0;
            sprintf(fileName, DriveLetter + ":\\clips\\" + lpszDateDirectory + "\\" + strDVRID + "_%d_%s_%s.mp4", i, lpszDateDirectory, lpszTimeFile);
            gFileHandle[i] = _open(fileName, _O_CREAT | _O_BINARY | _O_WRONLY| _O_TRUNC, _S_IREAD | _S_IWRITE);
            if (TurnPreviewOn == 1) {
                  sprintf(filePreviewName, DriveLetter + ":\\clips\\" + lpszDateDirectory + "\\pre_" + strDVRID + "_%d_%s_%s.mp4", i, lpszDateDirectory, lpszTimeFile);
                  gFilePreviewHandle[i] = _open(filePreviewName, _O_CREAT | _O_BINARY | _O_WRONLY| _O_TRUNC, _S_IREAD | _S_IWRITE);
            }            
            if(gFileHandle[i] == -1){
                  MessageBox("ERROR 1001: Cant open main channel clip. Please contact administrator with the error code.");
                  TRACE("channel %d file open error\n,i");
                  return;
            }
                  
            gChannelFrames[i] = 0;
            gChannelTotalLength[i] = 0;
            gChannelFramesLost[i] = 0;
            gChannelOverflow[i] = 0;
            gCurrentFileLen[i] = 0;
            ULONG length = 10000;
            gChannelTotalLength[i] += length;
            gCurrentFileLen[i] += length;
            _write(gFileHandle[i], FileHeader[i], FileHeaderLen);
            if (TurnPreviewOn == 1)
                  _write(gFilePreviewHandle[i], FilePreviewHeader[i], FilePreviewHeaderLen); // JLM
            gCaptureStartedNum++;

            CaptureIFrame(ChannelHandle[i]);
      }

      timeFileDBStart = CTime::GetCurrentTime();
      if(gCaptureStartedNum){
            m_ebRecordStatus.SetBkColor(RGB(255,255,255));
            m_ebRecordStatus.SetTextColor(RGB(0,160,0));
            m_ebRecordStatus.SetWindowText("Enabled");
      }

      // ******************* Setup Initial Timers ***************      
      if (TurnPreviewOn == 1) {
            previewTimer = SetTimer(16,30000,NULL); // Timer to create Preview Clip
            previewOff = FALSE;
      }
            
      // Setup 10 Minute Timer to keep the clips on the TENS: ex: 10:00:00, 10:10:00, 10:20:00
      if (UseOnStartTimerOne == 0) {
            time_t ltime;
            struct tm now;
            time(&ltime);
            now = *localtime(&ltime);
            int nMinsTillTen = (10 - (now.tm_min % 10));
            int nSecsTillTen = nMinsTillTen*60 - now.tm_sec;
            OnStartTimerOne = SetTimer(15, nSecsTillTen*1000, NULL);
      }
            
}



----------------------------------------------------------------------
I'd say the timer is getting a bit out of sync because you restart it each time the OnTimer function is called. Try this instead -

My OnTimer looks like this:
else if (nIDEvent == 15) // JLM
{    
// ************* This timer runs every 10 Minutes to create clips *********************************
// After 10 minutes time
// Stop Capture
     if (UseOnStartTimerOne == 0) {
          UseOnStartTimerOne = 1;
          KillTimer(OnStartTimerOne);
          OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);  // Timer only needs to be started once
     }
     OnStop();
     // if you start the timer here each time you will introduce a small incremental delay because of the time it takes to process OnStop()
     OnStart();
}
 
Additionally, if you wanted to be extra sure you could reset the timer say every 100 times or something...

e.g.

void CHKVisionDlg::ResetTensStartTimer()
{
          time_t ltime;
          struct tm now;
          time(&ltime);
          now = *localtime(&ltime);
          int nMinsTillTen = (10 - (now.tm_min % 10));
          int nSecsTillTen = nMinsTillTen*60 - now.tm_sec;
          OnStartTimerOne = SetTimer(15, nSecsTillTen*1000, NULL);
}

void CHKVisionDlg::OnStart()
{
     .
     .
     .

    if (UseOnStartTimerOne == 0) {
          ResetTensStartTimer();
     }
}

void CHKVisionDlg::OnTimer(...)
{
    .
    .
    .
    else if (nIDEvent == 15) // JLM
    {    
         if (UseOnStartTimerOne == 0) {
              UseOnStartTimerOne = 1;
              KillTimer(OnStartTimerOne);
              OnStartTimerTwo = SetTimer(15, 10*60*1000 , NULL);  // Second timer only needs to be started once
         }
         if (nTimerCount == 100)
         {
              // reset the timer to start again on the next 10 minute time in case we have got out of sync
              UseOnStartTimerOne = 0;
              KillTimer(OnStartTimerTwo);
              ResetTensStartTimer();
              nTimerCount = 0;
         }
         OnStop();
         OnStart();
         nTimerCount ++;  // global or member variable initially set to 0
    }
}



If you want it to start EXACTLY on the dot, I'd set the timer for the destination time minus 10 seconds.

Then when the timer fires do:     while( TimeNow() < WantedTime ) Sleep( 1 ) ; // milisecond sleep!!

Also note that Windows is not a real-time system-- your program might be delayed indefinitely and unpredictably if some higher-priority task is running, or if VM fills up, or .....



Thanks krbatge. I have implemented it....we'll see how it goes.

grg99:  In this scenario how do I no my "WantedTime". Because it keeps chaning. My wanted times would be 10:00:00, 10:10:00, 10:20:00, 10:30:00, 10:40:00, 10:50:00, 11:00:00

How would I make my "WantedTime" array/variable change so that it was looking for the right time on the TENS.

Example: If it is 11:50:00 how does my program now that the "WantedTime" should be equal to 12:00:00 ??
SOLUTION
Avatar of grg99
grg99

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This just is not accurate enough. Is there a way to use the windows clock instead?
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks guys.

I split the points and gave grg99 100 points because he helped spark some thought for me.

As for the solution I have tried in the past to just always use the re-sync timer function ...and it  didn't work. The problem was were I was starting the timer functinality.

Thanks everyone for your replies/time.