Hi,
I’m looking for some advice on the best way to set up my device first boot.
I’ve been following the Mongoose OS tutorials till now with good success, but I’ve now run in to a wall with implementing my first boot sequence.
This is the ideal sequence of events I would like on first boot:
- Device boots to some welcome message (my device has a screen)
- Device sits in this welcome screen till WiFi is connected
- With WiFi connected I orchestrate a bunch of functions that would normally be run on a schedule using
mgos_set_timer
- Once I have the state I need to show my normal operation screen I kick back over to the scheduled operation of the device.
This is what I have been using till now:
enum mgos_app_init_result mgos_app_init(void)
{
struct mgos_i2c *i2c;
// ili9341 Screen Configuration
mgos_ili9341_set_orientation((ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV), 321, 241);
mgos_ili9341_set_fgcolor(0, 0, 0);
mgos_ili9341_fillRect(0, 0, 321, 241); // clear screen
// Set device boot screen
bootScreen();
// Setup i2c bus and temp sensor
i2c = mgos_i2c_get_global();
s_si7021 = mgos_si7021_create(i2c, 0x40); // Default I2C address
// Network connectivity events
mgos_event_add_group_handler(MGOS_EVENT_GRP_NET, net_cb, NULL);
mgos_event_add_group_handler(MGOS_WIFI_EV_BASE, wifi_cb, NULL);
mgos_event_add_handler(MGOS_EVENT_CLOUD_CONNECTED, cloud_cb, NULL);
mgos_event_add_handler(MGOS_EVENT_CLOUD_DISCONNECTED, cloud_cb, NULL);
// Remote Procedure Call setup
mg_rpc_add_handler(mgos_rpc_get_global(), "Device.Foo", NULL, get_system_foo_handler, NULL);
mg_rpc_add_handler(mgos_rpc_get_global(), "Device.Bar", "{someValue: %d, otherValue: %d}", update_bar_handler, NULL);
// Set the time based callback functions
mgos_set_timer(1000, MGOS_TIMER_REPEAT, clock_cb, NULL); // every second
mgos_set_timer(10000, MGOS_TIMER_REPEAT, read_sensor_cb, NULL); // every ten seconds
// If the device passes the self test then the OTA update is OK to apply
if (deviceSelfTest())
{
struct mg_rpc_call_opts opts = {.dst = mg_mk_str(MGOS_RPC_LOOPBACK_ADDR) };
mg_rpc_callf(mgos_rpc_get_global(), mg_mk_str("OTA.Commit"), NULL, NULL, &opts, NULL);
LOG(LL_INFO, ("Commiting OTA changes"));
}
else
{
LOG(LL_INFO, ("Reverting back to old FW... rebooting"));
mgos_system_restart();
}
// Finished
return MGOS_APP_INIT_SUCCESS;
}
The issue I’m having is that if I try to hold up the mgos_app_init_result
function then my WiFI connection and other services do not start.
I attempted to move the mgos_set_timer
initialisation to a first boot function that was scheduled via a callback, then remove the schedule for the first boot script but that cause some unexpected results. Basically I was getting a hundreds of callbacks that I was not expecting. Almost like the timer division was off by a factor of 100 or 1000. This is what the code looked like:
static void first_boot_cb(void *user_data)
{
// Disable first boot callback
mgos_clear_timer(first_boot_timer_id);
// Wait for WiFi
// Orchestrate the sequence of events I need to get the info for first boot
// Now that first boot is complete, set all the recurring functions
mgos_set_timer(1000, MGOS_TIMER_REPEAT, clock_cb, NULL); // every second
mgos_set_timer(10000, MGOS_TIMER_REPEAT, read_sensor_cb, NULL); // every ten seconds
}
enum mgos_app_init_result mgos_app_init(void)
{
bla bla...
first_boot_timer_id = mgos_set_timer(0, MGOS_TIMER_REPEAT, first_boot_cb, NULL);
bla bla ...
}
I’m out of ideas on the best way to solve this problem.
I’d appreciate any suggestions.
Thanks.