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')