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
69 command,args=command.split(' ',1)
70 proc = subprocess.Popen([command,args],stdout=subprocess.PIPE)
72 proc = subprocess.Popen([command],stdout=subprocess.PIPE)
76 ser = serial.Serial(path,baud,timeout=timeout)
78 tcflush(ser,TCIOFLUSH);
84 timeout_timer = Timer(timeout, thread.interrupt_main)
88 except KeyboardInterrupt:
91 timeout_timer.cancel()
93 def read_loop(ser,callback):
101 if line=="<<TIMEOUT>>":
102 print "Reopening port..."
105 print "Terminating process..."
111 except KeyboardInterrupt:
120 system("logger -t weathermon \""+str+"\"")
122 def submit_narodmon():
124 param = { 'ID':devid }
126 c = database.cursor()
129 select nm_id,value from
131 SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
133 timestamp>=date_add(now(), INTERVAL -300 SECOND)
134 group by sensor_id,parameter_id
135 ) v,meteo.ext_sensors e
136 where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
137 and nm_id is not null
145 for (sensor,value) in queue:
146 param[sensor] = value
149 url = "http://narodmon.ru/post.php"
153 response_buffer = StringIO()
156 curl.setopt(curl.URL, url)
157 curl.setopt(curl.WRITEFUNCTION, response_buffer.write)
158 curl.setopt(curl.POST, 1)
159 curl.setopt(curl.POSTFIELDS, urlencode(param))
164 response_value = response_buffer.getvalue()
166 print_log('Narodmon response: '+response_value)
172 exc_type, exc_value, exc_traceback = sys.exc_info()
173 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
174 traceback.print_exception(exc_type, exc_value, exc_traceback,
175 limit=2, file=sys.stdout)
180 url = "http://openweathermap.org/data/post"
181 params = {'name':owm_station, 'lat':owm_lat, 'long':owm_lon}
183 c = database.cursor()
186 select owm_id,value from
188 SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
190 timestamp>=date_add(now(), INTERVAL -300 SECOND)
191 group by sensor_id,parameter_id
192 ) v,meteo.ext_sensors e
193 where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
194 and owm_id is not null
202 for (sensor,value) in queue:
208 response_buffer = StringIO()
211 curl.setopt(curl.URL, url)
212 curl.setopt(curl.USERPWD, '%s:%s' % (owmuser, owmpasswd))
213 curl.setopt(curl.WRITEFUNCTION, response_buffer.write)
214 curl.setopt(curl.POST, 1)
215 curl.setopt(curl.POSTFIELDS, urlencode(params))
220 response_value = response_buffer.getvalue()
222 print_log('Openweathermap response: '+response_value)
228 exc_type, exc_value, exc_traceback = sys.exc_info()
229 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
230 traceback.print_exception(exc_type, exc_value, exc_traceback,
231 limit=2, file=sys.stdout)
234 def submit_data(sensor_type,sensor_id,sensor_param,param_value):
236 global submit_time_owm
237 global external_submit_interval
238 global owm_submit_interval
239 c = database.cursor()
240 c.execute('CALL meteo.submit_value(%s,%s,%s,%s,NULL)', (sensor_type,sensor_id,sensor_param,param_value))
242 if narmon=='on' and time()>submit_time+external_submit_interval:
245 if owmuser and time()>submit_time_owm+owm_submit_interval:
247 submit_time_owm=time()
249 def process_str(str):
250 print_log("Received: "+str)
252 msg_type, msg_body = str.split(':')
256 if msg_type == 'STATUS':
257 print_log('Status: '+msg_body)
258 elif msg_type == 'ERROR':
259 print_log('Error: '+ msg_body)
260 elif msg_type == 'SENSOR':
261 sens = msg_body.split(',')
266 key,value = rec.split('=')
280 print_log('Type = '+sensor_type+', ID = '+sensor_id+', Param = '+key+', Value = '+sensor[key])
281 submit_data(sensor_type,sensor_id,key,sensor[key])
283 print_log('Error: got empty parameter value for '+sensor_type+'.'+sensor_id+'.'+key)
284 elif msg_type == "ALARM":
285 alarm = msg_body.split(',')
289 key,value = rec.split('=')
299 print_log("Alarm: Type = "+device_type+", ID = "+device_id)
302 proc = subprocess.Popen([alarm_script,device_type,device_id,msg_body])
304 print_log("Failed to execute alarm script")
306 print_log('Exception processing...')
307 exc_type, exc_value, exc_traceback = sys.exc_info()
308 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
309 traceback.print_exception(exc_type, exc_value, exc_traceback,
310 limit=5, file=sys.stdout)
323 ser = open_port(path)
324 read_loop(ser,process_str)
335 database = MySQLdb.connect(host=dbhost,user=dbuser,passwd=dbpasswd,use_unicode=True,connect_timeout=10)
336 database.set_character_set('utf8')
337 c = database.cursor()
338 c.execute('SET NAMES utf8;')
339 print_log("Database connected...")
344 print_log("Error connecting database")
352 cfg = ConfigParser.RawConfigParser(allow_no_value=True)
353 cfg.readfp(open('/etc/weathermon.conf'))
354 dbhost = cfg.get("mysql","host")
355 dbuser = cfg.get("mysql","user")
356 dbpasswd = cfg.get("mysql","passwd")
358 path = cfg.get("serial","port");
362 serialnum = cfg.get("serial","id")
366 logging = cfg.get("logging","enabled")
370 timeout = int(cfg.get("serial","timeout"))
374 baud = int(cfg.get("serial","baud"))
378 narmon = cfg.get("narodmon","enable")
382 devid = cfg.get("narodmon","devid")
384 devid = "{:0>12X}".format(getnode())
386 owmuser = cfg.get("openweathermap","user")
387 owmpasswd = cfg.get("openweathermap",'passwd')
391 owm_temp = cfg.get("openweathermap",'temp')
392 owm_pres = cfg.get("openweathermap",'pres')
393 owm_humi = cfg.get("openweathermap",'humi')
394 owm_lat = cfg.get("openweathermap",'lat')
395 owm_lon = cfg.get("openweathermap",'lon')
396 owm_station = cfg.get("openweathermap",'station')
398 alarm_script = cfg.get("alarm","exec")
407 print_log("Cannot intialize system")
410 if __name__ == "__main__":
413 sys.setdefaultencoding('utf-8')