Copyright © https://mongoose-os.com

Mongoose OS Forum

frame

Time based event

DuncanCTDuncanCT South Africa

I would like to reset a counter at midnight.

This is the basic idea but not sure if any of it is right? Any help is appreciated.

let resetcounter = function() {
  let now = Timer.now();
  let timestamp = Timer.fmt("%H:%M:%S", now);
};

if (resetcounter = '00:00:00') {
  let counter = 0;
}

Comments

  • SergeySergey Dublin, Ireland

    Use cron library

    Thanked by 1DuncanCT
  • DuncanCTDuncanCT South Africa

    So as far as I can gather from this...

    https://github.com/mongoose-os-libs/cron

    the c/c++ api ref suggests this...

    0 0 0 * * * for midnight.

    And here... https://www.npmjs.com/package/cron

    var CronJob = require('cron').CronJob;
    new CronJob('0 0 0 * * *', function() {
      let counter = 0;
    }, null);

    Assume this syntax (not sure that's the correct terminology?) is wrong for mJS?

    Or can someone please link to a mJS example somewhere?

  • nliviunliviu Romania
    edited April 11

    C/C++ interoperability
    You need to ffi mgos_cron_add in mJS code and define a callback.

    Thanked by 1DuncanCT
  • @nliviu
    Can you give an example code and js function to call a defined callback?

  • nliviunliviu Romania
    /*
     * Cron callback signature; `user_data` is a pointer given to
     * `mgos_cron_add()`, and `id` is the id of the corresponding cron job.
     * typedef void (*mgos_cron_callback_t)(void *user_data, mgos_cron_id_t id);
     */
    function cronCallback(arg, cron_id)
    {
        let now = Timer.now();
        let timestring = Timer.fmt('%FT%TZ', now);
        print('++++ cronCallback id=' + JSON.stringify(cronId) + ', time=' + timestring);
    }
    
    /*
     * Adds cron entry with the expression `expr` (a null-terminated string, should
     * be no longer that 256 bytes) and `cb` as a callback.
     * `user_data` is an arbitrary pointer which will be passed to `cb`.
     * Returns cron ID.
     * mgos_cron_id_t mgos_cron_add(const char *expr, mgos_cron_callback_t cb, void *user_data);
    */
    let cronAdd = ffi('int mgos_cron_add(char*, void (*)(userdata, int),userdata)');
    cronAdd("*/15 * * * * *", cronCallback, null);
    

    cronCallback is called every 15 seconds.

    Results:

    [Apr 13 06:32:14.254] s_print_time         Next invocation: 1523590350 [2018/04/13 03:32:30 UTC]
    [Apr 13 06:32:14.294] ++++ cronCallback id=1073531312, time=2018-04-13T03:32:15Z 
    [Apr 13 06:32:29.254] s_print_time         Next invocation: 1523590365 [2018/04/13 03:32:45 UTC]
    [Apr 13 06:32:29.299] ++++ cronCallback id=1073531312, time=2018-04-13T03:32:30Z 
    [Apr 13 06:32:44.255] s_print_time         Next invocation: 1523590380 [2018/04/13 03:33:00 UTC]
    [Apr 13 06:32:44.294] ++++ cronCallback id=1073531312, time=2018-04-13T03:32:45Z 
    
    Thanked by 2Generator DuncanCT
  • @nliviu Thank You!
    Everything works fine!
    However, the question remained: how to pick up an event, which is created through prc-service-cron?

  • DuncanCTDuncanCT South Africa
    edited April 13

    Back with the stupid questions, please forgive me.

    Do the two pieces of code @nliviu provided all need to be in init.js or elsewhere?

    For my example of resetting counter at midnight...

    function cronCallback(arg, cron_id)
    {
        let counter = 0;    
    }

    let cronAdd = ffi('int mgos_cron_add(char*, void (*)(userdata, int),userdata)');
    cronAdd("0 0 0 * * *", cronCallback, null);

    Are any other changes that need to be made to the device files?

  • DuncanCTDuncanCT South Africa
    edited April 13

    After adding the cron library to the yml file then build and flashing @nliviu code posted above...

    load('api_config.js');
    load('api_events.js');
    load('api_gpio.js');
    load('api_mqtt.js');
    load('api_net.js');
    load('api_sys.js');
    load('api_timer.js');
    load('api_shadow.js');
    function cronCallback(arg, cron_id) {
      let now = Timer.now();
      let timestring = Timer.fmt('%FT%TZ', now);
      print('++++ cronCallback id=' + JSON.stringify(cronId) + ', time=' + timestring);
    }
    let cronAdd = ffi('int mgos_cron_add(char*, void (*)(userdata, int),userdata)');
    cronAdd("*/15 * * * * *", cronCallback, null);

    I get this...

    [Apr 13 13:58:46.861] s_print_time         Next invocation: 1523620740 [2018/04/13 11:59:00 UTC]
    [Apr 13 13:58:46.923]   at init.js:13
    [Apr 13 13:58:46.924] MJS callback error: [cronId] is not defined

    Final edit see that JSON.stringify(cronId) should be JSON.stringify(cron_id)

  • @DuncanCT, replace

    cronAdd("*/15 * * * * *", cronCallback, null);

    to

    let cronId = cronAdd("*/15 * * * * *", cronCallback, null);

    Thanked by 1DuncanCT
  • nliviunliviu Romania

    Sorry, it was my fault, it was meant to be

    function cronCallback(arg, cronId)
    {
        let now = Timer.now();
        let timestring = Timer.fmt('%FT%TZ', now);
        print('++++ cronCallback id=' + JSON.stringify(cronId) + ', time=' + timestring);
    }
    
    Thanked by 1DuncanCT
  • nliviunliviu Romania

    @DuncanCT Something like that

    let counter=0;
    /*
    do something with the counter
    ...
    */
    
    function cronCallback(arg, cron_id)
    {
        counter = 0;    
    }
    
    Thanked by 1DuncanCT
  • nliviunliviu Romania

    @Generator What is your question? Ref: "However, the question remained: how to pick up an event, which is created through prc-service-cron?"

  • @nliviu
    After adding the entry to crontab, using RPC call Cron.add. The cron firing event
    and i have error message in log panel

    [Apr 13 19:52:35.816] cron_cb              Cron job 2 is firing: "bar" {}
    [Apr 13 19:52:35.822] cron_cb              No actual handler for the cron action "bar"
    

    Question - how to add a handler for the cron action "bar" in mJS code?

  • nliviunliviu Romania

    You have to associate the action from Cron.Add with a callback using mgos_crontab_register_handler
    Example in C:

    #include <mgos.h>
    #include "mgos_crontab.h"
    
    void test(struct mg_str action, struct mg_str payload, void *userdata) {
      (void) payload;
      (void) userdata;
      time_t t = time(0);
      struct tm* timeinfo = localtime(&t);
      char timestamp[24];
      strftime(timestamp, sizeof (timestamp), "%FT%TZ", timeinfo);
      LOG(LL_INFO, ("%s - crontab test, action: %.*s", timestamp, action.len, action.p));
    }
    
    enum mgos_app_init_result mgos_app_init(void) {
      /*
       * Add a handler for the given string action
       *
       * Example:
       *
       * ```c
       * static void my_foo_cb(struct mg_str action,
       *                       struct mg_str payload, void *userdata) {
       *   LOG(LL_INFO, ("Crontab foo job fired! Payload: %.*s", payload.len, payload.p));
       *   (void) action;
       *   (void) userdata;
       * }
       *
       * // Somewhere else:
       * mgos_crontab_register_handler("foo", my_foo_cb, NULL);
       * ```
       *
       * The code above maps action `foo` in the JSON to the callback `my_foo_cb`.
       */
      mgos_crontab_register_handler(mg_mk_str("test"), test, NULL);
    
      return MGOS_APP_INIT_SUCCESS;
    }
    

    Add cron:
    mos --port ws://<IP>/rpc call Cron.Add '{"at":"*/20 * * * * *", "action":"test"}'

    Results:

    [Apr 13 20:40:39.892] cron_cb              Cron job 1 is firing: "test" 
    [Apr 13 20:40:39.900] test                 2018-04-13T17:40:40Z - crontab test, action: test
    [Apr 13 20:40:59.892] cron_cb              Cron job 1 is firing: "test" 
    [Apr 13 20:40:59.900] test                 2018-04-13T17:41:00Z - crontab test, action: test
    [Apr 13 20:41:19.892] cron_cb              Cron job 1 is firing: "test" 
    [Apr 13 20:41:19.899] test                 2018-04-13T17:41:20Z - crontab test, action: test
    
    mos --port ws://<IP>/rpc call Cron.List
    [
      {
        "id": 1,
        "at": "*/20 * * * * *",
        "enable": true,
        "action": "test"
      }
    ]
    
  • edited April 13

    @nliviu
    Thanks. I tried this example. I just can not understand how to do ffi

    void test(struct mg_str action, struct mg_str payload, void *userdata)

    mgos_crontab_register_handler(mg_mk_str("test"), test, NULL);

    to use it in mJS code

  • nliviunliviu Romania

    C/C++ interoperability.
    AFAIK, the best ideea would be to use C.

  • DuncanCTDuncanCT South Africa

    For reference, I found this out the long way...

    Couldn't work out what was going on! :D

    Free version of cron library can only have 3 jobs max. For commercial version, please contact https://mongoose-os.com/contact.html

  • tripflextripflex Orlando, FL

    So does mgos_crontab_register_handler not work with mjs? I can't get it to work:

    let ctRegisterHandler = ffi('void mgos_crontab_register_handler(char*, void (*)(char*, char*,userdata),userdata)’);
    ctRegisterHandler( "start_mist", startMistCB, null );
    ctRegisterHandler( "stop_mist”, stopMistCB, null );
    

    I then add a cronjob via RPC which works perfectly fine ... except for when it's supposed to be triggered, and I get this:

    cron_cb No actual handler for the cron action “stop_mist"

  • mamuespmamuesp Germany/Northern coast

    Normally I don't like double or cross postings, but as it is mentioned here, I repeat my Gitter posting as well:

    @tripflex - Maybe it helps if you wrap the addition of the handler in a C function.

    I did something similar when I needed the hardware timer functions that only run in ISR context. I called the wrapper in C via MJS.

    BTW the firing of the cron jobs works fine, but as you stated, the handlers aren’t found. So it has to be analyzed if there is a similar situation as I described, but it is strange, because the direct setting works fine with MJS.

    So another solution could be to parse the crontab.json file by yourself and init the cron jobs when starting. Or look at the RPC implementation and use something similar as a wrapper - because you already tested this.

    But time permitting I’ll try to find out why the handler isn’t registered correctly, because I may use this functionality as well.

Sign In or Register to comment.