0

so i have an adrduino that sends me data constantly, I made it Json data. so arduino sends me [0,0,0,0] constantly and the 0 changes depending on the condition in the arduino. My Issue is, in my c# im reading this arduino data and i'm using it, however my methods keeps on firing because the conditions are met. i want it to just fire once if the value is changed and that's all. for example if i get from arduino [0,2,0,0] i want it to update and if stays 2 i don't want my method to fire unless it's back to 0 again.

This is my c# code where i read the data

void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) {

    var str = serial.ReadLine();

    outputStr = str;

    //intvalue = int.Parse(str);


    try{
        var json = JSON.Parse(str);

        FirstSet = int.Parse(json[0].Value); // can be either 0 or 1
        SecondSet = int.Parse(json[1].Value);// can be either 0 or 2
        ThirdSet = int.Parse(json[2].Value);// can be either 0 or 3
        ForthSet = int.Parse(json[3].Value);// can be either 0 or 4


    }catch(Exception ex){
        VLog.Info("EXCEPTION!: " + ex.Message);
    }

    // Set 1
    if (FirstSet == 1)
        On1();

    else if (FirstSet == 0) 
        Off1();


    // Set 2
    if (SecondSet == 2) 
        On2();

    else if (SecondSet == 0) 
        Off2();

    // Set 3
    if (ThirdSet == 3) 
        On3();

    else if (ThirdSet == 0) 
        Off3();

    // Set 4
    if (ForthSet == 4) 
        On4();

    else if (ForthSet == 0) 
        Off4();

    changed = true;


}
grek40
  • 13,113
  • 1
  • 24
  • 50
Nanopl
  • 77
  • 1
  • 13
  • Whatever class this is in could store the last received data and compare it with the data it has just received, if it's changed then do the stuff, if not then return – Dave Feb 14 '18 at 07:22
  • If I understood it correctly, you are saying you want to execute **ONLY** one method after parsing one JSON? or you want to keep record of previous json and if it changed (In current JSON) then execute method? Is that correct – Prasad Telkikar Feb 14 '18 at 07:23
  • It seems a very inefficient way to pass a 4bits flag. – Steve Feb 14 '18 at 07:26
  • I want to execute only if the values changes. for example i get 0 or 1 for First Set and 0 or 2 for SecodnSet and etc.. i want if FirstSet is 0 Constantly i dont want ti to fire. so basically i want to execute only if the value changes either 0 or 1 – Nanopl Feb 14 '18 at 07:26
  • @Steve how can i make it better? – Nanopl Feb 14 '18 at 07:27
  • Welcome on Stack Overflow. Please do not add tags to the title (C# in this case) – Thomas Weller Feb 14 '18 at 07:27
  • If I understand your comments correctly, you have those 8 (or so) methods (`On1 - On4` and `Off1 - Off4`) and you want to fire them only when the individual condition changes rather than when any data at all changes? – grek40 Feb 14 '18 at 07:28
  • Let me understand. In the same ReadLine you can get the first and second array element set together (1,2,0,0 or 1,2,3,4)? The point is, why Arduino sends a json when a single byte could do the same work? – Steve Feb 14 '18 at 07:29
  • @steve im using a sensor, and this sensor detects objects. basically if there is object it's 1 otherwise it's 0 – Nanopl Feb 14 '18 at 07:29
  • @Steve so i have 4 sensors, there for i made arduino send me json which is [0,0,0,0] or [FirstSet,SecondSet,ThirdSet,ForthSet] – Nanopl Feb 14 '18 at 07:30
  • @steve and arduino sends me data constantly. in the c# i just want to fire on off when the value is changed only but only the index value for example firstSet is json[0] and json [0] can be either 0 or 1 – Nanopl Feb 14 '18 at 07:31
  • If I had up to 8 sensors, I'd use a single byte with each bit representing a specific sensor to be On or Off... no need for big json there. – grek40 Feb 14 '18 at 07:32
  • 1
    declare a static string variable at the class level and initialize if with "0,0,0,0" or whatever default is from Arduino. Then whenever you receive data compare that data (without first parsing it) with the static variable. If they are different then you know that a parsing is required. if they match then there is no need to do further parsing, nothing changed from the last received data – Steve Feb 14 '18 at 07:32
  • Of course, if the data changed then you should update the static variable with the new string value received to reinitialize the loop – Steve Feb 14 '18 at 07:33
  • Last edit basically destroyed the question... what happened? – grek40 Feb 14 '18 at 08:29

3 Answers3

1

some basic validation?

above the class:

private string lastParsed;

inside the class start with:

if (lastParsed != null && lastParsed == str)
{
   return;
}
else 
{
   lastParsed = str;
}

EDIT: looks like you deleted your original code, but if you want to check only one of the int values for each sensor perhaps you could try another approach

above method:

private bool[] sensorState = new bool[4];

I don't remember exactly how you called the On & Off methods but in each IF and ELSE IF you could add

if (first == 0 && sensorState[0]) // it means you should switch OFF and it's currently ON
else if (first == 1 && !sensorState[0]) // it means you should switch ON and it's currently OFF

EDIT: after each if/else block you update the sensorState

if (first != 0)
   sensorState[0] = true;
else 
   sensorState[0] = false;

and so on..

marto
  • 420
  • 1
  • 4
  • 15
  • But where would that go? i have 4 values FirstSet SecondSet ThirdSet and ForthSet.. and check that i have if and else. so if (FirstSet == 1) on(); with your logic how would that be ? if (FirstSet ==1 && lastPared != null && lastpasted == str)? – Nanopl Feb 14 '18 at 07:24
  • 1
    put it under var str = serial.ReadLine(); – marto Feb 14 '18 at 07:25
  • but where does if (lastParsed != null && lastParsed == str) { return; } go? – Nanopl Feb 14 '18 at 07:27
  • You are comparing lastPared = str and str is the whole Json, i care about when i read from the json, which is FirstSet SecondSet and etc.. – Nanopl Feb 14 '18 at 07:28
  • let's see if I got this straight - the variable "str" eventually is evaluated to [0,0,0,0]? if this is the case you do not need to parse it in order to compare it with the last value and the validation should work just fine – marto Feb 14 '18 at 07:31
  • I have 4 sensors and 1 arduino, ardunio checks each sensor and sends 0 or sensorNumber , where 0 means false and sensorNumber means True . so in the end i might get [0,2,0,4] which means in c# FirstSet = 0 SecondSet = 2 ThirdSet = 0 and ForthSet = 4 . Issue is that im getting this data constantly. in the c# above i call my methods if coditions are met. so if sensor ONE is always detecting i will keep getting 1 and the condition will keep executing. i dont want that. i only want if the value changes like if its 0 execute once, if it changes to 1 execute again. – Nanopl Feb 14 '18 at 07:35
1

You probably want to look into Event Handlers. Specifically when properties change. You're already using event handlers for when data is received as a SerialDataReceivedEvent, now you're adding another layer on top of it to handle if the value changes.

The basic concept is you build a class that is responsible for reading your Arduino inputs. Use Task.Run() to monitor on another thread so it doesn't lock your main process. That class will have an event handler in it that you will call from within your monitor class.

When your app instantiates this monitoring object, it will then register an action to that event handler.

This answer lays out a modern version of a class with a PropertyChangedEventHandler. That class should be the monitor that is checking the sensor. Then if the property changes, it will fire the event handler that your main program has registered with.

If I use the example from that answer, here's what your program might look like:

class Program
{
    public ISensorMonitor Sensor1 { get; }
    public ISensorMonitor Sensor2 { get; }
    public ISensorMonitor Sensor3 { get; }
    public ISensorMonitor Sensor4 { get; }

    static void Main(string[] args)
    {
        // In this example Sensor1Monitor would implement ISensorMonitor
        Sensor1 = new Sensor1Monitor();
        Sensor1.PropertyChanged += DoSomethingWithSensor1;
        Sensor1.StartMonitoring();

        // ... implement the other 3 sensors.
    }

    void DoSomethingWithSensor1(object sender, PropertyChangedEventArgs e) 
    {
        // This ensures that only the SensorValue property will handled.
        if (e.PropertyName != nameof(ISensorMonitor.SensorValue))
            return;

        // ... Do something with Sensor1.SensorValue
    }

    // ... implement the other 3 sensors.
}

This will ensure DoSomething() only is called when the value of the monitor's sensor property reading changes.

Jim Yarbro
  • 2,063
  • 15
  • 21
0

Consider changing your model first... there is no need to store numbers for an On/Off state, just make your properties bool. Then, if you want to signal changes to the state, just pack it into the property setter instead of trying to be smart in some other area:

class MyContainerIsNotPartOfTheQuestion
{
    private bool m_FirstSet;
    public bool FirstSet
    {
        get { return m_FirstSet; }
        set
        {
            if (value != m_FirstSet)
            {
                m_FirstSet = value;
                // handle On/Off where it belongs
                if (value) On1();
                else Off1();
            }
        }
    }

    // same for SecondSet etc.

    void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // ... your starting code

        FirstSet = int.Parse(json[0].Value) != 0;
        // set others

        // Done, no handling of On/Off here
    }
}
grek40
  • 13,113
  • 1
  • 24
  • 50