System Events param problem

I need to know when the user holds the mode button to put the device into AP mode.
According to the docs there is a nice feature of System Events. Which they give an example:

void handle_all_the_events(system_event_t event, int param)
{
    Serial.printlnf("got event %d with value %d", event, param);
}

void setup()
{
    // listen for Wi-Fi Listen events and Firmware Update events
    System.on(wifi_listen+firmware_update, handle_all_the_events);
}

Yet, when I tried this i am unable to perform a if statement on the param value, so I changed it to this to see whats going on and I cannot make any sense of what the problem is. Here is my code.

void handle_AP_events(system_event_t event, int param)
{
    int x = param;

    Serial.printlnf("Got event %d with value %d", event, param);

	Serial.printlnf("Repeat:%d", x);

	if(x == 2)
	{
		Serial.printlnf("AP Mode Started");
	}
	else if(x == 4)
	{
		Serial.printlnf("AP Mode Running");
	}
	else if(x == 8)
	{
		Serial.printlnf("AP Mode Ended");
	}
}

Here is the output of the terminal, Why is X changing values over and over ?

Got event 129 with value 2
Repeat:0
Got event 129 with value 4
Repeat:1100
Got event 129 with value 4
Repeat:2200
Got event 129 with value 4
Repeat:3300
Got event 129 with value 4
Repeat:4400
Got event 129 with value 4
Repeat:5500
Got event 129 with value 4
Repeat:6600
Got event 129 with value 4
Repeat:7700
Got event 129 with value 4
Repeat:8800
Got event 129 with value 4
Repeat:9900
Got event 129 with value 4
Repeat:11000

I’m not sure exactly what your complete code is. I tried to duplicate your results, and I got different but still confusing results. The initial code I tested was the following,

void setup() {
	Serial.begin(9600);
	delay(4000);
  	System.on(button_status, handleEvents);
}

void loop() {}

void handleEvents(system_event_t event, int param) {
	Serial.printlnf("Got event: %d with param: %d", event, param);
	Serial.printlnf("Hold down time: %d ms", param);
	Serial.println();
}

Holding down, then releasing the setup button twice gave me these results,

Got event: 129 with param: 128
Hold down time: 0 ms

Got event: 129 with param: 128
Hold down time: 234 ms

Got event: 129 with param: 128
Hold down time: 0 ms

Got event: 129 with param: 128
Hold down time: 813 ms

129 doesn’t seem to be one of the events we should get, and why does param print as 128 (which should be the event code) on one print but 0 or a larger number on the second print?

If I copy both the event and param, I get the results I expect. The handler now is,

void handleEvents(system_event_t event, int param) {
	int p = param;
	int e = event;
	Serial.printlnf("Got event: %d with param: %d", e, p);
	Serial.printlnf("Hold down time: %d ms", p);
	Serial.println();
}

Now the results are,

Got event: 128 with param: 0
Hold down time: 0 ms

Got event: 128 with param: 479
Hold down time: 479 ms

Got event: 128 with param: 0
Hold down time: 0 ms

Got event: 128 with param: 1081
Hold down time: 1081 ms

Now, param correctly prints (both times) the time in ms that the button was held down.

Copying only param still gives me the first baffling results above, while copying only event, gives me the same correct result as copying both.

Thank you for your efforts. I should have added what i used in my setup, sorry.
System.on(wifi_listen, handle_AP_events);

OMG, I cannot believe I was so dumb to have missed the problem. The reason why I was getting different results from one Serial.print to another was because I cannot read the manual properly. It is working as expected, I am sorry for the trouble.

Just to add to the confusion I’ve been trying to get system info back from an electron and the only even I ever get is…

Got event: 0 with param: 32

There is no event 0 :S

If you want the button_click
This is how you’d handle the click count

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

If you use button_status you will get 0 when the button is pressed and the milliseconds when released.

@Nemiah, how do you subscribe to the system events?

Yes, I understand that. My question is about why, if I don’t copy (to local variables) the values passed in to the handler, I get weird results. How can passing param to two different print statements print different things? And, why does printing event give me 129, when it should give me 128 unless I copy event to e?

I found out the the problem seems to be the way Serial.print deals with event, which is typed as system_event_t (which is a typedef for a uint64_t). If I cast that to an int in the print statement, then everything prints out properly.

void handleEvents(system_event_t event, int param) {
	Serial.printlnf("Got event: %d with param: %d", (int)event, param);
	Serial.printlnf("Hold down time: %d ms", param);
	Serial.println();
}

Pressing and releasing the setup button once gives me this,

Got event: 128 with param: 0
Hold down time: 0 ms

Got event: 128 with param: 1237
Hold down time: 1237 ms

I have no idea why that cast should solve this problem; it still doesn’t make sense to me why the printout of param should be different on the two lines, and why it gives the correct value for event the first time it prints.

I see the same behavior with cloud_status (when not casting to an int); that is, event prints out as 129, param in the first print prints out 64 (the value of what event should be), and param in the second print, prints out the correct code.

@KyleG there seems to be something wrong with the way the system events handlers work, and I’d like to ping somebody at Particle to clear this up. Do you know who would be best to talk to? @mdma ?

void setup()
{
    // listen for network events and firmware update events
    System.on(all_events, handle_all_the_events);
}

void handle_all_the_events(system_event_t event, int param)
{
    Serial.printlnf("got event %d with value %d", event, param);
}

I just used the example from the docs

@Nemiah You may be seeing the same thing that I was seeing with a problem printing event. Try casting event to an int and see if that fixes the problem.

void handle_all_the_events(system_event_t event, int param)
{
    Serial.printlnf("got event %d with value %d", (int)event, param);
}
1 Like

@Ric, yes that sorted it - I should of just read the thread properly!

Thanks for the ping!

Kyle, I think I need to talk to someone at Particle about these system events; there is something wrong with the way they print out. Can you ping whoever would be best to handle this.

2 Likes

@rickkas7 have you seen this before?

Rick and I were just talking about this… and the problem seems like it stems from system_event_t being 64-bit as you pointed out @Ric Casting to int fixes it for now, but later when we have more events up in the upper 32-bit range you’ll need to shift them down and break up the event into two 32-bit unsigned ints.

// %llu is uint64_t type, but does NOT work
Log.info("EVENT: %llu DATA: %d", event, data);

// Good workaround
Log.info("EVENT_H: %lu EVENT_L: %lu DATA: %d", (uint32_t)(event>>32), (uint32_t)event, data);

The reason this doesn’t work is because it’s not supported in Wiring, unsigned long is the highest size supported:

4 Likes