#!/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()