System events handler

In the docs under

System Events Overview the following handler is described

void handler(system_event_t event, int data, void* moredata);

What value or type is the last parameter void* moredata - and how would it be used?

The moredata parameter is not used by any current system events.

In the future, some event might want to pass a pointer to something there. For example, a const char * string pointer, or a pointer to a structure with more data specific to that event.

Thanks - one more thing, so the param argument returns a value for the events that have them - in the docs for example

cloud_status	64	cloud connection status	
                    one of 
                    cloud_status_connecting, 
                    cloud_status_connected, 
                    cloud_status_disconnecting, 
                    cloud_status_disconnected

I have trapped this event and get it with a param value 8 just before this returns true

waitFor(Particle.connected, 30000);

So therefore working as expected - how do I decode the param value of 8 - it doesn’t seems to fit the messages above if I assign a binary value to each message?

What do you mean with "param argument"? Nowhere before in this thread was param mentioned.
Do you mean the int data parameter?

If so, this should do the trick

  if (event == cloud_status) {
    switch(data) {
      case cloud_status_connecting:
        ...
        break;   
      case cloud_status_connected:
        ...
        break;   
      case cloud_status_disconnecting:
        ...
        break;   
      case cloud_status_disconnected:
        ...
        break;
      default:
    } 
  }  

You don't assign the values, you get the event type plus the respective additional info in the additional parameteters (data as predefined constants and eventually more dynamic data as *moredata).

If you want to know the numeric values of the data constants look at the open source repo or write yourself a quick sketch that just prints them out for you.
However, these values are not fixed and - as unlikely it may be - they could change at any time, hence never use the numeric values in code.

Ahh - therein lies the rub, to a newbie like me it was not obvious that “cloud_status_disconnecting” or the others could be used as a value - thanks for the help!

I got param from the examples in the docs with the following given examples

void button_clicked(system_event_t event, int param)
{
    int times = system_button_clicks(param);
    Serial.printlnf("button was clicked %d times", times);
}
1 Like

So … based on this I created the following and it works really well for understanding more about what is happening and when it happens

// ---------------------------------------------------------------------------
void handle_all_the_events(system_event_t event, int param )
// ---------------------------------------------------------------------------
{
    const int maxSizeOfEventText = 30;
    const int maxSizeOfEventMsg = 60;
    const char unknownEvent[] = "Unknown event";
    
    char systemParamMsg[maxSizeOfEventMsg];
    
    switch (event) {
    
        case setup_begin: // signals the device has entered setup mode
            sprintf(systemParamMsg, "Setup started");   
            break;
        case setup_update: // periodic event signaling the device is still in setup mode.
            sprintf(systemParamMsg, "Setup busy for last %d ms", param);
            break;
        case setup_end: // signals setup mode was exited
            sprintf(systemParamMsg, "Setup ended after %d ms", param);
            break;
        case network_credentials: // network credentials were changed
            switch(param) {
                case network_credentials_added:
                    sprintf(systemParamMsg, "Network credentials added" ); 
                    break;   
                case network_credentials_cleared:
                    sprintf(systemParamMsg, "Network credentials cleared" ); 
                    break;   
                default:
                    break;
            } 
            break;
        case network_status: // network connection status
            switch(param) {
                case network_status_powering_on:
                    sprintf(systemParamMsg, "Network starting" ); 
                    break;   
                case network_status_on:
                    sprintf(systemParamMsg, "Network on" ); 
                    break;   
               case network_status_powering_off:
                    sprintf(systemParamMsg, "Network stopping" ); 
                    break;   
                case network_status_off:
                    sprintf(systemParamMsg, "Network off" ); 
                    break;   
               case network_status_connecting:
                    sprintf(systemParamMsg, "Network connecting" ); 
                    break;   
                case network_status_connected:
                    sprintf(systemParamMsg, "Network connected" ); 
                    break;   
                default:
                    break;
            } 
            break;
        case cloud_status: // cloud connection status
            switch (param) {
                case cloud_status_connecting:
                    sprintf(systemParamMsg, "Cloud connecting" ); 
                    break;
                case cloud_status_connected:
                    sprintf(systemParamMsg, "Cloud connected" ); 
                    break;
                case cloud_status_disconnecting:
                    sprintf(systemParamMsg, "Cloud disconnecting" ); 
                    break;
                case cloud_status_disconnected:
                    sprintf(systemParamMsg, "Cloud disconnected" ); 
                    break;
                default:
                    break;
            }    
            break;
        case button_status: // button pressed or released
            sprintf(systemParamMsg, "Mode button pressed for %d ms", param);
            break;
        case firmware_update: // firmware update status
            switch (param) {
                case firmware_update_begin:
                    sprintf(systemParamMsg, "F/W update started" ); 
                    break;
                case firmware_update_progress:
                    sprintf(systemParamMsg, "F/W update in progress" ); 
                    break;
                case firmware_update_complete:
                    sprintf(systemParamMsg,"F/W update done" ); 
                    break;
                case firmware_update_failed:
                    sprintf(systemParamMsg, "F/W update failed" ); 
                    break;
                default:
                    break;
            }  
            break;
        case firmware_update_pending: //  notifies the application that a firmware update is available. 

            break;
        case reset_pending: // notifies the application that the system would like to reset

            break;
        case reset: // notifies that the system will reset once the application has completed handling this event
            tbDisconnect();
            break;
        case button_click: // event sent each time setup button is clicked
            sprintf(systemParamMsg, "Mode button clicked %d times", system_button_clicks(param) );
            break;
        case button_final_click: // at the end of a series of clicks.
            sprintf(systemParamMsg, "Mode button clicked %d times in total", system_button_clicks(param) );
            break;
        case time_changed: // device time changed
            
            break;
        case low_battery: // low battery condition is detected
            checkBatt(); // sends particle.publish immediately with battery level
            break;
        case out_of_memory: // out of memeory
            sprintf(systemParamMsg, "Out of memory : %d bytes required", param );
            break;
        default:
            sprintf(systemParamMsg, "Unknown [%d]", param ); // unknown event so just show value
            break;
    }
    
    Log.warn(systemParamMsg);
    
    // special cses where the Log message needs to be shown before the next action i.e. Reset]
    switch (event) {
        case firmware_update_pending: //  notifies the application that a firmware update is available. 
            gracefullReset();
            break;
        case reset_pending: // notifies the application that the system would like to reset
            gracefullReset();
        default:
            break;
    }
}

Not everything seems to generate an event on my Argon - mode button clicks don’t register (or my code my be faulty) - but it is nice to see the underlying stuff working as expected.

1 Like

We'd need to see your System.on() call.

Mere single clicks don't trigger any system event, hence you won't get a trigger.
Mode button clicks can be read in your normal code flow via digitalRead(BTN).
Only when you trigger some system event (e.g. by double clicking MODE on Electrons or press/holding to enter Listening Mode) you'll get the respective system event.


Update:
After some more reading I guess it's due to a combination of events triggerd by the same click. Hence your switch(event) won't catch it

Event combinations should be treated via something like this

  if (event & button_status) {
    ...
  }

  if (event & button_click) {
    ...
  }
  
  if (event & button_final_click) {
    ...
  }
  
  ...
3 Likes