/*
   Verze c 1
   Studer ser com
*/
/*
debug: verbose_level=3
debug: port=COM1

send property_request:
device_addr=101
object_type=0x2
object_id=1287
property_id=5
length=4
data=
000| 01 00 00 00

debug: tx bytes:
headr> AA, 00, 01 00 00 00, 65 00 00 00, 0E 00, 73 79 
data>  00. 02. 02 00 07 05 00 00 05 00 01 00 00 00, 15 B9
*/

//				DEFINES ram[]
#define FRAME_START				0
#define DATA_START				32
#define	RX_BUFFER_START			64
#define RX_BUFFER_CHK_A			75								// RX_BUFFER_START + 11
#define RX_BUFFER_CHK_B			76								// RX_BUFFER_START + 12
#define RX_BUFFER_DATA_LENGTH	74								// RX_BUFFER_START + 10
#define	RX_DATA_START			128

//				DEFINES

#define WDT_TOT					30
#define	RX_TIMEOUT				200								// timeout cekani na znak [x 10ms]
#define	RX_TIMEOUT_CHAR			3								// timeout cekani na vycteni znaku [x 10ms]
#define SEND_TOT_TEMP			60								// TO odesilani teploty [sec]

#define	HEADR_SIZE				13

#define IS_RX_CHAR				sys[48]
#define GET_RX_CHAR				sys[49]
#define TIMER_COUNT				sys[64]
#define PWM_FREQ				sys[191]
#define PWM_DUTY				sys[192]
#define GET_ATOI				sys[62]
#define SAVE_LAST_TIMESTAMP		sys[1664]						// NV ram
#define	RE_DS					sys[231]						// RE1 - DS
#define	RE_FVE					sys[232]						// RE2 - FVE

#define SERVICE_FLAGS_OK		0x02							// response OK


#define MQTT_SUBSCRIBE_SWITCH_PWR	1							// kanal 1
#define MQTT_SUBSCRIBE_SWITCH_PWM	2							// kanal 2

#define PWM_FREQUENCY			20								// 20Hz
#define PWM_DUTY_CYCLE			20								// default 20% -> 0 W

#define	ASCI_1					0x31
#define	ASCI_2					0x32

//**************************************************************
//**************************************************************
//		********	Seznam adres Studer zarizeni		********
#define XTM_ALL_ADDR	100
#define XTM1_ADDR		101
#define XTM2_ADDR		102
#define XTM3_ADDR		103

#define	XCOM_ADDR		501

#define	XCAN_ADDR		601

//**************************************************************
//		********	Define seznam Studer cmd		********
#define CMD_XTM_START				1					// prvni prikaz pro XTM
#define CMD_XTM_BATERRY_VOLTAGE		0
#define	CMD_XTM_OUTPUT_VOLTAGE		1
#define	CMD_XTM_OUTPUT_CURRENT		2
#define	CMD_XTM_OUTPUT_POWER		3
#define	CMD_XTM_OUTPUT_FREQ			4
#define	CMD_XTM_INPUT_POWER			5
#define	CMD_XTM_INPUT_CURRENT		6
#define	CMD_XTM_STATE_AUX1			7
#define	CMD_XTM_STATE_AUX2			8
#define CMD_XTM_END					9					// posledni prikaz pro XTM

#define CMD_XCAN_START				20					// prvni prikaz pro XCAN
#define CMD_XCAN_BATERRY_VOLTAGE	20
#define CMD_XCAN_BATERRY_CURRENT	21
#define CMD_XCAN_BATERRY_SOC		22
#define CMD_XCAN_BATERRY_POWER		23
#define CMD_XCAN_BATERRY_TEMP		24
#define CMD_XCAN_BATERRY_CURR_REC	25
#define CMD_XCAN_END				26					// posledni prikaz pro XCAN

#define PRM_XTM_START				50					// prvni parametr pro XTM
#define	PRM_XTM_BATTERY_CURRENT		50
#define PRM_XTM_TRANSFER_RELAY		51
#define PRM_XTM_END					52					// posledni parametr pro XTM

#define	PRM_XTM_TRANSFER_RELAY_MODE	100					// zapis modu funkce AUX1


//**************************************************************
//		********		Define structure cmd		********
//					Service Flags
#define	REQUEST_SERVICE_FLAGS		0
//					Service Id
#define	READ_PROPERTY				1
#define	WRITE_PROPERTY				2
//					Object type
#define	OBJECT_USER_INFO			1
#define	OBJECT_PARAMETR				2
#define	OBJECT_MESSAGE				3
#define	OBJECT_DATALOG				5
//					Object Id	= Nr  infos					Xtender infos
#define	BATTERY_VOLTAGE				3000	//float
#define	OUTPUT_VOLTAGE				3021	// -*-
#define	OUTPUT_CURRENT				3022
#define	OUTPUT_POWER				3023
#define	OUTPUT_FREQ					3085
#define INPUT_POWER					3013
#define INPUT_CURRENT				3012
#define STATE_AUX1					3031
#define STATE_AUX2					3032


#define	BATTERY_VOLTAGE_XCAN		7000
#define	BATTERY_CURRENT				7001
#define	STATE_OF_CHARGE				7002
#define	BATTERY_POWER				7003	// float
#define	BATTERY_TEMP				7029	// float
#define	BATTERY_CUR_REC				7065	// float

//					Object Id	= Nr parameters
#define	BATTERY_CHARGE_CURRENT		1138	// float
#define TRANSFER_RELAY				1128	// bool
#define INVERTER_ALLOWED			1124	// bool
#define	OPERATING_MODE_AUX_1		1202	// LONG_ENUM - 32b integer

//					Property Id
//						Property Id for OBJECT_MESSAGE
#define	PROPERTY_MESSAGE			0
//						Property Id for OBJECT_USER_INFO
#define	PROPERTY_VALUE				1
//						Property Id for OBJECT_PARAMETR
#define	VALUE_QSP					5
#define	MIN_QSP						6
#define	MAX_QSP						7
#define	LEVEL_QSP					8
#define	US_SAVE_VALUE				0x0D
//					Format
#define BOOL						1
#define FLOAT						2
#define INT32						3
#define ERROR						4
#define	BYTE_STREAM					5
//					Operating mode (AUX 1)
#define	AUTOMATIC_VALUE				1			// zapnuti transfer rele
#define	REVERSED_AUTOMATIC_VALUE	2			// normal mod funkce transfer rele
#define	MANUAL_ON_VALUE				4			// zapnuti transfer rele

//	MSG promenne
var MaxMsgCnt;
var	MaxTimeStamp;
var	ObjectType;

var SaveDataIndex;

var	PropertyId;
var	PropertyData;
var	Src_Addresa;
var LastTimeStampMsg;

var Dst_Addresa;			// adresa zarizeni XTM1_ADDR, ...

var LastTimeStamp1;			// mqtt stampstep
var LastTimeStamp2;


//	Pomocne promenne
var RamIndex;				// pomocna promenna
var tmp, Write_Value;
var tmp2, Cmd_Id_Write;

InitPWM
{
	if(PWM_FREQ != PWM_FREQUENCY)
	{
		PWM_FREQ = PWM_FREQUENCY;
	}
	PWM_DUTY = PWM_DUTY_CYCLE;
	echo('PWM set to:', PWM_FREQ, 'Hz, ', PWM_DUTY, '%');
}

InitEthernet
{
	// network communication shall be started only after the SDS is connected to network (ethernet is up)
	echo('waiting for network availability');
 
waiting_ethernet:
	if (sys[24] == 0) goto waiting_ethernet; // 0 = no ethernet
	if (sys[27] == 0) goto waiting_ethernet; // 0 = no IP address
}

InitSerial
{
	 // -> nastaveni  pro COM1
	 /*
	  A fixed baudrate of 38400 bps
		 1 start bit
		 8 bit of data, LSB first
		 1 parity bit
		 even parity
		 1 stop bit
	 */
	echo('seting serial port');
	serial1_set(38400, 9, 1, 3);
}

// *************************************************
InitMQTT
{
// connect on start
	echo('connecting to MQTT Broker... / ver: ', sys[2199]);
	
 // is connected - OK ?
	if ((sys[2200] == 4) && (sys[2201] == 0)) goto end_init;
	
 //           	 ip   ip   ip ip   port  client-id  username   password    keepalive(sec)				//client-id -> musi byt jedinecne mezi MQTT klienty 
	mqtt_connect(192, 168, 1, 230, 1883, 'SDS Studer', 'ha_mqtt', 'mqtt123456', 120);


 // wait for a complete connection
	label waiting_for_mqqt_conn:
  
 // error - failed ?
	if (sys[2200] <= 0) goto mqtt_conn_fail; // error ? (any negative number is error code)

 // done - connected ?
	if (sys[2200] != 4) goto waiting_for_mqqt_conn; // success ? (yes only if == 4)

 // test the CONNACK result - see "3.2.2.3 Connect Return code" - we expect "0" as OK

	if (sys[2201] != 0) goto mqtt_conn_fail; // is broker's result code OK ? (OK only if == 0)
		
	LastTimeStamp1 = 0;
	LastTimeStamp2 = 0;
	
end_init:
	
	//			SUBSCRIBE MSG
	
	mqtt_subscribe(MQTT_SUBSCRIBE_SWITCH_PWR, 'sds/studer/control');

 // wait for the successful subscribe 
 wS:
	if (sys[2200] < 0) goto mqtt_conn_fail; // disconnected (if any negative number)
	if (sys[2202] == 4) goto wS;            // still working... (done when != 4)
	if (sys[2202] != 8)                     // success ? (only if == 8, otherwise error or failure)
	{ 
   // FAILED -> not subscribed !
		echo('subscribe error = ', sys[2202]); 
		goto mqtt_conn_fail;
	}

	 mqtt_subscribe(MQTT_SUBSCRIBE_SWITCH_PWM, 'sds/studer/pwm');

 // wait for the successful subscribe 
 wT:
	if (sys[2200] < 0) goto mqtt_conn_fail; // disconnected (if any negative number)
	if (sys[2202] == 4) goto wT;            // still working... (done when != 4)
	if (sys[2202] != 8)                     // success ? (only if == 8, otherwise error or failure)
	{ 
   // FAILED -> not subscribed !
		echo('subscribe error = ', sys[2202]); 
		goto mqtt_conn_fail;
	}
	
 // connected (CONNACK result is 0x00)
//end_init:
	echo('connected to broker: OK');
	Cmd_Id_Write = 0;
}

MQTT_Check_Incoming
{
 // any change ? (any new message?)
	if (LastTimeStamp1 != sys[2291])  // sys[2291] is a timestamp for index #1
	{
    // store so we can compare it later, again
		LastTimeStamp1 = sys[2291];

    // use the new value!
		echo('TOPIC #1: "',sys[2211],'" update to: "',sys[2251],'" ');
		sprintf(text[0], sys[2251]);				// x,y,...	-> text[0] x spotreba:  1 - DS/ 2 - FVE / 0 - no change; text[2] y charge batt.:  1 - ON/ 2 - OFF/ 0 - no change
		if(text[0] == ASCI_1)								// prepnuti spotreby na DS
		{
			RE_DS = 1;
			wait(2000);										// 2sec
			RE_DS = 0;
			echo('Switch to DS');
		}
		if(text[0] == ASCI_2)								// prepnuti spotreby na FVE
		{
			RE_FVE = 1;
			wait(2000);										// 2sec
			RE_FVE = 0;
			echo('Switch to FVE');
		}
		if(text[2] == ASCI_1)								// charge battery ON
		{
			Cmd_Id_Write = PRM_XTM_TRANSFER_RELAY_MODE;
			Write_Value = AUTOMATIC_VALUE;
			echo('Batt charge ON');
		}
		if(text[2] == ASCI_2)								// charge battery OFF
		{
			Cmd_Id_Write = PRM_XTM_TRANSFER_RELAY_MODE;
			Write_Value = REVERSED_AUTOMATIC_VALUE;
			echo('Batt charge OFF');
		}
	}

	if (sys[2200] < 0) goto mqtt_conn_fail; // disconnected
 
	if (LastTimeStamp2 != sys[2292])  // sys[2291] is a timestamp for index #1
	{
    // store so we can compare it later, again
		LastTimeStamp2 = sys[2292];

    // use the new value!
		echo('TOPIC #2: "',sys[2212],'" update to: "',sys[2252],'" ');
		GET_ATOI = 0;
		sprintf(text[0], sys[2252]);
		atoi(text[0]);
		tmp = GET_ATOI;
//		echo('Get atoi: ', tmp);
		
		if(tmp > 80)
		{
			tmp = 80;
		}
		if(tmp < 20)
		{
			tmp = 20;
		}
		
		PWM_DUTY = tmp;
		echo('Set PWM: ', tmp);
	}

	if (sys[2200] < 0) goto mqtt_conn_fail; // disconnected
}

var IndexChecksum;
var LengthChecksum;

scom_calc_checksum
{
var A,B;

	A = 0xFF;
	B = 0;

CheckSumComp:
	A = (A + ram[IndexChecksum]) & 0xFF;
	B = (B + A) & 0xFF;
	LengthChecksum--;
	IndexChecksum++;
	if(LengthChecksum) goto CheckSumComp;
}

var Data_Length;			// delka dat obsahujici Cmd
var Data_Index;				// index v ram[], zacatek dat Cmd

SendData
{
	RamIndex = FRAME_START;
	// start byte
	ram[RamIndex] = 0xAA;
	RamIndex++;
	// frame flag
	ram[RamIndex] = 0x00;
	RamIndex++;
	// src adresa
	ram[RamIndex] = 0x01;
	RamIndex++;
	ram[RamIndex] = 0x00;
	RamIndex++;
	ram[RamIndex] = 0x00;
	RamIndex++;
	ram[RamIndex] = 0x00;
	RamIndex++;
	// dst adresa
	ram[RamIndex] = Dst_Addresa & 0xFF;
	RamIndex++;
	ram[RamIndex] = (Dst_Addresa >> 8) & 0xFF;
	RamIndex++;
	ram[RamIndex] = 0x00;
	RamIndex++;
	ram[RamIndex] = 0x00;
	RamIndex++;
	// length adresa
	ram[RamIndex] = Data_Length & 0xFF;
	RamIndex++;
	ram[RamIndex] = (Data_Length >> 8) & 0xFF;
	RamIndex++;
	
	// header checksum / frame flag ... length adresa
	IndexChecksum = FRAME_START + 1;
	LengthChecksum = 11;
	scom_calc_checksum();
	ram[RamIndex] = A;
	RamIndex++;
	ram[RamIndex] = B;
	RamIndex++;
	
	// copy data + checksum data
	IndexChecksum = Data_Index;
	LengthChecksum = Data_Length;
	scom_calc_checksum();
		
jmp_CopyData:
	ram[RamIndex] = ram[Data_Index];
//	echo('*** ', ram[Data_Index]);
	RamIndex++;
	Data_Index++;
	Data_Length--;
	if(Data_Length) goto jmp_CopyData;
	
	ram[RamIndex] = A;
	RamIndex++;
	ram[RamIndex] = B;

	Data_Length = (RamIndex - FRAME_START) + 1;
	
	serial1_write(1, FRAME_START, Data_Length); // zápis do COM1
}

var Cmd_Id;

SendCmd_ReadUserInfo
{
	RamIndex = DATA_START;
	ram[RamIndex] = REQUEST_SERVICE_FLAGS;
	RamIndex++;
	
	ram[RamIndex] = READ_PROPERTY;
	RamIndex++;		
	
	ram[RamIndex] = OBJECT_USER_INFO & 0xFF;
	RamIndex++;
	ram[RamIndex] = (OBJECT_USER_INFO >> 8) & 0xFF;
	RamIndex++;
	tmp = 0;
														//   XTM parametry

	if(Cmd_Id == CMD_XTM_BATERRY_VOLTAGE)
	{
		tmp = BATTERY_VOLTAGE;
	}	
	
	if(Cmd_Id == CMD_XTM_OUTPUT_VOLTAGE)
	{
		tmp = OUTPUT_VOLTAGE;
	}
	
	if(Cmd_Id == CMD_XTM_OUTPUT_CURRENT)
	{
		tmp = OUTPUT_CURRENT;
	}
	
	if(Cmd_Id == CMD_XTM_OUTPUT_POWER)
	{
		tmp = OUTPUT_POWER;
	}
	
	if(Cmd_Id == CMD_XTM_OUTPUT_FREQ)
	{
		tmp = OUTPUT_FREQ;
	}
	
	if(Cmd_Id == CMD_XTM_INPUT_POWER)
	{
		tmp = INPUT_POWER;
	}
	
	if(Cmd_Id == CMD_XTM_INPUT_CURRENT)
	{
		tmp = INPUT_CURRENT;
	}
	
	if(Cmd_Id == CMD_XTM_STATE_AUX1)
	{
		tmp = STATE_AUX1;
	}
	
	if(Cmd_Id == CMD_XTM_STATE_AUX2)
	{
		tmp = STATE_AUX2;
	}
	
													//   XCAN parametry
	if(Cmd_Id == CMD_XCAN_BATERRY_VOLTAGE)
	{
		tmp = BATTERY_VOLTAGE_XCAN;
	}
	
	if(Cmd_Id == CMD_XCAN_BATERRY_CURRENT)
	{
		tmp = BATTERY_CURRENT;
	}
	
	if(Cmd_Id == CMD_XCAN_BATERRY_SOC)
	{
		tmp = STATE_OF_CHARGE;
	}
	
	if(Cmd_Id == CMD_XCAN_BATERRY_POWER)
	{
		tmp = BATTERY_POWER;
	}
	
	if(Cmd_Id == CMD_XCAN_BATERRY_TEMP)
	{
		tmp = BATTERY_TEMP;
	}
	
	if(Cmd_Id == CMD_XCAN_BATERRY_CURR_REC)
	{
		tmp = BATTERY_CUR_REC;
	}
	
	if(tmp)
	{
		ram[RamIndex] = tmp & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 8) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 16) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 24) & 0xFF;
		RamIndex++;

		ram[RamIndex] = PROPERTY_VALUE & 0xFF;
		RamIndex++;
		ram[RamIndex] = (PROPERTY_VALUE >> 8) & 0xFF;

		if(RamIndex != DATA_START)
		{
			echo('Send cmd: ', tmp);
			Data_Index = DATA_START;
			Data_Length = (RamIndex - DATA_START) + 1;
			if(Data_Length == 10)
				SendData();
		}
	}
}



SendCmd_Write_US_QspValue
{
	RamIndex = DATA_START;
	ram[RamIndex] = REQUEST_SERVICE_FLAGS;
	RamIndex++;
	
	ram[RamIndex] = WRITE_PROPERTY;
	RamIndex++;		
	
	ram[RamIndex] = OBJECT_PARAMETR & 0xFF;
	RamIndex++;
	ram[RamIndex] = (OBJECT_PARAMETR >> 8) & 0xFF;
	RamIndex++;
	tmp = 0;
		
	if(Cmd_Id == PRM_XTM_TRANSFER_RELAY_MODE)
	{
		tmp = OPERATING_MODE_AUX_1;
	}
	
	if(tmp)
	{
		ram[RamIndex] = tmp & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 8) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 16) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 24) & 0xFF;
		RamIndex++;
				
		ram[RamIndex] = US_SAVE_VALUE & 0xFF;
		RamIndex++;
		ram[RamIndex] = (US_SAVE_VALUE >> 8) & 0xFF;
		RamIndex++;

		ram[RamIndex] = Write_Value & 0xFF;
		RamIndex++;
		ram[RamIndex] = (Write_Value >> 8) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (Write_Value >> 16) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (Write_Value >> 24) & 0xFF;
		
		if(RamIndex != DATA_START)
		{
			Data_Index = DATA_START;
			Data_Length = (RamIndex - DATA_START) + 1;
			if(Data_Length == 14)
				SendData();
		}
	}
}

SendCmd_ReadQspValue
{
	RamIndex = DATA_START;
	ram[RamIndex] = REQUEST_SERVICE_FLAGS;
	RamIndex++;
	
	ram[RamIndex] = READ_PROPERTY;
	RamIndex++;		
	
	ram[RamIndex] = OBJECT_PARAMETR & 0xFF;
	RamIndex++;
	ram[RamIndex] = (OBJECT_PARAMETR >> 8) & 0xFF;
	RamIndex++;
	tmp = 0;
	
	if(Cmd_Id == PRM_XTM_BATTERY_CURRENT)
	{
		tmp = BATTERY_CHARGE_CURRENT;
	}
	
	if(Cmd_Id == PRM_XTM_TRANSFER_RELAY)
	{
		tmp = TRANSFER_RELAY;
	}
	
	if(tmp)
	{
		ram[RamIndex] = tmp & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 8) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 16) & 0xFF;
		RamIndex++;
		ram[RamIndex] = (tmp >> 24) & 0xFF;
		RamIndex++;
				
		ram[RamIndex] = VALUE_QSP & 0xFF;
		RamIndex++;
		ram[RamIndex] = (VALUE_QSP >> 8) & 0xFF;

		if(RamIndex != DATA_START)
		{
			Data_Index = DATA_START;
			Data_Length = (RamIndex - DATA_START) + 1;
			if(Data_Length == 10)
				SendData();
		}
	}
}

//Cmd_Id - message Id

SendCmd_ReadMessages
{
	RamIndex = DATA_START;
	ram[RamIndex] = REQUEST_SERVICE_FLAGS;
	RamIndex++;
	
	ram[RamIndex] = READ_PROPERTY;
	RamIndex++;		
	
	ram[RamIndex] = OBJECT_MESSAGE & 0xFF;
	RamIndex++;
	ram[RamIndex] = (OBJECT_MESSAGE >> 8) & 0xFF;
	RamIndex++;
	
	ram[RamIndex] = Cmd_Id & 0xFF;
	RamIndex++;
	ram[RamIndex] = (Cmd_Id >> 8) & 0xFF;
	RamIndex++;
	ram[RamIndex] = (Cmd_Id >> 16) & 0xFF;
	RamIndex++;
	ram[RamIndex] = (Cmd_Id >> 24) & 0xFF;
	RamIndex++;
				
	ram[RamIndex] = PROPERTY_MESSAGE & 0xFF;
	RamIndex++;
	ram[RamIndex] = (PROPERTY_MESSAGE >> 8) & 0xFF;

	if(RamIndex != DATA_START)
	{
		Data_Index = DATA_START;
		Data_Length = (RamIndex - DATA_START) + 1;
		if(Data_Length == 10)
			SendData();
	}
}


var RxCharCount;

Load_Rx_Buffer
{
var RxTimeOut;
var Headr_OK;

	RamIndex = RX_BUFFER_START;
	Headr_OK = 0;
	tmp = (RX_TIMEOUT - RxTimeOut) * 10;
	
	echo('********** TO[', tmp, ' ms]');
	echo('Rx Data:');
	
find_start:
	tmp = GET_RX_CHAR;
	if(tmp == 0xAA)					// zacatek frame
	{
		RxTimeOut = RX_TIMEOUT_CHAR;
		A = 0xFF;
		B = 0;
		RxCharCount = HEADR_SIZE;
		
next_char:
		tmp = GET_RX_CHAR;
		if(tmp == -1)				// neni znak
		{
			wait(10);
			RxTimeOut--;
			if(RxTimeOut) goto next_char;
		}
		else
		{
//			echo('.', tmp);
			ram[RamIndex] = tmp;
			RamIndex++;
			if((RamIndex - RX_BUFFER_START) > (RxCharCount - 1))
			{
//				echo('Rx checksum start ', A,', ', B);
				RamIndex = RX_BUFFER_START + RxCharCount - 2;
				tmp = ram[RamIndex];
				RamIndex ++;
				if(B != ram[RamIndex] || A != tmp)				// chyba checksum headr
				{
					RamIndex = RX_BUFFER_START;
					echo('Rx checksum err');
					goto find_start;
				}
				else					// headr OK, init checksum
				{
					if(Headr_OK == 0)
					{
						echo('Headr OK');
						A = 0xFF;
						B = 0;
						
						Headr_OK = 1;
						
						RamIndex = RX_BUFFER_DATA_LENGTH;			// Get Data size
						RxCharCount = (ram[RamIndex] << 8) & 0xFF00;
						RamIndex--;
						RxCharCount |= (0xFF & ram[RamIndex]);
						echo('Data Size: ', RxCharCount);
						tmp = RxCharCount;
						RxCharCount = tmp + 2;							// plus sizeof checksum
						
						RamIndex = RX_BUFFER_DATA_LENGTH - 8;		// Get src_addr
						tmp = (ram[RamIndex] << 8) & 0xFF00;
						RamIndex--;
						tmp |= (0xFF & ram[RamIndex]);
						echo('Src Address: ', tmp);
						Src_Addresa = tmp;
						
						RxTimeOut = RX_TIMEOUT_CHAR;
						RamIndex = RX_BUFFER_START;				// Set start bufferu
						
						goto next_char;
					}
					else				// Data OK
					{
						echo('Data OK');
						
						RamIndex = RX_BUFFER_START;				// Get service flags
						tmp = ram[RamIndex] & 0x00FF;
						if(tmp != SERVICE_FLAGS_OK)
						{
							echo('Response Error (' , tmp, ')');
							goto End_Load_Rx_Buffer;
						}
						
						RamIndex = RX_BUFFER_START + 5;			// Get object id
						tmp = (ram[RamIndex] << 8) & 0xFF00;
						RamIndex--;
						tmp |= (0xFF & ram[RamIndex]);
						echo('Parametr Id: ', tmp);
						PropertyId = tmp;
						PropertyData = 0;

						if(RxCharCount == 16)
						{
							RamIndex = RX_BUFFER_START + 13;			// Get data 4B
							tmp = (ram[RamIndex] << 24) & 0xFF000000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 16) & 0x00FF0000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 8) & 0x0000FF00;
							RamIndex--;
							tmp |= (ram[RamIndex]) & 0x000000FF;
							PropertyData = tmp;
						}
						if(RxCharCount == 14)
						{
							RamIndex = RX_BUFFER_START + 11;			// Get data 2B
							tmp = (ram[RamIndex] << 8) & 0x0000FF00;
							RamIndex--;
							tmp |= (ram[RamIndex]) & 0x000000FF;
							PropertyData = tmp;
						}
						if(RxCharCount == 13)
						{
							RamIndex = RX_BUFFER_START + 10;			// Get data 1B
							tmp = (ram[RamIndex]) & 0x000000FF;
							PropertyData = tmp;
						}
						if(RxCharCount == 12)							// Response of write cmd
						{
							echo('Write cmd OK');
							goto End_Load_Rx_Buffer;
						}
						echo('Data: ', tmp);
						
						if(RxCharCount == 30)							// message
						{
							RamIndex = RX_BUFFER_START + 27;			// Get data 18B
							tmp = (ram[RamIndex] << 24) & 0xFF000000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 16) & 0x00FF0000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 8) & 0x0000FF00;
							RamIndex--;
							tmp |= (ram[RamIndex]) & 0x000000FF;
							RamIndex--;
							echo('Value: ', tmp);
							
							tmp = (ram[RamIndex] << 24) & 0xFF000000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 16) & 0x00FF0000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 8) & 0x0000FF00;
							RamIndex--;
							tmp |= (ram[RamIndex]) & 0x000000FF;
							RamIndex--;
							echo('TimeStamp: ', tmp);
							LastTimeStampMsg = tmp;
							PropertyData = tmp;
							
							tmp = (ram[RamIndex] << 24) & 0xFF000000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 16) & 0x00FF0000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 8) & 0x0000FF00;
							RamIndex--;
							tmp |= (ram[RamIndex]) & 0x000000FF;
							RamIndex--;
							echo('Address: ', tmp);
							Src_Addresa = tmp;
							
							tmp = (ram[RamIndex] << 8) & 0x0000FF00;
							RamIndex--;
							tmp |= (ram[RamIndex]) & 0x000000FF;
							RamIndex--;
							echo('Msg Id: ', tmp);
							PropertyId = tmp;
							
							tmp = (ram[RamIndex] << 24) & 0xFF000000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 16) & 0x00FF0000;
							RamIndex--;
							tmp |= (ram[RamIndex] << 8) & 0x0000FF00;
							RamIndex--;
							tmp |= (ram[RamIndex]) & 0x000000FF;
							echo('Msg total nr: ', tmp);
							MaxMsgCnt = tmp;
						}
						else
						{
//							echo('****** *** : ', ram[128]);
//							echo('****** SaveDataIndex *** : ', SaveDataIndex);
							ram[SaveDataIndex] = Src_Addresa;
							SaveDataIndex++;
							ram[SaveDataIndex] = PropertyId;
							SaveDataIndex++;
							ram[SaveDataIndex] = PropertyData;
							SaveDataIndex++;
							goto End_Load_Rx_Buffer;
						}
					}
				}
			}
		
			if((RamIndex - RX_BUFFER_START) < (RxCharCount - 1))
			{
				A = (A + tmp) & 0xFF;
				B = (B + A) & 0xFF;
			}
			
			RxTimeOut = RX_TIMEOUT_CHAR;
			goto next_char;
		}
	}
	if(tmp != -1) goto find_start;
	
End_Load_Rx_Buffer:
}

ReceiveCmd
{
	RxTimeOut = RX_TIMEOUT;
wait_char:
	RxTimeOut--;
	if(IS_RX_CHAR == 0)			// znak v bufferu
	{
		Load_Rx_Buffer();
		RxTimeOut = 0;			// stop cekani
	}
	wait(10);
	if(RxTimeOut) goto wait_char;
	wait(20);
}

MQTT_Send_Tmp
{
	if (sys[311] == 16777216)
	{
		tmp = -1;
	}
	else
	{
		tmp = sys[311];
	}

	mqtt_publish('sds/teploty/studer', '{"temp_SDS":',sys[310], ', "temp_Boiler1":',tmp,'}');
	echo('sds/teploty/studer', '{"temp_SDS":',sys[310], ', "temp_Boiler1":',tmp,'}');
w1: 
	if (sys[2200] < 0)
	{
		echo('sds/teploty/studer... error=', sys[2200],' connack=', sys[2201]);
		goto mqtt_conn_fail;    // disconnected ?
	}
	if (sys[2202] == 1) goto w1;               // still working ?
	if (sys[2202] != 2)                        // success ?
	{ 
		echo('publish error = ', sys[2202]); 
	};
}

MQTT_Send
{
next_msg_send:

	tmp = RamIndex + 1;
	tmp2 = RamIndex + 2;

//	mqtt_publish('sds/teploty/solax', '{"temp_SDS":',sys[310],'}');

	mqtt_publish('sds/studer/val/', '{"address":', ram[RamIndex],', "cmd":', ram[tmp],', "val":', ram[tmp2],'}'); 
	echo('sds/studer/val/', '{"address":', ram[RamIndex],', "cmd":', ram[tmp],', "val":', ram[tmp2],'}'); 
	RamIndex = RamIndex + 3;
	
w2: 
	tmp++;
	if (sys[2200] < 0)
	{
		echo('sds/studer... error=', sys[2200],' connack=', sys[2201], ' cnt=', tmp);
		wait(10);
		goto mqtt_conn_fail;    // disconnected ?
	}
	if (sys[2202] == 1) goto w2;               // still working ?
	if (sys[2202] != 2)                        // success ?
	{ 
		echo('publish error = ', sys[2202]); 
	};
//	RamIndex++;
	if (SaveDataIndex > RamIndex)
		goto next_msg_send;
}


MQTT_Send_Msg
{
	mqtt_publish('sds/studer/msg/', '{"timestamp":', LastTimeStampMsg, ', "address":', Src_Addresa, ', "msg_id":', PropertyId,'}'); 
w3: 
	if (sys[2200] < 0)
	{
		echo('sds/studer_msg... error=', sys[2200],' connack=', sys[2201]);
		wait(10);
		goto mqtt_conn_fail;    // disconnected ?
	}
	if (sys[2202] == 1) goto w3;               // still working ?
	if (sys[2202] != 2)                        // success ?
	{ 
		echo('publish error = ', sys[2202]); 
	};
}

ControlProces
{
	if(Cmd_Id_Write != 0)
	{
		Cmd_Id = Cmd_Id_Write;
		Cmd_Id_Write = 0;
		echo(' ');
		echo('Cmd: ', Cmd_Id);
		Dst_Addresa = XTM_ALL_ADDR;
		SendCmd_Write_US_QspValue();
		ReceiveCmd();
		wait(200);
	}
}

main
{
	sdsc_set_wdg(WDT_TOT);
	echo(' ');
	echo(' ');
	echo('********** START **********');

	InitSerial();
	InitEthernet();
	InitMQTT();
	InitPWM();

main_start:

	if(TIMER_COUNT == 0)
	{
		TIMER_COUNT = SEND_TOT_TEMP;
		MQTT_Send_Tmp();
	}
	sdsc_kick_wdg(WDT_TOT);
	
	Cmd_Id = CMD_XTM_START;
	Dst_Addresa = XTM1_ADDR;
	SaveDataIndex = RX_DATA_START;						// nastaveni ukladani nactenych dat
	
jmp_XTM_Cmd:

	echo(' ');
	echo('Cmd: ', Cmd_Id);
	SendCmd_ReadUserInfo();
	ReceiveCmd();
	Cmd_Id++;
	wait(20);
	if(Cmd_Id < CMD_XTM_END) goto jmp_XTM_Cmd;
/*														// dalsi XTM
//	Cmd_Id = CMD_XTM_BATERRY_VOLTAGE;
//	Dst_Addresa = XTM2_ADDR;
//	goto jmp_XTM_Cmd;
														// dalsi XTM	
//	Cmd_Id = CMD_XTM_BATERRY_VOLTAGE;
//	Dst_Addresa = XTM3_ADDR;
//	goto jmp_XTM_Cmd;
*/
	Cmd_Id = CMD_XCAN_START;
	Dst_Addresa = XCAN_ADDR;

jmp_XCAN_Cmd:
	echo(' ');
	echo('Cmd: ', Cmd_Id);
	SendCmd_ReadUserInfo();
	ReceiveCmd();
	Cmd_Id++;
	wait(20);
	if(Cmd_Id < CMD_XCAN_END) goto jmp_XCAN_Cmd;

	Cmd_Id = PRM_XTM_START;
	Dst_Addresa = XTM1_ADDR;
/*
// jmp_XTM_Param:											// cteni nastavenych parametru

//	echo(' ');
//	echo('Cmd: ', Cmd_Id);
//	SendCmd_ReadQspValue();
//	ReceiveCmd();
//	Cmd_Id++;
//	if(Cmd_Id < PRM_XTM_END) goto jmp_XTM_Param;
*/
														// Send MQTT
	tmp = (SaveDataIndex - RX_DATA_START) / 3;
	echo(' ');
	echo('Vycteno ', tmp, ' zprav');
	
	RamIndex = RX_DATA_START;
	MQTT_Send();
	
													//******** Read MSG ********//
	echo(' ');
	echo('Read msg 0');
	Dst_Addresa = XCOM_ADDR;
	SaveDataIndex = RX_DATA_START;						// nastaveni ukladani nactenych dat
	Cmd_Id = 0;
	MaxTimeStamp = SAVE_LAST_TIMESTAMP;
	
Read_Next_Msg:

	MaxMsgCnt = 0;
	LastTimeStampMsg = 0;
	
	SendCmd_ReadMessages();
	ReceiveCmd();
	echo('timest s: ', SAVE_LAST_TIMESTAMP, ', a: ', LastTimeStampMsg);
	if(SAVE_LAST_TIMESTAMP < LastTimeStampMsg)				// je novejsi zprava
	{
		MQTT_Send_Msg();
		echo('sds/studer/msg/', LastTimeStampMsg, '/', Src_Addresa, '/', PropertyId);
		Cmd_Id++;
		SaveDataIndex = RX_DATA_START;
		if(MaxTimeStamp < LastTimeStampMsg)
		{
			echo('max timest m: ', MaxTimeStamp, ', a: ', LastTimeStampMsg);
			MaxTimeStamp = LastTimeStampMsg;
		}
		
		if(MaxMsgCnt == 0)
		{
			SAVE_LAST_TIMESTAMP = MaxTimeStamp;
			goto main_start;			
		}
		
		sdsc_kick_wdg(WDT_TOT);
		goto Read_Next_Msg;
	}
	else
	{
		SAVE_LAST_TIMESTAMP = MaxTimeStamp;
	}
	SaveDataIndex = RX_DATA_START;						// nastaveni ukladani nactenych dat

	echo(' ');
	
	MQTT_Check_Incoming();
	ControlProces();				// vlastni rizeni
	goto main_start;
	
mqtt_conn_fail:
	echo('unable to connect... error=', sys[2200],' connack=', sys[2201]);
	wait(1000);
	sdsc_reset_program(1);
}


