                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           #pragma once
#include "uart/ProtocolSender.h"
#include "net/NetManager.h"
#include "net/DhcpClient.h"
#include "net/tcp_client.h"
#include "net/s433Server.h"
#include "module/HumitureSensors.h"
#include <string>
#include <thread>
#include <unistd.h>
#include <sys/reboot.h>

#include "utils/GpioHelper.h"
#include "utils/TimeHelper.h"
#include "utils/TimeUtil.h"
#include "utils/CrcCheckUtil.h"
#include "utils/ByteUtil.h"
#include "base/strings.hpp"
#include "base/base.hpp"
#include "storage/StoragePreferences.h"
#include "service/BusinessConfig.h"
#include "manager/LanguageManager.h"
#include "server/http_server.h"
#include "restclient-cpp/restclient.h"


static bool serverInfoInited = false;	//是否初始化过。请求HTTP SERVER INFO成功则为初始化过

static int netOffCount = 0;	//断网计数，每秒+1
static int netOffMax = 300;	//断网300秒，则重启

Json::Value watchDeviceInfo;

#define LORA_TIME_HANDLE  18
#define HTTP_SERVER_PORT  80

srv::HttpServer httpServer;

#define ETHERNETMANAGER		NETMANAGER->getEthernetManager()


static net::Conn* udpConn;
class UdpThread: public Thread {
public:
	static bool getServerInfo(){
		string url = getHttpGateway() + "/ncs_url/server_info";
		LOGD("请求服务器信息. url = %s", url.c_str());
		//发起HTTP GET请求
		RestClient::Response r = RestClient::get(url);
		LOGD("code = %d, body= %s", r.code, r.body.c_str());
		if (r.code!=200){
			LOGD("code = %d, retry", r.code);
			return false;
		}
		//解析json
		Json::Reader reader;
		Json::Value root;
		if (reader.parse(r.body, root, false)){
			if (root.isMember("http_local_ip")) {
				// http
				StoragePreferences::putString(STORE_GATEWAY, root["http_local_ip"].asString());
				StoragePreferences::putInt(STORE_HTTP_PORT, root["http_port"].asInt());

				// tcp
				StoragePreferences::putString(STORE_TCP_LOCAL_IP, root["tcp_local_ip"].asString());
				StoragePreferences::putInt(STORE_TCP_PORT, root["tcp_port"].asInt());

				//TCP启动
				TcpClient::instance()->startTcp();

				serverInfoInited = true;
				return true;
			}
		}
		return false;
	}


	static void getDeviceInfo(){
		string url = getHttpGateway() + "/deviceBed/getBedDeviceInfoByEthMac/" + ETHERNETMANAGER->getMacAddr();
		LOGD("请求设备信息. url = %s", url.c_str());
		//发起HTTP GET请求
		RestClient::Response r = RestClient::get(url);
		if (r.code != 200) {
			LOGD("请求设备信息错误. 错误代码 = %d", r.code);
			return;
		}

		LOGD("获得设备信息. result = %s", r.body.c_str());
		//解析json
		Json::Reader reader;
		Json::Value root;
		if (reader.parse(r.body, root, false)){
			if (root.isMember("id")) {
				//设备
				StoragePreferences::putInt(STORE_DEVICE_ID, root["id"].asInt());
				StoragePreferences::putInt(STORE_DEVICE_TYPE, root["device_type"].asInt());

				//获取科室设置
				string partId = root["part_id"].asString();
				StoragePreferences::putString(STORE_PARTID, partId);

				getVersionUpdate();
			}
		}
	}

	static void getVersionUpdate() {
		std::string url = getHttpGateway() + "/deviceBed/getAppVersion?device_type=131&part_id=" + StoragePreferences::getString(STORE_PARTID, "");
		std::string content_type = std::string("application/json");

		LOGD("请求版本信息. url = %s", url.c_str());
		//发起HTTP POST请求
		RestClient::Response r = RestClient::post(url, content_type, "");
		if (r.code != 200) {
			LOGD("请求版本信息-> 错误代码： %d", r.code);
			return;
		}

		LOGD("获得版本信息. result = %s", r.body.c_str());
		//解析json
		Json::Reader reader;
		Json::Value root;

		if(reader.parse(r.body, root, false)) {
			int currentVersionNo = getVersionNo();
			int responseVersionNo = root["version_no"].asInt();
			std::string responseVersion = root["version_code"].asString();
			LOGD("服务器版本 : %s %d, 当前设备版本: %d", responseVersion.c_str(), responseVersionNo, currentVersionNo);

			if (currentVersionNo < responseVersionNo) {
				Intent* intent = new Intent();
				intent->putExtra(appUpdate, "true");
				EASYUICONTEXT->openActivity("updateActivity", intent);
			}
		}
	}



	static bool getWatchDeviceInfo(std::string mac) {

		string url = getHttpGateway() + "/watch/getDeviceByEthMac/" + mac;
		LOGD("请求设备信息. url = %s", url.c_str());
		//发起HTTP GET请求
		RestClient::Response r = RestClient::get(url);
		if (r.code != 200) {
			LOGD("请求设备信息错误. 错误代码 = %d", r.code);
			return false;
		}

		LOGD("获得设备信息. result = %s", r.body.c_str());
		//解析json
		Json::Reader reader;
		Json::Value root;
		if (reader.parse(r.body, root, false)){
			if (root.isMember("id")) {
				watchDeviceInfo = root;
				return true;
			}
			else {
				watchDeviceInfo["id"] = "";
				watchDeviceInfo["part_id"] = "";
				watchDeviceInfo["full_name"] = "";
				watchDeviceInfo["member_name"] = "";
				watchDeviceInfo["member_id"] = "";
				watchDeviceInfo["role_name"] = "";
				watchDeviceInfo["eth_mac"] = mac;
				return true;
			}
		}
		return false;
	}


	/**
	 * 线程创建成功后会调用该函数，可以在该函数中做一些初始化操作
	 * return true   继续线程
	 *        false  退出线程
	 */
	virtual bool readyToRun() {
		LOGD("Thread 已经创建完成");
		return true;
	}

	/**
	 * 线程循环函数
	 *
	 * return true  继续线程循环
	 *        false 推出线程
	 */
	virtual bool threadLoop() {
		LOGD("线程循环函数");

		//检查是否有退出线程的请求，如果有，则返回false，立即退出线程
		if (exitPending()) {
			return false;
		}

		udpConn = net::Dial("udp", "192.168.1.255:10010");
		if (udpConn) {
			byte buf[1024] = {0};
			const char* req = "search_server";
			//发送
			udpConn->Write((byte*)req, strlen(req));
			while (true && !exitPending()) {
				//读取，超时10*1000毫秒
				int n = udpConn->Read(buf, sizeof(buf) - 1, 10*1000);
				if (n > 0) {
					buf[n] = 0;
					char serverStr[1024];
					sprintf(serverStr,"%s",buf);
					LOGD("读取 %d字节： %s", n, serverStr);

					//解析json
					Json::Reader reader;
					Json::Value root;
					if (reader.parse(serverStr, root, false)){
						if (root.isMember("success") && root["success"].asBool()){
							serverIP = root["data"]["third_server"].asString();
							serverHttpPort = root["data"]["third_server_port"].asInt();

							StoragePreferences::putString(STORE_GATEWAY, serverIP);
							StoragePreferences::putInt(STORE_HTTP_PORT, serverHttpPort);

							//先获取服务器信息
							//getServerInfo();
							//就当在获取服务器信息完成后获取用户信息，这里测试用
							//getCustomerInfo();
							//退出UDP线程
							pthread_exit(NULL);
							break;
						}
					}
				} else if (n == 0) {
					LOGD("连接正常断开");
					break;
				} else if (n == net::E_TIMEOUT) {
					udpConn->Write((byte*)req, strlen(req));
					LOGD("读取超时");
				} else {
					LOGD("出错");
					break;
				}
			}
			//关闭连接
			udpConn->Close();
			//释放内存
			delete udpConn;
			udpConn = NULL;
		}

		//返回真，继续下次线程循环
		return true;
	}
};
static UdpThread udp_thread;

struct NetworkConfiguration {
	std::string ip;
	std::string sub_network_mask;
	std::string gateway;
};
NetworkConfiguration GetNetworkConfiguration() {
	char ip[64] = {0};
	char mask[64] = {0};
	char gateway[64] = {0};
	char dns1[64] = {0};
	char dns2[64] = {0};
	if (ETHERNETMANAGER->isAutoMode()) {
		ETHERNETMANAGER->getConfigureInfo(ip, mask, gateway, dns1, dns2);
	} else {
		ETHERNETMANAGER->getStaticConfigureInfo(ip, mask, gateway, dns1, dns2);
	}
	return NetworkConfiguration{ip, mask, gateway};
}

void getMsg() {
	mQRCode1Ptr->loadQRCode("http://www.wdklchina.com");

	mDeviceCodePtr->setText(GetDeviceUid());
	mDeviceMacPtr->setText(ETHERNETMANAGER->getMacAddr());
	mDeviceIpPtr->setText(ETHERNETMANAGER->getIp());
	mNetMaskPtr->setText(GetNetworkConfiguration().sub_network_mask);
	mGatewayPtr->setText(GetNetworkConfiguration().gateway);

	mVersionPtr->setText(StoragePreferences::getString(WDKL_VERSION, getVersion()));

	//server ip
	string sIP = StoragePreferences::getString(STORE_GATEWAY, serverIP);
	mServerIPPtr->setText(sIP);
}


static net::DhcpClient _s_eth_dhcp_client;

using namespace std;

static bool _start_eth_dhcp_client() {
	// 静态ip模式不做处理
	if (!ETHERNETMANAGER->isAutoMode()) {
		LOGD("以太网静态");
		return false;
	}

	if (!ETHERNETMANAGER->isConnected()) {
		LOGD("以太网连接状态");
		return false;
	}

	char ip[32], gw[32];
	if (!ETHERNETMANAGER->getConfigureInfo(ip, NULL, gw, NULL, NULL)) {
		return false;
	}

	LOGD("正在重新请求dhcp");
	return _s_eth_dhcp_client.start(ip, ETHERNETMANAGER->getMacAddr(), gw);
}

static void _stop_eth_dhcp_client() {
	_s_eth_dhcp_client.stop();
}

static void _dhcp_lease_cb(dhcp_lease_type_e type, void *data) {
	LOGD("_dhcp_lease_cb type %d\n", type);

	switch (type) {
	case E_DHCP_LEASE_TYPE_SUCCESS:
		LOGD("DHCP连接成功");
		break;

	case E_DHCP_LEASE_TYPE_FAIL:
		LOGD("DHCP连接失败，重连");
		_start_eth_dhcp_client();
		break;

	case E_DHCP_LEASE_TYPE_TIMEOUT:
		// 续租超时，可以断开再重连尝试
		LOGD("DHCP连接超时，断开重连");
		_stop_eth_dhcp_client();
		_start_eth_dhcp_client();
		break;
	}
}

namespace {

// 以太网状态监听
class EthernetConnStateListener : public EthernetManager::IEthernetConnStateListener {
public:
	virtual void handleEthernetConnState(EEthConnState state)  {
		LOGD("[net] handleEthernetConnState state: %d\n", state);

		switch (state) {
		case E_ETH_CONNECTED:
			LOGD("以太网连接");
			_start_eth_dhcp_client();
			getMsg();
			break;

		case E_ETH_DISCONNECTED:
			LOGD("以太网断开");
			_stop_eth_dhcp_client();
			break;

		default:
			break;
		}
	}
};
}

//地址总长
#define ADDRLEN 15

//定义字符串数组保存IP地址、掩码地址、网关地址、首选DNS服务器地址以及备选DNS服务器地址
static string addr[5];
/**
 * 字符长度是否正确
 * */
const bool isLengthCorrect(const string addr)
{
	return addr.size() <= ADDRLEN;
}

/**
 * 检查是不是最多只有3个.字符
 * */
const bool noMoreThan3charactor(const string addr)
{
	//.字符个数
	int count = 0;
	for(unsigned int level1 = 0; level1 < addr.size(); ++level1)
	{
		if('.' == addr[level1])
		{
			++count;
		}
	}
	return 3 >= count;
}

/*
 * 判断所有字符是不是由0~9和.组成
 * */
const bool allCharacterIsLegal(const string addr)
{
	for(unsigned int level1 = 0; level1 < addr.size(); ++level1)
	{
		if(false == (('0' <= addr[level1] && addr[level1] <= '9') || '.' == addr[level1]))
		{
			return false;
		}
	}
	return true;
}

/**
 * 判断开头是否是1`9
 * */
const bool headIsCorrect(string addr, unsigned int pos = 0)
{
	//查找到达末尾，直接返回true
	if(addr.size() == pos)
	{
		return true;
	}
	//查找.字符
	if(string::npos == addr.find('.', pos))
	{
		if('0' < addr[pos] && addr[pos] <= '9')
		{
			return true;
		}
		//如果开头为字符'0'且其后没有字符，那么返回true
		else if(addr.size()-1 == pos)
		{
			return true;
		}
		return false;
	}
	else
	{
		//开头为0~9
		if('0' > addr[pos] || addr[pos] > '9')
		{
			return false;
		}
		//开头为0，后面没有字符返回false
		if('0' == addr[pos] && addr.size()-1 <= pos)
		{
			return false;
		}
		//跳过.字符继续查找
		return headIsCorrect(addr, addr.find('.', pos)+1);
	}
	return true; //默认返回true
}

/**
 * 检查地址每一小段的长度，最长为3个字符
 * */
const bool partCheractorCorrect(const string addr, unsigned int pos = 0)
{
	//查找到达末尾，直接返回true
	if(addr.size() == pos)
	{
		return true;
	}
	//查找.字符
	if(string::npos == addr.find('.', pos))
	{
		if(3 >= addr.size()-pos)
		{
			return true;
		}
		return false;
	}
	else
	{
		//由于跳过了.字符进行查找，因此判断条件应该是>3
		if(3 < addr.find('.', pos) - pos)
		{
			return false;
		}
		//跳过.字符继续查找
		return partCheractorCorrect(addr, addr.find('.', pos)+1);
	}
	return true; //默认返回true
}

/**
 * 检测地址是否有误
 * */
const bool checkAddr(string addr)
{
	return  (true == headIsCorrect(addr))?			//地址每小段开头是否为0~9
			(true == partCheractorCorrect(addr))?	//每小段字符串最大长度是否为3
			(true == noMoreThan3charactor(addr))?	//最多是否只有3个.字符
			(true == isLengthCorrect(addr))?		//地址最大长度是否为15
			(true == allCharacterIsLegal(addr))?	//所有的字符是否都由0~9和.组成
			true: false: false: false: false: false;
}

static void updateNetState(){
	if (ETHERNETMANAGER->isConnected()){
		netOffCount = 0;
	} else {
		netOffCount++;
		//5分钟仍然断网，则重启
		if (netOffCount>netOffMax){
			netOffCount = 0;
			//重启
			sync();
			reboot(RB_AUTOBOOT);
		}
	}

	EEthConnState connState = ETHERNETMANAGER->getConnState();
	switch (connState) {
		case E_ETH_DISCONNECTED:	// 以太网断开
//			LOGD("eth conn state : E_ETH_DISCONNECTED");
			mtvNetPtr->setBackgroundColor(0xFF949494);
			break;
		case E_ETH_CONNECTING:		// 以太网连接中
			mtvNetPtr->setBackgroundColor(0xFF2F9DF1);
//			LOGD("eth conn state : E_ETH_CONNECTING");
			break;
		case E_ETH_CONNECTED:		// 以太网连接
//			LOGD("eth conn state : E_ETH_CONNECTED");
			mtvNetPtr->setBackgroundColor(0xFF37C127);
			break;
		case E_ETH_DISCONNECTING:	// 以太网断开连接中
//			LOGD("eth conn state : E_ETH_DISCONNECTING");
			mtvNetPtr->setBackgroundColor(0xFF949494);
			break;
		case E_ETH_CONN_UNKNOWN:	// 以太网未知
//			LOGD("eth conn state : E_ETH_CONN_UNKNOWN");
			mtvNetPtr->setBackgroundColor(0xFF949494);
			break;
	}
}

void tcpStatus(){
	if (TcpClient::instance()->connected()){
		mtvTcpPtr->setBackgroundColor(0xFF37C127);
	} else {
		mtvTcpPtr->setBackgroundColor(0xFF949494);
	}
}

void setDatetime(){
	struct tm *t = TimeHelper::getDateTime();
	mtvDatetimePtr->setText(TimeUtil::DatetimeToString(t));
}

void sosMsgSend(UartMsg model){
	const char* sendMsg = model.msg;
	sendProtocolTo(UART_TTYS1, (byte*)(sendMsg), strlen(sendMsg));
	model.count = model.count-1;
	//0.5秒后再发
	usleep(500*1000);
	if (model.count>0){
		//发送次数循环
		sosMsgSend(model);
	}
}

void threadSOSSend(){
	std::thread backend([](){
		UartMsg model = getUartMsg();
		if (model.count>0){
			sosMsgSend(model);
			//多个消息时排队循环
			threadSOSSend();
		}
	});
	backend.detach();
	return;
}


void sendToLora(int cmd, int content) {
	if (uartBaudRate2 == B9600) {
		byte loraMsg[5] = {0xa8, 0x02, 0x11, 0x00, 0x11};

		StoragePreferences::putInt(STORE_LORA_CMD, cmd);
		StoragePreferences::putInt(STORE_LORE_CONTENT, content);

		loraMsg[2] = cmd == 1 ? 0x11 : 0x10;
		loraMsg[3] = content == 1? 0x00 : 0x01;
		loraMsg[4] = CrcCheckHelper::loraCreateCrc(loraMsg, 4);
		sendSimpleTo(UART_TTYS2, loraMsg, 5);

		string revStr = "";
		//依次将读取到的数据输出到日志
		for (int i = 0; i < 5; ++i) {
			revStr += base::format("%02x",loraMsg[i]);
//				revStr += buffer[i];
		}
		LOGD("lora cmd ===================> %s", revStr.c_str());

		if (cmd == 1 && content == 1) {
			LOGD("============> 转换盒设置成工作状态，等待模块回应");
		}
		else if (cmd == 1 && content == 0) {
			LOGD("============> 转换盒设置成学习状态，等待模块回应");
		}
		else if (cmd == 0 && content == 1) {
			LOGD("============> 转换盒设置成学习模式，等待模块回应");
		}
		else if (cmd == 0 && content == 0) {
			LOGD("============> 转换盒设置成非学习模式，等待模块回应");
		}
	}
}


void parseSelectLora(string cmd) {
	string sizeStr = cmd.substr(2, 2);
	uint8_t sizeByte = static_cast<uint8_t>(std::stoi(sizeStr, nullptr, 16));
	int size = sizeByte;
	string data = "";
	if (size != 2) {
		data = cmd.substr(8, (size - 2) * 2);
	}

	TcpModel tcpModel;
	tcpModel.from_id = StoragePreferences::getInt(STORE_DEVICE_ID,0);
	tcpModel.type = TcpType::S433;
	tcpModel.action = S433Action::SELECT_LORA;
	tcpModel.tid = base::format("t%d", TimeHelper::getCurrentTime());
	tcpModel.data = data;
	std::string req = getTcpModelString(tcpModel);
	TcpClient::instance()->sendMsg(req.c_str());

}

void sendSelectToLora() {
	byte loraMsg[4] = {0xa8, 0x01, 0x15, 0x15};
	sendSimpleTo(UART_TTYS2, loraMsg, 4);
	string revStr1 = "";
	//依次将读取到的数据输出到日志
	for (int i = 0; i < 4; ++i) {
		revStr1 += base::format("%02x",loraMsg[i]);
	}
	LOGD("select lora ===================> %s", revStr1.c_str());
}


void sendDeleteToLora(std::string del, std::string mac) {
	if (del == "0") {
		byte loraMsg[4] = {0xa8, 0x01, 0x12, 0x12};
		sendSimpleTo(UART_TTYS2, loraMsg, 4);

		string revStr = "";
		//依次将读取到的数据输出到日志
		for (int i = 0; i < 4; ++i) {
			revStr += base::format("%02x",loraMsg[i]);
		}
		LOGD("delete all lora ===================> %s", revStr.c_str());
	}
	else {
		if (mac.length() != 6) {
			return;
		}
		byte loraMsg[7] = {0xa8, 0x04, 0x13, 0x00, 0x00, 0x00, 0x00};

		for (int i = 0; i < mac.length(); i += 2) {
			std::string byteStr = mac.substr(i, 2);
	        // 将字符串转换为字节
	        unsigned char byte = ByteUtil::hexStrToByte_16(byteStr);
			loraMsg[i / 2 + 3] = byte;
		}
		loraMsg[6] = CrcCheckHelper::loraCreateCrc(loraMsg, 6);
		sendSimpleTo(UART_TTYS2, loraMsg, 7);

		string revStr = "";
		//依次将读取到的数据输出到日志
		for (int i = 0; i < 7; ++i) {
			revStr += base::format("%02x",loraMsg[i]);
		}
		LOGD("delete lora ===================> %s", revStr.c_str());
	}
}

void sendDeleteToLoraAndRestart(std::string del, std::string mac) {
	sendDeleteToLora(del, mac);
	sleep(1);
	sendToLora(1, 1);
	sleep(1);
}


void sendAddToLora(std::string mac) {
	int macSize = mac.size();
	if (macSize % 6 != 0) {
		LOGD("输入的字数不对");
		return;
	}

	int macByteSize = macSize / 2;
	int macNumber = mac.size() / 6;

	byte loraMsg[4 + macByteSize] = {0};
	loraMsg[0] = 0xa8;
	loraMsg[1] = 2 + macByteSize;
	loraMsg[2] = 0x14;
	loraMsg[3] = macNumber;

	for (int i = 0; i < mac.length(); i += 2) {
		std::string byteStr = mac.substr(i, 2);
        // 将字符串转换为字节
        unsigned char byte = ByteUtil::hexStrToByte_16(byteStr);
		loraMsg[i / 2 + 4] = byte;
	}
	loraMsg[4 + macByteSize] = CrcCheckHelper::loraCreateCrc(loraMsg, 4 + macByteSize);
	sendSimpleTo(UART_TTYS2, loraMsg, 5 + macByteSize);

	string revStr = "";
	//依次将读取到的数据输出到日志
	for (int i = 0; i < 5 + macByteSize; ++i) {
		revStr += base::format("%02x",loraMsg[i]);
	}
	LOGD("add lora ===================> %s", revStr.c_str());
}


Json::FastWriter writer;
void s433DataHandle(std::string s433DataStr) {
	Json::Reader reader(Json::Features::strictMode());
	Json::Value root;
	if (reader.parse(s433DataStr.c_str(), root, false)){
		if (root.isMember("heartbeat")) {
			std::string _partId = root["partId"].asString();
			if (_partId == "0" || _partId == StoragePreferences::getString(STORE_PARTID, "0")) {
				const char* sendMsg = "1";
//				sendProtocolTo(UART_TTYS1, (byte*)(sendMsg), strlen(sendMsg));
				s433Send(sendMsg, 1, 2);
				return;
			}

		}
		else if (root.isMember("s433Type")) {
			std::string _s433Type = root["s433Type"].asString();
			LOGD("_s433Type ====================> %s", _s433Type.c_str());
			if (_s433Type == S433Type::ADDR_REQUEST) {
				std::string tid = root["tid"].asString();
				sendAck(tid);
				if (udp_thread.getWatchDeviceInfo(root["deviceMac"].asString())) {

					Json::Value reponse;
					reponse["s433Type"] = S433Type::ADDR_RESPONSE;
					reponse["tid"] = tid;
					reponse["deviceId"] = watchDeviceInfo["id"];
					reponse["partId"] = watchDeviceInfo["part_id"];
					reponse["partName"] = watchDeviceInfo["full_name"];
					reponse["memberName"] = watchDeviceInfo["member_name"];
					reponse["memberId"] = watchDeviceInfo["member_id"];
					reponse["roleName"] = watchDeviceInfo["role_name"];
					reponse["deviceMac"] = watchDeviceInfo["eth_mac"];
					reponse["time"] = TimeUtil::getDatelineStr();

					const std::string reponseStr = writer.write(reponse);
//					sendProtocolTo(UART_TTYS1, reponseStr);
					s433Send(reponseStr, 2, 1);
				}
			}
			else if (_s433Type == S433Type::EVENT_RECEIVED) {
				std::string tid = root["tid"].asString();
				sendAck(tid);

				string _deviceId = root["deviceId"].asString();
				if (_deviceId != "") {
					TcpModel tcpModel;
					tcpModel.from_id = std::stoi(_deviceId);
					tcpModel.type = TcpType::EVENT;
					tcpModel.action = EventAction::RECEIVED;
					tcpModel.tid = root["tid"].asString();
					tcpModel.json = root["tcpData"];
					std::string req = getTcpModelString(tcpModel);
					TcpClient::instance()->sendMsg(req.c_str());
				}
			}
			else if (_s433Type == S433Type::EVENT_REPONSE) {
				std::string tid = root["tid"].asString();
				sendAck(tid);

				string _deviceId = root["deviceId"].asString();
				if (_deviceId != "") {
					TcpModel tcpModel;
					tcpModel.from_id = std::stoi(_deviceId);
					tcpModel.type = TcpType::EVENT;
					tcpModel.action = EventAction::RESPONSE;
					tcpModel.tid = root["tid"].asString();
					tcpModel.data = root["tcpData"]["id"].asString();
					std::string req = getTcpModelString(tcpModel);
					TcpClient::instance()->sendMsg(req.c_str());
				}
			}
			else if (_s433Type == S433Type::SOS_CANCEL) {
				std::string tid = root["tid"].asString();
				sendAck(tid);

				string _deviceId = root["deviceId"].asString();
				if (_deviceId != "") {
					TcpModel tcpModel;
					tcpModel.from_id = std::stoi(_deviceId);
					tcpModel.type = TcpType::SOS;
					tcpModel.action = SosAction::CANCEL;
					tcpModel.tid = root["tid"].asString();
					tcpModel.data = root["tcpData"]["id"].asString();
					std::string req = getTcpModelString(tcpModel);
					TcpClient::instance()->sendMsg(req.c_str());
				}
			}
		}
	}

}

// 接收tcp消息
void handleMsg(byte* inBytes){
	TcpModel tcpModel;
	tcpModel = getTcpModel(inBytes);
	LOGD("tcp model: %s, %s", tcpModel.type.c_str(), tcpModel.action.c_str());
	if (tcpModel.type == TcpType::OTHER) {
		LOGD("trans tcp json failed");
	} else if (tcpModel.type == TcpType::TIME) {
		if (tcpModel.action == TimeAction::SYNC) {
			string serverTime = "";
			if (tcpModel.data != ""){
				serverTime = tcpModel.data;
			} else {
				serverTime = tcpModel.json["time"].asString();
			}
			LOGD("sync time ： %s", serverTime.c_str());

			time_t timet = stoi(serverTime);
			struct tm *t = gmtime(&timet);
			char pDate[25];
			sprintf(pDate,"%d-%02d-%02d %02d:%02d:%02d",
					1900 + t->tm_year, 1+ t->tm_mon, t->tm_mday,
					t->tm_hour + 8,t->tm_min,t->tm_sec);
			LOGD("transfered time ： %s", pDate);
			TimeHelper::setDateTime(pDate);

			threadInit();
		}
	}
	else if (tcpModel.type == TcpType::DEVICE){
		if (tcpModel.action == DeviceAction::APP_UPDATE){	//软件升级
			Intent* intent = new Intent();
			intent->putExtra(appUpdate, "true");
			EASYUICONTEXT->openActivity("DeviceUpdateActivity", intent);
		}
		else if (tcpModel.action == DeviceAction::RESTART) {	// 重启设备
			sync();
			reboot(RB_AUTOBOOT);
		}
		else if (tcpModel.action == DeviceAction::SERVER_CHANGE) {
			StoragePreferences::putString(STORE_GATEWAY, tcpModel.json["server_ip"].asCString());
			StoragePreferences::putString(STORE_HTTP_PORT, tcpModel.json["server_port"].asCString());

			const char* req = "-1";
			TcpClient::instance()->sendMsg(req);
			//重启
			sync();
			reboot(RB_AUTOBOOT);
		}
	}
	else if (tcpModel.type == TcpType::EVENT) {
		if (tcpModel.action == EventAction::KEY_CLICK) {
//			if (tcpModel.json["spreadMemberIds"] == "-1") {
//				return;
//			}
//
//			Json::Value tcpData;
//			tcpData["id"] = tcpModel.json["id"];
//			tcpData["createDate"] = tcpModel.json["createDate"];
//			tcpData["actionType"] = tcpModel.json["actionType"];
//			tcpData["fromFrameFullName"] = tcpModel.json["fromFrameFullName"];
//			tcpData["data"] = tcpModel.json["data"];
//			tcpData["actionType"] = tcpModel.json["actionType"];
//
//			Json::Value reponse;
//			reponse["s433Type"] = S433Type::EVENT_CLICK;
//			reponse["toMemberId"] = tcpModel.json["spreadMemberIds"].asString();
//			reponse["tcpData"] = tcpData;
//			reponse["tid"] = tcpModel.tid;
//
//			const std::string reponseStr = writer.write(reponse);
////			sendProtocolTo(UART_TTYS1, reponseStr);
//			s433Send(reponseStr, 2, 1);
		}
		else if (tcpModel.action == EventAction::RESPONSED ||
				tcpModel.action == EventAction::COMPLETED ||
				tcpModel.action == EventAction::CANCEL_CONFIRM ||
				tcpModel.action == EventAction::CANCEL
				) {
//			if (tcpModel.json["spreadMemberIds"] == "-1") {
//				return;
//			}
//
//			Json::Value reponse;
//			reponse["s433Type"] = S433Type::EVENT_OFF;
//			reponse["toMemberId"] = tcpModel.json["spreadMemberIds"].asString();
//			reponse["itId"] = tcpModel.json["id"].asInt();
//			reponse["tid"] = tcpModel.tid;
//
//			const std::string reponseStr = writer.write(reponse);
////			sendProtocolTo(UART_TTYS1, reponseStr);
//			s433Send(reponseStr, 2, 1);
		}
	}
	else if (tcpModel.type == TcpType::SOS) {
//		if (tcpModel.action == SosAction::CALL || tcpModel.action == SosAction::SOS_CALL) {
//			if (tcpModel.json["spreadMemberIds"] == "-1") {
//				return;
//			}
//
//			Json::Value tcpData;
//			tcpData["id"] = tcpModel.json["id"];
//			tcpData["createDate"] = tcpModel.json["createDate"];
//			tcpData["actionType"] = tcpModel.json["actionType"];
//			tcpData["fromFrameFullName"] = tcpModel.json["fromFrameFullName"];
//			tcpData["data"] = tcpModel.json["data"];
//			tcpData["actionType"] = tcpModel.json["actionType"];
//
//			Json::Value reponse;
//			reponse["s433Type"] = S433Type::SOS;
//			reponse["toMemberId"] = tcpModel.json["spreadMemberIds"].asString();
//			reponse["tcpData"] = tcpData;
//			reponse["tid"] = tcpModel.tid;
//
//			const std::string reponseStr = writer.write(reponse);
////			sendProtocolTo(UART_TTYS1, reponseStr);
//			s433Send(reponseStr, 2, 1);
		}
		else if (tcpModel.action == SosAction::CANCELED || tcpModel.action == SosAction::CANCEL) {
//			if (tcpModel.json == NULL || tcpModel.json["spreadMemberIds"] == "-1") {
//				return;
//			}
//
//			Json::Value reponse;
//			reponse["s433Type"] = S433Type::SOS_OFF;
//			reponse["toMemberId"] = tcpModel.json["spreadMemberIds"].asString();
//			reponse["itId"] = tcpModel.json["id"].asInt();
//			reponse["tid"] = tcpModel.tid;
//
//			const std::string reponseStr = writer.write(reponse);
////			sendProtocolTo(UART_TTYS1, reponseStr);
//			s433Send(reponseStr, 2, 1);
//		}
	}
	else if (tcpModel.type == TcpType::S433){
		if (tcpModel.action == S433Action::SOS_CALL){
			std::string msg = tcpModel.data + "RELAY0,1F";
			const char* sendMsg = msg.c_str();
			addUartMsg(sendMsg, 2);
			threadSOSSend();
		}
		else if (tcpModel.action == S433Action::CANCEL){
			std::string msg = tcpModel.data + "RELAY0,0F";
			const char* sendMsg = msg.c_str();
			addUartMsg(sendMsg, 3);
			threadSOSSend();
		}
		else if (tcpModel.action == S433Action::SELECT_LORA) {
			sendSelectToLora();
		}
		else if (tcpModel.action == S433Action::ADD_LORA) {
			if (tcpModel.data != "") {
				sendAddToLora(tcpModel.data);
			}
		}
		else if (tcpModel.action == S433Action::DELETE_LORA) {
			if (tcpModel.data != "") {
				sendDeleteToLora("1", tcpModel.data);
			}
		}
		else if (tcpModel.action == S433Action::DELETE_ALL_LORA) {
			sendDeleteToLora("0", "");
		}
	}
}

void loraStart() {
	string startMsg1 = "AT+FREQ=483200000,483200000,483200000,483200000\r\n";
	string statrMsg2 = "AT+RATE=6,6\r\n";
	string statrMsg3 = "AT+TXP=15\r\n";
	string statrMsg4 = "AT+WORKMODE=82\r\n";
	string statrMsg5 = "AT+WORKMODE=81\r\n";

	sendSimpleTo(UART_TTYS1, statrMsg4);
	sendSimpleTo(UART_TTYS1, startMsg1);
	sendSimpleTo(UART_TTYS1, statrMsg2);
	sendSimpleTo(UART_TTYS1, statrMsg3);
	sendSimpleTo(UART_TTYS1, statrMsg5);
	LOGD("启动LoRa模块");
}

Json::Value uartMsgList;
int uartMsgIndex = 0;
void setUartList(std::string text) {
	uartMsgList[uartMsgIndex] = text;
	uartMsgIndex += 1;
    mMsgListViewPtr->refreshListView();
}

void threadInit(){
	std::thread backend([](){
		//网络连接完成
		if (ETHERNETMANAGER->isConnected()){
			//初始化过不再请求，TCP连接本身会有5秒重连
			if (serverInfoInited){
				return;
			}
			//未请求成功过服务器信息，则进入请求，请求成功后进入tcp连接
			if (udp_thread.getServerInfo()){
				udp_thread.getDeviceInfo();
			}
			return;
		}
		//没有网络 或 没有http成功，5秒后重试
		usleep(5*1000*1000);
		threadInit();
	});
	backend.detach();
	return;
}

/**
 * 注册定时器
 * 填充数组用于注册定时器
 * 注意：id不能重复
 */
static S_ACTIVITY_TIMEER REGISTER_ACTIVITY_TIMER_TAB[] = {
	{0,  60*1000}, //定时器id=0, 时间间隔60秒
	{1,  1000},
};


static EthernetConnStateListener _s_eth_state_listener;
/**
 * 当界面构造时触发
 */
static void onUI_init(){
    //Tips :添加 UI初始化的显示代码到这里,如:mText1Ptr->setText("123");
	ETHERNETMANAGER->addEthernetConnStateListener(&_s_eth_state_listener);
	_s_eth_dhcp_client.set_lease_cb(_dhcp_lease_cb);
	// 这里也检测网络是否连接上 (有可能启动前网络已经连接触发不到回调)，启动dhcp租赁检测，之后都是根据网络的连接断开执行相应的操作
	_start_eth_dhcp_client();

	threadInit();
	getMsg();

	//开启网页
	httpServer.RunAsync(HTTP_SERVER_PORT);

	if (isHumAble) {
		HumitureSenors::instance()->DHT22Init();
	}

	int tcpPort = StoragePreferences::getInt(STORE_TCP_PORT, 5086);
	if (tcpPort == 5086) {
		mTcpPortRadioGroupPtr->getRadioItem(0)->setChecked(true);
	}
	else if (tcpPort == 5089) {
		mTcpPortRadioGroupPtr->getRadioItem(1)->setChecked(true);
	}

	int loraCmdInt = StoragePreferences::getInt(STORE_LORA_CMD, 1);
	int loraContentInt = StoragePreferences::getInt(STORE_LORE_CONTENT, 1);
	sendToLora(loraCmdInt, loraContentInt);

	GpioHelper::output(SV50PD_A0, 1);
	GpioHelper::output(SV50PD_A8, 0);

    mActivityPtr->registerUserTimer(LORA_TIME_HANDLE, 3 * 1000);
}

/**
 * 当切换到该界面时触发
 */
static void onUI_intent(const Intent *intentPtr) {
    if (intentPtr != NULL) {
        //TODO
    }
}

/*
 * 当界面显示时触发
 */
static void onUI_show() {

}

/*
 * 当界面隐藏时触发
 */
static void onUI_hide() {

}

/*
 * 当界面完全退出时触发
 */
static void onUI_quit() {

}

/**
 * 串口数据回调接口
 */
static void onProtocolDataUpdate(const SProtocolData &data) {
	LOGD("data.cmd %s",data.cmd.c_str());
	//tcp 5085

	string cmd = data.cmd;
	if (cmd.substr(0, 2) == "a8") {
		string _cmd = cmd.substr(4, 2);
		if (_cmd == "02" || _cmd == "03" || _cmd == "04" || _cmd == "05") {
			string signal = "ff";
			signal += data.cmd;
			const char* req = signal.c_str();
			LOGD("发送外部lora串口消息 ===> %s", req);
			TcpClient::instance()->sendMsg(req);
		}
		else if (_cmd == "10" || _cmd == "11") {
			if (cmd == "a802110112") {
				LOGD("============> 转换盒进入学习状态");
			}
			else if (cmd == "a802110011") {
				LOGD("============> 转换盒进入工作状态");
			}
			else if (cmd == "a802100010") {
				LOGD("============> 转换盒切换成学习模式");
			}
			else if (cmd == "a802100111") {
				LOGD("============> 转换盒切换成非学习模式");
			}
		}
		else if (_cmd == "12") {
			LOGD("============> 删除所有学习的设备");
			sendSelectToLora();
		}
		else if (_cmd == "13") {
			LOGD("============> 删除部分学习的设备");
			sendSelectToLora();
		}
		else if (_cmd == "14") {
			LOGD("============> 写入学习的设备");
			sendSelectToLora();
		}
		else if (_cmd == "15") {
			LOGD("============> 读取学习的设备");
			parseSelectLora(cmd);
		}
	}
	else {
		string signal = "";
		if (data.cmd.size() == 6) {
			if (StoragePreferences::getInt(STORE_TCP_PORT, 5086) == 5089) {
			    //ffdd 固定开头，03对应多功能按钮
			    signal = "ffdd03";
			}
			else {
				//ffcc 固定开头，02对应报警
				signal = "ffcc02";
			}
		}
		else {
			signal = "ffee04";
		}
	    int size = data.cmd.size();
	    signal += base::format("%04x", size);
	    signal += data.cmd;
	    const char* req = signal.c_str();
	    LOGD("发送串口按钮消息 ===> %s",req);
	    TcpClient::instance()->sendMsg(req);
	}
}

/**
 * 定时器触发函数
 * 不建议在此函数中写耗时操作，否则将影响UI刷新
 * 参数： id
 *         当前所触发定时器的id，与注册时的id相同
 * 返回值: true
 *             继续运行当前定时器
 *         false
 *             停止运行当前定时器
 */
static bool onUI_Timer(int id){
	switch (id) {
		case 0:{
				const char* req = "0";
				TcpClient::instance()->sendMsg(req);
				}
				break;
		case 1:{
			setDatetime();
			updateNetState();
			tcpStatus();
		}
			break;
        case LORA_TIME_HANDLE: {
        	loraStart();
        	return false;
        }
        	break;
		default:
			break;
	}


    return true;
}

/**
 * 有新的触摸事件时触发
 * 参数：ev
 *         新的触摸事件
 * 返回值：true
 *            表示该触摸事件在此被拦截，系统不再将此触摸事件传递到控件上
 *         false
 *            触摸事件将继续传递到控件上
 */
static bool onmainActivityTouchEvent(const MotionEvent &ev) {
    switch (ev.mActionStatus) {
		case MotionEvent::E_ACTION_DOWN://触摸按下
			//LOGD("时刻 = %ld 坐标  x = %d, y = %d", ev.mEventTime, ev.mX, ev.mY);
			break;
		case MotionEvent::E_ACTION_MOVE://触摸滑动
			break;
		case MotionEvent::E_ACTION_UP:  //触摸抬起
			break;
		default:
			break;
	}
	return false;
}
static void onEditTextChanged_EditTextPwd(const std::string &text) {
    //LOGD(" onEditTextChanged_ EditTextPwd %s !!!\n", text.c_str());
}

static bool onButtonClick_BtnPwdConfirm(ZKButton *pButton) {
	LOGD(" ButtonClick BtnPwdConfirm !!!\n");
	string pwd = mEditTextPwdPtr->getText();

	if (pwd == "666"){
		mWindowPwdPtr->hideWnd();
		mWindowServerIPPtr->showWnd();
		return false;
	} else {
		mTextPwdInfoPtr->setTextTr("PasswordWrong");
	}

	return false;
}

static bool onButtonClick_Setting(ZKButton *pButton) {
    LOGD(" ButtonClick Setting !!!\n");
    mWindowPwdPtr->showWnd();
    return false;
}

static void onEditTextChanged_EditTextServerIP(const std::string &text) {
    //LOGD(" onEditTextChanged_ EditTextServerIP %s !!!\n", text.c_str());
}

static bool onButtonClick_BtnServerIPConfirm(ZKButton *pButton) {
	LOGD("设置服务器ip !!!\n");
	LOGD("服务器ip set to %s",mEditTextServerIPPtr->getText().c_str());

	if(false == checkAddr(mEditTextServerIPPtr->getText())){
		mServerIPMsgPtr->setTextTr("ServerIPWrong");
		return false;
	}

	StoragePreferences::putString(STORE_GATEWAY, mEditTextServerIPPtr->getText().c_str());

	//mWindowServerIPPtr->hideWnd();
	//重启
	sync();
	reboot(RB_AUTOBOOT);
	return false;
}

static bool onButtonClick_BtnNetSetting(ZKButton *pButton) {
    LOGD(" ButtonClick BtnNetSetting !!!\n");
    EASYUICONTEXT->openActivity("EthernetSettingActivity");
    return false;
}

static bool onButtonClick_BtnSoftVer(ZKButton *pButton) {
    LOGD(" ButtonClick BtnSoftVer !!!\n");
    EASYUICONTEXT->openActivity("DeviceUpdateActivity");
    return false;
}

static bool onButtonClick_BtnRestart(ZKButton *pButton) {
	LOGD(" ButtonClick BtnRestart !!!\n");
	//重启
	sync();
	reboot(RB_AUTOBOOT);
	return false;
}
static void onCheckedChanged_TcpPortRadioGroup(ZKRadioGroup* pRadioGroup, int checkedID) {
    LOGD(" RadioGroup TcpPortRadioGroup checked %d", checkedID);
    switch (checkedID) {
		case ID_MAIN_TcpPortRadioButton1:
			StoragePreferences::putInt(STORE_TCP_PORT, 5086);
			break;
		case ID_MAIN_TcpPortRadioButton2:
			StoragePreferences::putInt(STORE_TCP_PORT, 5089);
			break;
    }

	sync();
	reboot(RB_AUTOBOOT);
}

static int getListItemCount_MsgListView(const ZKListView *pListView) {
    //LOGD("getListItemCount_MsgListView !\n");
	if (uartMsgList.size() > 10) {
		return uartMsgList.size();
	}
    return 10;
}

static void obtainListItemData_MsgListView(ZKListView *pListView,ZKListView::ZKListItem *pListItem, int index) {
    //LOGD(" obtainListItemData_ MsgListView  !!!\n");
    if (uartMsgIndex == 0 || uartMsgIndex - 1 < index) {
        return;
    }
    pListItem->setText(uartMsgList[uartMsgIndex - 1 - index].asString());
}

static void onListItemClick_MsgListView(ZKListView *pListView, int index, int id) {
    //LOGD(" onListItemClick_ MsgListView  !!!\n");
}
