Улучшена обработка ошибок при работе с проводными датчиками.
[weathermon.git] / weathermon
index 8c94dd0c14ca976d8e00845b6b4e3b4efe50ff57..66d6ac4390603399baeec4f11401fba71839a832 100755 (executable)
@@ -2,9 +2,11 @@
 
 import serial
 
 
 import serial
 
-from os import listdir
+from os import listdir,system
 from os.path import isfile, join
 
 from os.path import isfile, join
 
+from pprint import pprint
+
 from termios import tcflush, TCIOFLUSH
 
 from time import sleep,time
 from termios import tcflush, TCIOFLUSH
 
 from time import sleep,time
@@ -22,12 +24,15 @@ from urllib import urlencode
 from StringIO import StringIO
 
 searchpath = '/dev/serial/by-id/'
 from StringIO import StringIO
 
 searchpath = '/dev/serial/by-id/'
-baud = 9600
+baud = 57600
+path = None
 timeout = 5
 
 external_submit_interval = 320
 timeout = 5
 
 external_submit_interval = 320
+owm_submit_interval = 320
 expire_interval = 1200
 submit_time = time()
 expire_interval = 1200
 submit_time = time()
+submit_time_owm = time()
 submit_queue = {}
 
 import MySQLdb
 submit_queue = {}
 
 import MySQLdb
@@ -36,6 +41,7 @@ import ConfigParser
 def find_port():
 
   global serial_num
 def find_port():
 
   global serial_num
+  global path
 
   files = listdir(searchpath)
   for f in files:
 
   files = listdir(searchpath)
   for f in files:
@@ -68,17 +74,25 @@ def read_loop(ser,callback):
     finally:
       None
 
     finally:
       None
 
+def print_log(str):
+  global logging
+  print str
+  if logging == "on":
+    system("logger -t weathermon \""+str+"\"")
+
 def submit_narodmon(queue):
 
   param = { 'ID':"{:X}".format(getnode())}
 
 def submit_narodmon(queue):
 
   param = { 'ID':"{:X}".format(getnode())}
 
+  pprint(queue)
+
   for sensor in queue:
     value = submit_queue[sensor]['val']
     timestamp = submit_queue[sensor]['timestamp']
     digest = md5(sensor).hexdigest()[:18]
     param[digest] = value;
   
   for sensor in queue:
     value = submit_queue[sensor]['val']
     timestamp = submit_queue[sensor]['timestamp']
     digest = md5(sensor).hexdigest()[:18]
     param[digest] = value;
   
-  print param
+  pprint (param)
 
   url = "http://narodmon.ru/post.php"
 
 
   url = "http://narodmon.ru/post.php"
 
@@ -97,7 +111,7 @@ def submit_narodmon(queue):
                                                                           
     response_value = response_buffer.getvalue()
                                                                               
                                                                           
     response_value = response_buffer.getvalue()
                                                                               
-    print 'Content: ', response_value
+    print_log('Narodmon response: '+response_value)
                                                                                   
     return True
                                                                                       
                                                                                   
     return True
                                                                                       
@@ -137,7 +151,7 @@ def submit_owm(queue):
     
     response_value = response_buffer.getvalue()
     
     
     response_value = response_buffer.getvalue()
     
-    print 'Content: ', response_value
+    print_log('Openweathermap response: '+response_value)
   
     return True
   
   
     return True
   
@@ -154,34 +168,41 @@ def purge_queue():
   clean = []
   for key in submit_queue:
     if submit_queue[key]['timestamp'] < time()-expire_interval:
   clean = []
   for key in submit_queue:
     if submit_queue[key]['timestamp'] < time()-expire_interval:
-      print "Expired value for "+key
+      print_log("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
       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_time_owm
+  global external_submit_interval
+  global owm_submit_interval
   global submit_queue
   c = database.cursor()
   global submit_queue
   c = database.cursor()
-  c.execute('CALL meteo.submit_value(%s,%s,%s,%s)', (sensor_type,sensor_id,sensor_param,param_value))
+  c.execute('CALL meteo.submit_value(%s,%s,%s,%s,NULL)', (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:
   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()
+    submit_narodmon(submit_queue)
+    submit_time=time()
+  if owmuser and time()>submit_time_owm+owm_submit_interval:
+    submit_owm(submit_queue)
+    submit_time_owm=time()
+  purge_queue()
         
  
 def process_str(str):
         
  
 def process_str(str):
+  print_log("Received: "+str)
   try:
     msg_type, msg_body = str.split(':')
   try:
     msg_type, msg_body = str.split(':')
+  except:
+    return
+  try:  
     if msg_type == 'STATUS':
     if msg_type == 'STATUS':
-      print 'Status: ', msg_body
+      print_log('Status: '+msg_body)
     elif msg_type == 'ERROR':
     elif msg_type == 'ERROR':
-      print 'Error: ', msg_body
+      print_log('Error: '+ msg_body)
     elif msg_type == 'SENSOR':
       sens = msg_body.split(',')
       sensor = {}
     elif msg_type == 'SENSOR':
       sens = msg_body.split(',')
       sensor = {}
@@ -189,50 +210,64 @@ def process_str(str):
       sensor_id = None
       for rec in sens:
         key,value = rec.split('=')
       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
+       value=value.strip()
+       if len(value)>0:
+          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:
       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])
+       if sensor[key]:
+          print_log('Type = '+sensor_type+', ID = '+sensor_id+', Param = '+key+', Value = '+sensor[key])
+          submit_data(sensor_type,sensor_id,key,sensor[key])
+        else:
+          print_log('Error: got empty parameter value for '+sensor_type+'.'+sensor_id+'.'+key)
   except:
   except:
-    print 'Exception processing...'
+    print_log('Exception processing...')
+    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=5, file=sys.stdout)  
     try:
       database.close()
     except:
       None
     reconnect()
 
     try:
       database.close()
     except:
       None
     reconnect()
 
-def print_str(str):
-  print str 
-      
 def weather_mon():
 
 def weather_mon():
 
-  path = find_port()
+  global path
+
+  if path is None:
+    path = find_port()
   ser = open_port(path)
   read_loop(ser,process_str)
 
 def reconnect():
   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:
+  connected = False
+
+  while not connected:            
+
+    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_log("Database connected...")
+      connected = True 
+  
+    except:
         
         
-    print "Error connecting database"
-    sleep(30)
+      print_log("Error connecting database")
+      sleep(30)
       
 def main():
   weather_mon()
       
 def main():
   weather_mon()
@@ -244,7 +279,18 @@ try:
   dbhost = cfg.get("mysql","host")
   dbuser = cfg.get("mysql","user")
   dbpasswd = cfg.get("mysql","passwd")
   dbhost = cfg.get("mysql","host")
   dbuser = cfg.get("mysql","user")
   dbpasswd = cfg.get("mysql","passwd")
-  serialnum = cfg.get("serial","id")
+  try:
+    path = cfg.get("serial","port");
+  except:
+    path = None
+  try:    
+    serialnum = cfg.get("serial","id")
+  except:
+    serialnum = None  
+  try:
+    logging = cfg.get("logging","enabled")
+  except:
+    logging = None
   owmuser = cfg.get("openweathermap","user")
   owmpasswd = cfg.get("openweathermap",'passwd')
   if owmuser:
   owmuser = cfg.get("openweathermap","user")
   owmpasswd = cfg.get("openweathermap",'passwd')
   if owmuser:
@@ -258,7 +304,7 @@ try:
  
 except:
 
  
 except:
 
-  print "Cannot intialize system"
+  print_log("Cannot intialize system")
   exit() 
   
 if __name__ == "__main__":
   exit() 
   
 if __name__ == "__main__":