No announcement yet.

Receiving spurious Report Object Genie Event

  • Filter
  • Time
  • Show
Clear All
new posts

  • Receiving spurious Report Object Genie Event

    As part of investigating why something wasn't working properly, I've discovered that the display is sending a ReportObject event to the host. In my Genie Event Handler I'm printing some info out:

    In Genie Event Handler
    Event Command: 5
    From Object: 10
    Received an Object Report from: 10 Index: 0 With data: 4
    This is basically saying a Genie Event, ReportObject (5) was received from a Form (10), of index 0 (0), form number 4 (4). NOTE: the index doesn’t seem to represent the actual form, but the data value does. The data value always equals the form on the display at the time and Index is always 0.

    This ReportObject event is sent as soon as there is an interaction between the display and the host: either the host sends the display a message because of a host event, or the host sends the display a message in response to a Write Magic Bytes from the display. If I do anything on the display that does not require a host interaction, the ReportObject is not sent.
    • I don't have any code in my display that issues a Report Object: nothing in Magic Code and nothing in any widget Object Event.
    • Additionally, this message ONLY starts happening AFTER I have switched banks and switched back again, e.g. if I switch from Bank 0 to Bank 2 and back to Bank 0.
    • Further it doesn't ALWAYS occur after the first switch, maybe even after the second switch, but nearly always does so eventually (i.e. after at least 1 switch and before 4 switches.)
    • The data value is equal to the Form index displayed.
    • My Magic Objects that are processing the data from the host all send an ACK. I print out that ACK. What I see in my debug output is: Info on message sent; spurious ReportObject from display; ACK received. In other words, the ReportObject message is being sent before the ACK when the Magic Object has finished processing the message.
    • It doesn't always send that message, only sometimes. Once it has started, the frequency of issuing it seems random but often.
    • When it does send it, it seems to slow up processing on the display: judging by the debug messages, the host processes quickly, but the corresponding action on the display seems slightly delayed compared to when the ReportObject isn’t issued.
    • It may be my imagination but if, once it has started, I interact with the display quickly I don’t see the message; if I interact slowly - i.e. with a short 1 sec delay between interaction - then it gets issued.
    • It doesn’t matter what Form I’m actually displaying, the index is always 0.
    It feels like something that is deliberately coded into the display because it is so specific in its data value; in fact, it feels like it is part of ACK processing in some way but I don’t know why I think that. I've got no idea how to debug this further as I can't tie the receipt of the ReportObject on the host to a specific interaction on the display. Do you have any idea of why the display would issue such a message and how I might track it down?

  • #2
    Still struggling with this - I can't work out why the display is sending a ReportObject message. Take, as an example only, one of the simplest inputs. I can turn an encoder connected to my host and it will send a message to the display that it has turned CW, CCW. The display will move a cursor, that is drawn on the display accordingly. The only message that the display sends the host is an ACK after processing the encoder message:

    serout(ACK); // Acknowledge end of processing
    I can turn the encoder as fast as I like and the cursor moves accordingly - there's a good debounce on the Arduino so no step is missed and the action on the host and cursor movement on the display appears instantaneous to a human, i.e. me. This works fine until I switch banks and switch back again. At that point, the display wants to send the Report Object message to the host, when it receives a message from the host. Once this starts happening:
    • I can turn the encoder as fast as I like and the display doesn't send the ReportObject message and continues to draw the cursor.
    • I can turn the encoder once per second-ish, and the display doesn't send the ReportObject message and continues to draw the cursor.
    • I can turn the encoder once per 2 seconds or slower and for every single message sent to the display, it responds with the ReportObject message.
    I use the encoder as a simple example, the issue is the same with other display interactions, e.g. press a UserButton that asks the host to send some data to the display. So if I interact quickly, display sends no ReportObject; if I interact slowly, it always sends the message; it only starts sending the message once I've switched banks and back again (maybe 2 or 3 times.)

    I also put some debug print lines into the genieArduino library ReadObject function to see if my Host was sending that to the display. These lines produce no output on the console so it doesn't look like the host is asking the form to send me its current value.


    • #3
      I've been working on this all weekend but I believe I've found the cause, if not the solution.

      I firstly ruled out a display timeout by increasing the timeout value to a large value and it had no effect.

      In order to receive a REPORT_OBJ, the display should have received a GENIE_READ_OBJ. I looked to see what used that constant and there are four functions:
      AutoPing code in DoEvents()
      My host code doesn't use Ping() nor does it call ReadObject(). I made a change to to display text whenever the display ran through function ReadObject which is called when the display receives the GENIE_READ_OBJ command. I could see that this function was being called on the display.

      The source of the problem occurring is the autoping functionality in DoEvents(). I changed the code so it only runs once to get the display online for the library. With autoping not running, the problem doesn’t occur. Therefore it woud seem that after switching banks the response to GENIE_READ_OBJ that autoping sends isn’t always being consumed in DoEvents() but is being pushed into _incoming_queue for my code to deal with.

      I added further DebugSerial lines into DoEvents() and I can see in normal circumstances I see "Sending Autoping" followed by "Consuming Autoping REPORT_OBJECT". However once the problem starts, I can see that I get a “Sending Autoping” message followed by a “Received ACK” (library code) followed by “Sending Autoping”: in other words, the library is sending an Autoping, but is not processing a response before sending another one. That, I suspect, is then receiving two REPORT_OBJ messages, consuming one and leaving the other to fall through to my code to pick up.

      Every time I see that sequence of Send...ACK...Send..., I get the spurious REPORT_OBJ in my event queue.

      I have to suspect a timing issue in the interaction between my own display code and the library code: it only starts once I swap banks and swap back again (and then not every time.) What I can’t determine is the connection between the autoping and interacting with the display. The sequence isn’t seen if I interact with the display at least once a second-ish. From the above, my suspicion is that the autoping has sent a request to the display which isn’t getting answered quickly or, for some reason, not being consumed. I put a counter in - autoPingOutstanding: every time the autoping sends a GENIE_READ_OBJECT I increment; every time it consumes a REPORT_OBJECT I decrement. I print the outstanding count every time a response is consumed. Even at startup I can end up with one autoping outstanding but it stays in this steady state however much I interact with the display and however quickly or slowly. If I switch banks and switch back again, if the outstanding count doesn’t change there is no issue. If I switch banks and back again and I see the outstanding count has increased, then the problem starts. At this point, interacting with the display quickly doesn’t change the outstanding count; interacting with it increments the count every time - it just rises by 1 every time I interact. This leads me to think that the autoping and response are getting out of sync: perhaps the display just isn’t responding fast enough or is getting confuse by dealing with application messages from the host intermixed with the autoping messages.

      I put a further change into DoEvents() when it consumes the autoping response: if the outstanding count isn’t zero, I leave the autopingflag at 1 instead of just setting it to 0. This stops the problem occurring: I can see the outstanding count increment but then decrement so it would seem to be consuming an extra autoping.

      What is interesting is that the outstanding count never gets to 0, even after startup. This makes me think that the display isn’t responding to every request or the code isn't recognising a response (confusingly though, if that were the case, it isn't falling through to my code.) In fact, the outstanding count can go higher than 1 (currently, for example, it is reporting 5 sends that weren’t consumed but it’s not causing an issue.) The autoping code doesn't care whether it gets a response or not: it continues to send them regularly and consumes a response if received.

      I've reached the end of what I can do with this. I'm hoping someone can look at what is going on and provide a permanent fix in the library code. This is what I ended up with which alleviates this problem but doesn't actually sort out why its going wrong in the first place.

      In genieArduinoDEV.cpp
      // Define a variable to keep track of auto pings sent and auto ping responses consumed
      int autoPingOutstanding = 0; // TODO: ADDED THIS - Remove line
      inline int16_t Genie::DoEvents() {
        if ( millis() - autoPingTimer > ( ( displayDetected && !NAK_detected ) ? autoPing_swapSpeed = AUTO_PING_CYCLE : autoPing_swapSpeed = recover_pulse ) ) {
          autoPingTimer = millis();
          if ( displayDetected && millis() - display_uptime > DISPLAY_TIMEOUT ) {
            display_uptime = millis();
             if ( debugSerial != nullptr ) debugSerial->println(F("[Genie]: disconnected by display timeout"));
            uint8_t buffer[6] = { GENIE_DISCONNECTED, 0, 0, 0, 0 };
            _incomming_queue.push_back(buffer, 6);
            displayDetected = 0;
          uint8_t buffer[4] = { (uint8_t)GENIE_READ_OBJ, GENIE_OBJ_FORM , 0, 10 };
          autoPingFlag = 1;
          autoPingOutstanding += 1; // TODO: ADDED THIS - remove line.
                      if ( autoPingFlag ) {
                        autoPingOutstanding -= 1; // TODO: ADDED THIS - Remove this and following two debug lines
                        if ( debugSerial != nullptr ) debugSerial->print(F("[Genie]: *******AutoPings outstanding: "));
                        if ( debugSerial != nullptr ) debugSerial->println(autoPingOutstanding);
                        if (autoPingOutstanding) // TODO: ADDED THIS - Remove this check and just let autopingflag be set to 0
                          autoPingFlag = 1;
                          autoPingFlag = 0; // TODO: Original line to be left
                        if ( debugSerial != nullptr ) debugSerial->println(F("[Genie]: AutoPing success!"));
                        display_uptime = millis();
                        return GENIE_REPORT_OBJ;