# -*- coding:utf-8 -*-
import os, sys, time
import abc
import socket
import json
import numpy as np
import struct

#创建ProHeader数据类型
ProHead = np.dtype({'names': ['version', 'len'], 'formats': ['u1', 'u4']})

class BaseClient(object):
    __metaclass__ = abc.ABCMeta

    def __init__(self):
        """设备id"""
        self.device_id = 0
        '''设备名称'''
        self.device_name = ""
        '''设备命令'''
        self.device_cmd = ""
        '''设备通讯超时值:毫秒'''
        self.device_timeout = 300

        '''通信sock'''
        self.sock = None
        '''通信端口号'''
        self.port = 5566
        '''通信状态'''
        self.constate = False

    def __def__(self):
        self.disconnect()

    '''连接服务器'''
    def connect(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.connect(('127.0.0.1', self.port))  # 没有返回值;
            self.sock.sendall('111')
            self.constate = True
        except Exception, e:
            print "BaseClient=> socket connect error:", e, self.port
            self.constate = False

        return self.constate

    # 发送消息;
    def sendmsg(self):
        '''是否连接'''
        if self.constate is False:
            if self.connect() is False:
                return None

        '''拼装要发送的数据包'''
        msg_json = ""
        msg_dict = {'device_id': self.device_id, 'device_name': self.device_name, "device_cmd": self.device_cmd, "device_timeout": self.device_timeout}
        try:
            msg_json = json.dumps(msg_dict)
        except Exception:
            print "BaseClient=> to json error:", msg_dict
            return None

        '''发送请求数据'''
        try:
            self.sock.settimeout(5)
            phead = np.array([(0xAA, msg_json.__len__() + np.array([(0xAA, 0)], dtype=ProHead).itemsize)], dtype=ProHead)
            '''一次性发送完整包'''
            self.sock.sendall(bytearray(phead.tobytes() + bytes(msg_json)))
            '''分包发送:头、体'''
            # self.sock.sendall(phead.tobytes())
            # self.sock.sendall(bytes(msg_json))
            self.sock.settimeout(None)
        except Exception, e:
            print "BaseClient=> send Error:", e
            self.disconnect()
            self.connect()
            return None
        
        '''接收返回数据'''
        try:
            # 等待数据返回;(串口若请求失败,超时值应该设置在3秒以上)
            self.sock.settimeout(10)
            data = bytes(self.sock.recv(1024 * 8))
            self.sock.settimeout(None)

            phead = data[0: np.array([(0xAA, 0)], dtype=ProHead).itemsize]
            '''小端<I, 大端>I'''
            plen = struct.unpack('<I', phead[1:])[0]
            '''返回头是否有效'''
            if ord(phead[0]) != 0xAB:
                return None
            
            msg_json = data[np.array([(0xAA, 0)], dtype=ProHead).itemsize:]
            if plen - 5 != msg_json.__len__():
                return None
            
            # print msg_json
            msg_json = msg_json.decode('gb2312')
            # 解析成json;
            msg_dict = json.loads(msg_json)
            return msg_dict
        except Exception, e:
            print "BaseClient=> recv Error:", e
            return None

    '''断开连接'''
    def disconnect(self):
        try:
            self.sock.shutdown(2)
            self.sock.close()
        except Exception, e:
            print "BaseClient=> socket disconnect error:", e