#!/usr/bin/env python

# Example of using the MQTT client class to subscribe to and publish feed values.
# Author: Tony DiCola

# Import standard python modules.
import random
import sys
import time
import json
import datetime
import logging

# Import Adafruit IO MQTT client.
from Adafruit_IO import MQTTClient
conf = json.load(open('conf.json'))
logging.basicConfig(filename=conf["log"]["logSendMQTTPings"],level=logging.DEBUG)

# Set to your Adafruit IO key & username below.
ADAFRUIT_IO_KEY      = conf["adafruit"]["ADAFRUIT_IO_KEY"]
ADAFRUIT_IO_USERNAME = conf["adafruit"]["ADAFRUIT_IO_USERNAME"]

# Set to the ID of the feed to subscribe to for updates.
feed = conf["adafruit"]["feed"]

# Define callback functions which will be called when certain events happen.
def connected(client):
    # Connected function will be called when the client is connected to Adafruit IO.
    # This is a good place to subscribe to feed changes.  The client parameter
    # passed to this function is the Adafruit IO MQTT client so you can make
    # calls against it easily.
    try:
        print 'Connected to Adafruit IO!  This should never receive a message'
        logging.debug('Connected to Adafruit IO!  Listening for {0} changes at {1}...'.format(conf["adafruit"]["feed"],str(datetime.datetime.now())))
        client.subscribe(conf["adafruit"]["feed"])
    except:
        sys.exit(1)

def disconnected(client):
    # Disconnected function will be called when the client disconnects.
    print 'Disconnected from Adafruit IO!'
    logging.info('sendMQTTPings is disconnected from Adafruit IO at {0}!'.format(str(datetime.datetime.now())))
    sys.exit(1)

def message(client, feed, payload):
    # Message function will be called when a subscribed feed has a new value.
    # The feed_id parameter identifies the feed, and the payload parameter has
    # the new value.
    temp = 1
    #logging.info('sendMQTTPings received a message')

# Create an MQTT client instance.
client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)

# Setup the callback functions defined above.
client.on_connect    = connected
client.on_disconnect = disconnected
client.on_message    = message

# Connect to the Adafruit IO server.
client.connect()

# Now the program needs to use a client loop function to ensure messages are
# sent and received.  There are a few options for driving the message loop,
# depending on what your program needs to do.  

# The first option is to run a thread in the background so you can continue
# doing things in your program.
#client.loop_background()
# Now send new values every x seconds.
delay = 120
print 'Publishing a new message every {0} seconds (press Ctrl-C to quit)...'.format(delay)
try:
    while True:
        client.loop()
        value = conf["adafruit"]["pingValue"]
        print 'Publishing {0} to feed at {1}.'.format(value, str(datetime.datetime.now()))
        logging.info( 'Publishing {0} to feed at {1}.'.format(value, str(datetime.datetime.now())))
        client.publish(feed, value)
        logging.info( 'Successfully published {0} to feed at {1}.'.format(value, str(datetime.datetime.now())))
        time.sleep(delay)
except:
    print('Unexpected error: {0} at {1}'.format(sys.exc_info()[0], str(datetime.datetime.now())))
    logging.error('Unexpected error: {0} at {1}'.format(sys.exc_info()[0], str(datetime.datetime.now())))

	
# Another option is to pump the message loop yourself by periodically calling
# the client loop function.  Notice how the loop below changes to call loop
# continuously while still sending a new message every 10 seconds.  This is a
# good option if you don't want to or can't have a thread pumping the message
# loop in the background.
#last = 0
#print 'Publishing a new message every 10 seconds (press Ctrl-C to quit)...'
#while True:
#   # Explicitly pump the message loop.
#   client.loop()
#   # Send a new message every 10 seconds.
#   if (time.time() - last) >= 10.0:
#       value = random.randint(0, 100)
#       print 'Publishing {0} to DemoFeed.'.format(value)
#       client.publish('DemoFeed', value)
#       last = time.time()

# The last option is to just call loop_blocking.  This will run a message loop
# forever, so your program will not get past the loop_blocking call.  This is
# good for simple programs which only listen to events.  For more complex programs
# you probably need to have a background thread loop or explicit message loop like
# the two previous examples above.
#client.loop_blocking()
