-#!/usr/bin/python
-
-import serial
-
-from os import listdir,system
-from os.path import isfile, join
-
-from pprint import pprint
-
-from termios import tcflush, TCIOFLUSH
-
-from time import sleep,time
-
-from uuid import getnode
-
-from hashlib import md5
-
-import socket
-
-import sys,traceback
-
-import pycurl
-from urllib import urlencode
-from StringIO import StringIO
-
-searchpath = '/dev/serial/by-id/'
-path = None
-baud = None
-timeout = None
-
-proc = None
-
-external_submit_interval = 320
-owm_submit_interval = 320
-expire_interval = 1200
-submit_time = time()
-submit_time_owm = time()
-
-import MySQLdb
-import ConfigParser
-
-import thread
-from threading import Timer
-
-def find_port():
-
- global serial_num
- global path
-
- files = listdir(searchpath)
- for f in files:
- if serialnum in f:
- return join(searchpath,f)
- return None
-
-def open_port(path):
-
- global proc, debug
-
- if debug>0:
- print "Opening path "+path
-
- if path == "-":
- return sys.stdin
-
- if path[0] == "=":
- import subprocess
- sleep(3)
- command=path[1:]
- try:
- command,args=command.split(' ',1)
- proc = subprocess.Popen([command,args],stdout=subprocess.PIPE)
- except:
- proc = subprocess.Popen([command],stdout=subprocess.PIPE)
- import subprocess
- return proc.stdout
-
- ser = serial.Serial(path,baud,timeout=timeout)
- if ser.portstr:
- tcflush(ser,TCIOFLUSH);
- return ser
-
-def read_port(ser):
-
- try:
- timeout_timer = Timer(timeout, thread.interrupt_main)
- timeout_timer.start()
-
- line=''
- while line=='':
- line = ser.readline()
- line = line.strip()
-
- return line
-
- except KeyboardInterrupt:
- return "<<TIMEOUT>>"
- finally:
- timeout_timer.cancel()
-
-def read_loop(ser,callback):
-
- global proc
-
- while True:
-
- try:
- line=read_port(ser)
- if line=="<<TIMEOUT>>":
- if debug>0:
- print "Reopening port..."
- print line
- ser.close()
- if proc:
- try:
- if debug>0:
- print "Terminating process..."
- proc.terminate()
- sleep(5)
- finally:
- None
- ser=open_port(path)
- if line:
- callback(line)
- except KeyboardInterrupt:
- break
- finally:
- None
-
-def print_log(str):
- global logging
- if debug>0:
- print str
- if logging == "on":
- system("logger -t weathermon \""+str+"\"")
-
-def submit_narodmon():
-
- param = { 'ID':devid }
-
- c = database.cursor()
- c.execute(
- '''
- select nm_id,value from
- (
- SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
- where
- timestamp>=date_add(now(), INTERVAL -300 SECOND)
- group by sensor_id,parameter_id
- ) v,meteo.ext_sensors e
- where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
- and nm_id is not null
- '''
- )
-
- queue=c.fetchall()
-
- if debug>1:
- pprint(queue)
-
- for (sensor,value) in queue:
- param[sensor] = value
-
- if debug>1:
- pprint (param)
-
- url = "http://narodmon.ru/post.php"
-
- try:
-
- response_buffer = StringIO()
- curl = pycurl.Curl()
-
- curl.setopt(curl.URL, url)
- curl.setopt(curl.WRITEFUNCTION, response_buffer.write)
- curl.setopt(curl.POST, 1)
- curl.setopt(curl.POSTFIELDS, urlencode(param))
-
- curl.perform()
- curl.close()
-
- response_value = response_buffer.getvalue()
-
- print_log('Narodmon response: '+response_value)
-
- return True
-
- except:
-
- 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=2, file=sys.stdout)
- return False
-
-def submit_owm():
-
- url = "http://openweathermap.org/data/post"
- params = {'name':owm_station, 'lat':owm_lat, 'long':owm_lon}
-
- c = database.cursor()
- c.execute(
- '''
- select owm_id,value from
- (
- SELECT sensor_id,parameter_id,max(timestamp) timestamp,round(avg(value),1) value FROM meteo.sensor_values
- where
- timestamp>=date_add(now(), INTERVAL -300 SECOND)
- group by sensor_id,parameter_id
- ) v,meteo.ext_sensors e
- where v.sensor_id=e.sensor_id and v.parameter_id=e.param_id
- and owm_id is not null
- '''
- )
-
- queue=c.fetchall()
-
- if debug>1:
- pprint(queue)
-
- for (sensor,value) in queue:
- params[sensor]=value
- if debug>1:
- pprint (params)
-
- try:
-
- response_buffer = StringIO()
- curl = pycurl.Curl()
-
- curl.setopt(curl.URL, url)
- curl.setopt(curl.USERPWD, '%s:%s' % (owmuser, owmpasswd))
- curl.setopt(curl.WRITEFUNCTION, response_buffer.write)
- curl.setopt(curl.POST, 1)
- curl.setopt(curl.POSTFIELDS, urlencode(params))
-
- curl.perform()
- curl.close()
-
- response_value = response_buffer.getvalue()
-
- print_log('Openweathermap response: '+response_value)
-
- return True
-
- except:
-
- 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=2, file=sys.stdout)
- return False
-
-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
- c = database.cursor()
- c.execute('CALL meteo.submit_value(%s,%s,%s,%s,NULL)', (sensor_type,sensor_id,sensor_param,param_value))
- database.commit()
- if narmon=='on' and time()>submit_time+external_submit_interval:
- submit_narodmon()
- submit_time=time()
- if owmuser and time()>submit_time_owm+owm_submit_interval:
- submit_owm()
- submit_time_owm=time()
-
-def process_str(str):
- print_log("Received: "+str)
- try:
- msg_type, msg_body = str.split(':')
- except:
- return
- try:
- if msg_type == 'STATUS':
- print_log('Status: '+msg_body)
- elif msg_type == 'ERROR':
- print_log('Error: '+ msg_body)
- elif msg_type == 'SENSOR':
- sens = msg_body.split(',')
- sensor = {}
- sensor_type = None
- sensor_id = None
- for rec in sens:
- key,value = rec.split('=')
- 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=devid;
- for key in sensor:
- 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)
- elif msg_type == "ALARM":
- alarm = msg_body.split(',')
- device_type = None
- device_id = None
- for rec in alarm:
- key,value = rec.split('=')
- value=value.strip()
- if len(value)>0:
- if key == 'TYPE':
- device_type = value
- if key == 'ID':
- device_id = value
- if device_type:
- if not device_id:
- device_id=devid;
- print_log("Alarm: Type = "+device_type+", ID = "+device_id)
- if alarm_script:
- try:
- proc = subprocess.Popen([alarm_script,device_type,device_id,msg_body])
- except:
- print_log("Failed to execute alarm script")
- except:
- 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()
-
-def weather_mon():
-
- global path
-
- if path is None:
- path = find_port()
- ser = open_port(path)
- read_loop(ser,process_str)
-
-def reconnect():
-
- 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_log("Error connecting database")
- sleep(30)
-
-def main():
- weather_mon()
-
-def init():
-
- global dbhost,dbuser,dbpasswd,path,serialnum,logging,debug;
- global timeout,baud,narmon,devid;
- global owmuser,owmpasswd,owm_temp,owm_pres,owm_humi,owm_lat,owm_lon,owm_station;
- global alarm_script;
-
- try:
-
- cfg = ConfigParser.RawConfigParser(allow_no_value=True)
- cfg.readfp(open('/etc/weathermon.conf'))
- dbhost = cfg.get("mysql","host")
- dbuser = cfg.get("mysql","user")
- dbpasswd = cfg.get("mysql","passwd")
- try:
- debug = cfg.get("logging","debug")
- except:
- debug = 0
- 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
- try:
- timeout = int(cfg.get("serial","timeout"))
- except:
- timeout = 120
- try:
- baud = int(cfg.get("serial","baud"))
- except:
- baud = 57600
- try:
- narmon = cfg.get("narodmon","enable")
- except:
- narmon = 'off'
- try:
- devid = cfg.get("narodmon","devid")
- except:
- devid = "{:0>12X}".format(getnode())
- try:
- owmuser = cfg.get("openweathermap","user")
- owmpasswd = cfg.get("openweathermap",'passwd')
- except:
- owmuser = None
- if owmuser:
- owm_temp = cfg.get("openweathermap",'temp')
- owm_pres = cfg.get("openweathermap",'pres')
- owm_humi = cfg.get("openweathermap",'humi')
- owm_lat = cfg.get("openweathermap",'lat')
- owm_lon = cfg.get("openweathermap",'lon')
- owm_station = cfg.get("openweathermap",'station')
- try:
- alarm_script = cfg.get("alarm","exec")
- import subprocess
- except:
- alarm_script = None
-
- reconnect()
-
- except:
-
- print_log("Cannot intialize system")
- exit()
-
-if __name__ == "__main__":
- import sys
- reload(sys)
- sys.setdefaultencoding('utf-8')
- init()
- main()