From: Roman Bazalevskiy Date: Tue, 19 May 2015 13:56:17 +0000 (+0300) Subject: Merge branch 'master' of estia:weathermon X-Git-Url: https://git.rvb.name/weathermon.git/commitdiff_plain/2545d27aacfe57c8f26fccfd45e382fbf5c111ac?hp=-c Merge branch 'master' of estia:weathermon --- 2545d27aacfe57c8f26fccfd45e382fbf5c111ac diff --combined Weather_WH2.ino index a61dbff,a61dbff..0000000 deleted file mode 100644,100644 --- a/Weather_WH2.ino +++ /dev/null @@@ -1,435 -1,435 +1,0 @@@ --/* -- Updated code for receiving data from WH2 weather station -- This code implements timeouts to make decoding more robust -- Decodes received packets and writes a summary of each packet to the Arduino's -- serial port -- Created by Luc Small on 19 July 2013. -- Released into the public domain. --*/ -- --#include --#include --#include -- --// DHT11 and BMP085 wired sensors --dht DHT; --BMP085 bmp; -- --// Humidity sensor at pin 4 --#define DHT11PIN 5 --int sensorPin = 0; --#define DEBUG -- --// LED pins --#define REDPIN 11 --#define GREENPIN 12 -- --// Read data from 433MHz receiver on digital pin 3 --#define RF_IN 4 --// For better efficiency, the port is read directly --// the following two lines should be changed appropriately --// if the line above is changed. --#define RF_IN_RAW PIND4 --#define RF_IN_PIN PIND -- --// Port that is hooked to LED to indicate a packet has been received -- --#define COUNTER_RATE 3200-1 // 16,000,000Hz / 3200 = 5000 interrupts per second, ie. 200us between interrupts --// 1 is indicated by 500uS pulse --// wh2_accept from 2 = 400us to 3 = 600us --#define IS_HI_PULSE(interval) (interval >= 2 && interval <= 3) --// 0 is indicated by ~1500us pulse --// wh2_accept from 7 = 1400us to 8 = 1600us --#define IS_LOW_PULSE(interval) (interval >= 7 && interval <= 8) --// worst case packet length --// 6 bytes x 8 bits x (1.5 + 1) = 120ms; 120ms = 200us x 600 --#define HAS_TIMED_OUT(interval) (interval > 600) --// we expect 1ms of idle time between pulses --// so if our pulse hasn't arrived by 1.2ms, reset the wh2_packet_state machine --// 6 x 200us = 1.2ms --#define IDLE_HAS_TIMED_OUT(interval) (interval > 6) --// our expected pulse should arrive after 1ms --// we'll wh2_accept it if it arrives after --// 4 x 200us = 800us --#define IDLE_PERIOD_DONE(interval) (interval >= 4) --// Shorthand for tests --//#define RF_HI (digitalRead(RF_IN) == HIGH) --//#define RF_LOW (digitalRead(RF_IN) == LOW) --#define RF_HI (bit_is_set(RF_IN_PIN, RF_IN_RAW)) --#define RF_LOW (bit_is_clear(RF_IN_PIN, RF_IN_RAW)) -- --// wh2_flags --#define GOT_PULSE 0x01 --#define LOGIC_HI 0x02 --volatile byte wh2_flags = 0; --volatile byte wh2_packet_state = 0; --volatile int wh2_timeout = 0; --byte wh2_packet[5]; --byte wh2_calculated_crc; -- -- --#ifdef DEBUG --byte printed = 0; --#endif -- --ISR(TIMER1_COMPA_vect) --{ -- static byte sampling_state = 0; -- static byte count; -- static boolean was_low = false; -- -- switch(sampling_state) { -- case 0: // waiting -- wh2_packet_state = 0; -- if (RF_HI) { -- if (was_low) { -- count = 0; -- sampling_state = 1; -- was_low = false; -- } -- } else { -- was_low = true; -- } -- break; -- case 1: // acquiring first pulse -- count++; -- // end of first pulse -- if (RF_LOW) { -- if (IS_HI_PULSE(count)) { -- wh2_flags = GOT_PULSE | LOGIC_HI; -- sampling_state = 2; -- count = 0; -- } else if (IS_LOW_PULSE(count)) { -- wh2_flags = GOT_PULSE; // logic low -- sampling_state = 2; -- count = 0; -- } else { -- sampling_state = 0; -- } -- } -- break; -- case 2: // observe 1ms of idle time -- count++; -- if (RF_HI) { -- if (IDLE_HAS_TIMED_OUT(count)) { -- sampling_state = 0; -- } else if (IDLE_PERIOD_DONE(count)) { -- sampling_state = 1; -- count = 0; -- } -- } -- break; -- } -- -- if (wh2_timeout > 0) { -- wh2_timeout++; -- if (HAS_TIMED_OUT(wh2_timeout)) { -- wh2_packet_state = 0; -- wh2_timeout = 0; --#ifdef DEBUG -- if (printed) { -- Serial1.println(); -- printed=0; -- } --#endif -- } -- } --} -- --void setup() { -- -- Serial1.begin(115200); // Set the baud. -- -- // Wait for U-boot to finish startup. Consume all bytes until we are done. -- do { -- while (Serial1.available() > 0) { -- Serial1.read(); -- } -- -- delay(1000); -- } while (Serial1.available()>0); -- -- Serial1.begin(57600); -- Serial1.println(); -- Serial1.println("STATUS:STARTING"); -- -- bmp.begin(); -- -- pinMode(REDPIN,OUTPUT); -- pinMode(GREENPIN,OUTPUT); -- -- pinMode(RF_IN, INPUT); -- digitalWrite(RF_IN,HIGH); -- -- TCCR1A = 0x00; -- TCCR1B = 0x09; -- TCCR1C = 0x00; -- OCR1A = COUNTER_RATE; -- TIMSK1 = 0x02; -- -- // enable interrupts -- sei(); --} -- --unsigned long previousMillis = 0; --unsigned long indoor_interval = 60000; --unsigned long outdoor_interval = 45000; --unsigned long previousIndoor = 0; --unsigned long previousOutdoor = 0; -- --float temperature; --float pressure; -- --void loop() { -- unsigned long now; -- int gas = 0; -- byte i; -- -- now = millis(); -- -- if (wh2_flags) { -- if (wh2_accept()) { -- // calculate the CRC -- wh2_calculate_crc(); -- -- if (wh2_valid()) { -- -- Serial1.println(); -- Serial1.print("SENSOR:TYPE=OUTDOOR,"); -- -- Serial1.print("ID="); -- Serial1.print(wh2_sensor_id(), HEX); -- -- Serial1.print(",HUMIDITY="); -- Serial1.print(wh2_humidity(), DEC); -- -- Serial1.print(",TEMPERATURE="); -- Serial1.println(format_temp(wh2_temperature())); -- -- previousOutdoor = now; -- digitalWrite(REDPIN,HIGH); -- -- } else { -- -- Serial1.println(); -- Serial1.println("ERROR:OUTDOOR"); -- previousOutdoor = now; -- digitalWrite(REDPIN,LOW); -- -- } -- -- } -- wh2_flags = 0x00; -- } -- -- if ((unsigned long)(now - previousMillis) >= indoor_interval) { -- -- previousMillis = now; -- -- int chk = DHT.read11(DHT11PIN); -- -- if (chk==0) { -- -- Serial1.println(); -- Serial1.print("SENSOR:TYPE=INDOOR,"); -- Serial1.print("HUMIDITY="); -- Serial1.print(DHT.humidity); -- Serial1.print(",TEMPERATURE="); -- Serial1.print(DHT.temperature); -- -- previousIndoor = now; -- digitalWrite(GREENPIN,HIGH); -- -- -- } else { -- -- Serial1.println(); -- Serial1.println("ERROR:INDOOR"); -- previousIndoor = now; -- digitalWrite(GREENPIN,LOW); -- -- } -- -- pressure=bmp.readPressure(); -- temperature=bmp.readTemperature(); -- Serial1.println(); -- Serial1.print("SENSOR:TYPE=BARO,"); -- Serial1.print("PRESSURE="); -- Serial1.print(pressure); -- Serial1.print(",TEMPERATURE="); -- Serial1.println(temperature); -- -- gas = analogRead(sensorPin); // Получаем значения из датчика -- Serial1.print("SENSOR:TYPE=GAS,VALUE="); -- Serial1.println(gas); // Пишем в серийный порт -- -- } -- -- if ((unsigned long)(now - previousIndoor) > indoor_interval*10) { -- -- Serial1.println(); -- Serial1.println("ERROR:INDOOR TIMEOUT"); -- previousIndoor = now; -- digitalWrite(GREENPIN,LOW); -- -- } -- -- if ((unsigned long)(now - previousOutdoor) > outdoor_interval*10) { -- -- Serial1.println(); -- Serial1.println("ERROR:OUTDOOR TIMEOUT"); -- previousOutdoor = now; -- digitalWrite(REDPIN,LOW); -- -- } -- -- --} -- -- --// processes new pulse --boolean wh2_accept() --{ -- static byte packet_no, bit_no, history; -- -- // reset if in initial wh2_packet_state -- if(wh2_packet_state == 0) { -- // should history be 0, does it matter? -- history = 0xFF; -- wh2_packet_state = 1; -- // enable wh2_timeout -- wh2_timeout = 1; -- } // fall thru to wh2_packet_state one -- -- // acquire preamble -- if (wh2_packet_state == 1) { -- // shift history right and store new value -- history <<= 1; -- // store a 1 if required (right shift along will store a 0) -- if (wh2_flags & LOGIC_HI) { -- history |= 0x01; -- } -- // check if we have a valid start of frame -- // xxxxx110 -- if ((history & B00000111) == B00000110) { -- // need to clear packet, and counters -- packet_no = 0; -- // start at 1 becuase only need to acquire 7 bits for first packet byte. -- bit_no = 1; -- wh2_packet[0] = wh2_packet[1] = wh2_packet[2] = wh2_packet[3] = wh2_packet[4] = 0; -- // we've acquired the preamble -- wh2_packet_state = 2; -- } -- return false; -- } -- // acquire packet -- if (wh2_packet_state == 2) { -- -- wh2_packet[packet_no] <<= 1; -- if (wh2_flags & LOGIC_HI) { -- wh2_packet[packet_no] |= 0x01; --#ifdef DEBUG -- Serial1.print('1'); -- printed=1; -- } else { -- Serial1.print('0'); -- printed=1; --#endif -- } -- -- bit_no ++; -- if(bit_no > 7) { -- bit_no = 0; -- packet_no ++; -- } -- -- if (packet_no > 4) { -- // start the sampling process from scratch -- wh2_packet_state = 0; -- // clear wh2_timeout -- wh2_timeout = 0; -- return true; -- } -- } -- return false; --} -- -- --void wh2_calculate_crc() --{ -- wh2_calculated_crc = crc8(wh2_packet, 4); --} -- --bool wh2_valid() --{ -- return (wh2_calculated_crc == wh2_packet[4]); --} -- --int wh2_sensor_id() --{ -- return (wh2_packet[0] << 4) + (wh2_packet[1] >> 4); --} -- --byte wh2_humidity() --{ -- return wh2_packet[3]; --} -- --/* Temperature in deci-degrees. e.g. 251 = 25.1 */ --int wh2_temperature() --{ -- int temperature; -- temperature = ((wh2_packet[1] & B00000111) << 8) + wh2_packet[2]; -- // make negative -- if (wh2_packet[1] & B00001000) { -- temperature = -temperature; -- } -- return temperature; --} -- --String format_temp(int temperature) --{ -- byte whole, partial; -- String s; -- s = String(); -- if (temperature<0) { -- temperature = -temperature; -- s += String('-'); -- } -- -- whole = temperature / 10; -- partial = temperature - (whole*10); -- -- s += String(whole, DEC); -- s += '.'; -- s += String(partial, DEC); -- -- return s; -- --} -- --uint8_t crc8( uint8_t *addr, uint8_t len) --{ -- uint8_t crc = 0; -- -- // Indicated changes are from reference CRC-8 function in OneWire library -- while (len--) { -- uint8_t inbyte = *addr++; -- for (uint8_t i = 8; i; i--) { -- uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01 -- crc <<= 1; // changed from right shift -- if (mix) crc ^= 0x31;// changed from 0x8C; -- inbyte <<= 1; // changed from right shift -- } -- } -- return crc; --} -- -- -- -- -- -- -- -- -- diff --combined weathermon index 66d6ac4,68798a1..0000000 deleted file mode 100755,100755 --- a/weathermon +++ /dev/null @@@ -1,314 -1,414 +1,0 @@@ --#!/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/' - baud = 57600 --path = None - timeout = 5 -baud = None -timeout = None - -proc = None -- --external_submit_interval = 320 --owm_submit_interval = 320 --expire_interval = 1200 --submit_time = time() --submit_time_owm = time() - submit_queue = {} -- --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): -- - ser = serial.Serial(path,baud,timeout) - global proc - - print "Opening path "+path - - if path == "-": - return sys.stdin - - if path[0] == "=": - import subprocess - 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): -- - line = ser.readline() - return line.strip() - try: - timeout_timer = Timer(timeout, thread.interrupt_main) - timeout_timer.start() - line = ser.readline() - return line.strip() - except KeyboardInterrupt: - return "<>" - finally: - timeout_timer.cancel() -- --def read_loop(ser,callback): - - global proc -- -- while True: -- -- try: -- line=read_port(ser) - if line=="<>": - print "Reopening port..." - ser.close() - if proc: - print "Terminating process..." - proc.terminate() - sleep(5) - ser=open_port(path) -- if line: -- callback(line) -- except KeyboardInterrupt: -- break -- finally: -- None -- --def print_log(str): -- global logging -- print str -- if logging == "on": -- system("logger -t weathermon \""+str+"\"") -- - def submit_narodmon(queue): -def submit_narodmon(): -- - param = { 'ID':"{:X}".format(getnode())} - 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() -- -- pprint(queue) -- - for sensor in queue: - value = submit_queue[sensor]['val'] - timestamp = submit_queue[sensor]['timestamp'] - digest = md5(sensor).hexdigest()[:18] - param[digest] = value; - - for (sensor,value) in queue: - param[sensor] = value -- 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(queue): -def submit_owm(): -- -- url = "http://openweathermap.org/data/post" -- params = {'name':owm_station, 'lat':owm_lat, 'long':owm_lon} -- - try: - 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 - ''' - ) -- - try: - params['temp'] = queue[owm_temp]['val'] - params['pressure'] = queue[owm_pres]['val'] - params['humidity'] = queue[owm_humi]['val'] - except: - return False - queue=c.fetchall() - - pprint(queue) - - for (sensor,value) in queue: - params[sensor]=value - 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 purge_queue(): - global submit_queue - clean = [] - for key in submit_queue: - if submit_queue[key]['timestamp'] < time()-expire_interval: - print_log("Expired value for "+key) - clean.append(key) - for i in clean: - del submit_queue[i] - --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 - global submit_queue -- c = database.cursor() -- c.execute('CALL meteo.submit_value(%s,%s,%s,%s,NULL)', (sensor_type,sensor_id,sensor_param,param_value)) -- database.commit() - submit_queue[sensor_type+'.'+sensor_id+'.'+sensor_param]={'val':param_value,'timestamp':time()} - if time()>submit_time+external_submit_interval: - submit_narodmon(submit_queue) - 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_queue) - submit_time_owm=time() - purge_queue() - - 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='DEFAULT'; - 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() -- --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: -- 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 - owmuser = cfg.get("openweathermap","user") - owmpasswd = cfg.get("openweathermap",'passwd') - 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') -- main() diff --combined web/config_local.php index 9c9adb2,00afede..0000000 deleted file mode 100644,100644 --- a/web/config_local.php +++ /dev/null @@@ -1,11 -1,14 +1,0 @@@ --