Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: provide parse functions in a module

...

Code Block
linenumberstrue
  rule mail_router {
    select when mail parsed to re#assigned_id_2[+]([^@]*)@cloudmailin.net# setting(eci)
    event:send({"eci":eci, "domain":"testmail", "type":"testevents", "attrs":event:attrs()})
  }

...

The redacted "assigned_id_4" is an ECI of another pico to which the rule (in line 3) sends the testmail:testevents event with parsed fields from the email message as attributes. We created a new channel for this purpose, with name "email tests" and type "secret" whose id is known herein as "assigned_id_4". This is easily done in the "Channels" tab of the developer UI.

...

In this example, the other pico has a ruleset which handles numerous events with domain "aurora" and controls a set of 12 Nanoleaf Aurora units. Rather than modify the existing ruleset, we make a new ruleset and add it to the same pico. Shown here is a global definition and a rule that reacts to the testmail:testevents event.

Code Block
linenumberstrue
  global {
    newline = (13.chr() + "?" + 10.chr()).as("RegExp")
  }
  rule testmail_testevents {
    select when testmail testevents
    foreach event:attr("text").split(newline) setting(request)
    pre {
      parts = request.split(re#/#)
      aurora = parts.length() == 2 && parts[0] == "aurora"
    }
    if aurora then noop()
    fired {
      raise aurora event parts[1]
    }
  }

...

Upon receipt of this email message, our Mail pico will extract the "To" field and the "text" of the message body, and begin a cascade of events. Next, the same pico will parse out the ECI ("assigned_id_4") of the Aurora pico and send it the testmail:testevents event. This will trigger its new rule which will loop over the lines of the message body, ignoring comment lines, and raise a series of three events, which the existing ruleset will handle to turn the NanoLeaf display on and move through to the second-next theme.

...

Code Block
linenumberstrue
  global {
    newline = (13.chr() + "?" + 10.chr()).as("RegExp")
    var = function(s) {
      p = s.split(re#=#);
      {}.put(p[0],p[1])
    }
    vars = function(s) {
      p = s=>s.split(re#&#)|[];
      p.reduce(function(a,b){a.put(var(b))},{})
    }
    parse = function(text,domain) {
      dlpo = domain.length() + 1;
      text.split(newline)
          .filter(function(v){p=v.split(re#/#);p[0]==domain && p.length()==2})
          .map(function(v){p=v.split(re#[?]#);[p[0].substr(dlpo),vars(p[1])]})
    }
  }
  rule testmail_testevents {
    select when testmail testevents
    foreach parse(event:attr("text"),"aurora") setting(request)
    pre {
      type = request[0]
      attrs = request[1]
    }
    if request.length() == 2 then noop()
    fired {
      raise aurora event type attributes attrs;
      ent:lastRequest := "aurora/"+type
    }
  }

...

The rule loops over the parsed events (line 20), setting the type (line 22) and attributes (line 23) of each, and raises the corresponding events (line 27).

Update

The complete ruleset that first receives email, and reacts to the mail:received event, can be found at https://github.com/Picolab/pico_lessons/blob/master/mailin/io.picolabs.mail.krl and nearby is the ruleset to test this with Aurora, at https://github.com/Picolab/pico_lessons/blob/master/mailin/aurora_test.krl

We moved the parsing functions into the io.picolabs.mail ruleset, which provides them to rulesets which might want to react to the mail:events event. Such rulesets can include a clause in their meta block like

Code Block
  use module io.picolabs.mail alias mail

so that parsing can be done with a line like

Code Block
    foreach mail:parse(event:attr("text"),"aurora") setting(request)

This is a basic use of User Defined Modules and has the advantage that the parsing functions do not need to be replicated into a ruleset for every pico which needs them.