Todd Peterson
Created February 17, 2017

Asset Tamper, Damage & Movement Monitoring.

A particular asset can be monitored for position and damage. Readings are streamed to the cloud. User can monitor position and parameters.

39
Asset Tamper, Damage & Movement Monitoring.

Things used in this project

Hardware components

AT&T Cellular IoT Starter Kit
Avnet AT&T Cellular IoT Starter Kit
×1

Software apps and online services

PubNub Publish/Subscribe API
PubNub Publish/Subscribe API
AT&T Flow
AT&T Flow

Story

Read more

Custom parts and enclosures

Enclosure 3D Solidworks Model

This houses the AT&T IoT Starter Kit and the Xadow GPS module.

Lid 3d Solidworks Model

The lid for the enclosure.

Enclosure Drawing

A drawing of the enclosure.

Lid Drawing

Drawing of the lid.

Schematics

Add Xadow GPS Module

This documents how to add the Xadow GPS Module, including wiring.

Switches schematic

How to wire the switches that detect whether the case is open or closed.

BOM

Components required to build the system.

AT&T Flow Component

This is a screenshot of the Flow schematic

Switches Circuit

This shows how the switches are wired and how to hook them up to the AT&T IoT Starter Kit.

Code

MBED Asset Monitor Project

C/C++
This project communicates with AT&T Flow.
No preview (download only).

PubNub Python Code

Python
This is the main code to run on a server. It subscribes to a PubNub channel and registers a listener.
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub
from pubnub.callbacks import SubscribeCallback
from pubnub.enums import PNOperationType, PNStatusCategory
import pubnublistenercallback
import time

pnconfig = PNConfiguration()
# set your PubNub keys here
pnconfig.subscribe_key = "XXX"
pnconfig.publish_key = "XXX"
pnconfig.ssl = False

pubnub = PubNub(pnconfig)
pubnub.add_listener(pubnublistenercallback.MySubscribeCallback())
# set your PubNub channel here
pubnub.subscribe().channels('my_channel').execute()
while 1:
    time.sleep(1)

PubNub Listener

Python
This listener is registered by py-sub.py. It monitors the switch state of the asset. When first run, it sends an SMS message upon the first PubNub message received for the initial switch state. When the switch state changes, an SMS message is sent. This code may be modified to send an SMS on any interesting state of the asset.
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub
from pubnub.callbacks import SubscribeCallback
from pubnub.enums import PNOperationType, PNStatusCategory
from twilio.rest import TwilioRestClient
 
class MySubscribeCallback(SubscribeCallback):
    switch_state = -1 # initial state of undefined
    # set your Twilio keys here
    client = TwilioRestClient("XXX", "XXX")

    def status(self, pubnub, status):
        pass
        # The status object returned is always related to subscribe but could contain
        # information about subscribe, heartbeat, or errors
        # use the operationType to switch on different options
        if status.operation == PNOperationType.PNSubscribeOperation \
                or status.operation == PNOperationType.PNUnsubscribeOperation:
            if status.category == PNStatusCategory.PNConnectedCategory:
                print("PNStatusCategory.PNConnectedCategory")
                # This is expected for a subscribe, this means there is no error or issue whatsoever
            elif status.category == PNStatusCategory.PNReconnectedCategory:
                print("PNStatusCategory.PNReconnectedCategory")
                # This usually occurs if subscribe temporarily fails but reconnects. This means
                # there was an error but there is no longer any issue
            elif status.category == PNStatusCategory.PNDisconnectedCategory:
                print("PNStatusCategory.PNDisconnectedCategory")
                # This is the expected category for an unsubscribe. This means there
                # was no error in unsubscribing from everything
            elif status.category == PNStatusCategory.PNUnexpectedDisconnectCategory:
                print("PNStatusCategory.PNUnexpectedDisconnectCategory")
                # This is usually an issue with the internet connection, this is an error, handle
                # appropriately retry will be called automatically
            elif status.category == PNStatusCategory.PNAccessDeniedCategory:
                print("PNStatusCategory.PNAccessDeniedCategory")
                # This means that PAM does allow this client to subscribe to this
                # channel and channel group configuration. This is another explicit error
            else:
                print("unknown message")
                # This is usually an issue with the internet connection, this is an error, handle appropriately
                # retry will be called automatically
        elif status.operation == PNOperationType.PNSubscribeOperation:
            # Heartbeat operations can in fact have errors, so it is important to check first for an error.
            # For more information on how to configure heartbeat notifications through the status
            # PNObjectEventListener callback, consult <link to the PNCONFIGURATION heartbeart config>
            if status.is_error():
                print("status: " + status)
                # There was an error with the heartbeat operation, handle here
            else:
                print("heartbeat")
                # Heartbeat operation was successful
        else:
            print("unknown status: " + status)
            # Encountered unknown status type
 
    def presence(self, pubnub, presence):
        print("presence: " + presence)  # handle incoming presence data
 
    def message(self, pubnub, message):
        #print("message: " + str(message.message))  # handle incoming messages
        print("message: " + str(message.message['sw1']))
        sw1 = message.message['sw1']
        if self.switch_state == -1:
            print("initial state is " + str(sw1))
            self.switch_state = sw1
            # set your Twilio number and To number here
            self.client.messages.create(to="+XXX", from_="+XXX",
                       body="initial state is " + str(sw1))
        else:
            if self.switch_state != sw1:
                print("switch changed state to " + str(sw1))
                self.switch_state = sw1
                # set your Twilio number and To number here
                self.client.messages.create(to="+XXX", from_="+XXX",
                       body="switch changed state to " + str(sw1))
 
 

Credits

Todd Peterson

Todd Peterson

8 projects • 5 followers
Specialist in real-time embedded systems hardware, software and systems integration. Well rounded in many engineering disciplines.

Comments