Todo
Last active
April 10, 2018 21:01
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [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