from socket import *
import serial
import time
import thread
import pickle
from kid_data import *

#Can be Downloaded from this Link
#https://pypi.python.org/pypi/pyserial

#Global Variables


#Kid Server port
port = 50008

#Kid Serial Port
kid_serial_port = '/dev/ttyUSB0'

#Debug Serial Port
debug_serial_port = '/dev/ttyUSB1'

# Register mask
PK_TYPE_SET_mask=0b10000000
PK_TYPE_GET_mask=0b11000000
register_mask = 0b00111111 


class KidServer:
    def __init__(self,no):
        self.no = no
        self.k_data = KidData()
        self.ser = 0
        self.sock = socket(AF_INET, SOCK_STREAM)        

        print("KidServer %d" % self.no)
    
    def init_serial(self):        
        self.ser = serial.Serial()
        self.ser.baudrate = 57200
        self.ser.parity=serial.PARITY_NONE
        self.ser.bytesize=serial.EIGHTBITS
        self.ser.stopbits=serial.STOPBITS_ONE
        self.ser.port = kid_serial_port
        self.ser.open()          #Opens SerialPort
        # print port open or closed
        if self.ser.isOpen():
            print 'Open: ' + self.ser.portstr

    def init_server(self):
        self.sock.bind(('', port))
        self.sock.listen(5)
        
    def now(self):
        return time.ctime(time.time())        
    
    def handleClient(self,connection):
        print 'handleClient'
        while True:
            self.data = connection.recv(1024)
            if not self.data: break
            if self.data == 'GET':
                print('received GET')
                reply_string = pickle.dumps(self.k_data )
                self.writeserialdata(COMM_vPV)                
#                self.writeserialdata(COMM_batteryTemp)
                self.writeserialdata(COMM_fetTEMP)
                self.writeserialdata(COMM_KWH)                
                # print reply_string
                
                connection.send(reply_string)
            else:
                reply = 'Echo=>%s at %s' % (self.data, self.now())            
                print('Server reply : %s' % reply)                        
                connection.send(reply.encode())
        print('handleClient finish...')

    def writeserialdata(self, register):
        print('writeserialdata')
        b_array = bytearray('1234')
        register_data = PK_TYPE_GET_mask
        b_array[0] = register_data | register
        b_array[1] = 0
        b_array[2] = 0

        chk_xor=0
        for i in range(0,3):
            for j in range(0,4):
                bits_to_xor = (b_array[i] >> (j*2)) & 3
                chk_xor = chk_xor ^ bits_to_xor
        b_array[3] = chk_xor
        
        print b_array[0], b_array[1], b_array[2], b_array[3]
        print len(b_array)
        self.ser.write(b_array)         #Writes to the SerialPort
        
         
    def readserialdata(self):
        print('Start Reading Serial Data...')
        to_add=0
        while 1:    
            tt = int(time.time()) # tt - time in seconds
            bytes = self.ser.read(4)   # Read the first byte from Serial Port
            b_array = bytearray(bytes)

#            b_array[0] = b_array[0] & 1
            chk_xor=0
            for i in range(0,4):
                for j in range(0,4):
                    bits_to_xor = (b_array[i] >> (j*2)) & 3
                    chk_xor = chk_xor ^ bits_to_xor 
            if chk_xor == 0:
                print ('chk_xor: Ok')
            else:
                print ('chk_xor: Not Ok')                  
                         
            if (b_array[0] & PK_TYPE_SET_mask) and (chk_xor==0):  # if first byte type is PK_TYPE_SET
                register_name = b_array[0] & register_mask                                 
                register_data = b_array[1] << 8
                register_data = register_data | b_array[2]        
                if register_name == COMM_batteryTemp:
                    self.k_data.comm_battery_temp=register_data
                    print "COMM_batteryTemp (deg. C)"
                    print register_data
                elif register_name == COMM_batteryStage:
                    self.k_data.comm_battery_stage=register_data
                    print "COMM_batteryStage"
                    if register_data == 0:
                        print "Resting"
                    elif register_data == 3:
                        print "Absorb"
                    elif register_data == 4:
                        print "BulkMPPT"
                    elif register_data == 5:
                        print "Float"
                    elif register_data == 6:
                        print "FloatMPPT"
                elif register_name == COMM_absorbV:
                    self.k_data.comm_absorb_v = float(register_data)/10
                    print "COMM_absorbV (V)"                  
                    print float(register_data)/10                  
                elif register_name == COMM_floatV:
                    self.k_data.comm_float_v = float(register_data)/10  
                    print "COMM_floatV (V)"
                    print float(register_data) /10
                elif register_name == COMM_eqV:
                    self.k_data.comm_eq_v = float(register_data) / 10                     
                    print "COMM_eqV (V)"
                    print float(register_data) / 10
                elif register_name == COMM_TempCompV:
                    self.k_data.comm_temp_comp_v = register_data
                    print "COMM_TempCompV (mV)"
                    print register_data
                elif register_name == COMM_BattNominal:
                    self.k_data.comm_batt_nominal = register_data
                    print "COMM_BattNominal (V)"
                    print register_data
                elif register_name == COMM_vBATT:
                    self.k_data.comm_v_batt = float(register_data) / 10
                    print "COMM_vBATT (V)"
                    print float(register_data) / 10
                elif register_name == COMM_absorbT:
                    self.k_data.comm_absorb_t = register_data
                    print "COMM_absorbT (minutes)"
                    print register_data
                elif register_name == COMM_EqT:
                    self.k_data.comm_eq_t = register_data
                    print "COMM_EqT (minutes)"
                    print register_data
                elif register_name == COMM_vPV:
                    self.k_data.comm_v_pv = float(register_data) / 10
                    print "COMM_vPV"
                    print float(register_data)/10
                elif register_name == COMM_KWH:
                    self.k_data.comm_kwh = float(register_data)
                    print "COMM_KWH"
                    print float(register_data)
                elif register_name == COMM_fetTEMP:
#                    self.k_data.comm_kwh = float(register_data)
                    print "COMM_fetTEMP"
                    print float(register_data)
                 
#                d_tt=int(time.time()) - tt 
#            
#                if d_tt > 5:
#                  line = time.strftime('%X')
#                  line = line + "  " + ':'.join('{:02x}'.format(ord(c)) for c in bytes)
#                  to_add= to_add + 1
#            
#                elif to_add > 0:      
#                  line = line + "  " + ':'.join('{:02x}'.format(ord(c)) for c in bytes)
#                  to_add= to_add + 1      
#            
#                if to_add == 10:
#                  print line
#                  to_add=0
                  

    def dispatcher(self):
        thread.start_new_thread(self.readserialdata, () )
        while True:
            print('Waiting for client connection...')
            connection, address = self.sock.accept()
            print('Server connected by ', address)
            print('at', self.now())
            thread.start_new_thread(self.handleClient, (connection,))

#Call the Serial Initilization Function, Main Program Starts from here


#temp = raw_input('Type what you want to send, hit enter:\r\n')
#ser.write(temp)         #Writes to the SerialPort
if __name__ == '__main__': 
    kidserver = KidServer(1)
    kidserver.init_serial()
    kidserver.init_server()
    kidserver.dispatcher()

