# -*- coding: utf-8 -*-
"""
    demeter service
    name:device.py 处理设备
    author:rabin
"""
from demeter.core import *
class Device(object):
	type_info = []
	# 新增网关时，增加状态和电源或者其他设备
	def addDeviceByGateway(self, gateway):
		hardware_id = gateway['hardware_id']
		gateway_id = gateway['id']
		farm_id = gateway['farm_id']
		if hardware_id and gateway_id:
			self.add({'hardware_id':hardware_id,'server_id':gateway['server_id']}, '网关状态', farm_id, hardware_id, 5, gateway_id, 0, 0, 0, '2', 0, 0)

			'''
			info = Demeter.service('common').list('device_info', search={'hardware_id':hardware_id})
			if not info:
				# 网关状态
				insert = {}
				insert['farm_id'] = farm_id
				insert['name'] = '网关状态'
				insert['hardware_id'] = hardware_id
				insert['gateway_id'] = gateway_id
				insert['hardware_type'] = 5
				insert['value'] = '2'
				insert['type_id'] = 0
				insert['status'] = False
				Demeter.service('common').update('device_info', None, insert)

				# 电源
				"""
				insert = {}
				insert['farm_id'] = farm_id
				insert['name'] = '电源状态'
				insert['hardware_id'] = hardware_id
				insert['gateway_id'] = gateway_id
				insert['hardware_type'] = 4
				insert['value'] = '0'
				insert['type_id'] = 8
				insert['status'] = False
				Demeter.service('common').update('device_info', None, insert)
				"""
			'''

		if gateway['server_id'] and gateway['product_id']:
			server = Demeter.service('common').one('setting_server', id=gateway['server_id'])
			if server['server_type'] == 2 or server['server_type'] == 3:
				code = Demeter.service('common').list('setting_modbus_code', search={'product_id':gateway['product_id']})
				if code:
					for v in code:
						if v['slave_id']:
							#hardware_type = Demeter.service('core', 'setting').hardware_type(v['oper_type'])
							hardware_type = v['hardware_type']
							device_type_key = v['device_type_key'].split("\r\n")
							j = 0;
							for i in device_type_key:
								device_type = Demeter.service('common').one('setting_device_type', key=i)
								if device_type:
									self.add({'type_id':device_type['id'],'server_id':gateway['server_id']}, device_type['name'], farm_id, 0, hardware_type, gateway_id, device_type['id'], gateway['server_id'], gateway['product_id'], '', v['id'], j)
									j = j + 1
	# 添加设备
	def add(self, where, name, farm_id, hardware_id, hardware_type, gateway_id, type_id, server_id, product_id, value, code_id, code_index):
		info = Demeter.service('common').list('device_info', search=where)
		if not info:
			if hardware_id < 1:
				device = Demeter.service('common').list('device_info', search={'gateway_id':gateway_id}, order='hardware_id desc', limit='0,1')
				if device:
					if '_' in device[0]['hardware_id']:
						temp = device[0]['hardware_id'].split('_')
						hardware_id = int(temp[1]) + 1
					else:
						hardware_id = int(device[0]['hardware_id']) + 1
				else:
					hardware_id = 100001

				hardware_id = 's' + str(server_id) + '_' + str(hardware_id)

			device_info = Demeter.service('common').one('device_info', hardware_id=str(hardware_id))
			if device_info:
				return
			insert = {}
			insert['farm_id'] = farm_id
			insert['name'] = name + '#' + str(hardware_id)
			insert['hardware_id'] = str(hardware_id)
			insert['gateway_id'] = gateway_id
			insert['server_id'] = server_id
			insert['product_id'] = product_id
			insert['hardware_type'] = hardware_type
			insert['value'] = value
			insert['type_id'] = type_id
			insert['status'] = False
			insert['code_id'] = code_id
			insert['code_index'] = code_index
			Demeter.service('common').update('device_info', None, insert)

	# 批量处理开关
	def switchMul(self, value):
		if value['devices']:
			model = Demeter.model('device_info')
			value['devices'] = tuple(eval(value['devices']))
			if value['oper'] == 1:
				switch = 1
			else:
				switch = 2
			# 直到执行成功才执行下一个
			for v in value['devices']:
				feedback = self.switch(v, switch)
				if feedback:
					state = False
					while state == False:
						state = self.switchCheck(v)

	# 验证按钮执行状态 1为成功了
	def switchCheck(self, device_id):
		model = Demeter.model('device_info')
		model.id = device_id
		#model.exp = '1'
		model.exp.nq('-1')
		info = model.select(type='fetchone')
		if info:
			return True
		return False


	# 处理开关-向设备发送请求
	def switch(self, device_id, switch=1, mul=False, queue=False):
		model = Demeter.model('device_info')
		model.id = device_id
		info = model.select(type='fetchone')
		# 如果有批量控制，还要保存mul的id
		if mul:
			queue_model = Demeter.model('device_mul_queue')
			queue_model.mul_id = mul
			queue_model.device_id = info['id']
			queue_model.status = 1
			queue_model.value = switch
			if info['inorder']:
				queue_model.inorder = info['inorder']
			else:
				queue_model.inorder = 100
			queue_model.udate = info['udate']
			queue_model.hardware_id = info['hardware_id']
			queue_model.insert()
			return
		
		if info and info['status'] == True:
			"""
			if queue:
				oper = self.msg(info['type_id'], switch)
				queue_model = Demeter.model('device_mul_queue')
				queue_model.id = queue
				queue_model.update(oper='正在' + oper + info['name'])
			"""
			# 设置为loading状态,cxnum保存当前的值
			model.id = device_id
			model.update(exp='-1', cxnum=switch, oper=True, operdate=Demeter.time())

			model = Demeter.model('device_gateway')
			model.id = info['gateway_id']
			gateway_info = model.select(type='fetchone')

			if info['type_id'] > 0:
				model = Demeter.model('setting_device_type')
				model.id = info['type_id']
				type_info = model.select(type='fetchone')
				if type_info:
					info['hardware_id'] = str(info['hardware_id'])
					switch = str(switch)
					gateway_info['hardware_id'] = str(gateway_info['hardware_id'])
					
					feedback = self.send(type_info, gateway_info, info, switch)

					return feedback
		else:
			msg = self.notice('offline')
			model.id = device_id
			model.update(exp=msg, cxnum=switch, oper=True, operdate=Demeter.time())
			self.mul(info, info['name'] + '失败:' + msg, False)
			#Demeter.error('offline')
		return ''

	# 处理开关-响应
	def switchAction(self, param, client, userdata, mid, msg='ok'):
		info = param['info']
		if info and info['status'] == True:
			param['switch'] = info['cxnum']
			model = Demeter.model('device_gateway')
			model.id = info['gateway_id']
			gateway = model.select(type='fetchone')

			if msg == 'ok':
				model = Demeter.model('device_info')
				model.id = info['id']
				model.update(value=param['switch'], exp='1', oper=False, operdate=Demeter.time())

				# 如果有批量控制
				self.mul(info, info['name'] + '成功', True)
			else:
				msg = self.notice(msg)
				model = Demeter.model('device_info')
				model.id = info['id']
				model.update(exp=msg, oper=True, operdate=Demeter.time())

				# 如果有批量控制
				self.mul(info, info['name'] + '失败:' + msg, False)
				oper = self.msg(info['type_id'], param['switch'])
				content = oper + gateway['name'] + '下的'+ info['name'] + '失败，错误提示：' + msg
				Demeter.service('record').msg(info['id'], content, info['farm_id'], 3)

				#Demeter.error(msg)

	def notice(self, msg):
		model = Demeter.model('notice_type')
		model.key = msg
		info = model.select(type='fetchone')
		if info:
			msg = info['name']
		return msg

	def msg(self, type_id, switch):
		oper = ''
		type_model = Demeter.model('setting_device_type')
		type_model.id = type_id
		type_info = type_model.select(type='fetchone')
		if type_info['unit'] == 'button':
			if switch == 1:
				oper = '升起'
			elif switch == 2:
				oper = '降下'
			elif switch == 5:
				oper = '停止'
		else:
			if switch == 1:
				oper = '开启'
			else:
				oper = '关闭'
		return oper

	def mul(self, info, msg, state):
		model = Demeter.model('device_mul_queue')
		mul_model = Demeter.model('device_mul')
		model.device_id = info['id']
		model.status = 1
		queue = model.select()

		if queue:
			for v in queue:
				model.status = 1
				model.device_id = info['id']
				oper = self.msg(info['type_id'], v['value']) + msg
			if state:
				model.update(status=2, oper=oper, operdate=Demeter.time())
			else:
				model.update(status=3, oper=oper, operdate=Demeter.time())

	def save(self, config, value, name='', device_type=None):
		model = Demeter.model('device_gateway')
		model.hardware_id = config['parent']
		gateway = model.select(type='fetchone')
		if gateway:
			#更新网关状态
			self.gateway(config['parent'], gateway['farm_id'], gateway['id'])
			model_type = Demeter.model('hardware_type')
			model_type.key = config['method']
			hard = model_type.select(type='fetchone')
			model = Demeter.model('device_info')
			model.hardware_id = config['child']
			model.hardware_type = hard['id']
			device = model.select(type='fetchone')
			if device:
				model.id = device['id']
				if config['method'] == 'control' and (value == '0' or value == 0):
					model.update(status=True, cdate='time')
					return
				#update
				id = device['id']
				if config['method'] == 'sensor' or config['method'] == 'power':
					value = Demeter.exp(device['exp'], value)
				if config['method'] == 'control':
					model.update(exp='1', value=value,status=True,cdate='time',oper=False, operdate=Demeter.time())
				else:
					model.update(value=value,status=True,cdate='time')
				# 上下限判断
				# 条件判断
				if device['type_id'] > 0 and (hard['id'] == 2 or hard['id'] == 4):
					value = float(value)
					content = ''
					if device['max']:
						if value > device['max']:
							if device['cxtype'] == 1:
								if device['cxnum']:
									device['cxnum'] = device['cxnum'] + 1
								else:
									device['cxnum'] = 1
								if device['cxnum'] > 3:
									device['cxnum'] = 0
									content = '从' + Demeter.date(device['cxdate']) + '到' + Demeter.date(Demeter.time()) + '，' + gateway['name'] + '，'+device['name']+'超过'+str(device['max'])+device_type['unit']+'，当前值'+str(value)+device_type['unit']+'，请及时控制'+device_type['name']+'进行处理。'
									self.msg(id, content, gateway['farm_id'], 2)
							else:
								device['cxtype'] = 1
								device['cxnum'] = 1
							model.id = device['id']
							if device['cxnum'] == 1:
								model.update(farm_id=gateway['farm_id'], cxnum=device['cxnum'],cxtype=device['cxtype'], cxdate='time')
							else:
								model.update(farm_id=gateway['farm_id'], cxnum=device['cxnum'],cxtype=device['cxtype'])

					if device['min']:
						if value < device['min']:
							if device['cxtype'] == 2:
								if device['cxnum']:
									device['cxnum'] = device['cxnum'] + 1
								else:
									device['cxnum'] = 1
								if device['cxnum'] > 3:
									device['cxnum'] = 0
									content = '从' + Demeter.date(device['cxdate']) + '到' + Demeter.date(Demeter.time()) + '，' + gateway['name'] + '，'+device['name']+'少于'+str(device['min'])+device_type['unit']+'，当前值'+str(value)+device_type['unit']+'，请及时控制'+device_type['name']+'进行处理。'
									self.msg(id, content, gateway['farm_id'], 2)
							else:
								device['cxtype'] = 2
								device['cxnum'] = 1
							model.id = device['id']
							if device['cxnum'] == 1:
								model.update(farm_id=gateway['farm_id'], cxnum=device['cxnum'],cxtype=device['cxtype'], cxdate='time')
							else:
								model.update(farm_id=gateway['farm_id'], cxnum=device['cxnum'],cxtype=device['cxtype'])

					content = ''
					condition_model = Demeter.model('device_set_condition')
					condition_model.device_id = id
					condition_model.status = True
					condition = condition_model.select()
					if condition:
						
						for cv in condition:
							state = False
							text = ''
							cv['value'] = float(cv['value'])
							if cv['condition'] == 1 and value > cv['value']:
								state = True
								text = '超过'
							elif cv['condition'] == 2 and value < cv['value']:
								state = True
								text = '少于'
							elif value == cv['value']:
								state = True
								text = '等于'
							if state:
								if cv['notice'] == True:
									content = gateway['name'] + '，'+device['name']+text+str(cv['value'])+device_type['unit']+'，当前值'+str(value)+device_type['unit']+'，请及时控制'+device_type['name']+'进行处理。'
									self.msg(id, content, gateway['farm_id'], 2)
								if cv['oper'] == 2:
									cv['oper'] = 1
									Demeter.service('device').switchMul(cv)
								elif cv['oper'] == 3:
									cv['oper'] = 0
									Demeter.service('device').switchMul(cv)
						
			else:
				#insert
				model.hardware_id = config['child']
				model.farm_id = gateway['farm_id']
				model.name = name
				model.hardware_type = hard['id']
				model.gateway_id = gateway['id']
				if device_type:
					model.type_id = device_type['id']
				else:
					model.type_id = 0
				model.value = value
				model.status = True
				id = model.insert()
				self.hardware(id, config['child'], gateway['farm_id'],gateway['id'], hard['id'])

			if config['method'] == 'pic':
				model_pic = Demeter.model('device_pic')
				model_pic.farm_id = gateway['farm_id']
				model_pic.gateway_id = gateway['id']
				model_pic.device_id = id
				model_pic.pic = value
				model_pic.insert()
			else:
				data = {}
				data['type'] = config['type']
				data['gateway'] = config['parent']
				data['device'] = config['child']
				data['hard'] = config['method']
				data['farm'] = gateway['farm_id']
				data['source'] = value
				data['value'] = value
				data['time'] = Demeter.time()
				Demeter.model('data', 'tsdb').insert(data)

	def msg(self, device_id, content, farm_id, type_id):
		model = Demeter.model('msg')
		model.farm_id = farm_id
		model.content = content
		model.device_id = device_id
		model.type_id = type_id
		info = model.select(type='fetchone')
		if not info:
			model.farm_id = farm_id
			model.content = content
			model.device_id = device_id
			model.type_id = type_id
			model.insert()
		else:
			model.id = info['id']
			model.update(content=content, cdate='time')

	def gateway(self, gateway, farm, id):
		gateway = str(gateway)
		# 更新网关状态
		hardware_type = 5
		model = Demeter.model('device_info')
		model.hardware_id = gateway
		model.hardware_type = hardware_type
		device = model.select(type='fetchone')
		if device:
			model.id = device['id']
			model.update(value='1',status=True,cdate='time')
		else:
			model.hardware_id = gateway
			model.farm_id = farm
			model.name = '网关状态'
			model.status = True
			model.hardware_type = hardware_type
			model.gateway_id = id
			model.type_id = 0
			model.value = '1'
			model.insert()
			self.hardware(id, gateway, farm, id, 1)

	def hardware(self, id, hardware_id, farm, gateway, hard):
		# 记录硬件设备
		if hardware_id and id:
			model = Demeter.model('hardware')
			model.hardware_id = hardware_id
			info = model.select(type='fetchone')
			if not info:
				model.farm_id = farm
				model.hardware_id = hardware_id
				model.gateway_id = gateway
				model.device_id = id
				model.hardware_type = hard
				model.insert()

	# 通信
	def send(self, type_info, gateway_info, info, switch):
		# 这里要向服务器发送pub请求了,暂时使用临时文件代替
		#Demeter.temp(key=type_info['key'], name=info['hardware_id'], value=switch)
		feedback = ''
		state = False
		if 'server_id' in info and info['server_id']:
			server = Demeter.service('common').one('setting_server', id=info['server_id'])
			if server:
				if server['server_type'] == 2:
					feedback = self.send_modbus_tcp(type_info, gateway_info, info, switch, server)
					state = True
				elif server['server_type'] == 3:
					feedback = self.send_modbus_rtu(type_info, gateway_info, info, switch, server)
					state = True
		if not state:
			feedback = self.send_pub(type_info, gateway_info, info, switch)

		config = {'method':'control', 'type':type_info['key'], 'parent':gateway_info['hardware_id'], 'child':info['hardware_id']}
		name = type_info['name'] + '#' + str(info['hardware_id'])
		self.save(config, switch, name, type_info)

	def send_modbus_tcp(self, type_info, gateway_info, info, value, server):
		return Demeter.service('tcp', 'modbus').send(server, type_info, info, value)

	def send_modbus_rtu(self, type_info, gateway_info, info, value, server):
		return Demeter.service('rtu', 'modbus').send(server, type_info, info, value)

	def send_pub(self, type_info, gateway_info, info, value):
		from demeter.mqtt import Pub
		pub = Pub()
		key = type_info['key'] + '/' + gateway_info['hardware_id']  + '/' + info['hardware_id']
		update = 'update/' + key
		feedback = 'status/' + key
		#pub.push(update, value, qos=0, callback=self.switchAction, param={'info':info, 'key':feedback, 'switch':switch}, feedback=True)
		pub.push(update, value)

		return feedback