4 Replies Latest reply on May 27, 2016 5:23 AM by qngo RSS
    mnoack-2 Newbie

    What is the best way to achieve Complex Event Processing (CEP)?



    I'd like to ask how Complex Event Processing could be achieved in ThingWorx Composer for evaluating value streams. For example timescale based events:


    When the lamp is switched to ON/OFF 3 times within 10 seconds - fire an special event / call a special service.


    When the motion sensor A was triggered 10 times within the last hour and motion sensor B was triggered 30 % less - call a specific service.


    Is that possible out of the box? What would be a best practice to implement rules like this?


    Thank you very much,


      • Re: What is the best way to achieve Complex Event Processing (CEP)?
        aanjan Heavyweight Champ

        Markus, you could look into adding Alerts to that property and/or subscriptions. To start off simply, do you have access to ThingWorx tutorials? I believe there were some exercises around adding alerts to specific properties so that once they reach that value, a subscription would be triggered based on that.

        • Re: What is the best way to achieve Complex Event Processing (CEP)?
          moritzvonh Creator

          Hi Markus,

          I implemented such scenarios with a combination of Alerts and Converge BusinessProcesses (BP) with evaluations in custom, javascript-based services.

          The scenario that I implemented was the following:

          1. Exceeding a temperature threshold triggers an Alert
          2. The Alert triggers a BP
          3. In the BP an evaluation robot that used a Thing with a custom service that queried the Alert History and counted
            the number of Alerts of a type in a specified timeframe. The code used in the AlertRuleValidator is shown below.
          4. The result is a Boolean that is used to route the BP for the action that has to encapsulated in another custom service.
            In my case I used the ServiceMax ‘CreateCase’ service.


          Here is how the BP looks like:




          Here is the signature of the AlertRuleEvaluator.ValidateAlertCountInTimespan() service:


          and here is the code I used:


          //if alert source is a thing, then do it once, otherwise for all by QueryImplThing/Shape
          //for now I impl only per Thing
          var result = "false";
          logger.info("eventInfo: "+eventInfo.ToJSON());
              var alertDetails=eventInfo.eventData.getRow(0);
              //specify query based on input param
              var startDate, endDate = eventInfo.eventTime;
                  case 'MILLIS':  startDate = dateAddMilliseconds( endDate, -1*Timespan); break;
                  case 'SECONDS': startDate = dateAddSeconds( endDate, -1*Timespan); break;
                  case 'MINUTES': startDate = dateAddMinutes( endDate, -1*Timespan); break;
                  case 'HOURS':  startDate = dateAddHours( endDate, -1*Timespan); break;
                  case 'DAYS':  startDate = dateAddDays( endDate, -1*Timespan); break;
                  case 'MONTHS':  startDate = dateAddMonths( endDate, -1*Timespan); break;
                  case 'YEARS':  startDate = dateAddYears( endDate, -1*Timespan); break;
                  default:  startDate = dateAddSeconds( endDate, -1*Timespan); break;
              logger.info("timespan: from "+startDate+" to "+endDate);
              var query = {
                "filters": {
                  "type": "AND",
                  "filters": [
                      "fieldName": "name",
                      "type": "EQ",
                      "value": alertDetails.name
                      "fieldName": "sourceProperty",
                      "type": "EQ",
                      "value": eventInfo.sourceProperty
                      "fieldName": "eventName",
                      "type": "EQ",
                      "value": eventInfo.eventName
              logger.info("query: "+JSON.stringify(query));
              var params = {
                  startDate: startDate /* DATETIME */,
                  endDate: endDate /* DATETIME */,
                  query: query /* QUERY */,
                  name: eventInfo.source
              // result: INFOTABLE dataShape: AlertHistory
              var foundAlerts = Resources["AlertFunctions"].QueryAlertHistory(params);
              logger.info("foundAlerts: "+foundAlerts.ToJSON());
              result = ((foundAlerts.rows.length > AlertCountThreshold)).toString();


          I hope this gives you an impression how CEP can be implemented with ThingWorx.
          Best regards, moritz

            • Re: What is the best way to achieve Complex Event Processing (CEP)?
              mnoack-2 Newbie

              Hey Moritz, this seems to be very promising - thank you for this!

              However,  I think unfortunately I do not have access to the Converge Business Process Editor because I am in the academic program.


              Hey Aanjan, I am familiar with subscriptions - what I want to achieve is that the alert only triggers if a number of events occur in a defined time window. Normal alerts simply trigger when a threshold is reached, but I only want to fire an event when this threshold triggered i.e. 3 times within 10 seconds.


              Maybe someone has any other ideas how to do this ?

              My current solution would be to send relevant values out to a CEP-Engine like Esper or WSO2 an then trigger a service via REST API if a match is found, but it would be nicer to have all the logic in ThingWorx.

                • Re: What is the best way to achieve Complex Event Processing (CEP)?
                  qngo Creator

                  Hi, I think about a work-around. I'd create a new Thing which contains a property "counter" and a property "startingTime", or keep the same thing with these two new properties.


                  The first time the threshold is reached, a first alert increases this "counter" and set the date for "startingTime". The next time the threshold is reached, the alert checks firstly if "startingTime" + 10 seconds < now, then the counter will be incremented by 1 or set "counter" back to 1.


                  A second alert of "counter" will be triggered if it reach 3 in order to do the "real" action.