#!/usr/bin/python import serial from os import listdir from os.path import isfile, join from termios import tcflush, TCIOFLUSH from time import sleep,time from uuid import getnode from hashlib import md5 import socket import sys,traceback import pycurl from urllib import urlencode from StringIO import StringIO searchpath = '/dev/serial/by-id/' baud = 9600 timeout = 5 external_submit_interval = 320 expire_interval = 1200 submit_time = time() submit_queue = {} import MySQLdb import ConfigParser def find_port(): global serial_num files = listdir(searchpath) for f in files: if serialnum in f: return join(searchpath,f) return None def open_port(path): ser = serial.Serial(path,baud,timeout) if ser.portstr: tcflush(ser,TCIOFLUSH); return ser def read_port(ser): line = ser.readline() return line.strip() def read_loop(ser,callback): while True: try: line=read_port(ser) if line: callback(line) except KeyboardInterrupt: break finally: None def submit_narodmon(queue): param = { 'ID':"{:X}".format(getnode())} for sensor in queue: value = submit_queue[sensor]['val'] timestamp = submit_queue[sensor]['timestamp'] digest = md5(sensor).hexdigest()[:18] param[digest] = value; print param url = "http://narodmon.ru/post.php" try: response_buffer = StringIO() curl = pycurl.Curl() curl.setopt(curl.URL, url) curl.setopt(curl.WRITEFUNCTION, response_buffer.write) curl.setopt(curl.POST, 1) curl.setopt(curl.POSTFIELDS, urlencode(param)) curl.perform() curl.close() response_value = response_buffer.getvalue() print 'Content: ', response_value return True except: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) return False def submit_owm(queue): url = "http://openweathermap.org/data/post" params = {'name':owm_station, 'lat':owm_lat, 'long':owm_lon} try: try: params['temp'] = queue[owm_temp]['val'] params['pressure'] = queue[owm_pres]['val'] params['humidity'] = queue[owm_humi]['val'] except: return False response_buffer = StringIO() curl = pycurl.Curl() curl.setopt(curl.URL, url) curl.setopt(curl.USERPWD, '%s:%s' % (owmuser, owmpasswd)) curl.setopt(curl.WRITEFUNCTION, response_buffer.write) curl.setopt(curl.POST, 1) curl.setopt(curl.POSTFIELDS, urlencode(params)) curl.perform() curl.close() response_value = response_buffer.getvalue() print 'Content: ', response_value return True except: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) return False def purge_queue(): global submit_queue clean = [] for key in submit_queue: if submit_queue[key]['timestamp'] < time()-expire_interval: print "Expired value for "+key clean.append(key) for i in clean: del submit_queue[i] def submit_data(sensor_type,sensor_id,sensor_param,param_value): global submit_time global submit_queue c = database.cursor() c.execute('CALL meteo.submit_value(%s,%s,%s,%s)', (sensor_type,sensor_id,sensor_param,param_value)) database.commit() submit_queue[sensor_type+'.'+sensor_id+'.'+sensor_param]={'val':param_value,'timestamp':time()} if time()>submit_time+external_submit_interval: if submit_narodmon(submit_queue): if owmuser: submit_owm(submit_queue) print 'Purging queue...' submit_time=time() purge_queue() def process_str(str): try: msg_type, msg_body = str.split(':') if msg_type == 'STATUS': print 'Status: ', msg_body elif msg_type == 'ERROR': print 'Error: ', msg_body elif msg_type == 'SENSOR': sens = msg_body.split(',') sensor = {} sensor_type = None sensor_id = None for rec in sens: key,value = rec.split('=') if key == 'TYPE': sensor_type = value elif key == 'ID': sensor_id = value else: sensor[key] = value if sensor_type: if not sensor_id: sensor_id='DEFAULT'; for key in sensor: print 'Type = ', sensor_type, ', ID = ', sensor_id, ', Param = ', key, ', Value = ', sensor[key] submit_data(sensor_type,sensor_id,key,sensor[key]) except: print 'Exception processing...' try: database.close() except: None reconnect() def print_str(str): print str def weather_mon(): path = find_port() ser = open_port(path) read_loop(ser,process_str) def reconnect(): try: global database database = MySQLdb.connect(host=dbhost,user=dbuser,passwd=dbpasswd,use_unicode=True,connect_timeout=10) database.set_character_set('utf8') c = database.cursor() c.execute('SET NAMES utf8;') print "Database connected..." except: print "Error connecting database" sleep(30) def main(): weather_mon() try: cfg = ConfigParser.RawConfigParser(allow_no_value=True) cfg.readfp(open('/etc/weathermon.conf')) dbhost = cfg.get("mysql","host") dbuser = cfg.get("mysql","user") dbpasswd = cfg.get("mysql","passwd") serialnum = cfg.get("serial","id") owmuser = cfg.get("openweathermap","user") owmpasswd = cfg.get("openweathermap",'passwd') if owmuser: owm_temp = cfg.get("openweathermap",'temp') owm_pres = cfg.get("openweathermap",'pres') owm_humi = cfg.get("openweathermap",'humi') owm_lat = cfg.get("openweathermap",'lat') owm_lon = cfg.get("openweathermap",'lon') owm_station = cfg.get("openweathermap",'station') reconnect() except: print "Cannot intialize system" exit() if __name__ == "__main__": import sys reload(sys) sys.setdefaultencoding('utf-8') main()