Change Streams in MongoDB 3.6

Gone are the days when expectations of information were not instantaneous access to the data. In today’s world, people expect real-time results and information. What’s the moisture content of the soil around grapevine X right now? Not yesterday, not five minutes ago, but now. Being notified about constantly changing data points is critical in many of today’s applications. In the latest 3.6 release of MongoDB a new feature is being introduced to assist with these real-time expectations: Change Streams.

Change Streams Defined

Change streams are being implemented in the driver with a new aggregation operator, $changeStream and watch method in the API. We can now specify a $changeStream stage at the beginning of our pipeline and request that notifications are sent for specific changes to a particular collection.

Example Use Case

Let’s take the soil moisture example I stated earlier. Imagine that you have a farm with multiple moisture sensors or a TMP36 Analog temperature sensor connected to something like a NodeMCU ESP8266 or LoPy device. Without going into detail about how to set the IoT network up, for the sake of our use case we can assume that they are sending readings back to a MongoDB server. Perhaps the data is being stored on MongoDB Atlas even. I have, however, written about the LoPy microcontroller and ESP8266 with temperature sensors in the past if you are interested in learning more.

Anyway, for the sake of argument, let’s say that we need to know when the moisture content of the soil drops below a certain level. Moisture values on similar devices are measured as a raw number between 0-1024. The higher the number, the more moisture in the soil. For our use case, we need to know when the moisture level drops below 350 (too dry).

Change Stream in action

Since these recordings are frequently changing, we can set up a change stream to get notified. It’s fairly straightforward to establish a notification with the watch method. We could set something like this up:

change_stream = client.winery.collection.watch([
  {'$match': {
       'operationType': {'$in': ['insert']}
    }},
    {'$match': {
        'moisture_level': {'$lt': 350}
    }}
]);
for change in change_stream:
    turn_on_water();
    # Something else magical

Now when we have an insert into the database where the moisture_level is below 350, we’ll turn our watering system on along with whatever else needs to be done. We could set up a similar change stream for when the moisture level gets high enough to warrant shutting the system off at 450.

This is but one example of where change streams would be a useful tool. Updating reports dynamically on data changes, publish/subscribe types of functionality, brokers, and many other use cases are now open to native MongoDB actions.

Change Steam Details

You’ll notice that there is an operationType being looked at there. Change streams look at five different events, or Operation Types

  • Insert
  • Delete
  • Replace (everything but the unique id)
  • Update
  • Invalidate (in cases of an invalid cursor being returned)

Change streams also utilize access controls and can be set up based on user roles. They present a defined API and enable scaling across primaries and secondaries. MongoDB is supporting up to 1,000 concurrent change streams per data bearing node in 3.6.

They are durable, meaning they rely on the data being majority committed in a replica set. The order of the changes in data is important too, right? 3.6 also introduces a global logical clock which, among other uses, will ensure that clients always will get changes in the order they occurred on the server. This is very important for replace and update operations.

Wrap Up

There are a lot more technical details about change streams forthcoming as 3.6 moves closer to production and documentation is further flushed out. Change streams are inherent in the 3.6 Server and are available in both the community and enterprise versions of the product. MongoDB Version 3.6 is available to download today as a release candidate. Which means that while the high-level concepts of change streams discussed here likely will remain in tack in the final release, there may be some subtle changes. That being said, change streams are a great feature being implemented in the new release. If your applications require or could use real-time information, I would encourage you to have a look.


Follow me on Twitter @kenwalger to get the latest updates on my postings.

There are a few MongoDB specific terms in this post. I created a MongoDB Dictionary skill for the Amazon Echo line of products. Check it out and you can say “Alexa, ask MongoDB for the definition of a document?” and get a helpful response.

Facebooktwitterredditlinkedinmail

MicroPython Temperature Sensor

I’ve shown an example of the “Hello World” in IoT, a blinking light, in this post. Blinking lights are great and make for a nice visual experience, but what if we want to do something with an IoT device, such as a NodeMCU ESP8266 that goes beyond the visual? Let’s take our NodeMCU and add a temperature sensor. Then, with MicroPython, we’ll get our readings.

Needed Equipment

To get started on this project you’ll need the following equipment:

I have found this kit of basic electronic components to be pretty good for starting one’s IoT device journey. It doesn’t include things like the TMP36 temperature sensor, but it has a wide variety of other pieces that are ultimately useful.

TMP36 Specs

Since this project will be using the TMP36, let’s discuss it briefly.

TMP36 Temperature Sensor

This temperature sensor is a low voltage sensor, requiring 2.7 V to 5.5 VDC input. It returns a Celsius temperature reading from the Vout pin in an operating range of -40°C to +125°C. It is reasonably accurate, especially for hobby/demo situations with a ±2°C accuracy. You can download the specs for the TMP36 here.

Temperature Sensor Project

Hardware Configuration

Make sure the NodeMCU is disconnected from USB when making connections.

Temperature Sensor schematic

  1. To add the TMP36 sensor to the NodeMCU we need to make sure that it is properly oriented. The flat side of the temperature sensor should be facing the bottom of the board.
  2. Connect the rightmost lead, in position a8 to the negative rail on the board.
  3. The negative rail then is connected to the GND pin (pin a29)on the NodeMCU.
  4. Connect the leftmost lead (a10) of the TMP36 to the positive rail.
  5. Connect the 3v3 pin (a30) on the NodeMCU to the positive rail.
  6. Finally, connect a jumper wire from the center lead (c9) to the A0 pin on the NodecMCU (j16).

Temperature Sensor bread board

The A0 pin on the NodeMCU is the analog-to-digital conversion (ADC) pin.

Code

With the hardware side of things built, let’s see what we can do in MicroPython to get a temperature! Fortunately, MicroPython’s machine library makes this pretty simple for us.

I’ll be working in the console REPL.  The code should work the same, however, if you are working in the WebREPL environment.

Our first step is to handle our imports

from machine import ADC

That brings in our necessary ADC connections, and we can assign a variable to pin 0 for that

adc = ADC(0)

We can print out the value from the TMP36 now with adc.read() which returns the Celsius temperature, well almost. The value it returns is ten times the temperature. Let’s write a function that will handle that conversion for us.

def temp(value):
    return value/10

While we’re at it, let’s write a function to convert to Fahrenheit as well.

def fahrenheit(celsius):
    return (celsius * (9/5)) + 32

With those in place, we can get, and display our readings.

reading = adc.read()

celsius_temp = temp(reading)

fahrenheit_temp = fahrenheit(celsius_temp)

print("TMP36 reading {}\nDegrees Celsius {}\nDegrees Fahrenheit {}".format(reading, celsius_temp, fahrenheit_temp))

After executing our print statement we should get back our readings. MicroPython certainly has made things easy for us with the ADC methods.

Temperature Sensor REPL

For your convenience I have included the code is available as a Gist on GitHub as well.

Wrap Up

In this post, I have shown how to get temperature readings from an analog temperature sensor, such as the TMP36. In just a few lines of MicroPython code, we are able to get quite a bit of functionality. This is one of the many great things about MicroPython, the direct access to hardware is generally pretty easy.

I think the next step in exploring MicroPython and the NodeMCU will be to take these temperature readings and see if we can connect them to a service such as Losant and generate some visualizations of our temperatures.


Follow me on Twitter @kenwalger to get the latest updates on my postings on MicroPython and IoT and let me know what you are building with MicroPython.

Facebooktwitterredditlinkedinmail