# -*- coding: utf-8 -*-
from demeter.core import *
import modbus_tk
import modbus_tk.modbus_tcp as modbus_tcp
import modbus_tk.defines as mdef
import time
import random
import struct
import serial

class Old(object):

	def server(self):
		# 启动服务
		server = modbus_tcp.TcpServer(port=8010)
		server.start()
		slave_1 = server.add_slave(1)
		slave_1.add_block('block1', modbus_tk.defines.HOLDING_REGISTERS, 0, 16)

		while 1:
			tempr = round(((random.random()*1000)), 2)
			value = struct.unpack('>HH', struct.pack('>f', tempr))
			#value = tempr
			Demeter.echo('tempr:' + str(tempr))
			Demeter.echo('value:' + str(value))
			slave_1.set_values('block1', 0, value)

			shidu = round(((random.random()*1000)), 2)
			value = struct.unpack('>HH', struct.pack('>f', shidu))
			#value = shidu
			Demeter.echo('shidu:' + str(shidu))
			Demeter.echo('value:' + str(value))
			slave_1.set_values('block1', 2, value)


			famen = random.randint(1,2)
			value = struct.unpack('>HH', struct.pack('>f', famen))
			#Demeter.echo('famen:' + str(famen))
			#Demeter.echo('value:' + str(value))
			#slave_1.set_values('block1', 4, value)
			
			Demeter.echo('=========')
			time.sleep(3)

	def test(self):
		port = 'COM3'
		#master = modbus_rtu.RtuMaster(serial.Serial(port=port, baudrate=38400, bytesize=8, parity='O', stopbits=1, xonxoff=0))
		master = modbus_tcp.TcpMaster(host='192.168.33.10', port=int(1152))
		master.set_timeout(30)  #timeout表示若超过3秒没有连接上slave就会自动断开

		value = master.execute(1, modbus_tk.defines.READ_HOLDING_REGISTERS, 0, 2)

		print(value)

		value = master.execute(1, modbus_tk.defines.READ_HOLDING_REGISTERS, 2, 2)

		print(value)

	# 获取数据
	def getData(self, type, slave_id):
		pass

	def server_s(self):
		server = modbus_tk.modbus_tcp.TcpServer(port=1152, address='0.0.0.0', timeout_in_sec=3)       
		server.start()  
		slave_1 = server.add_slave(1)  
		slave_3 = server.add_slave(3)
		slave_2 = server.add_slave(2)
		slave_5 = server.add_slave(5)
		# 创建寄存器，寄存器的别名为block1，寄存器为保持寄存器（Holding_Register），寄存器起始地址为0，寄存器个数为...

		slave_1.add_block('block1', modbus_tk.defines.HOLDING_REGISTERS, 0, 10) 
		slave_3.add_block('block1', modbus_tk.defines.HOLDING_REGISTERS, 0, 2)
		slave_2.add_block('block1', modbus_tk.defines.READ_INPUT_REGISTERS, 0, 44)
		slave_5.add_block('block1', modbus_tk.defines.READ_INPUT_REGISTERS, 0, 28)

		#给slave_1添加一个模块（模块名，只读，地址，长度）  
		valueAll_1 = slave_1.get_values('block1', 0, 10)
		print('valueAll--1: ', valueAll_1)

		valueAll_3 = slave_3.get_values('block1', 0, 2)
		print('valueAll--3: ', valueAll_3)

		valueAll_2 = slave_2.get_values('block1', 0, 44)
		print('valueAll--2: ', valueAll_2)

		valueAll_5 = slave_5.get_values('block1', 0, 28)
		print('valueAll--5: ', valueAll_5)

		# value0 = slave_1.get_values('block1', 0, 1)   # 寄存器0000 -- 状态位初始值为全0
		# print 'value0:  ', value0

		while True:
			# slave只set数据，不再读取数据，以防端口被占用，master读不上来
			#value_all = slave_1.get_values('block1', 0, 10)
			#sys.stdout.write('done: values read: %s\r\n' % (str(value_all)))    

			# 室内温度
			# 小数点后保留2位
			tempr = round(((random.random()*1000)+10000), 2)

			# 室内湿度
			humid = round(((random.random()*1000)+10000), 2)

			# 光照
			sunlight = round(((random.random()*900)+10000), 2)

			# CO2
			co2 = round(((random.random()*1000)+10000), 2)

			# 营养液温度
			nuTempr = round(((random.random()*1000)+10000), 2)

			# 含氧量
			oxyg = round((random.uniform(200, 600)), 2)

			# 室内温度1
			tempr1 = round(random.uniform(10000, 20000), 2)

			# 室内湿度1
			humid1 = round(random.uniform(10000, 12000), 2)

			# CO2_1
			co2_1 = round(random.uniform(10000, 15000), 2)

			# 瓶内温度1
			bo_tempr1 = round(random.uniform(10000, 20000), 2)

			# 室内温度2
			tempr2 = round(random.uniform(10000, 20000), 2)

			# 室内湿度2
			humid2 = round(random.uniform(10000, 13000), 2)

			# CO2
			co2_2 = round(random.uniform(10000, 20000), 2)

			# 瓶内温度2
			bo_tempr2 = round(random.uniform(10000, 14000), 2)

			# slave_1
			slave_1.set_values('block1', 1, tempr) 
			slave_1.set_values('block1', 3, humid)
			slave_1.set_values('block1', 5, sunlight)
			slave_1.set_values('block1', 7, co2)
			slave_1.set_values('block1', 9, nuTempr)

			#slave_3
			slave_3.set_values('block1', 1, oxyg) 

			# slave_2
			slave_2.set_values('block1', 0, tempr1) 
			slave_2.set_values('block1', 1, humid1)
			slave_2.set_values('block1', 2, co2_1)
			slave_2.set_values('block1', 3, bo_tempr1)
			slave_2.set_values('block1', 8, tempr2)
			slave_2.set_values('block1', 9, humid2) 
			slave_2.set_values('block1', 10, co2_2)
			slave_2.set_values('block1', 11, bo_tempr2)
			slave_2.set_values('block1', 16, tempr1)
			slave_2.set_values('block1', 17, humid1)
			slave_2.set_values('block1', 18, co2_1)
			slave_2.set_values('block1', 19, bo_tempr1)
			slave_2.set_values('block1', 24, tempr2)
			slave_2.set_values('block1', 25, humid2)
			slave_2.set_values('block1', 26, co2_2)
			slave_2.set_values('block1', 27, bo_tempr2)
			slave_2.set_values('block1', 32, tempr1)
			slave_2.set_values('block1', 33, humid1)
			slave_2.set_values('block1', 34, co2_1)
			slave_2.set_values('block1', 35, bo_tempr1)
			slave_2.set_values('block1', 40, tempr2)
			slave_2.set_values('block1', 41, humid2)
			slave_2.set_values('block1', 42, co2_2)
			slave_2.set_values('block1', 43, bo_tempr2)

			# slave_5
			slave_5.set_values('block1', 0, tempr1) 
			slave_5.set_values('block1', 1, humid1)
			slave_5.set_values('block1', 2, co2_1)
			slave_5.set_values('block1', 3, bo_tempr1)
			slave_5.set_values('block1', 8, tempr2)
			slave_5.set_values('block1', 9, humid2) 
			slave_5.set_values('block1', 10, co2_2)
			slave_5.set_values('block1', 11, bo_tempr2)
			slave_5.set_values('block1', 16, tempr1)
			slave_5.set_values('block1', 17, humid1)
			slave_5.set_values('block1', 18, co2_1)
			slave_5.set_values('block1', 19, bo_tempr1)
			slave_5.set_values('block1', 24, tempr2)
			slave_5.set_values('block1', 25, humid2)
			slave_5.set_values('block1', 26, co2_2)
			slave_5.set_values('block1', 27, bo_tempr2)


			print('======================')
			time.sleep(1)

	def master(self, master, id):
		info = Demeter.service('common').list('device_info', search={'server_id':id})
		if info:
			for v in info:
				if v['product_id']:
					code = Demeter.service('common').one('setting_modbus_code', id=v['product_id'])
					if code['oper_type'] == 1:
						self.setValue(code, master, v)

	def setValue(self, code, master, info):
		config = {}
		gateway = Demeter.service('common').one('device_gateway', id=info['gateway_id'])
		hardware = Demeter.service('common').one('hardware_type', id=info['hardware_type'])
		config['parent'] = gateway['hardware_id']
		config['method'] = hardware['key']
		config['child'] = info['hardware_id']
		address = code['register_address'].split("\r\n")
		device_type_key = code['device_type_key'].split("\r\n")
		exp = code['exp'].split("\r\n")
		name = info['name']
		j = 0
		for i in address:
			(code['register_address'],code['register_length']) = i.split(',')
			code['exp'] = exp[j]
			value = self.getValue(code, master, info)
			device_type = device_type_key[j]
			device_type = Demeter.service('common').one('setting_device_type', key=device_type)
			config['type'] = device_type['key']
			
			j = j + 1
			Demeter.service('device').save(config, value, name, device_type)

	def getValue(self, code, master, info):
		if code['register_type'] == 1:
			# 线圈
			modbus_register_type = mdef.READ_COILS
		elif code['register_type'] == 2:
			modbus_register_type = mdef.READ_DISCRETE_INPUTS
		elif code['register_type'] == 3:
			modbus_register_type = mdef.READ_HOLDING_REGISTERS
		elif code['register_type'] == 4:
			modbus_register_type = mdef.READ_INPUT_REGISTERS

		temp = master.execute(int(code['slave_id']), modbus_register_type, int(code['register_address']), int(code['register_length']))

		#Demeter.echo('temp:' + str(temp) + 'size:' + str(len(temp)))
		value = struct.unpack('>f', struct.pack('>HH', temp[0], temp[1]))
		value = str(round(value[0], 2))
		
		if 'exp' in code:
			value = Demeter.exp(code['exp'], value)
		if 'exp' in info:
			value = Demeter.exp(info['exp'], value)
		return value

	def send(self, server, type_info, info, value):
		master = modbus_tcp.TcpMaster(host=server['host'], port=int(server['port']))
		master.set_timeout(6.0)
		master.set_verbose(True)
		if 'exp' in device:
			value = Demeter.exp(device['exp'], value)
		if 'exp' in info:
			value = Demeter.exp(info['exp'], value)

		if ',' in value:
			value = value.split(',')

		modbus_register_type = ''
		if device['modbus_register_type'] == 1:
			modbus_register_type = mdef.WRITE_SINGLE_COIL
		elif device['modbus_register_type'] == 2:
			modbus_register_type = mdef.WRITE_MULTIPLE_COILS
		elif device['modbus_register_type'] == 3:
			modbus_register_type = mdef.WRITE_SINGLE_REGISTER
		elif device['modbus_register_type'] == 4:
			modbus_register_type = mdef.WRITE_MULTIPLE_REGISTERS

		result = ''
		if modbus_register_type:
			master.execute(device['modbus_slave_id'], modbus_register_type, device['modbus_register_address'], output_value=value)
			result = master.execute(device['modbus_slave_id'], modbus_register_type, device['modbus_register_address'], len(value))
		return result

	def start(self):
		server = Demeter.service('common').list('setting_server', search={'server_type':2})
		if server:
			modbus = Demeter.path + 'modbus.py'
			for v in server:
				Shell.popen('python3 ' + modbus + ' -m client -i ' + v['id'])

	def client(self, id):
		server = Demeter.service('common').one('setting_server', id=id)
		master = modbus_tcp.TcpMaster(host=server['server_host'], port=int(server['server_port']))
		master.set_timeout(6.0)
		while(True):
			self.master(master, server['id'])

	def test2(self):
		master = modbus_tcp.TcpMaster(host="192.168.33.10", port=1152)
		master.set_timeout(3)  #timeout表示若超过3秒没有连接上slave就会自动断开
		tempr = master.execute(1, modbus_tk.defines.READ_HOLDING_REGISTERS, 0, 2)
		#（slave id，只读，block地址，长度：即字节乘个数）
		Demeter.echo('tempr:' + str(tempr) + 'size:' + str(len(tempr)))
		value = struct.unpack('>f', struct.pack('>HH', tempr[0], tempr[1]))
		#在slave中，是先打包成'>f'在以'>HH'解包的，在master中刚好相反
		#struct.unpack里解出来的是一个元组，可以用bb, = 或者输出bb[0]
		print(value)
		Demeter.echo('value:' + str(round(value[0], 2)))
		time.sleep(3)

	def test1(self):
		master = modbus_tcp.TcpMaster(host="192.168.33.10", port=1152)
		master.set_timeout(3)  #timeout表示若超过3秒没有连接上slave就会自动断开
		aa = master.execute(1, modbus_tk.defines.ANALOG_INPUTS, 0, 2)
		#（slave id，只读，block地址，长度：即字节乘个数）
		Demeter.echo('aa:' + str(aa) + 'size:' + str(len(aa)))
		bb = struct.unpack('>f', struct.pack('>HH', aa[0], aa[1]))
		#在slave中，是先打包成'>f'在以'>HH'解包的，在master中刚好相反
		#struct.unpack里解出来的是一个元组，可以用bb, = 或者输出bb[0]
		Demeter.echo('bb:' + str(bb[0]))
		time.sleep(3)

		slave = 1

		# 读线圈寄存器
		master.execute(slave, mdef.READ_COILS, 0, 16)

		# 读离散输入寄存器
		master.execute(slave, mdef.READ_DISCRETE_INPUTS, 0, 16)

		# 读保持寄存器
		master.execute(slave, mdef.READ_HOLDING_REGISTERS, 0, 16)

		# 读输入寄存器
		master.execute(slave, mdef.READ_INPUT_REGISTERS, 0, 16)

		# 单个读写寄存器操作

		# 写单个线圈 写寄存器地址为0的线圈寄存器，写入内容为0（位操作）
		master.execute(slave, mdef.WRITE_SINGLE_COIL, 0, output_value=0)
		master.execute(slave, mdef.READ_COILS, 0, 1)

		# 写单个保持寄存器 写寄存器地址为0的保持寄存器
		master.execute(slave, mdef.WRITE_SINGLE_REGISTER, 0, output_value=21)
		master.execute(slave, mdef.READ_HOLDING_REGISTERS, 0, 1)


		# 多个寄存器读写操作

		# 写多个保持寄存器 写寄存器起始地址为0的保持寄存器，操作寄存器个数为4
		master.execute(slave, mdef.WRITE_MULTIPLE_REGISTERS, 0, output_value=[20,21,22,23])
		master.execute(slave, mdef.READ_HOLDING_REGISTERS, 0, 4)

		# 写寄存器起始地址为0的线圈寄存器
		master.execute(slave, mdef.WRITE_MULTIPLE_COILS, 0, output_value=[0,0,0,0])
		master.execute(slave, mdef.READ_COILS, 0, 4)

		# slave_id，类型，地址，长度（或者值）、读取还是写入、计算公式