The joys of event stream pattern matching

While working on a project that involves gathering data from a large number of distributed sensors and then using that to make notification decisions (the intent is to detect certain conditions and then alert the relevant people to correct them before it becomes too expensive) I finally had the perfect opportunity to play with Esper (, a complex event processing (CEP) engine.

CEP's claim to fame is that it allows you to express in a compact syntax a condition or pattern in your data that you're interested in, and then you feed your data into it as it becomes available, and the system will notify you when it finds stuff that looks like what you asked it for. Seems reasonable.

The project documentation style is very similar to Hibernate's, so its quite accessible that way. The blend of state machine behavior with a pseudo-SQL query language did take a bit of getting used and there were some links off their website to really old examples that they'd probably be better off without, but after a couple of hours I was humming along.

So what's this eventually turn into? As an example I have a sensor that sends me values every 5 minutes, and I want to receive a notification whenever the values stray over a defined upper limit, but only when the value changes: if the value stays over the limit I shouldn't send out a new notification. The values are written into an SQL database, and I could periodically reach in to the database and run a series of SQL queries and (either) implement a finite state machine myself or use an FSM library such as tungsten-fsm (


I could do what I did and use Esper:

select '1',,b.temperature,b.timestamp from pattern [every(a=SensorEvent(target=5 and value<=50) -> b=SensorEvent(target=5 and value>50))]

The statement above says "notify me with the string 1, the target, the temperature value and the timestamp any time I see a SensorEvent with the target field set to 5 and a sensor value less than or equal to 50 followed by a SensorEvent with the target field set to 5 and a sensor value greater than 50.

And...we're done. Esper calls a method on my class with the requested values and I can use the string '1' to figure out who to notify.

Now need to see how it performs under load, but if it holds up it'll be quite nice. Adding new notification criteria is just a matter of sticking in a new pattern expression.

P.S. If you're looking to use your Android phone as a Bluetooth GPS device, checkout SolidSync Network/Bluetooth GPS in the Google Play Store or on the web at