+++ /dev/null
--/*
-- 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 <dht.h>
--#include <Wire.h>
--#include <BMP085.h>
--
--// 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;
--}
--
--
--
--
--
--
--
--
--
+++ /dev/null
--#!/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 "<<TIMEOUT>>"
- finally:
- timeout_timer.cancel()
--
--def read_loop(ser,callback):
-
- global proc
--
-- while True:
--
-- try:
-- line=read_port(ser)
- if line=="<<TIMEOUT>>":
- 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()