5 from os import listdir,system
 
   6 from os.path import isfile, join
 
   8 from pprint import pprint
 
  10 from termios import tcflush, TCIOFLUSH
 
  12 from time import sleep,time
 
  14 from uuid import getnode
 
  16 from hashlib import md5
 
  23 from urllib import urlencode
 
  24 from StringIO import StringIO
 
  26 searchpath = '/dev/serial/by-id/'
 
  33 external_submit_interval = 320
 
  34 owm_submit_interval = 320
 
  35 expire_interval = 1200
 
  37 submit_time_owm = time()
 
  43 from threading import Timer
 
  50   files = listdir(searchpath)
 
  53       return join(searchpath,f)
 
  61     print "Opening path "+path
 
  71       command,args=command.split(' ',1)
 
  72       proc = subprocess.Popen([command,args],stdout=subprocess.PIPE)
 
  74       proc = subprocess.Popen([command],stdout=subprocess.PIPE)
 
  78   ser = serial.Serial(path,baud,timeout=timeout)
 
  80     tcflush(ser,TCIOFLUSH);
 
  86     timeout_timer = Timer(timeout, thread.interrupt_main)
 
  96   except KeyboardInterrupt:
 
  99     timeout_timer.cancel()
 
 101 def read_loop(ser,callback):
 
 109       if line=="<<TIMEOUT>>":
 
 111           print "Reopening port..."
 
 117               print "Terminating process..."
 
 125     except KeyboardInterrupt:
 
 135     system("logger -t weathermon \""+str+"\"")
 
 137 def submit_narodmon():
 
 139   param = { 'ID':devid }
 
 141   c = database.cursor()
 
 144     select nm_id,value from
 
 146     SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
 
 148     timestamp>=date_add(now(), INTERVAL -300 SECOND)
 
 149     group by sensor_id,parameter_id
 
 150     ) v,meteo.ext_sensors e
 
 151     where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
 
 152     and nm_id is not null
 
 161   for (sensor,value) in queue:
 
 162     param[sensor] = value  
 
 167   url = "http://narodmon.ru/post.php"
 
 171     response_buffer = StringIO()
 
 174     curl.setopt(curl.URL, url)
 
 175     curl.setopt(curl.WRITEFUNCTION, response_buffer.write)   
 
 176     curl.setopt(curl.POST, 1)
 
 177     curl.setopt(curl.POSTFIELDS, urlencode(param))
 
 182     response_value = response_buffer.getvalue()
 
 184     print_log('Narodmon response: '+response_value)
 
 190     exc_type, exc_value, exc_traceback = sys.exc_info()
 
 191     traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
 
 192     traceback.print_exception(exc_type, exc_value, exc_traceback,
 
 193                               limit=2, file=sys.stdout)  
 
 198   url = "http://openweathermap.org/data/post"
 
 199   params = {'name':owm_station, 'lat':owm_lat, 'long':owm_lon}
 
 201   c = database.cursor()
 
 204     select owm_id,value from
 
 206     SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
 
 208     timestamp>=date_add(now(), INTERVAL -300 SECOND)
 
 209     group by sensor_id,parameter_id
 
 210     ) v,meteo.ext_sensors e
 
 211     where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
 
 212     and owm_id is not null
 
 221   for (sensor,value) in queue:
 
 228     response_buffer = StringIO()
 
 231     curl.setopt(curl.URL, url)
 
 232     curl.setopt(curl.USERPWD, '%s:%s' % (owmuser, owmpasswd))
 
 233     curl.setopt(curl.WRITEFUNCTION, response_buffer.write)
 
 234     curl.setopt(curl.POST, 1)
 
 235     curl.setopt(curl.POSTFIELDS, urlencode(params))
 
 240     response_value = response_buffer.getvalue()
 
 242     print_log('Openweathermap response: '+response_value)
 
 248     exc_type, exc_value, exc_traceback = sys.exc_info()
 
 249     traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
 
 250     traceback.print_exception(exc_type, exc_value, exc_traceback,
 
 251                                   limit=2, file=sys.stdout)
 
 254 def submit_data(sensor_type,sensor_id,sensor_param,param_value):
 
 256   global submit_time_owm
 
 257   global external_submit_interval
 
 258   global owm_submit_interval
 
 259   c = database.cursor()
 
 260   c.execute('CALL meteo.submit_value(%s,%s,%s,%s,NULL)', (sensor_type,sensor_id,sensor_param,param_value))
 
 262   if narmon=='on' and time()>submit_time+external_submit_interval:
 
 265   if owmuser and time()>submit_time_owm+owm_submit_interval:
 
 267     submit_time_owm=time()        
 
 269 def process_str(str):
 
 270   print_log("Received: "+str)
 
 272     msg_type, msg_body = str.split(':')
 
 276     if msg_type == 'STATUS':
 
 277       print_log('Status: '+msg_body)
 
 278     elif msg_type == 'ERROR':
 
 279       print_log('Error: '+ msg_body)
 
 280     elif msg_type == 'SENSOR':
 
 281       sens = msg_body.split(',')
 
 286         key,value = rec.split('=')
 
 300           print_log('Type = '+sensor_type+', ID = '+sensor_id+', Param = '+key+', Value = '+sensor[key])
 
 301           submit_data(sensor_type,sensor_id,key,sensor[key])
 
 303           print_log('Error: got empty parameter value for '+sensor_type+'.'+sensor_id+'.'+key)
 
 304     elif msg_type == "ALARM":
 
 305       alarm = msg_body.split(',')
 
 309         key,value = rec.split('=')
 
 319         print_log("Alarm: Type = "+device_type+", ID = "+device_id)
 
 322             proc = subprocess.Popen([alarm_script,device_type,device_id,msg_body])
 
 324             print_log("Failed to execute alarm script")          
 
 326     print_log('Exception processing...')
 
 327     exc_type, exc_value, exc_traceback = sys.exc_info()
 
 328     traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
 
 329     traceback.print_exception(exc_type, exc_value, exc_traceback,
 
 330                               limit=5, file=sys.stdout)  
 
 343   ser = open_port(path)
 
 344   read_loop(ser,process_str)
 
 355       database = MySQLdb.connect(host=dbhost,user=dbuser,passwd=dbpasswd,use_unicode=True,connect_timeout=10)
 
 356       database.set_character_set('utf8')
 
 357       c = database.cursor()
 
 358       c.execute('SET NAMES utf8;')
 
 359       print_log("Database connected...")
 
 364       print_log("Error connecting database")
 
 372   global dbhost,dbuser,dbpasswd,path,serialnum,logging,debug;
 
 373   global timeout,baud,narmon,devid;
 
 374   global owmuser,owmpasswd,owm_temp,owm_pres,owm_humi,owm_lat,owm_lon,owm_station;
 
 379     cfg = ConfigParser.RawConfigParser(allow_no_value=True)
 
 380     cfg.readfp(open('/etc/weathermon.conf'))
 
 381     dbhost = cfg.get("mysql","host")
 
 382     dbuser = cfg.get("mysql","user")
 
 383     dbpasswd = cfg.get("mysql","passwd")
 
 385       debug = cfg.get("logging","debug")
 
 389       path = cfg.get("serial","port");
 
 393       serialnum = cfg.get("serial","id")
 
 397       logging = cfg.get("logging","enabled")
 
 401       timeout = int(cfg.get("serial","timeout"))
 
 405       baud = int(cfg.get("serial","baud"))
 
 409       narmon = cfg.get("narodmon","enable")
 
 413       devid = cfg.get("narodmon","devid")
 
 415       devid = "{:0>12X}".format(getnode())   
 
 417       owmuser = cfg.get("openweathermap","user")
 
 418       owmpasswd = cfg.get("openweathermap",'passwd')
 
 422       owm_temp = cfg.get("openweathermap",'temp')
 
 423       owm_pres = cfg.get("openweathermap",'pres')
 
 424       owm_humi = cfg.get("openweathermap",'humi')
 
 425       owm_lat = cfg.get("openweathermap",'lat')
 
 426       owm_lon = cfg.get("openweathermap",'lon')
 
 427       owm_station = cfg.get("openweathermap",'station')
 
 429       alarm_script = cfg.get("alarm","exec")
 
 438     print_log("Cannot intialize system")
 
 441 if __name__ == "__main__":
 
 444   sys.setdefaultencoding('utf-8')