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)
60 print "Opening path "+path
70 command,args=command.split(' ',1)
71 proc = subprocess.Popen([command,args],stdout=subprocess.PIPE)
73 proc = subprocess.Popen([command],stdout=subprocess.PIPE)
77 ser = serial.Serial(path,baud,timeout=timeout)
79 tcflush(ser,TCIOFLUSH);
85 timeout_timer = Timer(timeout, thread.interrupt_main)
95 except KeyboardInterrupt:
98 timeout_timer.cancel()
100 def read_loop(ser,callback):
108 if line=="<<TIMEOUT>>":
109 print "Reopening port..."
114 print "Terminating process..."
122 except KeyboardInterrupt:
131 system("logger -t weathermon \""+str+"\"")
133 def submit_narodmon():
135 param = { 'ID':devid }
137 c = database.cursor()
140 select nm_id,value from
142 SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
144 timestamp>=date_add(now(), INTERVAL -300 SECOND)
145 group by sensor_id,parameter_id
146 ) v,meteo.ext_sensors e
147 where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
148 and nm_id is not null
156 for (sensor,value) in queue:
157 param[sensor] = value
160 url = "http://narodmon.ru/post.php"
164 response_buffer = StringIO()
167 curl.setopt(curl.URL, url)
168 curl.setopt(curl.WRITEFUNCTION, response_buffer.write)
169 curl.setopt(curl.POST, 1)
170 curl.setopt(curl.POSTFIELDS, urlencode(param))
175 response_value = response_buffer.getvalue()
177 print_log('Narodmon response: '+response_value)
183 exc_type, exc_value, exc_traceback = sys.exc_info()
184 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
185 traceback.print_exception(exc_type, exc_value, exc_traceback,
186 limit=2, file=sys.stdout)
191 url = "http://openweathermap.org/data/post"
192 params = {'name':owm_station, 'lat':owm_lat, 'long':owm_lon}
194 c = database.cursor()
197 select owm_id,value from
199 SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
201 timestamp>=date_add(now(), INTERVAL -300 SECOND)
202 group by sensor_id,parameter_id
203 ) v,meteo.ext_sensors e
204 where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
205 and owm_id is not null
213 for (sensor,value) in queue:
219 response_buffer = StringIO()
222 curl.setopt(curl.URL, url)
223 curl.setopt(curl.USERPWD, '%s:%s' % (owmuser, owmpasswd))
224 curl.setopt(curl.WRITEFUNCTION, response_buffer.write)
225 curl.setopt(curl.POST, 1)
226 curl.setopt(curl.POSTFIELDS, urlencode(params))
231 response_value = response_buffer.getvalue()
233 print_log('Openweathermap response: '+response_value)
239 exc_type, exc_value, exc_traceback = sys.exc_info()
240 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
241 traceback.print_exception(exc_type, exc_value, exc_traceback,
242 limit=2, file=sys.stdout)
245 def submit_data(sensor_type,sensor_id,sensor_param,param_value):
247 global submit_time_owm
248 global external_submit_interval
249 global owm_submit_interval
250 c = database.cursor()
251 c.execute('CALL meteo.submit_value(%s,%s,%s,%s,NULL)', (sensor_type,sensor_id,sensor_param,param_value))
253 if narmon=='on' and time()>submit_time+external_submit_interval:
256 if owmuser and time()>submit_time_owm+owm_submit_interval:
258 submit_time_owm=time()
260 def process_str(str):
261 print_log("Received: "+str)
263 msg_type, msg_body = str.split(':')
267 if msg_type == 'STATUS':
268 print_log('Status: '+msg_body)
269 elif msg_type == 'ERROR':
270 print_log('Error: '+ msg_body)
271 elif msg_type == 'SENSOR':
272 sens = msg_body.split(',')
277 key,value = rec.split('=')
291 print_log('Type = '+sensor_type+', ID = '+sensor_id+', Param = '+key+', Value = '+sensor[key])
292 submit_data(sensor_type,sensor_id,key,sensor[key])
294 print_log('Error: got empty parameter value for '+sensor_type+'.'+sensor_id+'.'+key)
295 elif msg_type == "ALARM":
296 alarm = msg_body.split(',')
300 key,value = rec.split('=')
310 print_log("Alarm: Type = "+device_type+", ID = "+device_id)
313 proc = subprocess.Popen([alarm_script,device_type,device_id,msg_body])
315 print_log("Failed to execute alarm script")
317 print_log('Exception processing...')
318 exc_type, exc_value, exc_traceback = sys.exc_info()
319 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
320 traceback.print_exception(exc_type, exc_value, exc_traceback,
321 limit=5, file=sys.stdout)
334 ser = open_port(path)
335 read_loop(ser,process_str)
346 database = MySQLdb.connect(host=dbhost,user=dbuser,passwd=dbpasswd,use_unicode=True,connect_timeout=10)
347 database.set_character_set('utf8')
348 c = database.cursor()
349 c.execute('SET NAMES utf8;')
350 print_log("Database connected...")
355 print_log("Error connecting database")
363 global dbhost,dbuser,dbpasswd,path,serialnum,logging;
364 global timeout,baud,narmon,devid;
365 global owmuser,owmpasswd,owm_temp,owm_pres,owm_humi,owm_lat,owm_lon,owm_station;
370 cfg = ConfigParser.RawConfigParser(allow_no_value=True)
371 cfg.readfp(open('/etc/weathermon.conf'))
372 dbhost = cfg.get("mysql","host")
373 dbuser = cfg.get("mysql","user")
374 dbpasswd = cfg.get("mysql","passwd")
376 path = cfg.get("serial","port");
380 serialnum = cfg.get("serial","id")
384 logging = cfg.get("logging","enabled")
388 timeout = int(cfg.get("serial","timeout"))
392 baud = int(cfg.get("serial","baud"))
396 narmon = cfg.get("narodmon","enable")
400 devid = cfg.get("narodmon","devid")
402 devid = "{:0>12X}".format(getnode())
404 owmuser = cfg.get("openweathermap","user")
405 owmpasswd = cfg.get("openweathermap",'passwd')
409 owm_temp = cfg.get("openweathermap",'temp')
410 owm_pres = cfg.get("openweathermap",'pres')
411 owm_humi = cfg.get("openweathermap",'humi')
412 owm_lat = cfg.get("openweathermap",'lat')
413 owm_lon = cfg.get("openweathermap",'lon')
414 owm_station = cfg.get("openweathermap",'station')
416 alarm_script = cfg.get("alarm","exec")
425 print_log("Cannot intialize system")
428 if __name__ == "__main__":
431 sys.setdefaultencoding('utf-8')