Merge branch 'master' of estia:weathermon
authorRoman Bazalevskiy <rvb@rvb.name>
Tue, 19 May 2015 13:56:17 +0000 (16:56 +0300)
committerRoman Bazalevskiy <rvb@rvb.name>
Tue, 19 May 2015 13:56:17 +0000 (16:56 +0300)
Weather_WH2.ino [deleted file]
weathermon [deleted file]
weathermon-light [new file with mode: 0755]
weathermon.lua [new file with mode: 0755]
weathermon.sh [new file with mode: 0755]
weathermon.uci [new file with mode: 0644]
web/config_local.php [deleted file]
web/send.php [new file with mode: 0644]

diff --git a/Weather_WH2.ino b/Weather_WH2.ino
deleted file mode 100644 (file)
index a61dbff..0000000
+++ /dev/null
@@ -1,435 +0,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 <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;
-}
-
-
-
-
-
-
-
-
-
diff --git a/weathermon b/weathermon
deleted file mode 100755 (executable)
index 66d6ac4..0000000
+++ /dev/null
@@ -1,314 +0,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
-
-external_submit_interval = 320
-owm_submit_interval = 320
-expire_interval = 1200
-submit_time = time()
-submit_time_owm = time()
-submit_queue = {}
-
-import MySQLdb
-import ConfigParser
-
-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)
-  if ser.portstr:
-    tcflush(ser,TCIOFLUSH);
-  return ser
-  
-def read_port(ser):
-
-  line = ser.readline()
-  return line.strip()
-  
-def read_loop(ser,callback):
-
-  while True:
-  
-    try:
-      line=read_port(ser)
-      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):
-
-  param = { 'ID':"{:X}".format(getnode())}
-
-  pprint(queue)
-
-  for sensor in queue:
-    value = submit_queue[sensor]['val']
-    timestamp = submit_queue[sensor]['timestamp']
-    digest = md5(sensor).hexdigest()[:18]
-    param[digest] = 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):
-
-  url = "http://openweathermap.org/data/post"
-  params = {'name':owm_station, 'lat':owm_lat, 'long':owm_lon}
-
-  try:
-
-    try:
-      params['temp'] = queue[owm_temp]['val']
-      params['pressure'] = queue[owm_pres]['val']
-      params['humidity'] = queue[owm_humi]['val']
-    except:
-      return False  
-
-    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)
-    submit_time=time()
-  if owmuser and time()>submit_time_owm+owm_submit_interval:
-    submit_owm(submit_queue)
-    submit_time_owm=time()
-  purge_queue()
-        
-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';    
-      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)
-  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')
-  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')
-  reconnect()
-except:
-
-  print_log("Cannot intialize system")
-  exit() 
-  
-if __name__ == "__main__":
-  import sys
-  reload(sys)
-  sys.setdefaultencoding('utf-8')
-  main()
diff --git a/weathermon-light b/weathermon-light
new file mode 100755 (executable)
index 0000000..1827377
--- /dev/null
@@ -0,0 +1,209 @@
+#!/usr/bin/python
+
+import serial
+
+from os import system
+
+from pprint import pprint
+
+from termios import tcflush, TCIOFLUSH
+
+from time import sleep
+
+from uuid import getnode
+
+import sys,traceback
+
+import pycurl
+from urllib import urlencode
+from StringIO import StringIO
+
+path = None
+baud = None
+timeout = None
+
+import ConfigParser
+
+import thread
+from threading import Timer
+
+def open_port(path):
+
+  global proc
+
+  print "Opening path "+path
+
+  ser = serial.Serial(path,1200);
+  ser.open();
+  ser.close();
+
+  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 = 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()
+        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_data(stype,sid,param,value):
+
+  global url,username,password
+
+  params = {'stype':stype, 'sid':sid, 'param':param, 'value':value}
+
+  pprint (params)
+
+  try:
+
+    response_buffer = StringIO()
+    curl = pycurl.Curl()
+
+    curl.setopt(curl.URL, url)
+    if username:
+      curl.setopt(curl.USERPWD, '%s:%s' % (username, password))
+    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('Server 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 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)
+  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)  
+
+def weather_mon():
+
+  global path
+
+  ser = open_port(path)
+  read_loop(ser,process_str)
+
+def main():
+  weather_mon()
+
+try:
+
+  cfg = ConfigParser.RawConfigParser(allow_no_value=True)
+  cfg.readfp(open('/etc/weathermon.conf'))
+  url = cfg.get("web","url")
+  path = cfg.get("serial","port");
+  try:
+    username = cfg.get("web","user");
+    password = cfg.get("web","password");
+  except:
+    username = None
+    password = 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:
+    devid = cfg.get("web","devid")
+  except:
+    devid = "{:0>12X}".format(getnode())   
+except:
+
+  print_log("Cannot intialize system")
+  exit() 
+  
+if __name__ == "__main__":
+  import sys
+  reload(sys)
+  sys.setdefaultencoding('utf-8')
+  main()
diff --git a/weathermon.lua b/weathermon.lua
new file mode 100755 (executable)
index 0000000..20f5aca
--- /dev/null
@@ -0,0 +1,124 @@
+#!/usr/bin/lua
+
+function getConfig()
+
+  local uci=require("uci")
+  local cur=uci.cursor()
+  local config="weathermon"
+
+  web_url  = cur.get(config,"web","url")
+  web_user = cur.get(config,"web","user")
+  web_pass = cur.get(config,"web","password")
+  web_devid = cur.get(config,"web","devid")
+  
+  io.input("/sys/class/net/eth0/address")
+  mac = io.read("*line")
+  mac = mac:gsub(":","")
+  mac = mac:upper()
+
+  web_devid = web_devid or mac
+
+  logging = cur.get(config,"logging","enabled") 
+
+end
+
+require "socket"
+
+function sleep(sec)
+  socket.select(nil, nil, sec)
+end
+
+function splitStr(str,char)
+
+  local res = {}
+  local idx = 1
+
+
+  while str:len()>0 do
+    pos = str:find(char); 
+    if pos == nil then
+      res[idx]=str
+      str=""
+    else
+      res[idx]=str:sub(1,pos-1)
+      idx=idx+1
+      str=str:sub(pos+1)
+    end
+  end
+
+  return res
+
+end
+
+function printLog(str)
+  print(str)
+  if logging=="on" then
+    os.execute("logger -t weathermon "..str)
+  end 
+end
+
+function submitValue(type,id,param,val)
+
+  printLog("URL="..web_url)
+
+  url = web_url.."?stype="..type.."&sid="..id.."&param="..param.."&value="..val
+
+  printLog(url)
+
+  command = "curl"
+
+  if web_user then
+    command = command.." -u "..web_user..":"..web_pass
+  end
+
+  command = command.." \""..url.."\""
+
+  printLog("COMMAND=\""..command.."\"")
+  os.execute(command)
+  print("")
+
+end
+
+function processLine(str)
+
+  msg=splitStr(line,':')
+  msg_type=msg[1] or nil
+  msg_body=msg[2] or nil
+  if msg_type=="STATUS" then
+    printLog("Status: "..msg_body)
+  elseif msg_type=="ERROR" then
+    printLog("Error: "..msg_body)  
+  elseif msg_type=="SENSOR" then
+    printLog("SENSOR: "..msg_body)  
+    sens = splitStr(msg_body,",")
+    sensor = {}
+    idx = 1
+    sensor_type = nil
+    sensor_id = web_devid
+    for i,rec in ipairs(sens) do
+      recrd=splitStr(rec,'=')
+      key=recrd[1] or nil
+      value=recrd[2] or nil
+      if value then
+        if key=="TYPE" then
+          sensor_type=value
+        elseif key=="ID" then
+          sensor_id=value
+        else
+          sensor[key]=value
+        end
+      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)
+    end
+  end
+
+end
+
+getConfig()
+
+line=arg[1]
+print(line)
+processLine(line)
diff --git a/weathermon.sh b/weathermon.sh
new file mode 100755 (executable)
index 0000000..3f42275
--- /dev/null
@@ -0,0 +1,9 @@
+#!/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
new file mode 100644 (file)
index 0000000..490ba91
--- /dev/null
@@ -0,0 +1,12 @@
+config internal 'web'
+       option url http://estia.rvb-home.lan/meteo/send.php
+       option user meteo
+       option password somestrictpassword
+
+config internal 'serial'
+       option port /dev/ttyUSB0
+       option timeout 100
+       option baud 9600
+
+config internal 'logging'
+       option enabled on
diff --git a/web/config_local.php b/web/config_local.php
deleted file mode 100644 (file)
index 9c9adb2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-
-  $mysql_host = 'host';
-  $mysql_schema = 'meteo';
-  $mysql_user = 'meteo';
-  $mysql_pwd = 'somestrictpasswd';
-  $mysql_port = 3306;
-
-  setlocale(LC_ALL,'ru_RU.UTF8');
-                
-?>
\ No newline at end of file
diff --git a/web/send.php b/web/send.php
new file mode 100644 (file)
index 0000000..7a69838
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+    require_once 'config_local.php';
+
+    $client_ip = ip2long($_SERVER["REMOTE_ADDR"]);
+
+    if (!client_ip || $client_ip > $valid_ip_end || $valid_ip_start > $client_ip) {
+      header('HTTP/1.1 403 Forbidden');
+      echo "IP not in allowed range";
+      exit;
+    }
+
+    $stype = $_REQUEST['stype'];
+    $sid   = $_REQUEST['sid'];
+    $param = $_REQUEST['param'];
+    $value = $_REQUEST['value'];
+
+    $connection = new mysqli($mysql_host, $mysql_user, $mysql_pwd, $mysql_schema, $mysql_port);
+    if ($connection->connect_errno) {
+        header('HTTP/1.1 500 Internal Server Error');
+        exit;    
+    }
+        
+    $str = "CALL meteo.submit_value('".$stype."','".$sid."','".$param."',".$value.",NULL)";
+        if (!$connection->query($str)) {
+            header('HTTP/1.1 500 Internal Server Error');
+            exit;    
+        } else {
+            $connection->commit();
+?>        
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Meteo logger</title>
+</head>
+<body>
+OK Logged
+</body>
+</html>
+<?
+    }
+
+?>