简体   繁体   中英

How to trigger an event when a variable gets the same value in a specified timeframe?

static void barreader_method()
{
   barreader.OpenPort(barport, 19200); //opens the port connected to the rfid reader
   byte TagType; //tag type
   byte[] TagSerial = new byte[4]; //tag serial in reverse order
   byte ReturnCode = 0; //return code sent from the rfid reader
   string bartagno; //tag no as a string

   while (true)
   {
      bartagno = "";
      while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode)) /*wait until a tag is present in the rf field, if present return the tag number.*/
      {
      }
      for (int i = 0; i < 4; i++)
      {
         bartagno += TagSerial[i].ToString("X2");
      }
      barprocess(bartagno); //barprocess method
      Thread.Sleep(1200); //this is to prevent multiple reads
   }
}

If the bartagno variable gets the same value within a minute, i don't want to execute the barprocess method but to continue the infinite loop. Otherwise barprocess method will be executed. How can i achieve this? I don't even know where to start. I tried different datetime, loop combinations with no success.

---------------------------------------------------------progress added below-----------------------------------------------

Multiple cards can be read within a minute, so comparing only with the previous one won't help unfortunately. I tried to use an arraylist instead building on Kelly Ethridge's answer (thanks). But if we get readings once every ten seconds for example, this will be useless. We still have to delete items older than 1 minute.

static void barreader_method()
{
    barreader.OpenPort(barport, 19200);
    byte TagType;
    byte[] TagSerial = new byte[4];
    byte ReturnCode = 0;
    string bartagno;
    ArrayList previoustagnos = new ArrayList();
    DateTime lastreaddt = DateTime.MinValue;

    while (true)
    {
        bartagno = "";
        while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode))
        {
        }
        for (int i = 0; i < 4; i++)
        {
            bartagno += TagSerial[i].ToString("X2");
        }
        if (DateTime.Now - lastreaddt > TimeSpan.FromMinutes(1))
        {
            previoustagnos.Clear();
            barprocess(bartagno);
            previoustagnos.Add(bartagno);
            lastreaddt = DateTime.Now;
        }
        else
        {
            previoustagnos.Sort();
            if (previoustagnos.BinarySearch(bartagno) < 0)
            {
                barprocess(bartagno);
                previoustagnos.Add(bartagno);
                lastreaddt = DateTime.Now;
            }
        }
        Thread.Sleep(1200);
    }
}

You'll need to keep track of the last time the barprocess was called and what the previous bartango was.

static void barreader_method()
{
   barreader.OpenPort(barport, 19200); //opens the port connected to the rfid reader
   byte TagType; //tag type
   byte[] TagSerial = new byte[4]; //tag serial in reverse order
   byte ReturnCode = 0; //return code sent from the rfid reader
   string bartagno; //tag no as a string
   string previousbartango;
   var lastTimeCalled = DateTime.MinValue;

   while (true)
   {
      bartagno = "";
      while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode)) /*wait until a tag is present in the rf field, if present return the tag number.*/
      {
      }
      for (int i = 0; i < 4; i++)
      {
         bartagno += TagSerial[i].ToString("X2");
      }
      var spanSinceLastCalled = DateTime.Now - lastTimeCalled;
      if (spanSinceLastCalled > TimeSpan.FromMinutes(1) || bartango != previousbartango)
      {
          barprocess(bartagno); //barprocess method
          previousbartango = bartango;
          lastTimeCalled = DateTime.Now;
      }
      Thread.Sleep(1200); //this is to prevent multiple reads
   }
}

This is air-code, but I think you get the idea.

That depends on how many tags you expect to see in a minute.

An ugly way that comes to mind is to create a new variable

List<Tuple<DateTime, String>> recentTags = new List<Tuple<DateTime, String>>()

Every time you see a bartagno, search this list to see if it's already here. If it is, skip over it. If not, add it to the list:

recentTags.Add(Tuple.Create(DateTime.Now, bartagno));

Occasionally (perhaps once 5 - 10 times through your main loop) you'll want to remove old records from this list.

recentTags.RemoveAll(e => e.Item1....

(crud - I don't recall the syntax for "e.Item1 is more than 1 minute in the past")

Isn't it as simple as storing the last processed values and a datetime. If the read is within the time limit then test for sameness before calling the barprocess() method?

... String lastBarTagNo = ""; DateTime lastTagProcessDateTime = DateTime.MinValue; ... while(true){ ... // read tag and build new bartagno if(DateTime.Now - lastTagProcessDateTime < TimeSpan.FromMinutes(1)) && lastBarTagNo.Equals(bartagno){ barprocess(); } }

(Sorry about the formatting - doing this on a smart phone)

static void barreader_method()
{
    barreader.OpenPort(barport, 19200);
    byte TagType;
    byte[] TagSerial = new byte[4];
    byte ReturnCode = 0;
    string bartagno;
    List<Tuple<DateTime, String>> previoustags = new List<Tuple<DateTime, String>>();
    DateTime lastreaddt = DateTime.MinValue;

    while (true)
    {
        bartagno = "";
        while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode))
        {
        }
        for (int i = 0; i < 4; i++)
        {
            bartagno += TagSerial[i].ToString("X2");
        }
        if (DateTime.Now - lastreaddt > TimeSpan.FromMinutes(1))
        {
            previoustags.Clear();
            barprocess(bartagno);
            previoustags.Add(Tuple.Create(DateTime.Now, bartagno));
            lastreaddt = DateTime.Now;
        }
        else
        {
            if (!previoustags.Exists(a => a.Item2.Equals(bartagno)))
            {
                barprocess(bartagno);
                previoustags.Add(Tuple.Create(DateTime.Now, bartagno));
                lastreaddt = DateTime.Now;
            }
        }
        previoustags.RemoveAll(a => a.Item1.CompareTo(DateTime.Now - TimeSpan.FromMinutes(1)) < 0);
        Thread.Sleep(1200);
    }
}

Thanks a lot Dan and Kelly. Without your help, i wouldn't be able to solve this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM