1

I am currently working with the LeJOS Ev3 library and have programmed the following listener:

    import lejos.hardware.port.Port;
    import robots.ev3.drive.parts.LightSensor;

    public abstract class LightListener {
        protected int trigger;
        protected boolean dark;

        public LightListener(int triggerLevel) { trigger = triggerLevel; }
        public void notify(LightSensor s) {
            // Depending on the value that s measures, either the method
            // dark or bright is called
        }
        public void initialValue(int level) {
            dark = level < trigger;
        }

        abstract public void bright(Port port, int level);
        abstract public void dark(Port port, int level);
    }

As you can see, there is a method called notify that is supposed to call different methods, depending on what the sensor is measuring. I would like to be able to call the method notify only when the value the sensor is measuring changes, without using a while-loop that constantly checks if the value has changed. But I couldn't think of or find the way to achieve this.

The only thing that occurred to me, is to start a thread that would run this code:

    while(true) {
        waitForSensorValueToChange();
        listener.notify(sensor);
    }

But, again, I don't even know if it is possible to wait for an event to happen (without constantly checking the values).

EDIT - Since it has been repeatedly been suggested to me, I will mention that I already added a method on my LightSensor called addLightListener(LightListener listener). This does not solve my problem with avoiding to poll.

  • You have to register and attach your `LightListener` to your sensor in order for the sensor to invoke your listener every time the light changes. That way, on your notify, you just need to validate the value of `LightSensor` and act accordingly. – António Ribeiro Feb 09 '16 at 22:22
  • @aribeiro That sounds like a valid answer to me, maybe with a small code sample. – Jim Garrison Feb 09 '16 at 22:26
  • @aribeiro I already created a class called LightSensor to which you can attach a LightListener. There isn't, however, a method inherited from the superclass (NXTLightSensor) with which you can call a method when the value changes. Therefore it doesn't solve my problem. –  Feb 09 '16 at 22:27
  • @aribeiro That is what I don't know how to do. How does one make the LightSensor call a method when the value changes, without periodically checking the value the sensor is measuring and comparing it with the previous one? –  Feb 09 '16 at 22:44
  • From [this](http://sourceforge.net/p/lejos/wiki/Sensor%20Framework/) example found on the leJOS wiki, it is used a `while(true)` to fetch the samples as @N.Pich suggested. – António Ribeiro Feb 09 '16 at 22:46
  • @N.Pich, what `NXTLightSensor`library are you using? The [leJOS](http://www.lejos.org/ev3/docs/lejos/hardware/sensor/NXTLightSensor.html) one or [this](http://www.aplu.ch/classdoc/ev3jliba/ch/aplu/ev3/NxtLightSensor.html) one? – António Ribeiro Feb 09 '16 at 23:01
  • @aribeiro the leJOS one. –  Feb 09 '16 at 23:03
  • @N.Pich, then what you could do is continue with what you've done so far, plus create a new method on your `LightSensor` called `addLightListener(LightListener lightListener)` that allows a listener to register on your sensor. Afterwards (unfortunately) you'll have to execute the `while(true)` that you've posted, validating that the sensor change and call your listener there. – António Ribeiro Feb 09 '16 at 23:13
  • @aribeiro But then, how did the programmers of the ch library you linked to in one of your previous comments achieve to do what I want to do. They also seem to have built on the leJOS library. Is there a way I could find out if they are also polling all the time? –  Feb 09 '16 at 23:20
  • @N.Pich, I've managed o find [this](https://r-n-d.informatik.hs-augsburg.de:8080/nicolas/urbanchallenge2015/blob/1c066855897df03f91a94c8ddb55bbaab2bcccca/code_snippet_eduard_kesler/ev3/NxtLightSensor.java) source code. It is based on a `thread` with a `while(true)`. – António Ribeiro Feb 09 '16 at 23:27
  • @aribeiro Thank you!!! –  Feb 09 '16 at 23:29
  • @N.Pich, you're welcome! :) – António Ribeiro Feb 09 '16 at 23:35

1 Answers1

0

Not familiar with that library but your two basic options are polling (what you've tried so far) or go with an observer pattern.

In the observer pattern, you notify any classes that have registered to the provider when the event happens.

class ObserveMe {
    List<Observer> observers = new ArrayList<>();

    public updateSensorValue(){
        //do what you need to
        for(Observer observer : observers){
            observer.notify();
        }
    }

    public void addObserver(Observer o){
        this.observers.add(o);
    }
}

interface Observer {
    public void notify();
}
nlloyd
  • 1,966
  • 2
  • 15
  • 18
  • I already did this. The problem with it is that you either need to constantly call the method updateSensorValue(), which, in that case, would only notify the listeners if the current value differs from the previously measured, or you have to run a while loop that only calls updateSensorValue() if the current value differs from the previous one. In both cases you have to be constantly periodically be checking the value that the sensor measures to decide whether to call the method notify() or not. Still, thank you for your answer. –  Feb 09 '16 at 22:35
  • @N. Pich - it sounds like you're trying to poll the LightSensor and see when the value changes - this is almost the opposite of the observer pattern. in the observer pattern, the LightListener would need to register with the LightSensor, and the LightSensor would notify the LightListener when the value chaged. The LightListener would be the Subscriber/Observer and the LightSensor would be the Publisher (the ObserveMe class above) – nlloyd Feb 09 '16 at 22:49
  • As I repeatetly statet, I do not want to poll the sensor to check if the current value... What I want to do is what you suggested: That the LightSensor calls notify() on its listeners ONLY WHEN the value changes. However, I don't know how to do this, and the class you described doesn't do it either, since I have to call the updateSensorValue() method MYSELF. My question is: Is there a way I can achieve that notify() is called by the LightSensor ONLY when the value changes, WITHOUT comparing it to others, the same way an ActionEvent takes place automatically when the mouse is clicked? –  Feb 09 '16 at 23:00
  • If you cannot modify the LightSensor class directly to implement the observer pattern, you can extend it and add the list of LightListeners. Then make a new method "observableGetSensorValue()" that calls the original LightSensor "getSensorValue()" and then notifies all of the registered LightListeners. The LightSensor would also need to keep the last read value around so you can detect if the next read is a change or not. – nlloyd Feb 09 '16 at 23:12