From: Roman Bazalevskiy Date: Sat, 3 Sep 2016 18:32:52 +0000 (+0300) Subject: Merge branch 'master' of estia:weathermon X-Git-Url: https://git.rvb.name/weathermon.git/commitdiff_plain/a26fd989812acc9c3b91360a12a2685589acd942?hp=357607fbe9159afef9ba89f1dbe86abe7966efc8 Merge branch 'master' of estia:weathermon --- diff --git a/mysql/meteo_routines.sql b/mysql/meteo_routines.sql index bf72780..5f819b3 100644 --- a/mysql/meteo_routines.sql +++ b/mysql/meteo_routines.sql @@ -128,4 +128,55 @@ DELIMITER ; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +DELIMITER $$ +CREATE DEFINER=`admin`@`%` PROCEDURE `Reduce`(pUpTo datetime,pRID integer) +BEGIN + declare lNewRID integer; + declare lSeconds integer; + + declare lStart,lEnd timestamp; + + set lNewRID:=pRID+1; + select seconds into lSeconds from reduce_ranges where id=lNewRID; + + delete from tmp_sensor_values; + + insert into tmp_sensor_values(sensor_id,parameter_id,timestamp,value) + select sensor_id,parameter_id,from_unixtime(avg(unix_timestamp(timestamp))),avg(value) + from sensor_values + where timestamp=lStart and day<=lEnd; + + insert into sensors_ranges(day,sensor,parameter,timestamp,min,max) + select date(timestamp),sensor_id,parameter_id,max(timestamp),min(value),max(value) + from sensor_values + where timestamp>=lStart and timestamp0: + 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 "<>" + finally: + timeout_timer.cancel() + +def read_loop(ser,callback): + + global proc + + while True: + + try: + line=read_port(ser) + if line=="<>": + 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() diff --git a/weathermon.lua b/weathermon.lua index 20f5aca..19cd912 100755 --- a/weathermon.lua +++ b/weathermon.lua @@ -10,16 +10,28 @@ function getConfig() web_user = cur.get(config,"web","user") web_pass = cur.get(config,"web","password") web_devid = cur.get(config,"web","devid") + + web_iface = cur.get(config,"web","iface") - io.input("/sys/class/net/eth0/address") + if web_iface then + io.input("/sys/class/net/"..web_iface.."/address") + else + io.input("/sys/class/net/eth0/address") + end + mac = io.read("*line") mac = mac:gsub(":","") mac = mac:upper() web_devid = web_devid or mac - logging = cur.get(config,"logging","enabled") + serial_port = cur.get(config,"serial","port") + serial_baud = cur.get(config,"serial","baud") + + command = "stty -F "..serial_port.." "..serial_baud + os.execute(command) + end require "socket" @@ -59,21 +71,21 @@ end function submitValue(type,id,param,val) - printLog("URL="..web_url) - url = web_url.."?stype="..type.."&sid="..id.."¶m="..param.."&value="..val - printLog(url) - command = "curl" + if web_iface then + command = command.." --interface "..web_iface + end + if web_user then command = command.." -u "..web_user..":"..web_pass end command = command.." \""..url.."\"" - printLog("COMMAND=\""..command.."\"") + print(command) os.execute(command) print("") @@ -110,8 +122,8 @@ function processLine(str) end end for k,v in pairs(sensor) do - printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..key..", Value = "..value) - submitValue(sensor_type,sensor_id,key,value) + printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = "..v) + submitValue(sensor_type,sensor_id,k,v) end end @@ -119,6 +131,9 @@ end getConfig() -line=arg[1] -print(line) -processLine(line) +serialin=io.open(serial_port,"r") +while 1 do + line=serialin:read() + print(line) + processLine(line) +end diff --git a/weathermon.sh b/weathermon.sh deleted file mode 100755 index 3f42275..0000000 --- a/weathermon.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -ARDUINO_PORT=`uci get weathermon.serial.port` -BAUD=`uci get weathermon.serial.baud` -stty -F $ARDUINO_PORT $BAUD - -while read LINE; do - weathermon.lua $LINE -done < $ARDUINO_PORT diff --git a/weathermon.uci b/weathermon.uci index 490ba91..27631ac 100644 --- a/weathermon.uci +++ b/weathermon.uci @@ -2,6 +2,7 @@ config internal 'web' option url http://estia.rvb-home.lan/meteo/send.php option user meteo option password somestrictpassword + option iface eth0 config internal 'serial' option port /dev/ttyUSB0 diff --git a/web/archive.php b/web/archive.php index c403863..1b21599 100644 --- a/web/archive.php +++ b/web/archive.php @@ -23,7 +23,7 @@ } a:visited { text-decoration: none; color:darkblue; } a:link { text-decoration: none; color:blue; } - a:hover { text-decoration: none; color:navy; } + a:hover { text-decoration: underline; color:navy; } @@ -33,6 +33,21 @@ include('config_local.php'); include('calendar.php'); include('units.php'); + $client_ip = $_SERVER["REMOTE_ADDR"]; + + if ((strpos($client_ip, "192.168.") === 0) || (strpos($client_ip, "10.8.") === 0) + || (strpos($client_ip, "2a02:578:5002:8174:") === 0) + || (strpos($client_ip, "2a02:578:5002:196::2") === 0)) { + + $local_net = True; + + } else { + + $local_net = False; + + } + + $year = $_REQUEST['year']; $month = $_REQUEST['month']; $day = $_REQUEST['day']; @@ -58,7 +73,7 @@ if (! $year) { fetch(PDO::FETCH_ASSOC)) { ?> - Данные за год
+ Данные за год prepare ( 'select s.id sensor,p.id param,s.s_description sensor_name,p.st_description param_name, @@ -128,7 +155,7 @@ if (! $year) { v.parameter=p.id and p.st_unit=u.id and v.day>=str_to_date(\''.$year.'-01-01\',\'%Y-%m-%d\') and - v.day prepare( 'select date_format(day,\'%d\') as day from - sensors_ranges + sensors_ranges r,sensors s where + s.id=r.sensor and day>=str_to_date(\''.$year.'-'.$month.'-01\',\'%Y-%m-%d\') and - day prepare ( 'select @@ -221,7 +271,7 @@ if (! $year) { v.parameter=p.id and p.st_unit=u.id and v.day>=str_to_date(\''.$year.'-'.$month.'-01\',\'%Y-%m-%d\') and - v.day prepare( 'select distinct v.sensor as sensor_id,s.s_description,p.id as param_id,p.st_description @@ -270,7 +331,7 @@ if (! $year) { where v.day=str_to_date(\''.$year.'-'.$month.'-'.$day.'\',\'%Y-%m-%d\') and v.sensor=s.id - and v.parameter=p.id' + and v.parameter=p.id'.$filter ); $q -> execute(); diff --git a/web/config_local.php b/web/config_local.php index eef2134..d6cce97 100644 --- a/web/config_local.php +++ b/web/config_local.php @@ -3,15 +3,12 @@ $mysql_host = 'host'; $mysql_schema = 'meteo'; $mysql_user = 'meteo'; - $mysql_pwd = 'somestrictpasswd'; + $mysql_pwd = 'somestrongpasswd'; $mysql_port = 3306; setlocale(LC_ALL,'ru_RU.UTF8'); -<<<<<<< HEAD -======= - $valid_ip_start = ip2long('192.168.1.161'); - $valid_ip_end = ip2long('192.168.1.190'); ->>>>>>> 438eca78d7802bd2758a4969b80bb0be6b9f14f6 + $valid_ip_start = ip2long('192.168.1.0'); + $valid_ip_end = ip2long('192.168.1.255'); ?> \ No newline at end of file diff --git a/web/graphs.php b/web/graphs.php index dfc7450..850d9d7 100644 --- a/web/graphs.php +++ b/web/graphs.php @@ -8,7 +8,7 @@ @@ -16,12 +16,37 @@ include('config_local.php'); +$client_ip = $_SERVER["REMOTE_ADDR"]; + +if ((strpos($client_ip, "192.168.") === 0) || (strpos($client_ip, "10.8.") === 0) + || (strpos($client_ip, "2a02:578:5002:8174:") === 0) + || (strpos($client_ip, "2a02:578:5002:196::2") === 0)) { + + $local_net = True; + +} else { + + $local_net = False; + +} + + if (! ($db = new PDO("mysql:host=$mysql_host;port=$mysql_port;dbname=$mysql_schema",$mysql_user,$mysql_pwd,array( PDO::ATTR_PERSISTENT => false)))) { die($err); } $db -> exec('SET CHARACTER SET utf8'); +if (!$local_net) { + + $filter = ' and s.is_public=1'; + +} else { + + $filter = ''; + +} + $q = $db -> prepare( 'select distinct v.sensor_id,s.s_description,p.id as param_id,p.st_description @@ -31,7 +56,7 @@ $q = $db -> prepare( v.timestamp>adddate(now(), -1) and v.sensor_id=s.id and s.st_id=p.st_id - and p.id>=0 + and p.id>=0'.$filter.' order by s_description,st_description' ); $q -> execute(); diff --git a/web/image.php b/web/image.php index 16fbafb..9b6ca84 100644 --- a/web/image.php +++ b/web/image.php @@ -1,6 +1,6 @@ false)))) { - die('Не могу подключиться к БД'); + die('Не могу подключиться к БД'); } @@ -65,12 +65,13 @@ if ($type and $param) { } $q = $db -> prepare( - 'select u.name_short from units u where u.id='.$to_unit + 'select u.name_short,u.prec from units u where u.id='.$to_unit ); $q -> execute(); while ($row = $q -> fetch(PDO::FETCH_ASSOC)) { $param_unit = $row['name_short']; + $precision = $row['prec']; } $xdata = array(); @@ -198,18 +199,24 @@ if ($type and $param) { $g->xaxis->HideLabels(True); } $g->xaxis->SetPos("min"); + $g->yaxis->SetLabelFormat("%0.".$precision."f"); # $g->xaxis->scale->SetTimeAlign( HOURADJ_1 ); - // We use a scatterplot to illustrate the original - // contro points. - $splot = new ScatterPlot($ydata,$xdata); - $g->Add($splot); - // - $splot->mark->SetFillColor($dot_color); - $splot->mark->SetColor($dot_color); - $splot->mark->SetType(MARK_FILLEDCIRCLE); - $splot->mark->SetSize(2); + if ($type!="last24small") { + + // We use a scatterplot to illustrate the original + // contro points. + $splot = new ScatterPlot($ydata,$xdata); + $g->Add($splot); + + // + $splot->mark->SetFillColor($dot_color); + $splot->mark->SetColor($dot_color); + $splot->mark->SetType(MARK_FILLEDCIRCLE); + $splot->mark->SetSize(2); + + } $fplot = new LinePlot($f_ydata,$xdata); $g->Add($fplot); @@ -234,7 +241,7 @@ if ($type and $param) { } else { header("Content-Type: text/html; charset=UTF-8"); - die('Сенсор не выбран!'); + die('Сенсор не выбран!'); } diff --git a/web/image_minmax.php b/web/image_minmax.php index dfa66d2..edc1708 100644 --- a/web/image_minmax.php +++ b/web/image_minmax.php @@ -48,8 +48,7 @@ if ($type and $param) { } $q = $db -> prepare( - 'select st.st_fill_color_top,st.st_fill_color_bottom,st.st_description,u.id,u.unit_group from st_parameters st,units u where st.id='.$param.' and st.st_unit=u.id -' + 'select st.st_fill_color_top,st.st_fill_color_bottom,st.st_description,u.id,u.unit_group from st_parameters st,units u where st.id='.$param.' and st.st_unit=u.id' ); $q -> execute(); @@ -84,23 +83,27 @@ if ($type and $param) { $next_year = $year; $next_month = $month+1; - if ($month==13) { + if ($month==12) { $next_year++; $next_month=1; - + } $curr = date("Ym"); + $ym=sprintf('%04d%02d',$next_year,$next_month); - if ($curr>$next_year.$next_month) { + if ($curr>$ym) { $cachefilename='meteo.month.'.$sensor.'.'.$param.'.'.$to_unit.'.'.$year.'-'.$month.'.'.$img_format; } + $datestr=sprintf("%04d%02d01",$year,$month); + $nextdatestr=sprintf("%04d%02d01",$next_year,$next_month); + $q = $db -> prepare( - ' + ' select x, unitconv(min(min),'.$from_unit.','.$to_unit.') min_value, @@ -113,14 +116,14 @@ if ($type and $param) { from sensors_ranges where - day>=str_to_date(\''.$year.$month.'\',\'%Y%m\') - and day=STR_TO_DATE(\''.$datestr.'\',\'%Y%m%d\') + and day prepare( ' select @@ -149,8 +155,8 @@ if ($type and $param) { from sensors_ranges where - day>=str_to_date(\''.$year.'\',\'%Y\') - and day=STR_TO_DATE(\''.$datestr.'\',\'%Y%m%d\') + and daygraph_theme = null; diff --git a/web/index.php b/web/index.php index 37251e6..92a8e8e 100644 --- a/web/index.php +++ b/web/index.php @@ -9,7 +9,7 @@