Welcome to the new FlexRadio Community! Please review the new Community Rules and other important new Community information on the Message Board.
If you are having a problem, please refer to the product documentation or check the Help Center for known solutions.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.

OnSliceAdded not firing

Walt - KZ1F
Walt - KZ1F Member ✭✭
edited February 2017 in SmartSDR API
I'd like to continue this, if I may, from Mark's question on RadioAck.

In my comment about MVC and MVVM, I understood the notion of an object's notification of a change in an attribute, i.e. radioAck. However, what I meant by subtle difference, is the property changed notification occurs before the object instantiation notification occurs.

public final void checkRadioACK() {
        Panadapter pan = _radio.FindPanadapterByStreamID(_panadapterStreamID);
        if (!_radioAck && _fullStatusReceived && ((pan != null && pan.getRadioAck()) || _panadapterStreamID == 0)) {
            _panadapter = pan;
            setRadioAck(true);   <---- this occurs before
            _radio.onSliceAdded(this);   <---- this occurs
        }
    }

In the above code, how do I wire interest in the slice object's radioAck property before I am aware of the slice's existence?

The root issue I have is I am not getting any OnSliceAdded event notifications, which I do subscribe to as they flow from the radio object. Perhaps, the issue has something to do with, even with persistence turned off, I get two pans created and 2 slices created without even asking for them. So, in other words, I did not trigger their coming into existence.

In the above segment, setRadioAck(true) triggers a propertyChangedNotification but I haven't subscribed to that as I am unaware of the slice itself.

I hope that makes sense.

Just by way of a little background. I've noticed this with SSDR. Most times I start SSDR it starts with the same single Panafall I had when I shut down last. This is persistence, correct?
Sometimes, however, SSDR starts with 2 or 4 panafalls for no apparent reason. Occasionally even it starts with no panadapter. This Eric said will fixed in the successor to 1.4.11. Since I did not create these it is unclear how I get access to them. I have tried turning off persistence.

Steve, at one point, mentioned if <something> isn't done the radio will create a panafall (and slice) on 14.1MHz. Yep, I see that. I get OnRadioAdded as well as OnPanadapterAdded events just fine. I do not receive OnSliceAdded events at all, even though I've registered for them as well as OnSlicePanReferenceChangeListener. Code follows:

            PanadapterAddedEventHandler panAdded = (Panadapter panx, Waterfall fall) -> processPanAdded(panx, fall);
            PanadapterRemovedEventHandler panRemoved = (Panadapter pan) -> processPanRemoved(pan);
            activeRadio.addPanAddedEventListener(panAdded);
            activeRadio.addPanRemovedEventListener(panRemoved);
           
            SliceEventHandler sliceAdded = (Slice slc) -> processSliceAdded(slc);
            SliceEventHandler sliceRemoved = (Slice slc) -> processSliceRemoved(slc);
            SlicePanReferenceChangeEventHandler slcpan = (Slice slc) -> processSliceAdded(slc);
            SlicePanReferenceChangeEventHandler slcpan1 = (Slice slc) -> processSliceRemoved(slc);
            activeRadio.addSliceAddedEventListener(sliceAdded);
            activeRadio.addSliceRemovedEventListener(sliceRemoved);
            activeRadio.addSlicePanReferenceChangeListener(slcpan1);          
            activeRadio.Connect();

Is there something obvious I am missing?

Answers

  • Eric-KE5DTO
    Eric-KE5DTO Administrator, FlexRadio Employee admin
    edited February 2017
    Walt,

    We set the RadioAck property to true before firing the RadioAdded event so that when the event fires, the client using the event will know that the object data is safe to use.  

    The reality is that in a system like this where the client can make asynchronous requests to the radio to create objects (like Slices), there are timing race conditions.  For example, when you create a Slice, without something like the RadioAck property, you don't really know when the radio knows about it.  When using the object, the rule of thumb is to check the RadioAck property and wait until it is true to manipulate the object.  Note that sometimes you might check RadioAck right after creating the object (and telling the radio about it) and it might already be true (the radio already responded).  At this point you can use the data.  If not, subscribing to the PropertyChanged event and watching for the RadioAck property to change to true allows the client to handle the asynchronous waiting in an event oriented way rather than just blocking waiting on the value to change.

    As for persistence, what version of firmware are you running in the radio?  What is the RequiredFirmwareVersion set to in FlexLib?  If these don't match, persistence will not run as the connection is expected to be for update only.

    Looking at the code you shared, I am not familiar with the syntax being used.  Is this C#?  The function names do not appear to match those in FlexLib, so it is hard to comment on what may be going wrong.
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Hi Eric, thanks.

    Actually no it is not C# and it is not the flexlib.dll. For all intents and purposes one may think of it as functionally equivalent. It was more the timing of things, yes I understand race conditions as well. Using your code:
     bottom part of Slice.cs:2544
                if (set_radio_ack)
                {
                    checkRadioACK();
                }
            }

            public void checkRadioACK()
            {
                Panadapter pan = _radio.FindPanadapterByStreamID(_panadapterStreamID);
                if (!_radioAck && _fullStatusReceived && ((pan != null && pan.RadioAck) || _panadapterStreamID == 0))
                {
                    _panadapter = pan;
                    RadioAck = true;   <--- this does not happen
                    _radio.OnSliceAdded(this); <---this does not happen
                }
            }

    RadioAck, btw, starts life as false

    That is a very busy compound if so, in English

    for RadioAck to be true
        RadioAck has to be false AND fullstatusReceived has to be true AND
    either
                pan is populated and pan has RadioAck set
          OR
                panadapter.streamID has to be zero (unset)

    I suspect it is something in that compound if stmt that doesn't resolve to true.

    I would think, though I am not sure, and anecdotally it doesn't appear true, that I will receive either a OnPanAdded event and an OnSliceAdded event.

    I do get an OnPanAdded event for the pan I create.

    Honest Eric, I am not trying to be dense or miss what you are trying to tell me.
    I do not know how to get addressability to pans and slices I don't create.

    I think, part of the issue is we don't have visibility into SSDR which, likely, was not an oversight. This is why I mentioned the times when SSDR startup shows just a single pan that you shut down with and sometimes 2 or 4 pans, which  I never instantiate and sometimes none, which we discussed.

    I also added the slicePanReferenceChange event handler, just in case,  as well as adding the control app as a listener for propertyChanges.

    You asked about FirmwareRequiredVersion. Yes, that was a problem. Currently I simply always mark the radio as Available as opposed to Update, which is the state it was trying to put the radio in as the shipped version of FirmwareRequiredVersion was not the 1.4.11 version.  I set persistence off as I thought that would prevent the panafall and slices from autogenerating.
    The radio was upgraded to 1.4.11 when I installed SSDR 1.4.11. The VitaDiscovery packet shows the required version being 1.4.11.60.

    In Radio:2574 there is this comment in AddSlice()
                   //OnSliceAdded(slc); -- this is now done in the Slice class to ensure that good status info is present before notifying the client
    I assume that is to resolve your race condition.

    my first status is
    14:30:19.569 received status slices=4 panadapters=4 lineout_gain=53 lineout_mute=0 headphone_gain=54 headphone_mute=0 remote_on_enabled=0 pll_done=0 freq_error_ppb=0 cal_freq=15.000 tnf_enabled=1 snap_tune_enabled=1 nickname=Walt/kz1f callsign=KZ1F binaural_rx=0

    14:30:19.883 received status  slices=3 panadapters=3 lineout_gain=53 lineout_mute=0 headphone_gain=54 headphone_mute=0 remote_on_enabled=0 pll_done=0 freq_error_ppb=0 cal_freq=15.000 tnf_enabled=1 snap_tune_enabled=1 nickname=Walt/kz1f callsign=KZ1F binaural_rx=0

    No indication of the slice object

    14:30:19.963 slices=2 panadapters=2 lineout_gain=53 lineout_mute=0 headphone_gain=54 headphone_mute=0 remote_on_enabled=0 pll_done=0 freq_error_ppb=0 cal_freq=15.000 tnf_enabled=1 snap_tune_enabled=1 nickname=Walt/kz1f callsign=KZ1F binaural_rx=0

    So far as I can tell, I asked for 1, not 2.

    I can see it being made:
    14:30:19.915 sending cmd C21|slice create  pan=0x40000000 freq=10.0000006 mode=AM
    14:30:19:958 received status S9547987B|slice 0 pan=0x40000000 mode=CW qsk=1 tx=1
    14:30:20.090 received reply  R21|0|1
    14:30:20.092  received status S9547987B|slice 1 audio_gain=50 audio_pan=50 audio_mute=0

    I never see a ReplyAck nor do I see a request generating slice 0.
    I  don't see the ReplyAck for the panadapter because I create it via the
    radio.RequestPanafall(), so I have no partial pan in advance of the radio.RequestPanafall();

    15:40:55.826 RadioAck value changed <-- this occurs before there is anything to observe
    15:40:55.826 Notifying listeners of Pan Panadapter{streamId=0x40000000, band=30, centerFreq=10.0000006, size=0,0} added

    Upon receiving this notification I set center freq and new size.
     I do see multiple OnPanAdded as I had to add the following
            if (activePan.getStreamID() > 0x40000000) {
                activeRadio.RemovePanadapter(activePan.getStreamID(), true);
                return;
            }


    It sounds like though, from what you are implying,

    1) maybe manually check the RadioAck boolean, it may or may not be set
    2) maybe you'll get an asynchronous notification of it
    3) when you get the asynchronous notification of a OnEventAdded check to see if the RadioAck is set because it may not be really added and ready

    I realize there are several buried subquestions, so to percolate to the top, In the case of the Slice, why would you guess neither the slice.RadioAck nor the OnSliceAdded are being fired? Isn't that an issue with SSDR?

    Thanks,
    Walt - kz1f

    BTW, this is the 2nd or 3rd one of these I've seen in the last week

    received reply  R21|0|Unable to get foundation receiver assignment

    Isn't the creation of a pan supposed to have an associated slice?



  • Eric-KE5DTO
    Eric-KE5DTO Administrator, FlexRadio Employee admin
    edited December 2016
    Walt,

    I am thoroughly confused.  If you are creating a client based on the ethernet API, this is probably what we should be talking about.  Note that RadioAck is a FlexLib construct and is not comprehended in the radio.  The radio just knows about commands and sends replies and status messages (in terms of command and control).

    I can speak to the FlexLib code and how it works.  I can explain how the ethernet API functions and how we use it in FlexLib.  Given the information I have, I don't see a way to answer the question of why you aren't seeing your SliceAdded events in your client.

    This would be more of a question of how you are handling the status messages coming across the wire of the "display pan <stream id> in_use=1" variety.

    The complexity in the FlexLib code mentioned is there to ensure that Slices get properly attached to the right Panadapter.  Again, the complexity is that the Panadapter or the Slice status message might end up coming across the wire first, so the code must handle both orders.
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    did you mean slice n in_use=1?

    I found it: second line under case "pan":

    Thank you for helping on this.

    I still don't know why it is making 2 of these 2 pans, 2 slices.
    This also occasionally happens in SSDR, do you know why?

    For all intents and purposes, my core logic is essentially your core logic

    Think of this as FlexLib code, except it is not flexlib. This is what has taken me months to write.  In the StatusUpdate() of Slice:

                        case "pan": {
                            try {
                                int temp = Integer.parseInt(value.substring(2));
                                if (_panadapterStreamID != temp) {
                                    _panadapterStreamID = temp;

                                    Panadapter pan = _radio.findPanadapterByStreamID(_panadapterStreamID);
                                    if (pan != null && _radioAck) {
                                        this.setPanadapter(pan);
                                        _radio.onSlicePanReferenceChange(this);
                                    }
                                    raisePropertyChanged("Panadapter");
                                }
                            } catch (NumberFormatException e) {
                                if (log.isDebugEnabled()) {
                                    log.debug("Slice::StatusUpdate: Invalid value (" + kv + ")");
                                }
                            }
                        }
                        break;

                        case "in_use": {
                            try {
                                byte temp = Byte.parseByte(value);
                                boolean slice_in_use = (temp == 1);

                                _fullStatusReceived = (temp == 1);
                                if (_fullStatusReceived) {
                                    set_radio_ack = true;
                                }
                            } catch (NumberFormatException e) {
                                if (log.isDebugEnabled()) {
                                    log.debug("Slice::StatusUpdate: Invalid value (" + kv + ")");
                                }
                            }
                        }
                        break;
    At end of loop, having processed all KV pairs


            if (set_radio_ack) {
                checkRadioACK();
            }
        }

        public final void checkRadioACK() {
            Panadapter pan = _radio.findPanadapterByStreamID(_panadapterStreamID);
            if (!_radioAck && _fullStatusReceived && ((pan != null && pan.getRadioAck()) || _panadapterStreamID == 0)) {
                _panadapter = pan;
                setRadioAck(true);
                _radio.onSliceAdded(this);
            }
        }



Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.