Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Connected Bees: IoT-Enabled Bee Health

DZone's Guide to

Connected Bees: IoT-Enabled Bee Health

The theme of the Cisco DevNet hackathon was to use IoT and collaboration tools to help in tracking bees, enabling research scientists with data to unearth bee health problems. Let's check out this awesome solution that was created in less than 24 hours!

· IoT Zone
Free Resource

Cisco IoT makes digital transformation a reality in factories, transportation, and utilities. Learn how to start integrating with Cisco DevNet.

Imagine what the impact on the world would be if bees ceased to be, per Albert Einstein, “If the bee disappeared off the face of the Earth, man would only have four years left to live.” The theme of the Cisco DevNet hackathon was to use IoT and collaboration tools to help in tracking bees, enabling research scientists with data to unearth bee health problems. I had the privilege to be a part of this hackathon before Cisco Live 2016 Las Vegas.

It was amazing to see developers with different skillsets collaborating to solve the global declining bee population. There were ten teams that participated in the Hackathon, and every team put forth lots of effort developing their solution. The hackathon was a lot of fun and everyone really enjoyed the experience.

I was closely watching the passionate developers of BeeTri team (@GTRI_Global) Cameron Pope, Michael Edwards, Thomas Maier, Bill Donovan, and Josh Proano. They built the IoT Enabled Bee Health solution (pictured below) using Cisco platforms in combination with the CSIRO and relayr platforms. These platforms not only enabled the developers to build the solution within 24 hours but also helped them focus on the solution rather than worrying about the infrastructure or intricacies of open source integration.

Image title

This solution was developed using Microservices, IoT, and Cloud architecture. The solution works with CSIRO, a Cisco Innovation Central Ecosystem Partner in Australia, and CSIRO Data61 that captures the data from bees using tiny micro-sensors (also known as backpacks). These sensors are manually fitted to bees and work similar to a vehicle e-tag system; with strategically placed receivers identifying the bee’s movement, data is recorded in Data61. Relayr’s middleware platform then utilizes an MQTT message broker to send real-time alerts based on the rules engine configuration to collaboration tools Cisco Tropo and Cisco Spark. Relayr has time series data APIs allowing the Cisco Zeus platform to pull data from these APIs for analytics. Also, these time series data APIs are utilized by Microservices to pull the data and load it in a database to integrate, analyze, and visualize. To deploy this solution, BeeTri team took advantage of Cisco Shipped and Mantl support for existing Docker projects in GitHub; it did not take them a lot of effort to deploy the code to Shipped and Mantl, other than turning up the memory limits for the application. Here is the high-level view into the code base of this solution.

Microservices

A set of microservices were developed and deployed to Cisco Shipped and Mantl in order to automate the dashboard update process. The microservices are:

  • Scripts to send simulated data.
  • Packages Jupyter with Cisco Zeus libraries.
  • Embeddable Cisco Spark room Script.
  • Scripts to message beehive data and import to Zeus (refer below code snippet).
import glob2
import csv
from zeus.client import ZeusClient
import re
import datetime

ZEUS_API = "http://api.site1.ciscozeus.io"
ZEUS_TOKEN = " "

def hiveDataToDict(row):
    timestamp = datetime.datetime.strptime(row[0],"%Y%m%dT%H%M%SZ")
    epoch = datetime.datetime.utcfromtimestamp(0)
    rowDict = {"eventTime":row[0]}
    rowDict["timestamp"] = int((timestamp - epoch).total_seconds())
    if len(row) > 3:
        rowDict["readerId"] = row[3]
    beeId = row[1]
    m = re.match(r'^(..)(...)(..)(...)(...)(..)(.)(....)(....)',beeId)
    siteId = m.group(2)
    if m.group(1) == '0D':
        rowDict["country"] = "Australia"
        if siteId == '007':
            rowDict["siteName"] = "Cairns"
        elif siteId == "001":
            rowDict["siteName"] = "Geeveston"
        elif siteId == "008":
            rowDict["siteName"] = "Sandy Bay"
    else:
        rowDict["country"] = "Brazil"
        rowDict["siteName"] = "Belem"
    rowDict["site"] = m.group(2)
    rowDict["platform"] = m.group(3)
    rowDict["hive"] = m.group(4)
    rowDict["species"] = m.group(5)
    rowDict["strain"] = m.group(6)
    rowDict["type"] = m.group(7)
    rowDict["beeId"] = m.group(9)
#    print rowDict
    return rowDict

def fileRows(reader):
    reader.next()
    reader.next()
    for row in reader:
        if len(row):
            yield row

def hiveRows(reader):
    for row in fileRows(reader):
        rowDict = hiveDataToDict(row)
        if rowDict['site'] != 'FFF':
          yield rowDict

def readFiles(zeusClient):
  csvFiles = glob2.glob("./HiveData/**/*.csv")
  for file in csvFiles:
      if file.find("Bee_data") >= 0 and file.find("tagging_log") == -1:
        print "Parsing " + file
        rows = []
        with open(file,'rb') as csvFile:
            hiveReader = csv.reader(csvFile)
            rows = []
            for rowJson in hiveRows(hiveReader):
                rows.append(rowJson)
                if len(rows) % 1000 == 0:
                    print "Sending 1000 rows"
                    zeusClient.sendLog("HiveData",rows)
                    rows = []
            if len(rows):
                print "Sending " + str(len(rows)) + " rows"
                zeusClient.sendLog("HiveData",rows)

zeusClient = ZeusClient(ZEUS_TOKEN,ZEUS_API)
readFiles(zeusClient)

Raspberry Pi Beehive Simulator

The most interesting part of the code base is the Raspberry Pi Beehive Simulator. Here is the gist of the code that is running on a Raspberry Pi to take environmental readings—this script polls the temperature once a second using the DS18B20 digital one-wire temperature sensor, then it:

  • Updates the device readings in relayr via MQTT messages
  • Locates devices in real-time using Cisco Meraki
  • Logs the device stats to Cisco Zeus via the Python API
  • Calls Cisco Tropo via its REST API to send text and cell phone alerts
  • Scripts in Cisco Tropo updates the Cisco Spark room

So, this Raspberry Pi code touches on almost all of the technologies that were part of the Hackathon Solution (Cisco Tropo, relayr, Cisco Zeus, etc). Check it out:

import time
import random
import datetime
from zeus.client import ZeusClient
import paho.mqtt.client as mqtt
import json
import requests

# Zeus Credentials
ZEUS_API = "http://api.site1.ciscozeus.io"
ZEUS_TOKEN = "MY_ZEUS_TOKEN"
# Tropo Credentials
TROPO_TOKEN = "MY_TROPO_TOKEN"
# Relayr Credentials
credentials = {
    "user": " ",
    "password": " ",
    "clientId": " ",
    "topic": " ",
    'server':   'mqtt.relayr.io',
    'port':     1883
}

# Enable the kernel modules that provide one-wire support
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

# Open the one-wire device on the Pi
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'

def read_temp_raw():
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines

# Read the temperature from the DS1B820 Temperature sensor
def read_temp():
    lines = read_temp_raw()
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw()
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
        temp_f = temp_c * 9.0 / 5.0 + 32.0
        return temp_c, temp_f

class MqttDelegate(object):
    "A delegate class providing callbacks for an MQTT client."

    def __init__(self, client, credentials):
        self.client = client
        self.credentials = credentials

    def on_connect(self, client, userdata, flags, rc):
        print('Connected.')
        # self.client.subscribe(self.credentials['topic'].encode('utf-8'))
        self.client.subscribe(self.credentials['topic'] + 'cmd')

    def on_message(self, client, userdata, msg):
        print('Command received: %s' % msg.payload)

    def on_publish(self, client, userdata, mid):
        0+0

def mockHiveData():
    temp_c,temp_f = read_temp()
    hiveData = {"siteName":"Devnet Zone","Country":"United States","hive":"01","species":"03","strain":"04","type":"1"}
    hiveData["beeId"] = str(random.randrange(0,1500))
    hiveData["eventTime"] = datetime.datetime.now().isoformat()
    hiveData["humidity"] = random.randrange(85,90)
    hiveData["insideTemperature"] = temp_c
    hiveData["weight"] = random.randrange(50,60) / 10.0
    hiveData["batteryPercent"] = 97
    return hiveData

# Send metrics to Relayr for real-time display and Zeus for logging
def logHiveData(hiveData,zeusClient,mqttClient):
    print hiveData
    zeusClient.sendLog("HiveData",hiveData)
    message = {'meaning': 'insideTemperature', 'value': hiveData['insideTemperature']}
    client.publish(credentials['topic'] +'data', json.dumps(message))
    message = {'meaning': 'humidity', 'value': hiveData['humidity']}
    client.publish(credentials['topic'] +'data', json.dumps(message))
    message = {'meaning': 'weight', 'value': hiveData['weight']}
    client.publish(credentials['topic'] +'data', json.dumps(message))
    message = {'meaning': 'batteryPercent', 'value': hiveData['batteryPercent']}
    client.publish(credentials['topic'] +'data', json.dumps(message))

# Connect to Zeus
zeusClient = ZeusClient(ZEUS_TOKEN,ZEUS_API)

# Connect to Relayr
client = mqtt.Client(client_id=credentials['clientId'])
delegate = MqttDelegate(client, credentials)
client.on_connect = delegate.on_connect
client.on_message = delegate.on_message
client.on_publish = delegate.on_publish
user, password = credentials['user'], credentials['password']
client.username_pw_set(user, password)
print('Connecting to mqtt server.')
server, port = credentials['server'], credentials['port']
client.connect(server, port=port, keepalive=60)

alertState = 'Normal'
while True:
    hiveData = mockHiveData()
    if hiveData['insideTemperature'] > 24.0 and alertState == 'Normal':
      alertState = 'Alarm'
      print "Alarm!"
      # Post alarm to Tropo
      requests.get("https://api.tropo.com/1.0/sessions?action=create&token=" + TROPO_TOKEN)
    elif hiveData['insideTemperature'] < 23.8 and alertState == 'Alarm':
      alertState = 'Normal'
      print "Back to Normal"
    logHiveData(hiveData,zeusClient,client)
    time.sleep(1)

Zeus iPython Notebook

Here is some more of Beetri team’s code to the Jupyter notebook that queries for log data in Zeus, loads it into a Pandas data frame, and graphs it:

Image title

Cisco Zeus is a cloud-based logging and monitoring service. There are plenty of really cool things that one could potentially do with Cisco Zeus and Jupyter, such as root cause analysis, business intelligence, and exploratory data analysis.

In this case, to deploy the iPython solution, BeeTri team have taken advantage of Cisco Shipped and Mantl support for existing Docker projects on GitHub. And, it did not take them much to deploy the code to Shipped and Mantl, other than turning up the memory limits for the application.

Screenshots from BeeTri team's solution:

Image title


You can use Cisco Shipped and Mantl platforms for microservices container deployments. Cisco Shipped and Mantl are Cisco's take on how to manage a container infrastructure for the next generation of cloud-native applications. Cisco Shipped comes with build-packs of popular programming languages including: Ruby, Python, Java, PHP, Golang, Node.js, and ASP.NET MVC, so you can quickly get started building with microservices. Mantl is an open source, pre-integrated, and Cisco-validated container stack that packages Mesos, Marathon, Kubernetes, and several other components into a straightforward installation process. Cisco Shipped builds upon the Mantl foundation to provide a continuous integration (CI) and continuous deployment (CD) pipeline for a developer. Shipped provides a consistent local development environment using popular tools like Docker and Vagrant to mimic the Shipped cloud platform. Using Shipped, you can take your code hosted on GitHub and deploy it to a production environment in minutes—that’s what BeeTri team has done to accelerate their development work.

You can develop this solution too and should consider automating your full develop, test, and deploy lifecycles. If you'd like to check out Cisco Shipped which is based on Mantl, you can head over to the Shipped and Mantl Learning Labs on Cisco DevNet for in-depth tutorials. Also, check out the other components of the solution here: Cisco Zeus, Meraki, Tropo, and Spark.

If you have any questions or want to share your own IoT-enabled solution for tracking bee health? Find me @YadavYogesh and share your story. Thanks for reading!

Cisco is a software company. Surprised? Don’t be. Join DevNet to explore APIs, tools, and techniques that developers are using to add collaboration, IoT, security, network priority, and more!

Topics:
use case ,hackathon ,cisco ,devnet ,meraki ,cisco zeus ,csiro ,relayr ,microservices ,mqtt

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}