Saturday, June 30, 2018

Cronjobs on the ESP8266 with Mongoose OS

This is a copy of a post I made on StackOverflow helping another user getting a Cronjob up and going on mgos, but I thought it might be useful to add it here also, with a bit more info.  All it does is turn on an LED at a particular time of the day and turn it off at another time of the day.
There are 6 steps.  They're all pretty easy.  But if you're less experienced with Mongoose OS or experience a bug, please let me know the comments below.
Step 1: Add wifi setup to your mos.yml so it can connect to your wireless AP.  If you don't do this you won't be able to successfully pull the time from the NTP server using SNTP.
config_schema:
  - ["wifi.sta.enable", true]
  - ["wifi.sta.ssid", "MyAP"]
  - ["wifi.sta.pass", "Passwd"]
Step 2: Add these to your mos.yml. Leave off rpc-uart if you have no intention of making rpc calls over UART.  You'll notice there's a lib sntp in here.  There's nothing that needs to be done after adding it to your mos.yml. You don't need to add anything into your app code.  As soon as an internet connection is established it grabs the latest time.  It uses time.google.com by default.
libs:
  - origin: https://github.com/mongoose-os-libs/sntp
  - origin: https://github.com/mongoose-os-libs/crontab
  - origin: https://github.com/mongoose-os-libs/rpc-service-cron
  - origin: https://github.com/mongoose-os-libs/wifi
  - origin: https://github.com/mongoose-os-libs/rpc-uart
Step 3: In your application code, in the entry point for your app (mgos_app_init()), add crontab handlers.  In this case we're just going to add two cronjobs, one for LED on, and LED off. mgos_crontab_register_handler() takes three arguments, the name of the action (we will get to this in step 6), and the exact name of the callback function, which we will define in the next step.  The third argument is void *userdata. For now it's safe to leave this as NULL, because we don't intend of passing any extra data into our callback functions.
enum mgos_app_init_result mgos_app_init(void) {
  /* Set LED GPIOs as outputs */
  mgos_gpio_set_mode(YOUR_LED_GPIO, MGOS_GPIO_MODE_OUTPUT);

  /* Register crontab handler - LED OFF */
  mgos_crontab_register_handler(mg_mk_str("ledoff"), ledoff, NULL);

  /* Register crontab handler - LED ON */
  mgos_crontab_register_handler(mg_mk_str("ledon"), ledon, NULL);

  return MGOS_APP_INIT_SUCCESS;
}
Step 4: Add callbacks.  These callback functions need to match the name of the second argument of mgos_crontab_register_handler() in the previous step.  It's worth noting that the mos-tool build system is extremely pedantic and with error out if you pass a parameter into a function and don't utilize it.  This is why we use (void) parameter; to trick the compiler into letting us pass.
void ledoff(struct mg_str action, struct mg_str payload, void *userdata) {
  mgos_gpio_write(YOUR_LED_GPIO, 0);
  (void) payload;
  (void) userdata;
  (void) action;
}

void ledon(struct mg_str action, struct mg_str payload, void *userdata) {
  mgos_gpio_write(YOUR_LED_GPIO, 1);
  (void) payload;
  (void) userdata;
  (void) action;
}
Step 5: From your app's main directory, build the app as you normally would (eg. mos build --arch esp8266 --verbose).
Step 6: Add your cronjobs from the web UI or UART:
call Cron.Add '{"at":"0 0 10 00 * *, "action":"ledon"}'
call Cron.Add '{"at":"0 0 16 00 * *, "action":"ledoff"}'
The format of cronjob times on Unix-like systems typically looks like this:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                  7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *  command to execute
But Mongoose OS's cron lib specifies a slightly different format:
# ┌───────────── seconds (0 - 59)
# │ ┌───────────── minutes (0 - 59)
# │ │ ┌───────────── hours (0 - 23)
# │ │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ │ ┌───────────── month 1-12 or JAN-DEC
# │ │ │ │ │ ┌───────────── day of week 0-6 or SUN-SAT
# │ │ │ │ │ │
# │ │ │ │ │ │ 
# * * * * * *