Skip to content

Instantly share code, notes, and snippets.

@matbor
Last active April 10, 2018 21:01
Show Gist options
  • Select an option

  • Save matbor/6920e48e056bff51141c to your computer and use it in GitHub Desktop.

Select an option

Save matbor/6920e48e056bff51141c to your computer and use it in GitHub Desktop.
bom weather 2 mqtt -- bom = bom.gov.au weather. Old example of a script I am stil using daily.
#!/usr/bin/env python
'''
Jan 2014
@bordignon on Twitter
Using https://github.com/claws/txBOM to grab the weather forecast daily for Melbourne
and publish to a mqtt broker
Setup with a cronjob to run every hour if you like, but really only need to run at 6am/5pm
fix/todo:
- multiple forecast_ids isn't working atm
-
'''
#txtbom
import txbom.forecasts
from twisted.internet import reactor, defer
#logging
import os
import logging
import logging.config
#exit/terminating/signal
import signal
import sys
import mosquitto
import time
import json
#BEGIN SETTIGNS
logging.config.fileConfig('logging.cfg') #logfile setup file location
forecast_id = "IDV10450" # melbourne forecast identifier
pidfile = "/tmp/bom_forecast2mqtt.pid"
broker = "mqtt.localdomain" #mqtt broker location
broker_port = 1883 #mqtt broker port
willtopic = "/lwt/bom_forecast2mqtt" #last will and testament (will_set) topic location
topic_forecast = "/software/bom/forecast"
#END SETTIGNS
logging.info('')
logging.info('')
logging.info("######################################")
logging.info("Starting BOM-FORECAST 2 MQTT Script")
logging.info("INFO MODE")
logging.warning("WARNING MODE")
logging.debug("DEBUG MODE")
mqttc = mosquitto.Mosquitto()
######################
# taken from https://github.com/claws/txBOM/blob/master/examples/retrieve_forecast.py
# Jan 2014
@defer.inlineCallbacks
def demo(forecast_id):
#changed the print statements to logging.info
forecast = yield txbom.forecasts.get_forecast(forecast_id)
logging.info ("Received forecast text:")
logging.debug (forecast)
# demonstrate how the forecast can be parsed into a dict
forecastDict = txbom.forecasts.forecastToDict(forecast)
forecastDictKeys = forecastDict.keys()
forecastDictKeys.sort()
logging.info ("Forecast dict: ")
#publish dictionary converted to json format
jsonarray = json.dumps(forecastDict)
jsonttopic = topic_forecast + '/' + forecastDict['fcast_state'] + '/' + forecastDict['fcast_town'] + '/json'
mqttc.publish(jsonttopic, payload=jsonarray, qos=0, retain=True) #publish to broker
for k in forecastDictKeys:
################
#added the publish to topic part here
#create a new topic, comes out like this /software/bom_forecast2mqtt/forecast/Victoria/Melbourne/fcast_state
topicnew = topic_forecast + '/' + forecastDict['fcast_state'] + '/' + forecastDict['fcast_town'] + '/' + k
logging.debug (topicnew)
logging.info ("%s : %s" % (k, forecastDict[k]))
if k != 'fcast_raw': #stop the raw output from being published to a topic
logging.debug('currently publishing to: %s : %s' % (topicnew, forecastDict[k]))
mqttc.publish(topicnew, payload=str(forecastDict[k]), qos=0, retain=True) #publish to broker
time.sleep(1) #putting this small delay in as the mqtt publuishing works better.
#end of the publish code
################
# this is the end of the test, stop reactor to finish script
reactor.callLater(0.1, reactor.stop)
defer.returnValue(True)
#added the below to the start of my script
#logging.basicConfig(level=logging.DEBUG)
#reactor.callWhenRunning(demo, forecast_id)
#reactor.run()
###############################
def cleanup(signum, frame):
"""
Signal handler to disconnect and cleanup.
"""
try:
mqttc.publish(willtopic, "offline", retain=True)
logging.info("Disconnecting from broker")
mqttc.loop_stop()
mqttc.disconnect()
except:
logging.info("no broker?")
logging.info("Exiting on signal %d", signum)
sys.exit(signum)
def on_connect(mosq, obj, rc):
logging.info("connected to broker - rc: "+str(rc))
mqttc.publish(willtopic, payload="online", qos=0, retain=True)
def on_message(mosq, obj, msg):
logging.info(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
def on_publish(mosq, obj, mid):
logging.info("on-publish - mid: "+str(mid))
def on_subscribe(mosq, obj, mid, granted_qos):
logging.info("on-Subscribed: "+str(mid)+" "+str(granted_qos))
def on_log(mosq, obj, level, string):
logging.info(string)
if __name__ == '__main__':
#create a pid file so we don't accidently run the program again
pid = str(os.getpid())
if os.path.isfile(pidfile):
logging.info ("%s already exists, exiting" % pidfile)
sys.exit()
else:
file(pidfile, 'w').write(pid)
signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)
#now connect to the broker and publish the data to a topic
try:
logging.info('Connecting to broker')
mqttc = mosquitto.Mosquitto()
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
mqttc.will_set(willtopic, payload="offline", qos=0, retain=True)
mqttc.reconnect_delay_set(delay=3, delay_max=30, exponential_backoff=True)
mqttc.connect(broker, broker_port, 60)
mqttc.loop_start()
except:
logging.info('error connecting to broker, removing pidfile and exiting')
os.unlink(pidfile)
sys.exit(1)
#get the forecasts from BOM and publish to topic
logging.info('starting forecast_id: %s' % forecast_id)
reactor.callWhenRunning(demo, forecast_id) #grab the forecast
reactor.run()
logging.info('Finished with forecast_id: %s' % forecast_id)
#clean up and exit
mqttc.publish(willtopic, "offline", retain=True)
logging.info("Disconnecting from broker")
mqttc.loop_stop()
mqttc.disconnect()
logging.info('removing pidfile')
os.unlink(pidfile)
[loggers]
keys=root
[logger_root]
handlers=screen,file
level=NOTSET
[formatters]
keys=simple,complex
[formatter_simple]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
[formatter_complex]
format=%(asctime)s - %(name)s - %(levelname)s - %(module)s : %(lineno)d - %(message)s
[handlers]
keys=file,screen
[handler_file]
class=handlers.TimedRotatingFileHandler
interval=midnight
backupCount=10
formatter=complex
level=DEBUG
args=('logs/bom_forecast2mqtt.log','midnight',)
[handler_screen]
class=StreamHandler
formatter=simple
level=DEBUG
args=(sys.stdout,)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment