@@ -77,12 +77,12 @@ static void running_run(void *o);
7777static void triggering_entry (void * o );
7878static void triggering_run (void * o );
7979
80- static void requesting_location_entry (void * o );
81- static void requesting_location_run (void * o );
80+ static void sample_data_entry (void * o );
81+ static void sample_data_run (void * o );
8282
83- static void requesting_sensors_and_polling_entry (void * o );
84- static void requesting_sensors_and_polling_run (void * o );
85- static void requesting_sensors_and_polling_exit (void * o );
83+ static void wait_for_trigger_entry (void * o );
84+ static void wait_for_trigger_run (void * o );
85+ static void wait_for_trigger_exit (void * o );
8686
8787static void idle_entry (void * o );
8888static void idle_run (void * o );
@@ -110,10 +110,13 @@ enum state {
110110 STATE_IDLE ,
111111 /* Triggers are periodically sent at a configured interval */
112112 STATE_TRIGGERING ,
113- /* Requesting location from the location module */
114- STATE_REQUESTING_LOCATION ,
115- /* Requesting sensor values and polling for downlink data */
116- STATE_REQUESTING_SENSORS_AND_POLLING ,
113+ /* Requesting data samples from relevant modules.
114+ * Location data is requested first, upon state entry.
115+ * After location data is received, the other modules are polled.
116+ */
117+ STATE_SAMPLE_DATA ,
118+ /* Wait for timer or button press to trigger the next sample */
119+ STATE_WAIT_FOR_TRIGGER ,
117120 /* Ongoing FOTA process, triggers are blocked */
118121 STATE_FOTA ,
119122 /* FOTA image is being downloaded */
@@ -144,10 +147,15 @@ struct main_state {
144147 uint8_t msg_buf [MAX_MSG_SIZE ];
145148
146149 /* Trigger interval */
147- uint64_t interval_sec ;
150+ uint32_t interval_sec ;
148151
149152 /* Cloud connection status */
150153 bool connected ;
154+
155+ /* Start time of the most recent sampling. This is used to calculate the correct
156+ * time when scheduling the next sampling trigger.
157+ */
158+ uint32_t sample_start_time ;
151159};
152160
153161/* Construct state table */
@@ -171,19 +179,19 @@ static const struct smf_state states[] = {
171179 triggering_run ,
172180 NULL ,
173181 & states [STATE_RUNNING ],
174- & states [STATE_REQUESTING_LOCATION ]
182+ & states [STATE_SAMPLE_DATA ]
175183 ),
176- [STATE_REQUESTING_LOCATION ] = SMF_CREATE_STATE (
177- requesting_location_entry ,
178- requesting_location_run ,
184+ [STATE_SAMPLE_DATA ] = SMF_CREATE_STATE (
185+ sample_data_entry ,
186+ sample_data_run ,
179187 NULL ,
180188 & states [STATE_TRIGGERING ],
181189 NULL
182190 ),
183- [STATE_REQUESTING_SENSORS_AND_POLLING ] = SMF_CREATE_STATE (
184- requesting_sensors_and_polling_entry ,
185- requesting_sensors_and_polling_run ,
186- requesting_sensors_and_polling_exit ,
191+ [STATE_WAIT_FOR_TRIGGER ] = SMF_CREATE_STATE (
192+ wait_for_trigger_entry ,
193+ wait_for_trigger_run ,
194+ wait_for_trigger_exit ,
187195 & states [STATE_TRIGGERING ],
188196 NULL
189197 ),
@@ -293,18 +301,6 @@ static void sensor_and_poll_triggers_send(void)
293301 SEND_FATAL_ERROR ();
294302 return ;
295303 }
296-
297- /* Send trigger for shadow polling */
298- struct cloud_msg cloud_msg = {
299- .type = CLOUD_POLL_SHADOW
300- };
301-
302- err = zbus_chan_pub (& CLOUD_CHAN , & cloud_msg , K_SECONDS (1 ));
303- if (err ) {
304- LOG_ERR ("zbus_chan_pub shadow trigger, error: %d" , err );
305- SEND_FATAL_ERROR ();
306- return ;
307- }
308304}
309305
310306/* Delayable work used to send messages on the TIMER_CHAN */
@@ -476,17 +472,30 @@ static void triggering_run(void *o)
476472 }
477473}
478474
479- /* STATE_REQUESTING_LOCATION */
475+ /* STATE_SAMPLE_DATA */
480476
481- static void requesting_location_entry (void * o )
477+ static void sample_data_entry (void * o )
482478{
483479 int err ;
484480 enum location_msg_type location_msg = LOCATION_SEARCH_TRIGGER ;
481+ struct cloud_msg cloud_msg = {
482+ .type = CLOUD_POLL_SHADOW
483+ };
484+ struct main_state * state_object = (struct main_state * )o ;
485485
486- ARG_UNUSED (o );
487486
488487 LOG_DBG ("%s" , __func__ );
489488
489+ /* Record the start time of sampling */
490+ state_object -> sample_start_time = k_uptime_seconds ();
491+
492+ err = zbus_chan_pub (& CLOUD_CHAN , & cloud_msg , K_SECONDS (1 ));
493+ if (err ) {
494+ LOG_ERR ("zbus_chan_pub shadow trigger, error: %d" , err );
495+ SEND_FATAL_ERROR ();
496+ return ;
497+ }
498+
490499 err = zbus_chan_pub (& LOCATION_CHAN , & location_msg , K_SECONDS (1 ));
491500 if (err ) {
492501 LOG_ERR ("zbus_chan_pub data sample trigger, error: %d" , err );
@@ -495,62 +504,77 @@ static void requesting_location_entry(void *o)
495504 }
496505}
497506
498- static void requesting_location_run (void * o )
507+ static void sample_data_run (void * o )
499508{
500509 const struct main_state * state_object = (const struct main_state * )o ;
501510
502511 if (state_object -> chan == & LOCATION_CHAN ) {
503512 enum location_msg_type msg = MSG_TO_LOCATION_TYPE (state_object -> msg_buf );
504513
505514 if (msg == LOCATION_SEARCH_DONE ) {
506- smf_set_state ( SMF_CTX ( state_object ),
507- & states [STATE_REQUESTING_SENSORS_AND_POLLING ]);
515+ sensor_and_poll_triggers_send ();
516+ smf_set_state ( SMF_CTX ( state_object ), & states [STATE_WAIT_FOR_TRIGGER ]);
508517 return ;
509518 }
510519 }
511520
521+ /* We are already sampling, ignore any new triggers */
512522 if (state_object -> chan == & BUTTON_CHAN ) {
513523 smf_set_handled (SMF_CTX (state_object ));
514524 return ;
515525 }
526+
527+ if (state_object -> chan == & TIMER_CHAN ) {
528+ smf_set_handled (SMF_CTX (state_object ));
529+ return ;
530+ }
516531}
517532
518- /* STATE_REQUESTING_SENSORS_AND_POLLING */
533+ /* STATE_WAIT_FOR_TRIGGER */
519534
520- static void requesting_sensors_and_polling_entry (void * o )
535+ static void wait_for_trigger_entry (void * o )
521536{
522537 int err ;
523538 const struct main_state * state_object = (const struct main_state * )o ;
539+ uint32_t time_elapsed = k_uptime_seconds () - state_object -> sample_start_time ;
540+ uint32_t time_remaining ;
541+
542+ if (time_elapsed > state_object -> interval_sec ) {
543+ LOG_WRN ("Sampling took longer than the interval, skipping next trigger" );
544+ time_remaining = 0 ;
545+ } else {
546+ time_remaining = state_object -> interval_sec - time_elapsed ;
547+ }
524548
525549 LOG_DBG ("%s" , __func__ );
526550
527- sensor_and_poll_triggers_send ( );
551+ LOG_DBG ( "Next trigger in %d seconds" , time_remaining );
528552
529- LOG_DBG ("Next trigger in %lld seconds" , state_object -> interval_sec );
530-
531- err = k_work_reschedule (& trigger_work , K_SECONDS (state_object -> interval_sec ));
553+ (void )k_work_cancel_delayable (& trigger_work );
554+ err = k_work_reschedule (& trigger_work , K_SECONDS (time_remaining ));
532555 if (err < 0 ) {
533556 LOG_ERR ("k_work_reschedule, error: %d" , err );
534557 SEND_FATAL_ERROR ();
535558 }
536559}
537560
538- static void requesting_sensors_and_polling_run (void * o )
561+ static void wait_for_trigger_run (void * o )
539562{
540563 const struct main_state * state_object = (const struct main_state * )o ;
541564
542565 if (state_object -> chan == & TIMER_CHAN ) {
543- smf_set_state (SMF_CTX (state_object ), & states [STATE_REQUESTING_LOCATION ]);
566+ LOG_DBG ("Timer trigger received" );
567+ smf_set_state (SMF_CTX (state_object ), & states [STATE_SAMPLE_DATA ]);
544568 return ;
545569 }
546570
547571 if (state_object -> chan == & BUTTON_CHAN ) {
548- smf_set_state (SMF_CTX (state_object ), & states [STATE_REQUESTING_LOCATION ]);
572+ smf_set_state (SMF_CTX (state_object ), & states [STATE_SAMPLE_DATA ]);
549573 return ;
550574 }
551575}
552576
553- static void requesting_sensors_and_polling_exit (void * o )
577+ static void wait_for_trigger_exit (void * o )
554578{
555579 ARG_UNUSED (o );
556580
0 commit comments