Skip to content

Instantly share code, notes, and snippets.

@mangrovemike
Created December 10, 2012 22:52
Show Gist options
  • Select an option

  • Save mangrovemike/4254071 to your computer and use it in GitHub Desktop.

Select an option

Save mangrovemike/4254071 to your computer and use it in GitHub Desktop.
XTIDE to MQTT Bridge
#!/usr/bin/python
#
# MangroveMike (www.merewether.com.au)
#
# Get tides, moonrise, moonset, sunrise and sut set from XTIDE and publish to local MQTT server.
# We publish when the actual event occurs to the /now/ topic and the next 6 hours worth of activity to the /future/ topic.
#
# 10/12/2012 Initially created.
#
#
# Subscribe output looks similar to:
# astronomy/harrington_inlet/future/low_tide 0.35 m
# astronomy/harrington_inlet/future/low_tide/time 2012-12-11 13:56
# astronomy/merewether/future/low_tide 0.26 m
# astronomy/merewether/future/low_tide/time 2012-12-11 13:38
import time
import mosquitto
import subprocess
import sys
import csv
import re
import string
# Global Definitions
gtideprog = "/usr/local/bin/tide"
gtideargs = ' -fc -df"%Y-%m-%d" -tf"%H:%M"'
#
# MQTT Callbacks
#
ticks = time.time();
mqttc = mosquitto.Mosquitto("python_pub_local_tides" + str(ticks))
def on_connect(mosq, obj, rc):
if rc ==0:
print("Connect local rc: "+str(rc))
else:
raise Exception
def on_message(mosq, obj, msg):
print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
def on_publish(mosq, obj, mid):
print("mid: "+str(mid))
localtime = time.asctime( time.localtime(time.time()) )
print "Local current time :", localtime
def on_subscribe(mosq, obj, mid, granted_qos):
print("Subscribed: "+str(mid)+" "+str(granted_qos))
def on_log(mosq, obj, level, string):
print(string)
def on_disconnect (mosq, obj, rc):
if rc == 0:
print("Disconnected local successfully.")
else:
print("Disconnected local unexpectantly. Result code: "+str(rc))
#
# General Program Modules
#
def cleanup():
print "Ending and cleaning up"
mqttc.disconnect()
def delete_file(filename):
try:
retcode = subprocess.call("rm -f " + filename, shell=True)
if retcode < 0:
print >>sys.stderr, "Child was terminated by signal", -retcode
else:
print >>sys.stderr, "Child returned", retcode
except OSError as e:
print >>sys.stderr, "Execution failed:", e
def generate_tide(tlocation, toutfile, tstarttime, tendtime):
location = '"' + tlocation + '"'
starttime = '"' + tstarttime + '"'
endtime = '"' + tendtime + '"'
try:
delete_file(toutfile)
tcommand = gtideprog + gtideargs + " -l" + location + " -b" + starttime + " -e" + endtime + " -o" + toutfile
print tcommand
retcode = subprocess.call(tcommand, shell=True)
if retcode < 0:
print >>sys.stderr, "Child was terminated by signal", -retcode
else:
print >>sys.stderr, "Child returned", retcode
except OSError as e:
print >>sys.stderr, "Execution failed:", e
def process_and_publish(voutfile, vlocation_simple, vmode):
# Read the CSV
csvfile = csv.reader( open(voutfile, 'rb'), delimiter=',', quotechar='"')
for row in csvfile:
tdate = row[1]
ttime = row[1] + " " + row[2]
tcommand = re.sub(" ","_",string.lower(row[4]))
tvalue = row[3]
print "Date:" + tdate + " Time:" + ttime + " Command:" + tcommand + " Value:" +tvalue
# Now publish the data
if tcommand == "high_tide" or tcommand == "low_tide":
mqttValue = tvalue
else:
mqttValue = ttime
# Publish
mqttc.publish("astronomy/" + vlocation_simple + "/" + vmode + "/" + tcommand, mqttValue)
mqttc.publish("astronomy/" + vlocation_simple + "/" + vmode + "/" + tcommand + "/time" , ttime)
# mqttc.disconnect()
def connectAndSetupLocal():
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
# Uncomment to enable debug messages
mqttc.on_log = on_log
mqttc.connect("127.0.0.1", 1883, 60)
# This gets very cool system stats
# mqttc.subscribe("$SYS/#", 0)
# mqttc.subscribe("#", 0)
def main_processing():
vdate = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()))
vdate2mins = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()+(2*60)))
vdate6hrs = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()+(6*60*60)))
# vdate1hr2mins = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()+(62*60)))
print "Vdate :", vdate
print "Vdate2mins :", vdate2mins
print "Vdate6hrs :", vdate6hrs
# Generate tide files
outfile = "/usr/local/scripts/tides/harrington_tides_now.csv"
generate_tide("Harrington Inlet, Australia",outfile, vdate, vdate2mins)
process_and_publish(outfile, "harrington_inlet", "now")
# Generate tide files for next 6 hours
outfile = "/usr/local/scripts/tides/harrington_tides_future.csv"
generate_tide("Harrington Inlet, Australia",outfile, vdate2mins, vdate6hrs)
process_and_publish(outfile, "harrington_inlet", "future")
# Generate tide files
outfile = "/usr/local/scripts/tides/merewether_tides_now.csv"
generate_tide("Newcastle, Australia",outfile, vdate, vdate2mins)
process_and_publish(outfile, "merewether", "now")
# Generate tide files for next 6 hours
outfile = "/usr/local/scripts/tides/merewether_tides_future.csv"
generate_tide("Newcastle, Australia",outfile, vdate2mins, vdate6hrs)
process_and_publish(outfile, "merewether", "future")
def mainloop():
try:
rc = 0
while rc == 0:
rc = mqttc.loop()
main_processing()
time.sleep(60)
except (KeyboardInterrupt):
print "Keyboard Interrupt received"
cleanup()
raise
except (RuntimeError):
print "The candle that burns twice as bring only burns half as long. "
cleanup()
raise
except:
print "Unexpected error in mainloop(). Result code 1 is "+str(rc)
raise
localtime = time.asctime( time.localtime(time.time()) )
print "Local current time :", localtime
print(re.sub(" ","_","Low Tide"))
connectAndSetupLocal()
mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment