/*
 * ServicePort.c
 *
 *  Created on: Jan 28, 2012
 *      Author: RomanM
 */

#include "stm32f10x.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#include "CmdLine/cmdline.h"
#include "ServicePort.h"
#include "setting.h"

#include "drivers/drivers.h"
#include "uIP/uip.h"
#include "uIP/uip_arp.h"

#define	TEST_LOCK()		if (servicePortStatus.unlocked == 0) return

tCmdLineEntry g_sCmdTable[] = {
	{ "showmeyoursecret",	(void*)Service_Login,				"Login through service port" },
	{ "exit",				(void*)Service_Exit,				"Exit from service port"},
	{ "help",				(void*)Service_Help,				"Help" },
	{ "setting",			(void*)Service_Setting,				"Setting [save / load]" },
	{ "setdoortime",		(void*)Service_SetDoorTime,			"Set door control timeout in seconds" },
	{ "getdoortime",		(void*)Service_GetDoorTime,			"Get door control timeout" },
	{ "setlockvoltage",		(void*)Service_SetLockVoltage,		"Set door lock voltage 0 - 65535" },
	{ "getlockvoltage",		(void*)Service_GetLockVoltage,		"Get door lock voltage" },
	{ "sensorcalibration",	(void*)Service_SensorCalibration,	"Calibration of light sensors" },
	{ "settime",			(void*)Service_SetTime,				"Set RTC time.\r\nsettime [unit] [value]\r\n[unit] - hour / minute / day / month / year" },
	{ "gettime",			(void*)Service_GetTime,				"Get time from RTC" },
	{ "setip",				(void*)Service_SetIP,				"Set IP configuration\r\nsetip [type] [value]\r\n[type] - address / gateway / mask / server" },
	{ "getip",				(void*)Service_GetIP,				"Get IP configuration" },
	{ "ethstat",			(void*)Service_EthStat,				"Get ethernet status" },
	{ "setname",			(void*)Service_SetName,				"Set device name" },
	{ "getname",			(void*)Service_GetName,				"Get device name" },
	{ "setpassword",		(void*)Service_SetPassword,			"Set password to service port" },
	{ "reset", 				(void*)Service_Reset,				"Restart RFID terminal" },
	{ 0, 0, 0 }
};

struct {
	uint8_t unlocked : 1;
	uint8_t badpass : 3;
} servicePortStatus = {0, 0};

// ============================================================================

/*
 * Log in to the service port
 */
void Service_Login(int argc, char *argv[]) {
	if (servicePortStatus.badpass < 3) {
		if (argc == 2) {
			if (!strncmp(argv[1], setting.password, sizeof(setting.password))) {
				servicePortStatus.unlocked = 1;
				UART_SendString("Service port unlocked");
			}
			else {
				UART_SendString("Bad password");
				servicePortStatus.badpass ++;
			}
		}
	}
	else {
		UART_SendString("Service port locked");
	}
}

/*
 * Log out from service port
 */
void Service_Exit(int argc, char *argv[]) {
	servicePortStatus.unlocked = 0;
	UART_SendString("Service port locked");
}

/*
 * Show commands or description
 */
void Service_Help(int argc, char *argv[]) {
	tCmdLineEntry *pEntry = &g_sCmdTable[0];

	TEST_LOCK();

	if (argc == 1) {
		UART_SendString("Available commands:\r\n");
		while (pEntry->pcCmd) {
			UART_SendString((char*)(pEntry->pcCmd));
			UART_SendString("\r\n");
			pEntry ++;
		}
	}
	else if (argc == 2) {
		while (pEntry->pcCmd) {
			if (!strcmp(pEntry->pcCmd, argv[1])) {
				UART_SendString((char*)(pEntry->pcHelp));
				UART_SendString("\r\n");
			}
			pEntry ++;
		}
	}
}

/*******************************************************************************
 * Setting
 ******************************************************************************/

/*
 * Save/Load settings
 */
void Service_Setting(int argc, char *argv[]) {
	TEST_LOCK();

	if (argc == 2) {
		if (!strcmp(argv[1], "save")) {
			Setting_Save();
			UART_SendString("Saved");
		}
		else if (!strcmp(argv[1], "load")) {
			Setting_Load();
			UART_SendString("Loaded");
		}
		else {
			UART_SendString("Command bad format");
			return;
		}
	}
	else {
		UART_SendString("Command bad format");
	}
}

/*
 * Set door control timeout
 */
void Service_SetDoorTime(int argc, char *argv[]) {
	TEST_LOCK();

	if (argc == 2) {
		setting.doorTimeout = atoi(argv[1]);
		Service_GetDoorTime(0, 0);
	}
	else {
		UART_SendString("Command bad format");
	}
}

/*
 * Get door control timeout
 */
void Service_GetDoorTime(int argc, char *argv[]) {
	char str[32];
	TEST_LOCK();

	sprintf(str, "Door timeout: %d s", setting.doorTimeout);
	UART_SendString(str);
}


void Service_SetLockVoltage(int argc, char *argv[]) {
	TEST_LOCK();

	if (argc == 2) {
		setting.doorLockVoltage = atoi(argv[1]);
		Service_GetLockVoltage(0, 0);
	}
	else {
		UART_SendString("Command bad format");
	}
}

void Service_GetLockVoltage(int argc, char *argv[]) {
	char str[32];
	TEST_LOCK();

	sprintf(str, "Door lock voltage: %d", setting.doorLockVoltage);
	UART_SendString(str);
}

void Service_SensorCalibration(int argc, char *argv[]) {
	TEST_LOCK();

	setting.calibCh1 = ADC1_GetValueFilt(SENSOR1) - 200;
	setting.calibCh2 = ADC1_GetValueFilt(SENSOR2) - 200;

	UART_SendString("Calibration finished");
}

/*******************************************************************************
 * RTC part
 ******************************************************************************/

/*
 * Set RTC time
 */
void Service_SetTime(int argc, char *argv[]) {
	TEST_LOCK();

	if (argc == 3) {
		if (!strcmp(argv[1], "hour")) RTC_SetHour(atoi(argv[2]));
		else if (!strcmp(argv[1], "minute")) RTC_SetMinute(atoi(argv[2]));
		else if (!strcmp(argv[1], "day")) RTC_SetDay(atoi(argv[2]));
		else if (!strcmp(argv[1], "month")) RTC_SetMonth(atoi(argv[2]));
		else if (!strcmp(argv[1], "year")) RTC_SetYear(atoi(argv[2]));
		else {
			UART_SendString("Command bad format");
			return;
		}
		Service_GetTime(0, 0);
	}
	else {
		UART_SendString("Command bad format");
	}
}

/*
 * Show RTC time
 */
void Service_GetTime(int argc, char *argv[]) {
	TEST_LOCK();

	char str[40];

	sprintf(str, "Time: %2d:%02d.%02d\r\nDate: %2d.%2d.%4d\r\n",
			RTC_GetHour(), RTC_GetMinute(), RTC_GetSecond(),
			RTC_GetDay(), RTC_GetMonth(), RTC_GetYear());
	UART_SendString(str);
}

/*******************************************************************************
 * Ethernet part
 ******************************************************************************/

/*
 * Set IP address
 */
void Service_SetIP(int argc, char *argv[]) {
	TEST_LOCK();

	uip_ipaddr_t ipaddr;
	int address[4];

	if (argc == 3) {
		sscanf(argv[2], "%d.%d.%d.%d", &address[3], &address[2], &address[1], &address[0]);
		uip_ipaddr(ipaddr, address[3], address[2], address[1], address[0]);

		if (!strcmp(argv[1], "address")) uip_sethostaddr(ipaddr);
		else if (!strcmp(argv[1], "gateway")) uip_setdraddr(ipaddr);
		else if (!strcmp(argv[1], "mask")) uip_setnetmask(ipaddr);
		else if (!strcmp(argv[1], "server")) memcpy(setting.serverAddress, ipaddr, sizeof(uip_ipaddr_t));
		else {
			UART_SendString("Command bad format");
			return;
		}
		Service_GetIP(0, 0);
	}
	else {
		UART_SendString("Command bad format");
	}
}

/*
 * Show IP configuration
 */
void Service_GetIP(int argc, char *argv[]) {
	TEST_LOCK();

	char str[40];
	uip_ipaddr_t ipaddr;

	uip_gethostaddr(ipaddr);
	sprintf(str, "IP address:     %3d.%3d.%3d.%3d\r\n",
			((char*)ipaddr)[0],
			((char*)ipaddr)[1],
			((char*)ipaddr)[2],
			((char*)ipaddr)[3]);
	UART_SendString(str);

	uip_getdraddr(ipaddr);
	sprintf(str, "Gateway:        %3d.%3d.%3d.%3d\r\n",
			((char*)ipaddr)[0],
			((char*)ipaddr)[1],
			((char*)ipaddr)[2],
			((char*)ipaddr)[3]);
	UART_SendString(str);

	uip_getnetmask(ipaddr);
	sprintf(str, "Network mask:   %3d.%3d.%3d.%3d\r\n",
			((char*)ipaddr)[0],
			((char*)ipaddr)[1],
			((char*)ipaddr)[2],
			((char*)ipaddr)[3]);
	UART_SendString(str);


	sprintf(str, "Server address: %3d.%3d.%3d.%3d\r\n",
			((char*)setting.serverAddress)[0],
			((char*)setting.serverAddress)[1],
			((char*)setting.serverAddress)[2],
			((char*)setting.serverAddress)[3]);
	UART_SendString(str);
}

/*
 * Show ethernet status
 */
void Service_EthStat(int argc, char *argv[]) {
	TEST_LOCK();

	char str[40];
	if (Enc424j600_IsLinked()) UART_SendString("Connected\r\n");
	else UART_SendString("Disconnected\r\n");

	sprintf(str, "MAC address: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
			uip_ethaddr.addr[0],
			uip_ethaddr.addr[1],
			uip_ethaddr.addr[2],
			uip_ethaddr.addr[3],
			uip_ethaddr.addr[4],
			uip_ethaddr.addr[5]);
	UART_SendString(str);
}

/*******************************************************************************
 * Device information
 ******************************************************************************/

void Service_SetName(int argc, char *argv[]) {
	TEST_LOCK();

	if (argc == 2) {
		strncpy(setting.devName, argv[1], sizeof(setting.devName)-1);
		Service_GetName(0,0);
	}
	else {
		UART_SendString("Bad format");
	}
}

void Service_GetName(int argc, char *argv[]) {
	TEST_LOCK();

	char str[40];
	sprintf(str, "Device name: %s", setting.devName);
	UART_SendString(str);
}

/*******************************************************************************
 * Utilities
 ******************************************************************************/

void Service_SetPassword(int argc, char *argv[]) {
	TEST_LOCK();

	if (argc == 2) {
		strncpy(setting.password, argv[1], sizeof(setting.password)-1);
		UART_SendString("Password changed");
	}
	else {
		UART_SendString("Bad format");
	}
}

void Service_Reset(int argc, char *argv[]) {
	TEST_LOCK();
	NVIC_SystemReset();
}
